blob: a1bd82dfff29d6dc86cc0e93473c93a495ccf120 [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
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Mathias Agopian518ec112011-05-13 16:21:08 -070019#include <ctype.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <hardware/gralloc.h>
24#include <system/window.h>
25
26#include <EGL/egl.h>
27#include <EGL/eglext.h>
28#include <GLES/gl.h>
29#include <GLES/glext.h>
30
31#include <cutils/log.h>
32#include <cutils/atomic.h>
33#include <cutils/properties.h>
34#include <cutils/memory.h>
35
36#include <utils/KeyedVector.h>
37#include <utils/SortedVector.h>
38#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080039#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070040
41#include "egl_impl.h"
42#include "egl_tls.h"
Siva Velusamy0469dd62011-11-30 15:05:37 -080043#include "glestrace.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070044#include "hooks.h"
45
46#include "egl_display.h"
47#include "egl_impl.h"
48#include "egl_object.h"
49#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080050#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070051
52using namespace android;
53
54// ----------------------------------------------------------------------------
55
Mathias Agopianbc2d79e2011-11-29 17:55:46 -080056#define EGL_VERSION_HW_ANDROID 0x3143
57
Mathias Agopian518ec112011-05-13 16:21:08 -070058struct extention_map_t {
59 const char* name;
60 __eglMustCastToProperFunctionPointerType address;
61};
62
63static const extention_map_t sExtentionMap[] = {
64 { "eglLockSurfaceKHR",
65 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
66 { "eglUnlockSurfaceKHR",
67 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
68 { "eglCreateImageKHR",
69 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
70 { "eglDestroyImageKHR",
71 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Jonas Yang1c3d72a2011-08-26 20:04:39 +080072 { "eglGetSystemTimeFrequencyNV",
73 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
74 { "eglGetSystemTimeNV",
75 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopian518ec112011-05-13 16:21:08 -070076};
77
78// accesses protected by sExtensionMapMutex
79static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
80static int sGLExtentionSlot = 0;
81static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
82
83static void(*findProcAddress(const char* name,
84 const extention_map_t* map, size_t n))() {
85 for (uint32_t i=0 ; i<n ; i++) {
86 if (!strcmp(name, map[i].name)) {
87 return map[i].address;
88 }
89 }
90 return NULL;
91}
92
93// ----------------------------------------------------------------------------
94
Mathias Agopian518ec112011-05-13 16:21:08 -070095namespace android {
96extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
97extern EGLBoolean egl_init_drivers();
98extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
99extern int gEGLDebugLevel;
100extern gl_hooks_t gHooksTrace;
Mathias Agopian518ec112011-05-13 16:21:08 -0700101} // namespace android;
102
103// ----------------------------------------------------------------------------
104
105static inline void clearError() { egl_tls_t::clearError(); }
106static inline EGLContext getContext() { return egl_tls_t::getContext(); }
107
108// ----------------------------------------------------------------------------
109
110EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
111{
112 clearError();
113
114 uint32_t index = uint32_t(display);
115 if (index >= NUM_DISPLAYS) {
116 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
117 }
118
119 if (egl_init_drivers() == EGL_FALSE) {
120 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
121 }
122
123 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
124 return dpy;
125}
126
127// ----------------------------------------------------------------------------
128// Initialization
129// ----------------------------------------------------------------------------
130
131EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
132{
133 clearError();
134
135 egl_display_t * const dp = get_display(dpy);
136 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
137
138 EGLBoolean res = dp->initialize(major, minor);
139
140 return res;
141}
142
143EGLBoolean eglTerminate(EGLDisplay dpy)
144{
145 // NOTE: don't unload the drivers b/c some APIs can be called
146 // after eglTerminate() has been called. eglTerminate() only
147 // terminates an EGLDisplay, not a EGL itself.
148
149 clearError();
150
151 egl_display_t* const dp = get_display(dpy);
152 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
153
154 EGLBoolean res = dp->terminate();
155
156 return res;
157}
158
159// ----------------------------------------------------------------------------
160// configuration
161// ----------------------------------------------------------------------------
162
163EGLBoolean eglGetConfigs( EGLDisplay dpy,
164 EGLConfig *configs,
165 EGLint config_size, EGLint *num_config)
166{
167 clearError();
168
169 egl_display_t const * const dp = validate_display(dpy);
170 if (!dp) return EGL_FALSE;
171
Mathias Agopian7773c432012-02-13 20:06:08 -0800172 if (num_config==0) {
173 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700174 }
175
Mathias Agopian7773c432012-02-13 20:06:08 -0800176 EGLBoolean res = EGL_FALSE;
177 *num_config = 0;
178
179 egl_connection_t* const cnx = &gEGLImpl;
180 if (cnx->dso) {
181 res = cnx->egl.eglGetConfigs(
182 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700183 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800184
185 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700186}
187
188EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
189 EGLConfig *configs, EGLint config_size,
190 EGLint *num_config)
191{
192 clearError();
193
194 egl_display_t const * const dp = validate_display(dpy);
195 if (!dp) return EGL_FALSE;
196
197 if (num_config==0) {
198 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
199 }
200
Mathias Agopian518ec112011-05-13 16:21:08 -0700201 EGLBoolean res = EGL_FALSE;
202 *num_config = 0;
203
Mathias Agopianada798b2012-02-13 17:09:30 -0800204 egl_connection_t* const cnx = &gEGLImpl;
205 if (cnx->dso) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800206 res = cnx->egl.eglChooseConfig(
207 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700208 }
209 return res;
210}
211
212EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
213 EGLint attribute, EGLint *value)
214{
215 clearError();
216
217 egl_display_t const* dp = 0;
218 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
219 if (!cnx) return EGL_FALSE;
220
Mathias Agopian518ec112011-05-13 16:21:08 -0700221 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800222 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700223}
224
225// ----------------------------------------------------------------------------
226// surfaces
227// ----------------------------------------------------------------------------
228
229EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
230 NativeWindowType window,
231 const EGLint *attrib_list)
232{
233 clearError();
234
235 egl_display_t const* dp = 0;
236 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
237 if (cnx) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800238 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700239 EGLint format;
240
Mathias Agopian81a63352011-07-29 17:55:48 -0700241 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000242 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700243 window);
244 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
245 }
246
Mathias Agopian518ec112011-05-13 16:21:08 -0700247 // set the native window's buffers format to match this config
248 if (cnx->egl.eglGetConfigAttrib(iDpy,
Mathias Agopian7773c432012-02-13 20:06:08 -0800249 config, EGL_NATIVE_VISUAL_ID, &format)) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700250 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700251 int err = native_window_set_buffers_format(window, format);
252 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000253 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700254 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700255 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700256 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
257 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700258 }
259 }
260
Jamie Gennis59769462011-11-19 18:04:43 -0800261 // the EGL spec requires that a new EGLSurface default to swap interval
262 // 1, so explicitly set that on the window here.
263 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
264 anw->setSwapInterval(anw, 1);
265
Mathias Agopian518ec112011-05-13 16:21:08 -0700266 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800267 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700268 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800269 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700270 return s;
271 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700272
273 // EGLSurface creation failed
274 native_window_set_buffers_format(window, 0);
275 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700276 }
277 return EGL_NO_SURFACE;
278}
279
280EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
281 NativePixmapType pixmap,
282 const EGLint *attrib_list)
283{
284 clearError();
285
286 egl_display_t const* dp = 0;
287 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
288 if (cnx) {
289 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800290 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700291 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800292 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700293 return s;
294 }
295 }
296 return EGL_NO_SURFACE;
297}
298
299EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
300 const EGLint *attrib_list)
301{
302 clearError();
303
304 egl_display_t const* dp = 0;
305 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
306 if (cnx) {
307 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800308 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700309 if (surface != EGL_NO_SURFACE) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800310 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700311 return s;
312 }
313 }
314 return EGL_NO_SURFACE;
315}
316
317EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
318{
319 clearError();
320
321 egl_display_t const * const dp = validate_display(dpy);
322 if (!dp) return EGL_FALSE;
323
Mathias Agopianf0480de2011-11-13 20:50:07 -0800324 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700325 if (!_s.get())
326 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700327
328 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800329 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700330 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700331 _s.terminate();
332 }
333 return result;
334}
335
336EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
337 EGLint attribute, EGLint *value)
338{
339 clearError();
340
341 egl_display_t const * const dp = validate_display(dpy);
342 if (!dp) return EGL_FALSE;
343
Mathias Agopianf0480de2011-11-13 20:50:07 -0800344 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700345 if (!_s.get())
346 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700347
Mathias Agopian518ec112011-05-13 16:21:08 -0700348 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800349 return s->cnx->egl.eglQuerySurface(
350 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700351}
352
Jamie Gennise8696a42012-01-15 18:54:57 -0800353void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800354 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800355 clearError();
356
357 egl_display_t const * const dp = validate_display(dpy);
358 if (!dp) {
359 return;
360 }
361
362 SurfaceRef _s(dp, surface);
363 if (!_s.get()) {
364 setError(EGL_BAD_SURFACE, EGL_FALSE);
365 return;
366 }
367
368 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
369
370 egl_surface_t const * const s = get_surface(surface);
371 native_window_set_buffers_timestamp(s->win.get(), timestamp);
372}
373
Mathias Agopian518ec112011-05-13 16:21:08 -0700374// ----------------------------------------------------------------------------
375// Contexts
376// ----------------------------------------------------------------------------
377
378EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
379 EGLContext share_list, const EGLint *attrib_list)
380{
381 clearError();
382
383 egl_display_t const* dp = 0;
384 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
385 if (cnx) {
386 if (share_list != EGL_NO_CONTEXT) {
387 egl_context_t* const c = get_context(share_list);
388 share_list = c->context;
389 }
390 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800391 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700392 if (context != EGL_NO_CONTEXT) {
393 // figure out if it's a GLESv1 or GLESv2
394 int version = 0;
395 if (attrib_list) {
396 while (*attrib_list != EGL_NONE) {
397 GLint attr = *attrib_list++;
398 GLint value = *attrib_list++;
399 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
400 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800401 version = egl_connection_t::GLESv1_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700402 } else if (value == 2) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800403 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700404 }
405 }
406 };
407 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800408 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800409#if EGL_TRACE
410 if (gEGLDebugLevel > 0)
411 GLTrace_eglCreateContext(version, c);
412#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700413 return c;
414 }
415 }
416 return EGL_NO_CONTEXT;
417}
418
419EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
420{
421 clearError();
422
423 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700424 if (!dp)
425 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700426
Mathias Agopianf0480de2011-11-13 20:50:07 -0800427 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700428 if (!_c.get())
429 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700430
Mathias Agopian518ec112011-05-13 16:21:08 -0700431 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800432 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700433 if (result == EGL_TRUE) {
434 _c.terminate();
435 }
436 return result;
437}
438
Mathias Agopian518ec112011-05-13 16:21:08 -0700439EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
440 EGLSurface read, EGLContext ctx)
441{
442 clearError();
443
444 egl_display_t const * const dp = get_display(dpy);
445 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
446
Mathias Agopian5b287a62011-05-16 18:58:55 -0700447 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
448 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
449 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700450 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
451 (draw != EGL_NO_SURFACE) ) {
452 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
453 }
454
455 // get a reference to the object passed in
Mathias Agopianf0480de2011-11-13 20:50:07 -0800456 ContextRef _c(dp, ctx);
457 SurfaceRef _d(dp, draw);
458 SurfaceRef _r(dp, read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700459
460 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700461 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700462 // EGL_NO_CONTEXT is valid
463 return EGL_FALSE;
464 }
465
466 // these are the underlying implementation's object
467 EGLContext impl_ctx = EGL_NO_CONTEXT;
468 EGLSurface impl_draw = EGL_NO_SURFACE;
469 EGLSurface impl_read = EGL_NO_SURFACE;
470
471 // these are our objects structs passed in
472 egl_context_t * c = NULL;
473 egl_surface_t const * d = NULL;
474 egl_surface_t const * r = NULL;
475
476 // these are the current objects structs
477 egl_context_t * cur_c = get_context(getContext());
478
479 if (ctx != EGL_NO_CONTEXT) {
480 c = get_context(ctx);
481 impl_ctx = c->context;
482 } else {
483 // no context given, use the implementation of the current context
484 if (cur_c == NULL) {
485 // no current context
486 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
487 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
488 return setError(EGL_BAD_MATCH, EGL_FALSE);
489 }
490 // not an error, there is just no current context.
491 return EGL_TRUE;
492 }
493 }
494
495 // retrieve the underlying implementation's draw EGLSurface
496 if (draw != EGL_NO_SURFACE) {
497 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700498 impl_draw = d->surface;
499 }
500
501 // retrieve the underlying implementation's read EGLSurface
502 if (read != EGL_NO_SURFACE) {
503 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700504 impl_read = r->surface;
505 }
506
Mathias Agopian518ec112011-05-13 16:21:08 -0700507
Mathias Agopianfb87e542012-01-30 18:20:52 -0800508 EGLBoolean result = const_cast<egl_display_t*>(dp)->makeCurrent(c, cur_c,
509 draw, read, ctx,
510 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700511
512 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800513 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700514 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
515 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800516#if EGL_TRACE
517 if (gEGLDebugLevel > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800518 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800519#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700520 _c.acquire();
521 _r.acquire();
522 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700523 } else {
524 setGLHooksThreadSpecific(&gHooksNoContext);
525 egl_tls_t::setContext(EGL_NO_CONTEXT);
526 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700527 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000528 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700529 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700530 }
531 return result;
532}
533
534
535EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
536 EGLint attribute, EGLint *value)
537{
538 clearError();
539
540 egl_display_t const * const dp = validate_display(dpy);
541 if (!dp) return EGL_FALSE;
542
Mathias Agopianf0480de2011-11-13 20:50:07 -0800543 ContextRef _c(dp, ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700544 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
545
Mathias Agopian518ec112011-05-13 16:21:08 -0700546 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800547 return c->cnx->egl.eglQueryContext(
548 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700549
Mathias Agopian518ec112011-05-13 16:21:08 -0700550}
551
552EGLContext eglGetCurrentContext(void)
553{
554 // could be called before eglInitialize(), but we wouldn't have a context
555 // then, and this function would correctly return EGL_NO_CONTEXT.
556
557 clearError();
558
559 EGLContext ctx = getContext();
560 return ctx;
561}
562
563EGLSurface eglGetCurrentSurface(EGLint readdraw)
564{
565 // could be called before eglInitialize(), but we wouldn't have a context
566 // then, and this function would correctly return EGL_NO_SURFACE.
567
568 clearError();
569
570 EGLContext ctx = getContext();
571 if (ctx) {
572 egl_context_t const * const c = get_context(ctx);
573 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
574 switch (readdraw) {
575 case EGL_READ: return c->read;
576 case EGL_DRAW: return c->draw;
577 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
578 }
579 }
580 return EGL_NO_SURFACE;
581}
582
583EGLDisplay eglGetCurrentDisplay(void)
584{
585 // could be called before eglInitialize(), but we wouldn't have a context
586 // then, and this function would correctly return EGL_NO_DISPLAY.
587
588 clearError();
589
590 EGLContext ctx = getContext();
591 if (ctx) {
592 egl_context_t const * const c = get_context(ctx);
593 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
594 return c->dpy;
595 }
596 return EGL_NO_DISPLAY;
597}
598
599EGLBoolean eglWaitGL(void)
600{
Mathias Agopian518ec112011-05-13 16:21:08 -0700601 clearError();
602
Mathias Agopianada798b2012-02-13 17:09:30 -0800603 egl_connection_t* const cnx = &gEGLImpl;
604 if (!cnx->dso)
605 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
606
607 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700608}
609
610EGLBoolean eglWaitNative(EGLint engine)
611{
Mathias Agopian518ec112011-05-13 16:21:08 -0700612 clearError();
613
Mathias Agopianada798b2012-02-13 17:09:30 -0800614 egl_connection_t* const cnx = &gEGLImpl;
615 if (!cnx->dso)
616 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
617
618 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700619}
620
621EGLint eglGetError(void)
622{
Mathias Agopianada798b2012-02-13 17:09:30 -0800623 EGLint err = EGL_SUCCESS;
624 egl_connection_t* const cnx = &gEGLImpl;
625 if (cnx->dso) {
626 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700627 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800628 if (err == EGL_SUCCESS) {
629 err = egl_tls_t::getError();
630 }
631 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700632}
633
Mathias Agopian518ec112011-05-13 16:21:08 -0700634__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
635{
636 // eglGetProcAddress() could be the very first function called
637 // in which case we must make sure we've initialized ourselves, this
638 // happens the first time egl_get_display() is called.
639
640 clearError();
641
642 if (egl_init_drivers() == EGL_FALSE) {
643 setError(EGL_BAD_PARAMETER, NULL);
644 return NULL;
645 }
646
Jamie Gennisaca51c02011-11-03 17:42:43 -0700647 // The EGL_ANDROID_blob_cache extension should not be exposed to
648 // applications. It is used internally by the Android EGL layer.
Jamie Gennisc42fcf02011-11-09 15:35:34 -0800649 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700650 return NULL;
651 }
652
Mathias Agopian518ec112011-05-13 16:21:08 -0700653 __eglMustCastToProperFunctionPointerType addr;
654 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
655 if (addr) return addr;
656
Jamie Gennisaca51c02011-11-03 17:42:43 -0700657
Mathias Agopian518ec112011-05-13 16:21:08 -0700658 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
659 pthread_mutex_lock(&sExtensionMapMutex);
660
661 /*
662 * Since eglGetProcAddress() is not associated to anything, it needs
663 * to return a function pointer that "works" regardless of what
664 * the current context is.
665 *
666 * For this reason, we return a "forwarder", a small stub that takes
667 * care of calling the function associated with the context
668 * currently bound.
669 *
670 * We first look for extensions we've already resolved, if we're seeing
671 * this extension for the first time, we go through all our
672 * implementations and call eglGetProcAddress() and record the
673 * result in the appropriate implementation hooks and return the
674 * address of the forwarder corresponding to that hook set.
675 *
676 */
677
678 const String8 name(procname);
679 addr = sGLExtentionMap.valueFor(name);
680 const int slot = sGLExtentionSlot;
681
Steve Blocke6f43dd2012-01-06 19:20:56 +0000682 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700683 "no more slots for eglGetProcAddress(\"%s\")",
684 procname);
685
Siva Velusamy0469dd62011-11-30 15:05:37 -0800686#if EGL_TRACE
687 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
688#endif
689
Mathias Agopian518ec112011-05-13 16:21:08 -0700690 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
691 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800692
693 egl_connection_t* const cnx = &gEGLImpl;
694 if (cnx->dso && cnx->egl.eglGetProcAddress) {
695 found = true;
696 // Extensions are independent of the bound context
Mathias Agopian7773c432012-02-13 20:06:08 -0800697 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
698 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700699#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800700 debugHooks->ext.extensions[slot] =
701 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700702#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800703 cnx->egl.eglGetProcAddress(procname);
Mathias Agopian518ec112011-05-13 16:21:08 -0700704 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800705
Mathias Agopian518ec112011-05-13 16:21:08 -0700706 if (found) {
707 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700708 sGLExtentionMap.add(name, addr);
709 sGLExtentionSlot++;
710 }
711 }
712
713 pthread_mutex_unlock(&sExtensionMapMutex);
714 return addr;
715}
716
717EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
718{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800719 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700720 clearError();
721
722 egl_display_t const * const dp = validate_display(dpy);
723 if (!dp) return EGL_FALSE;
724
Mathias Agopianf0480de2011-11-13 20:50:07 -0800725 SurfaceRef _s(dp, draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700726 if (!_s.get())
727 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700728
Siva Velusamy0469dd62011-11-30 15:05:37 -0800729#if EGL_TRACE
730 if (gEGLDebugLevel > 0)
731 GLTrace_eglSwapBuffers(dpy, draw);
732#endif
733
Mathias Agopian518ec112011-05-13 16:21:08 -0700734 egl_surface_t const * const s = get_surface(draw);
Mathias Agopianada798b2012-02-13 17:09:30 -0800735 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700736}
737
738EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
739 NativePixmapType target)
740{
741 clearError();
742
743 egl_display_t const * const dp = validate_display(dpy);
744 if (!dp) return EGL_FALSE;
745
Mathias Agopianf0480de2011-11-13 20:50:07 -0800746 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700747 if (!_s.get())
748 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700749
Mathias Agopian518ec112011-05-13 16:21:08 -0700750 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800751 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -0700752}
753
754const char* eglQueryString(EGLDisplay dpy, EGLint name)
755{
756 clearError();
757
758 egl_display_t const * const dp = validate_display(dpy);
759 if (!dp) return (const char *) NULL;
760
761 switch (name) {
762 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800763 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700764 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800765 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700766 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800767 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700768 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800769 return dp->getClientApiString();
Mathias Agopianada798b2012-02-13 17:09:30 -0800770 case EGL_VERSION_HW_ANDROID:
771 return dp->disp.queryString.version;
Mathias Agopian518ec112011-05-13 16:21:08 -0700772 }
773 return setError(EGL_BAD_PARAMETER, (const char *)0);
774}
775
776
777// ----------------------------------------------------------------------------
778// EGL 1.1
779// ----------------------------------------------------------------------------
780
781EGLBoolean eglSurfaceAttrib(
782 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
783{
784 clearError();
785
786 egl_display_t const * const dp = validate_display(dpy);
787 if (!dp) return EGL_FALSE;
788
Mathias Agopianf0480de2011-11-13 20:50:07 -0800789 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700790 if (!_s.get())
791 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700792
Mathias Agopian518ec112011-05-13 16:21:08 -0700793 egl_surface_t const * const s = get_surface(surface);
794 if (s->cnx->egl.eglSurfaceAttrib) {
795 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -0800796 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700797 }
798 return setError(EGL_BAD_SURFACE, EGL_FALSE);
799}
800
801EGLBoolean eglBindTexImage(
802 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
803{
804 clearError();
805
806 egl_display_t const * const dp = validate_display(dpy);
807 if (!dp) return EGL_FALSE;
808
Mathias Agopianf0480de2011-11-13 20:50:07 -0800809 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700810 if (!_s.get())
811 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700812
Mathias Agopian518ec112011-05-13 16:21:08 -0700813 egl_surface_t const * const s = get_surface(surface);
814 if (s->cnx->egl.eglBindTexImage) {
815 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -0800816 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -0700817 }
818 return setError(EGL_BAD_SURFACE, EGL_FALSE);
819}
820
821EGLBoolean eglReleaseTexImage(
822 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
823{
824 clearError();
825
826 egl_display_t const * const dp = validate_display(dpy);
827 if (!dp) return EGL_FALSE;
828
Mathias Agopianf0480de2011-11-13 20:50:07 -0800829 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700830 if (!_s.get())
831 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700832
Mathias Agopian518ec112011-05-13 16:21:08 -0700833 egl_surface_t const * const s = get_surface(surface);
834 if (s->cnx->egl.eglReleaseTexImage) {
835 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -0800836 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -0700837 }
838 return setError(EGL_BAD_SURFACE, EGL_FALSE);
839}
840
841EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
842{
843 clearError();
844
845 egl_display_t const * const dp = validate_display(dpy);
846 if (!dp) return EGL_FALSE;
847
848 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -0800849 egl_connection_t* const cnx = &gEGLImpl;
850 if (cnx->dso && cnx->egl.eglSwapInterval) {
851 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -0700852 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800853
Mathias Agopian518ec112011-05-13 16:21:08 -0700854 return res;
855}
856
857
858// ----------------------------------------------------------------------------
859// EGL 1.2
860// ----------------------------------------------------------------------------
861
862EGLBoolean eglWaitClient(void)
863{
864 clearError();
865
Mathias Agopianada798b2012-02-13 17:09:30 -0800866 egl_connection_t* const cnx = &gEGLImpl;
867 if (!cnx->dso)
868 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
869
870 EGLBoolean res;
871 if (cnx->egl.eglWaitClient) {
872 res = cnx->egl.eglWaitClient();
873 } else {
874 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700875 }
876 return res;
877}
878
879EGLBoolean eglBindAPI(EGLenum api)
880{
881 clearError();
882
883 if (egl_init_drivers() == EGL_FALSE) {
884 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
885 }
886
887 // bind this API on all EGLs
888 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -0800889 egl_connection_t* const cnx = &gEGLImpl;
890 if (cnx->dso && cnx->egl.eglBindAPI) {
891 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -0700892 }
893 return res;
894}
895
896EGLenum eglQueryAPI(void)
897{
898 clearError();
899
900 if (egl_init_drivers() == EGL_FALSE) {
901 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
902 }
903
Mathias Agopianada798b2012-02-13 17:09:30 -0800904 egl_connection_t* const cnx = &gEGLImpl;
905 if (cnx->dso && cnx->egl.eglQueryAPI) {
906 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -0700907 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800908
Mathias Agopian518ec112011-05-13 16:21:08 -0700909 // or, it can only be OpenGL ES
910 return EGL_OPENGL_ES_API;
911}
912
913EGLBoolean eglReleaseThread(void)
914{
915 clearError();
916
917 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -0800918 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -0700919
Mathias Agopianada798b2012-02-13 17:09:30 -0800920 egl_connection_t* const cnx = &gEGLImpl;
921 if (cnx->dso && cnx->egl.eglReleaseThread) {
922 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -0700923 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800924
Mathias Agopian518ec112011-05-13 16:21:08 -0700925 egl_tls_t::clearTLS();
Siva Velusamy0469dd62011-11-30 15:05:37 -0800926#if EGL_TRACE
927 if (gEGLDebugLevel > 0)
928 GLTrace_eglReleaseThread();
929#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700930 return EGL_TRUE;
931}
932
933EGLSurface eglCreatePbufferFromClientBuffer(
934 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
935 EGLConfig config, const EGLint *attrib_list)
936{
937 clearError();
938
939 egl_display_t const* dp = 0;
940 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
941 if (!cnx) return EGL_FALSE;
942 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
943 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -0800944 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700945 }
946 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
947}
948
949// ----------------------------------------------------------------------------
950// EGL_EGLEXT_VERSION 3
951// ----------------------------------------------------------------------------
952
953EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
954 const EGLint *attrib_list)
955{
956 clearError();
957
958 egl_display_t const * const dp = validate_display(dpy);
959 if (!dp) return EGL_FALSE;
960
Mathias Agopianf0480de2011-11-13 20:50:07 -0800961 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700962 if (!_s.get())
963 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700964
965 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700966 if (s->cnx->egl.eglLockSurfaceKHR) {
967 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -0800968 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700969 }
970 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
971}
972
973EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
974{
975 clearError();
976
977 egl_display_t const * const dp = validate_display(dpy);
978 if (!dp) return EGL_FALSE;
979
Mathias Agopianf0480de2011-11-13 20:50:07 -0800980 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700981 if (!_s.get())
982 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700983
984 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700985 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800986 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700987 }
988 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
989}
990
991EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
992 EGLClientBuffer buffer, const EGLint *attrib_list)
993{
994 clearError();
995
996 egl_display_t const * const dp = validate_display(dpy);
997 if (!dp) return EGL_NO_IMAGE_KHR;
998
Mathias Agopian7c0441a2012-02-14 17:14:36 -0800999 ContextRef _c(dp, ctx);
1000 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001001
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001002 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1003 egl_connection_t* const cnx = &gEGLImpl;
1004 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1005 result = cnx->egl.eglCreateImageKHR(
1006 dp->disp.dpy,
1007 c ? c->context : EGL_NO_CONTEXT,
1008 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001009 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001010 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001011}
1012
1013EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1014{
1015 clearError();
1016
1017 egl_display_t const * const dp = validate_display(dpy);
1018 if (!dp) return EGL_FALSE;
1019
Mathias Agopianada798b2012-02-13 17:09:30 -08001020 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001021 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1022 cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001023 }
Mathias Agopian518ec112011-05-13 16:21:08 -07001024 return EGL_TRUE;
1025}
1026
1027// ----------------------------------------------------------------------------
1028// EGL_EGLEXT_VERSION 5
1029// ----------------------------------------------------------------------------
1030
1031
1032EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1033{
1034 clearError();
1035
1036 egl_display_t const * const dp = validate_display(dpy);
1037 if (!dp) return EGL_NO_SYNC_KHR;
1038
Mathias Agopian518ec112011-05-13 16:21:08 -07001039 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001040 egl_connection_t* const cnx = &gEGLImpl;
1041 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1042 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001043 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001044 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001045}
1046
1047EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1048{
1049 clearError();
1050
1051 egl_display_t const * const dp = validate_display(dpy);
1052 if (!dp) return EGL_FALSE;
1053
Mathias Agopian518ec112011-05-13 16:21:08 -07001054 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001055 egl_connection_t* const cnx = &gEGLImpl;
1056 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1057 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001058 }
1059 return result;
1060}
1061
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001062EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1063 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001064{
1065 clearError();
1066
1067 egl_display_t const * const dp = validate_display(dpy);
1068 if (!dp) return EGL_FALSE;
1069
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001070 EGLBoolean result = EGL_FALSE;
1071 egl_connection_t* const cnx = &gEGLImpl;
1072 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1073 result = cnx->egl.eglClientWaitSyncKHR(
1074 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001075 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001076 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001077}
1078
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001079EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1080 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001081{
1082 clearError();
1083
1084 egl_display_t const * const dp = validate_display(dpy);
1085 if (!dp) return EGL_FALSE;
1086
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001087 EGLBoolean result = EGL_FALSE;
1088 egl_connection_t* const cnx = &gEGLImpl;
1089 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1090 result = cnx->egl.eglGetSyncAttribKHR(
1091 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001092 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001093 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001094}
1095
1096// ----------------------------------------------------------------------------
1097// ANDROID extensions
1098// ----------------------------------------------------------------------------
1099
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001100/* ANDROID extensions entry-point go here */
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001101
1102// ----------------------------------------------------------------------------
1103// NVIDIA extensions
1104// ----------------------------------------------------------------------------
1105EGLuint64NV eglGetSystemTimeFrequencyNV()
1106{
1107 clearError();
1108
1109 if (egl_init_drivers() == EGL_FALSE) {
1110 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1111 }
1112
1113 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001114 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001115
Mathias Agopianada798b2012-02-13 17:09:30 -08001116 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1117 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001118 }
1119
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001120 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001121}
1122
1123EGLuint64NV eglGetSystemTimeNV()
1124{
1125 clearError();
1126
1127 if (egl_init_drivers() == EGL_FALSE) {
1128 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1129 }
1130
1131 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001132 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001133
Mathias Agopianada798b2012-02-13 17:09:30 -08001134 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1135 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001136 }
1137
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001138 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001139}