1 /*
2 * Copyright (C) 2011 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 //
18 // WARNING -------------------------- WARNING
19 // This code meant to be used for testing purposes only. It is not production
20 // level quality.
21 // Use on your own risk !!
22 //
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <dlfcn.h>
28 #include "egl_dispatch.h"
29 #include "egl_ftable.h"
30 #include <log/log.h>
31 #include "ServerConnection.h"
32 #include "ThreadInfo.h"
33 #include <pthread.h>
34 #include "gl_wrapper_context.h"
35 #include "gl2_wrapper_context.h"
36
37 #define GLES_EMUL_TARGETS_FILE "/system/etc/gles_emul.cfg"
38 // implementation libraries;
39 #define GLESv1_enc_LIB "/system/lib/libGLESv1_enc.so"
40 #define GLESv2_enc_LIB "/system/lib/libGLESv2_enc.so"
41 #define GLES_android_LIB "/system/lib/egl/libGLES_android.so"
42 // driver libraries;
43 #define GLESv1_DRIVER "/system/lib/egl/libGLESv1_CM_emul.so"
44 #define GLESv2_DRIVER "/system/lib/egl/libGLESv2_emul.so"
45
46
47 static struct egl_dispatch *s_dispatch = NULL;
48 pthread_once_t dispatchTablesInitialized = PTHREAD_ONCE_INIT;
49
50 static bool s_needEncode = false;
51
52 static gl_wrapper_context_t *g_gl_dispatch = NULL;
53 static gl2_wrapper_context_t *g_gl2_dispatch = NULL;
54
55 template <class T>
initApi(const char * driverLibName,const char * implLibName,T ** dispatchTable,T * (* accessor)())56 int initApi(const char *driverLibName, const char *implLibName, T **dispatchTable, T *(*accessor)())
57 {
58 void *driverLib = dlopen(driverLibName, RTLD_NOW | RTLD_LOCAL);
59 if (driverLib == NULL) {
60 ALOGE("failed to load %s : %s\n", driverLibName, dlerror());
61 return -1;
62 }
63
64 typedef T *(*createFcn_t)(void *, T *(*accessor)());
65 createFcn_t createFcn;
66 createFcn = (createFcn_t) dlsym(driverLib, "createFromLib");
67 if (createFcn == NULL) {
68 ALOGE("failed to load createFromLib constructor function\n");
69 return -1;
70 }
71
72 void *implLib = dlopen(implLibName, RTLD_NOW | RTLD_LOCAL);
73 if (implLib == NULL) {
74 ALOGE("couldn't open %s", implLibName);
75 return -2;
76 }
77 *dispatchTable = createFcn(implLib, accessor);
78 if (*dispatchTable == NULL) {
79 return -3;
80 }
81
82 // XXX - we do close the impl library since it doesn't have data, as far as we concern.
83 dlclose(implLib);
84
85 // XXX - we do not dlclose the driver library, so its not initialized when
86 // later loaded by android - is this required?
87 ALOGD("loading %s into %s complete\n", implLibName, driverLibName);
88 return 0;
89
90 }
91
getGLContext()92 static gl_wrapper_context_t *getGLContext()
93 {
94 return g_gl_dispatch;
95 }
96
getGL2Context()97 static gl2_wrapper_context_t *getGL2Context()
98 {
99 return g_gl2_dispatch;
100 }
101
getProcName()102 const char *getProcName()
103 {
104 static constexpr size_t kMaxProcessNameLength = 100;
105 static const char procname[kMaxProcessNameLength]{0};
106
107 int rc = pthread_getname_np(pthread_self(), procname, kMaxProcessNameLength);
108
109 if (rc == 0) {
110 return procname;
111 }
112
113 return nullptr;
114 }
115
116
117
isNeedEncode()118 bool isNeedEncode()
119 {
120 const char *procname = getProcName();
121 if (procname == NULL) return false;
122 ALOGD("isNeedEncode? for %s\n", procname);
123 // check on our whitelist
124 FILE *fp = fopen(GLES_EMUL_TARGETS_FILE, "rt");
125 if (fp == NULL) {
126 ALOGE("couldn't open %s\n", GLES_EMUL_TARGETS_FILE);
127 return false;
128 }
129
130 char line[100];
131 bool found = false;
132 size_t procnameLen = strlen(procname);
133
134 while (fgets(line, sizeof(line), fp) != NULL) {
135 if (strlen(line) >= procnameLen &&
136 !strncmp(procname, line, procnameLen)) {
137 char c = line[procnameLen];
138 if (c == '\0' || c == ' ' || c == '\t' || c == '\n') {
139 found = true;
140 ALOGD("should use encoder for %s\n", procname);
141 break;
142 }
143 }
144 }
145 fclose(fp);
146 return found;
147 }
148
initDispatchTables()149 void initDispatchTables()
150 {
151 //
152 // Load our back-end implementation of EGL/GLES
153 //
154 ALOGD("Loading egl dispatch for %s\n", getProcName());
155
156 void *gles_android = dlopen("/system/lib/egl/libGLES_android.so", RTLD_NOW | RTLD_LOCAL);
157 if (!gles_android) {
158 fprintf(stderr,"FATAL ERROR: Could not load libGLES_android lib\n");
159 exit(-1);
160 }
161
162 //
163 // Load back-end EGL implementation library
164 //
165 s_dispatch = create_egl_dispatch( gles_android );
166 if (!s_dispatch) {
167 fprintf(stderr,"FATAL ERROR: Could not create egl dispatch\n");
168 exit(-1);
169 }
170
171 //
172 // initialize gles
173 //
174 s_needEncode = isNeedEncode();
175 void *gles_encoder = NULL;
176 if (s_needEncode) {
177 // initialize a connection to the server, and the GLESv1/v2 encoders;
178 ServerConnection * connection = ServerConnection::s_getServerConnection();
179 if (connection == NULL) {
180 ALOGE("couldn't create server connection\n");
181 s_needEncode = false;
182 }
183 }
184
185 // init dispatch tabels for GLESv1 & GLESv2
186 if (s_needEncode) {
187 // XXX - we do not check the retrun value because there isn't much we can do here on failure.
188
189 if (initApi<gl_wrapper_context_t>(GLESv1_DRIVER, GLESv1_enc_LIB, &g_gl_dispatch, getGLContext) < 0) {
190 // fallback to android on faluire
191 s_needEncode = false;
192 } else {
193 initApi<gl2_wrapper_context_t>(GLESv2_DRIVER, GLESv2_enc_LIB, &g_gl2_dispatch, getGL2Context);
194 }
195 }
196
197 if (!s_needEncode) {
198 ALOGD("Initializing native opengl for %s\n", getProcName());
199 initApi<gl_wrapper_context_t>(GLESv1_DRIVER, GLES_android_LIB, &g_gl_dispatch, getGLContext);
200 // try to initialize gl2 from GLES, though its probably going to fail
201 initApi<gl2_wrapper_context_t>(GLESv2_DRIVER, GLES_android_LIB, &g_gl2_dispatch, getGL2Context);
202 }
203 }
204
getDispatch()205 static struct egl_dispatch *getDispatch()
206 {
207 pthread_once(&dispatchTablesInitialized, initDispatchTables);
208 return s_dispatch;
209 }
210
eglGetProcAddress(const char * procname)211 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
212 {
213
214 // search in EGL function table
215 for (int i=0; i<egl_num_funcs; i++) {
216 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
217 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
218 }
219 }
220
221 // we do not support eglGetProcAddress for GLESv1 & GLESv2. The loader
222 // should be able to find this function through dynamic loading.
223 return NULL;
224 }
225
226 //////////////// Path through functions //////////
227
eglGetError()228 EGLint eglGetError()
229 {
230 return getDispatch()->eglGetError();
231 }
232
eglGetDisplay(EGLNativeDisplayType display_id)233 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
234 {
235 return getDispatch()->eglGetDisplay(display_id);
236 }
237
eglInitialize(EGLDisplay dpy,EGLint * major,EGLint * minor)238 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
239 {
240 return getDispatch()->eglInitialize(dpy, major, minor);
241 }
242
eglTerminate(EGLDisplay dpy)243 EGLBoolean eglTerminate(EGLDisplay dpy)
244 {
245 return getDispatch()->eglTerminate(dpy);
246 }
247
eglQueryString(EGLDisplay dpy,EGLint name)248 const char* eglQueryString(EGLDisplay dpy, EGLint name)
249 {
250 return getDispatch()->eglQueryString(dpy, name);
251 }
252
eglGetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)253 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
254 {
255 return getDispatch()->eglGetConfigs(dpy, configs, config_size, num_config);
256 }
257
filter_es2_bit(const EGLint * attrib_list,bool * isES2)258 static EGLint * filter_es2_bit(const EGLint *attrib_list, bool *isES2)
259 {
260 if (attrib_list == NULL) {
261 if (isES2 != NULL) *isES2 = false;
262 return NULL;
263 }
264
265 EGLint *attribs = NULL;
266 int nAttribs = 0;
267 while(attrib_list[nAttribs] != EGL_NONE) nAttribs++;
268 nAttribs++;
269
270 attribs = new EGLint[nAttribs];
271 memcpy(attribs, attrib_list, nAttribs * sizeof(EGLint));
272 if (isES2 != NULL) *isES2 = false;
273
274 // scan the attribute list for ES2 request and replace with ES1.
275 for (int i = 0; i < nAttribs; i++) {
276 if (attribs[i] == EGL_RENDERABLE_TYPE) {
277 if (attribs[i + 1] & EGL_OPENGL_ES2_BIT) {
278 attribs[i + 1] &= ~EGL_OPENGL_ES2_BIT;
279 attribs[i + 1] |= EGL_OPENGL_ES_BIT;
280 ALOGD("removing ES2 bit 0x%x\n", attribs[i + 1]);
281 if (isES2 != NULL) *isES2 = true;
282 }
283 }
284 }
285 return attribs;
286 }
287
eglChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)288 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
289 {
290 EGLBoolean res;
291 if (s_needEncode) {
292 EGLint *attribs = filter_es2_bit(attrib_list, NULL);
293 res = getDispatch()->eglChooseConfig(dpy,
294 attribs,
295 configs,
296 config_size,
297 num_config);
298 ALOGD("eglChooseConfig: %d configs found\n", *num_config);
299 if (*num_config == 0 && attribs != NULL) {
300 ALOGD("requested attributes:\n");
301 for (int i = 0; attribs[i] != EGL_NONE; i++) {
302 ALOGD("%d: 0x%x\n", i, attribs[i]);
303 }
304 }
305
306 delete attribs;
307 } else {
308 res = getDispatch()->eglChooseConfig(dpy, attrib_list, configs, config_size, num_config);
309 }
310 return res;
311 }
312
eglGetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)313 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
314 {
315 if (s_needEncode && attribute == EGL_RENDERABLE_TYPE) {
316 *value = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
317 return EGL_TRUE;
318 } else {
319 return getDispatch()->eglGetConfigAttrib(dpy, config, attribute, value);
320 }
321 }
322
eglCreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)323 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
324 {
325 EGLSurface surface = getDispatch()->eglCreateWindowSurface(dpy, config, win, attrib_list);
326 if (surface != EGL_NO_SURFACE) {
327 ServerConnection *server;
328 if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) {
329 server->utEnc()->createSurface(server->utEnc(), getpid(), (uint32_t)surface);
330 }
331 }
332 return surface;
333 }
334
eglCreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)335 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
336 {
337 EGLSurface surface = getDispatch()->eglCreatePbufferSurface(dpy, config, attrib_list);
338 if (surface != EGL_NO_SURFACE) {
339 ServerConnection *server;
340 if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) {
341 server->utEnc()->createSurface(server->utEnc(), getpid(), (uint32_t)surface);
342 }
343 }
344 return surface;
345 }
346
eglCreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)347 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
348 {
349 EGLSurface surface = getDispatch()->eglCreatePixmapSurface(dpy, config, pixmap, attrib_list);
350 if (surface != EGL_NO_SURFACE) {
351 ServerConnection *server;
352 if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) {
353 server->utEnc()->createSurface(server->utEnc(), getpid(), (uint32_t)surface);
354 }
355 }
356 return surface;
357 }
358
eglDestroySurface(EGLDisplay dpy,EGLSurface surface)359 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
360 {
361 EGLBoolean res = getDispatch()->eglDestroySurface(dpy, surface);
362 if (res && surface != EGL_NO_SURFACE) {
363 ServerConnection *server;
364 if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) {
365 server->utEnc()->destroySurface(server->utEnc(), getpid(), (uint32_t)surface);
366 }
367 }
368 return res;
369 }
370
eglQuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)371 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
372 {
373 EGLBoolean res = getDispatch()->eglQuerySurface(dpy, surface, attribute, value);
374 if (res && attribute == EGL_RENDERABLE_TYPE) {
375 *value |= EGL_OPENGL_ES2_BIT;
376 }
377 return res;
378 }
379
eglBindAPI(EGLenum api)380 EGLBoolean eglBindAPI(EGLenum api)
381 {
382 return getDispatch()->eglBindAPI(api);
383 }
384
eglQueryAPI()385 EGLenum eglQueryAPI()
386 {
387 return getDispatch()->eglQueryAPI();
388 }
389
eglWaitClient()390 EGLBoolean eglWaitClient()
391 {
392 return getDispatch()->eglWaitClient();
393 }
394
eglReleaseThread()395 EGLBoolean eglReleaseThread()
396 {
397 return getDispatch()->eglReleaseThread();
398 }
399
eglCreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)400 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
401 {
402 return getDispatch()->eglCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list);
403 }
404
eglSurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)405 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
406 {
407 return getDispatch()->eglSurfaceAttrib(dpy, surface, attribute, value);
408 }
409
eglBindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)410 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
411 {
412 return getDispatch()->eglBindTexImage(dpy, surface, buffer);
413 }
414
eglReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)415 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
416 {
417 return getDispatch()->eglReleaseTexImage(dpy, surface, buffer);
418 }
419
eglSwapInterval(EGLDisplay dpy,EGLint interval)420 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
421 {
422 return getDispatch()->eglSwapInterval(dpy, interval);
423 }
424
eglCreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)425 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
426 {
427
428 EGLContext share = share_context;
429 if (share) share = ((EGLWrapperContext *)share_context)->aglContext;
430
431 // check if are ES2, and convert it to ES1.
432 int nAttribs = 0;
433 if (attrib_list != NULL) {
434 while(attrib_list[nAttribs] != EGL_NONE) {
435 nAttribs++;
436 }
437 nAttribs++;
438 }
439
440 EGLint *attrib = NULL;
441 if (nAttribs > 0) {
442 attrib = new EGLint[nAttribs];
443 memcpy(attrib, attrib_list, nAttribs * sizeof(EGLint));
444 }
445
446 int version = 1;
447 for (int i = 0; i < nAttribs; i++) {
448 if (attrib[i] == EGL_CONTEXT_CLIENT_VERSION &&
449 attrib[i + 1] == 2) {
450 version = 2;
451 attrib[i + 1] = 1; // replace to version 1
452 }
453 }
454
455 EGLContext ctx = getDispatch()->eglCreateContext(dpy, config, share, attrib);
456 delete[] attrib;
457 EGLWrapperContext *wctx = new EGLWrapperContext(ctx, version);
458 if (ctx != EGL_NO_CONTEXT) {
459 ServerConnection *server;
460 if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) {
461 wctx->clientState = new GLClientState();
462 server->utEnc()->createContext(server->utEnc(), getpid(),
463 (uint32_t)wctx,
464 (uint32_t)(share_context == EGL_NO_CONTEXT ? 0 : share_context), wctx->version);
465 }
466 }
467 return (EGLContext)wctx;
468 }
469
eglDestroyContext(EGLDisplay dpy,EGLContext ctx)470 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
471 {
472 EGLWrapperContext *wctx = (EGLWrapperContext *)ctx;
473 EGLBoolean res = EGL_FALSE;
474
475 if (ctx && ctx != EGL_NO_CONTEXT) {
476 res = getDispatch()->eglDestroyContext(dpy, wctx->aglContext);
477 if (res) {
478 EGLThreadInfo *ti = getEGLThreadInfo();
479 ServerConnection *server;
480 if (s_needEncode && (server = ServerConnection::s_getServerConnection())) {
481 server->utEnc()->destroyContext(ti->serverConn->utEnc(), getpid(), (uint32_t)ctx);
482 }
483 if (ti->currentContext == wctx) ti->currentContext = NULL;
484 delete wctx;
485 }
486 }
487
488 return res;
489 }
490
eglMakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)491 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
492 {
493 EGLWrapperContext *wctx = (EGLWrapperContext *)ctx;
494 EGLContext aglContext = (ctx == EGL_NO_CONTEXT ? EGL_NO_CONTEXT : wctx->aglContext);
495 EGLThreadInfo *ti = getEGLThreadInfo();
496 EGLBoolean res = getDispatch()->eglMakeCurrent(dpy, draw, read, aglContext);
497 if (res ) {
498 // NOTE - we do get a pointer to the server connection, (rather then using ti->serverConn)
499 // for cases that this is the first egl call of the current thread.
500
501 ServerConnection *server;
502 if (s_needEncode && (server = ServerConnection::s_getServerConnection())) {
503 server->utEnc()->makeCurrentContext(server->utEnc(), getpid(),
504 (uint32_t) (draw == EGL_NO_SURFACE ? 0 : draw),
505 (uint32_t) (read == EGL_NO_SURFACE ? 0 : read),
506 (uint32_t) (ctx == EGL_NO_CONTEXT ? 0 : ctx));
507 server->glEncoder()->setClientState( wctx ? wctx->clientState : NULL );
508 server->gl2Encoder()->setClientState( wctx ? wctx->clientState : NULL );
509 }
510
511 // set current context in our thread info
512 ti->currentContext = wctx;
513 }
514 return res;
515
516 }
517
eglGetCurrentContext()518 EGLContext eglGetCurrentContext()
519 {
520 EGLThreadInfo *ti = getEGLThreadInfo();
521 return (ti->currentContext ? ti->currentContext : EGL_NO_CONTEXT);
522 }
523
eglGetCurrentSurface(EGLint readdraw)524 EGLSurface eglGetCurrentSurface(EGLint readdraw)
525 {
526 return getDispatch()->eglGetCurrentSurface(readdraw);
527 }
528
eglGetCurrentDisplay()529 EGLDisplay eglGetCurrentDisplay()
530 {
531 return getDispatch()->eglGetCurrentDisplay();
532 }
533
eglQueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)534 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
535 {
536 EGLWrapperContext *wctx = (EGLWrapperContext *)ctx;
537 if (wctx) {
538 if (attribute == EGL_CONTEXT_CLIENT_VERSION) {
539 *value = wctx->version;
540 return EGL_TRUE;
541 } else {
542 return getDispatch()->eglQueryContext(dpy, wctx->aglContext, attribute, value);
543 }
544 }
545 else {
546 return EGL_BAD_CONTEXT;
547 }
548 }
549
eglWaitGL()550 EGLBoolean eglWaitGL()
551 {
552 return getDispatch()->eglWaitGL();
553 }
554
eglWaitNative(EGLint engine)555 EGLBoolean eglWaitNative(EGLint engine)
556 {
557 return getDispatch()->eglWaitNative(engine);
558 }
559
eglSwapBuffers(EGLDisplay dpy,EGLSurface surface)560 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
561 {
562 ServerConnection *server;
563 if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) {
564 server->utEnc()->swapBuffers(server->utEnc(), getpid(), (uint32_t)surface);
565 server->glEncoder()->flush();
566 server->gl2Encoder()->flush();
567 return 1;
568 }
569 return getDispatch()->eglSwapBuffers(dpy, surface);
570 }
571
eglCopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)572 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
573 {
574 return getDispatch()->eglCopyBuffers(dpy, surface, target);
575 }
576
eglLockSurfaceKHR(EGLDisplay display,EGLSurface surface,const EGLint * attrib_list)577 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
578 {
579 return getDispatch()->eglLockSurfaceKHR(display, surface, attrib_list);
580 }
581
eglUnlockSurfaceKHR(EGLDisplay display,EGLSurface surface)582 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
583 {
584 return getDispatch()->eglUnlockSurfaceKHR(display, surface);
585 }
586
eglCreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)587 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
588 {
589 EGLWrapperContext *wctx = (EGLWrapperContext *)ctx;
590 EGLContext aglContext = (wctx ? wctx->aglContext : EGL_NO_CONTEXT);
591 return getDispatch()->eglCreateImageKHR(dpy, aglContext, target, buffer, attrib_list);
592 }
593
eglDestroyImageKHR(EGLDisplay dpy,EGLImageKHR image)594 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
595 {
596 return getDispatch()->eglDestroyImageKHR(dpy, image);
597 }
598
eglCreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)599 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
600 {
601 return getDispatch()->eglCreateSyncKHR(dpy, type, attrib_list);
602 }
603
eglDestroySyncKHR(EGLDisplay dpy,EGLSyncKHR sync)604 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
605 {
606 return getDispatch()->eglDestroySyncKHR(dpy, sync);
607 }
608
eglClientWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)609 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
610 {
611 return getDispatch()->eglClientWaitSyncKHR(dpy, sync, flags, timeout);
612 }
613
eglSignalSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLenum mode)614 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
615 {
616 return getDispatch()->eglSignalSyncKHR(dpy, sync, mode);
617 }
618
eglGetSyncAttribKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)619 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
620 {
621 return getDispatch()->eglGetSyncAttribKHR(dpy, sync, attribute, value);
622 }
623
eglSetSwapRectangleANDROID(EGLDisplay dpy,EGLSurface draw,EGLint left,EGLint top,EGLint width,EGLint height)624 EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height)
625 {
626 return getDispatch()->eglSetSwapRectangleANDROID(dpy, draw, left, top, width, height);
627 }
628