• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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