OSDN Git Service

Return error code in eglCreatePixmapSurface
[android-x86/device-generic-goldfish-opengl.git] / system / egl / egl.cpp
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 #include <assert.h>
18 #include "HostConnection.h"
19 #include "ThreadInfo.h"
20 #include "eglDisplay.h"
21 #include "eglSync.h"
22 #include "egl_ftable.h"
23 #include <cutils/log.h>
24 #include "goldfish_sync.h"
25 #include "gralloc_cb.h"
26 #include "GLClientState.h"
27 #include "GLSharedGroup.h"
28 #include "eglContext.h"
29 #include "ClientAPIExts.h"
30 #include "EGLImage.h"
31 #include "ProcessPipe.h"
32
33 #include "GLEncoder.h"
34 #ifdef WITH_GLES2
35 #include "GL2Encoder.h"
36 #endif
37
38 #if PLATFORM_SDK_VERSION >= 16
39 #include <system/window.h>
40 #else // PLATFORM_SDK_VERSION >= 16
41 #include <private/ui/android_natives_priv.h>
42 #endif // PLATFORM_SDK_VERSION >= 16
43
44 #if PLATFORM_SDK_VERSION <= 16
45 #define queueBuffer_DEPRECATED queueBuffer
46 #define dequeueBuffer_DEPRECATED dequeueBuffer
47 #define cancelBuffer_DEPRECATED cancelBuffer
48 #endif // PLATFORM_SDK_VERSION <= 16
49
50 #define DEBUG_EGL 0
51
52 #if DEBUG_EGL
53 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
54 #else
55 #define DPRINT(...)
56 #endif
57
58 template<typename T>
59 static T setErrorFunc(GLint error, T returnValue) {
60     getEGLThreadInfo()->eglError = error;
61     return returnValue;
62 }
63
64 const char *  eglStrError(EGLint err)
65 {
66     switch (err){
67         case EGL_SUCCESS:           return "EGL_SUCCESS";
68         case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
69         case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
70         case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
71         case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
72         case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
73         case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
74         case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
75         case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
76         case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
77         case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
78         case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
79         case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
80         case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
81         case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
82         default: return "UNKNOWN";
83     }
84 }
85
86 #define LOG_EGL_ERRORS 1
87
88 #ifdef LOG_EGL_ERRORS
89
90 #define setErrorReturn(error, retVal)     \
91     {                                                \
92         ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
93         return setErrorFunc(error, retVal);            \
94     }
95
96 #define RETURN_ERROR(ret,err)           \
97     ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
98     getEGLThreadInfo()->eglError = err;    \
99     return ret;
100
101 #else //!LOG_EGL_ERRORS
102
103 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
104
105 #define RETURN_ERROR(ret,err)           \
106     getEGLThreadInfo()->eglError = err; \
107     return ret;
108
109 #endif //LOG_EGL_ERRORS
110
111 #define VALIDATE_CONFIG(cfg,ret) \
112     if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
113         RETURN_ERROR(ret,EGL_BAD_CONFIG); \
114     }
115
116 #define VALIDATE_DISPLAY(dpy,ret) \
117     if ((dpy) != (EGLDisplay)&s_display) { \
118         RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
119     }
120
121 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
122     VALIDATE_DISPLAY(dpy, ret)    \
123     if (!s_display.initialized()) {        \
124         RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
125     }
126
127 #define DEFINE_HOST_CONNECTION \
128     HostConnection *hostCon = HostConnection::get(); \
129     ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
130
131 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
132     HostConnection *hostCon = HostConnection::get(); \
133     if (!hostCon) { \
134         ALOGE("egl: Failed to get host connection\n"); \
135         return ret; \
136     } \
137     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
138     if (!rcEnc) { \
139         ALOGE("egl: Failed to get renderControl encoder context\n"); \
140         return ret; \
141     }
142
143 #define VALIDATE_CONTEXT_RETURN(context,ret)  \
144     if (!(context)) {                         \
145         RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
146     }
147
148 #define VALIDATE_SURFACE_RETURN(surface, ret)    \
149     if ((surface) != EGL_NO_SURFACE) {    \
150         egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
151         if (s->dpy != (EGLDisplay)&s_display)    \
152             setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
153     }
154
155 // The one and only supported display object.
156 static eglDisplay s_display;
157
158 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
159     dpy(dpy),
160     config(config),
161     read(EGL_NO_SURFACE),
162     draw(EGL_NO_SURFACE),
163     shareCtx(shareCtx),
164     rcContext(0),
165     versionString(NULL),
166     vendorString(NULL),
167     rendererString(NULL),
168     shaderVersionString(NULL),
169     extensionString(NULL),
170     deletePending(0),
171     goldfishSyncFd(-1)
172 {
173     flags = 0;
174     version = 1;
175     clientState = new GLClientState();
176     if (shareCtx)
177         sharedGroup = shareCtx->getSharedGroup();
178     else
179         sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
180     assert(dpy == (EGLDisplay)&s_display);
181     s_display.onCreateContext((EGLContext)this);
182 };
183
184 int EGLContext_t::getGoldfishSyncFd() {
185     if (goldfishSyncFd < 0) {
186         goldfishSyncFd = goldfish_sync_open();
187     }
188     return goldfishSyncFd;
189 }
190
191 EGLContext_t::~EGLContext_t()
192 {
193     if (goldfishSyncFd > 0) {
194         goldfish_sync_close(goldfishSyncFd);
195         goldfishSyncFd = -1;
196     }
197     assert(dpy == (EGLDisplay)&s_display);
198     s_display.onDestroyContext((EGLContext)this);
199     delete clientState;
200     delete [] versionString;
201     delete [] vendorString;
202     delete [] rendererString;
203     delete [] shaderVersionString;
204     delete [] extensionString;
205 }
206
207 // ----------------------------------------------------------------------------
208 //egl_surface_t
209
210 //we don't need to handle depth since it's handled when window created on the host
211
212 struct egl_surface_t {
213
214     EGLDisplay          dpy;
215     EGLConfig           config;
216
217
218     egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
219     virtual     ~egl_surface_t();
220
221     virtual     void        setSwapInterval(int interval) = 0;
222     virtual     EGLBoolean  swapBuffers() = 0;
223
224     EGLint      getSwapBehavior() const;
225     uint32_t    getRcSurface()   { return rcSurface; }
226     EGLint      getSurfaceType() { return surfaceType; }
227
228     EGLint      getWidth(){ return width; }
229     EGLint      getHeight(){ return height; }
230     void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
231     EGLint      getTextureFormat() { return texFormat; }
232     void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
233     EGLint      getTextureTarget() { return texTarget; }
234
235 private:
236     //
237     //Surface attributes
238     //
239     EGLint      width;
240     EGLint      height;
241     EGLint      texFormat;
242     EGLint      texTarget;
243
244 protected:
245     void        setWidth(EGLint w)  { width = w;  }
246     void        setHeight(EGLint h) { height = h; }
247
248     EGLint      surfaceType;
249     uint32_t    rcSurface; //handle to surface created via remote control
250 };
251
252 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
253     : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
254 {
255     width = 0;
256     height = 0;
257     texFormat = EGL_NO_TEXTURE;
258     texTarget = EGL_NO_TEXTURE;
259     assert(dpy == (EGLDisplay)&s_display);
260     s_display.onCreateSurface((EGLSurface)this);
261 }
262
263 EGLint egl_surface_t::getSwapBehavior() const {
264     return EGL_BUFFER_PRESERVED;
265 }
266
267 egl_surface_t::~egl_surface_t()
268 {
269     assert(dpy == (EGLDisplay)&s_display);
270     s_display.onDestroySurface((EGLSurface)this);
271 }
272
273 // ----------------------------------------------------------------------------
274 // egl_window_surface_t
275
276 struct egl_window_surface_t : public egl_surface_t {
277     static egl_window_surface_t* create(
278             EGLDisplay dpy, EGLConfig config, EGLint surfType,
279             ANativeWindow* window);
280
281     virtual ~egl_window_surface_t();
282
283     virtual void       setSwapInterval(int interval);
284     virtual EGLBoolean swapBuffers();
285
286 private:
287     egl_window_surface_t(
288             EGLDisplay dpy, EGLConfig config, EGLint surfType,
289             ANativeWindow* window);
290     EGLBoolean init();
291
292     ANativeWindow*              nativeWindow;
293     android_native_buffer_t*    buffer;
294 };
295
296 egl_window_surface_t::egl_window_surface_t (
297         EGLDisplay dpy, EGLConfig config, EGLint surfType,
298         ANativeWindow* window)
299 :   egl_surface_t(dpy, config, surfType),
300     nativeWindow(window),
301     buffer(NULL)
302 {
303     // keep a reference on the window
304     nativeWindow->common.incRef(&nativeWindow->common);
305 }
306
307
308 EGLBoolean egl_window_surface_t::init()
309 {
310     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
311         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
312     }
313     setWidth(buffer->width);
314     setHeight(buffer->height);
315
316     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
317     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
318             getWidth(), getHeight());
319     if (!rcSurface) {
320         ALOGE("rcCreateWindowSurface returned 0");
321         return EGL_FALSE;
322     }
323     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
324             ((cb_handle_t*)(buffer->handle))->hostHandle);
325
326     return EGL_TRUE;
327 }
328
329 egl_window_surface_t* egl_window_surface_t::create(
330         EGLDisplay dpy, EGLConfig config, EGLint surfType,
331         ANativeWindow* window)
332 {
333     egl_window_surface_t* wnd = new egl_window_surface_t(
334             dpy, config, surfType, window);
335     if (wnd && !wnd->init()) {
336         delete wnd;
337         wnd = NULL;
338     }
339     return wnd;
340 }
341
342 egl_window_surface_t::~egl_window_surface_t() {
343     DEFINE_HOST_CONNECTION;
344     if (rcSurface && rcEnc) {
345         rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
346     }
347     if (buffer) {
348         nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
349     }
350     nativeWindow->common.decRef(&nativeWindow->common);
351 }
352
353 void egl_window_surface_t::setSwapInterval(int interval)
354 {
355     nativeWindow->setSwapInterval(nativeWindow, interval);
356 }
357
358 // createNativeSync() creates an OpenGL sync object on the host
359 // using rcCreateSyncKHR. If necessary, a native fence FD will
360 // also be created through the goldfish sync device.
361 // Returns a handle to the host-side FenceSync object.
362 static uint64_t createNativeSync(EGLenum type,
363                                  const EGLint* attrib_list,
364                                  int num_actual_attribs,
365                                  bool destroy_when_signaled,
366                                  int fd_in,
367                                  int* fd_out) {
368     DEFINE_HOST_CONNECTION;
369
370     uint64_t sync_handle;
371     uint64_t thread_handle;
372
373     EGLint* actual_attribs =
374         (EGLint*)(num_actual_attribs == 0 ? NULL : attrib_list);
375
376     rcEnc->rcCreateSyncKHR(rcEnc, type,
377                            actual_attribs,
378                            num_actual_attribs * sizeof(EGLint),
379                            destroy_when_signaled,
380                            &sync_handle,
381                            &thread_handle);
382
383     if (type == EGL_SYNC_NATIVE_FENCE_ANDROID && fd_in < 0) {
384         int queue_work_err =
385             goldfish_sync_queue_work(
386                     getEGLThreadInfo()->currentContext->getGoldfishSyncFd(),
387                     sync_handle,
388                     thread_handle,
389                     fd_out);
390
391         DPRINT("got native fence fd=%d queue_work_err=%d",
392                *fd_out, queue_work_err);
393     }
394
395     return sync_handle;
396 }
397
398 // createGoldfishOpenGLNativeSync() is for creating host-only sync objects
399 // that are needed by only this goldfish opengl driver,
400 // such as in swapBuffers().
401 // The guest will not see any of these, and these sync objects will be
402 // destroyed on the host when signaled.
403 // A native fence FD is possibly returned.
404 static void createGoldfishOpenGLNativeSync(int* fd_out) {
405     createNativeSync(EGL_SYNC_NATIVE_FENCE_ANDROID,
406                      NULL /* empty attrib list */,
407                      0 /* 0 attrib count */,
408                      true /* destroy when signaled. this is host-only
409                              and there will only be one waiter */,
410                      -1 /* we want a new fd */,
411                      fd_out);
412 }
413
414 EGLBoolean egl_window_surface_t::swapBuffers()
415 {
416
417     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
418
419     // Follow up flushWindowColorBuffer with a fence command.
420     // When the fence command finishes,
421     // we're sure that the buffer on the host
422     // has been blitted.
423     //
424     // |presentFenceFd| guards the presentation of the
425     // current frame with a goldfish sync fence fd.
426     //
427     // When |presentFenceFd| is signaled, the recipient
428     // of the buffer that was sent through queueBuffer
429     // can be sure that the buffer is current.
430     //
431     // If we don't take care of this synchronization,
432     // an old frame can be processed by surfaceflinger,
433     // resulting in out of order frames.
434
435     int presentFenceFd = -1;
436
437 #if PLATFORM_SDK_VERSION <= 16
438     rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
439     // equivalent to glFinish if no native sync
440     eglWaitClient();
441     nativeWindow->queueBuffer(nativeWindow, buffer);
442 #else
443     if (rcEnc->hasNativeSync()) {
444         rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
445         createGoldfishOpenGLNativeSync(&presentFenceFd);
446     } else {
447         rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
448         // equivalent to glFinish if no native sync
449         eglWaitClient();
450     }
451
452     DPRINT("queueBuffer with fence %d", presentFenceFd);
453     nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
454 #endif
455
456     DPRINT("calling dequeueBuffer...");
457
458 #if PLATFORM_SDK_VERSION <= 16
459     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
460         buffer = NULL;
461         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
462     }
463 #else
464     int acquireFenceFd = -1;
465     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &acquireFenceFd)) {
466         buffer = NULL;
467         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
468     }
469
470     DPRINT("dequeueBuffer with fence %d", acquireFenceFd);
471
472     if (acquireFenceFd > 0) {
473         close(acquireFenceFd);
474     }
475 #endif
476
477     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
478             ((cb_handle_t *)(buffer->handle))->hostHandle);
479
480     setWidth(buffer->width);
481     setHeight(buffer->height);
482
483     return EGL_TRUE;
484 }
485
486 // ----------------------------------------------------------------------------
487 //egl_pbuffer_surface_t
488
489 struct egl_pbuffer_surface_t : public egl_surface_t {
490     static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
491             EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
492
493     virtual ~egl_pbuffer_surface_t();
494
495     virtual void       setSwapInterval(int interval) { (void)interval; }
496     virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
497
498     uint32_t getRcColorBuffer() { return rcColorBuffer; }
499
500 private:
501     egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
502             int32_t w, int32_t h);
503     EGLBoolean init(GLenum format);
504
505     uint32_t rcColorBuffer;
506 };
507
508 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
509         EGLint surfType, int32_t w, int32_t h)
510 :   egl_surface_t(dpy, config, surfType),
511     rcColorBuffer(0)
512 {
513     setWidth(w);
514     setHeight(h);
515 }
516
517 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
518 {
519     DEFINE_HOST_CONNECTION;
520     if (rcEnc) {
521         if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
522         if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
523     }
524 }
525
526 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
527 {
528     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
529
530     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
531             getWidth(), getHeight());
532     if (!rcSurface) {
533         ALOGE("rcCreateWindowSurface returned 0");
534         return EGL_FALSE;
535     }
536
537     rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
538             pixelFormat);
539     if (!rcColorBuffer) {
540         ALOGE("rcCreateColorBuffer returned 0");
541         return EGL_FALSE;
542     }
543
544     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
545
546     return EGL_TRUE;
547 }
548
549 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
550         EGLConfig config, EGLint surfType, int32_t w, int32_t h,
551         GLenum pixelFormat)
552 {
553     egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
554             w, h);
555     if (pb && !pb->init(pixelFormat)) {
556         delete pb;
557         pb = NULL;
558     }
559     return pb;
560 }
561
562 static const char *getGLString(int glEnum)
563 {
564     EGLThreadInfo *tInfo = getEGLThreadInfo();
565     if (!tInfo || !tInfo->currentContext) {
566         return NULL;
567     }
568
569     const char** strPtr = NULL;
570
571 #define GL_VENDOR                         0x1F00
572 #define GL_RENDERER                       0x1F01
573 #define GL_VERSION                        0x1F02
574 #define GL_SHADING_LANGUAGE_VERSION       0x8B8C
575 #define GL_EXTENSIONS                     0x1F03
576
577     switch(glEnum) {
578         case GL_VERSION:
579             strPtr = &tInfo->currentContext->versionString;
580             break;
581         case GL_VENDOR:
582             strPtr = &tInfo->currentContext->vendorString;
583             break;
584         case GL_RENDERER:
585             strPtr = &tInfo->currentContext->rendererString;
586             break;
587         case GL_SHADING_LANGUAGE_VERSION:
588             strPtr = &tInfo->currentContext->shaderVersionString;
589             break;
590         case GL_EXTENSIONS:
591             strPtr = &tInfo->currentContext->extensionString;
592             break;
593     }
594
595     if (!strPtr) {
596         return NULL;
597     }
598
599     if (*strPtr != NULL) {
600         //
601         // string is already cached
602         //
603         return *strPtr;
604     }
605
606     //
607     // first query of that string - need to query host
608     //
609     DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
610     char *hostStr = NULL;
611     int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
612     if (n < 0) {
613         hostStr = new char[-n+1];
614         n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
615         if (n <= 0) {
616             delete [] hostStr;
617             hostStr = NULL;
618         }
619     }
620
621     //
622     // keep the string in the context and return its value
623     //
624     *strPtr = hostStr;
625     return hostStr;
626 }
627
628 // ----------------------------------------------------------------------------
629
630 static EGLClient_eglInterface s_eglIface = {
631     getThreadInfo: getEGLThreadInfo,
632     getGLString: getGLString
633 };
634
635 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
636 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
637 {
638     //
639     // we support only EGL_DEFAULT_DISPLAY.
640     //
641     if (display_id != EGL_DEFAULT_DISPLAY) {
642         return EGL_NO_DISPLAY;
643     }
644
645     return (EGLDisplay)&s_display;
646 }
647
648 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
649 {
650     VALIDATE_DISPLAY(dpy,EGL_FALSE);
651
652     if (!s_display.initialize(&s_eglIface)) {
653         return EGL_FALSE;
654     }
655     if (major!=NULL)
656         *major = s_display.getVersionMajor();
657     if (minor!=NULL)
658         *minor = s_display.getVersionMinor();
659     return EGL_TRUE;
660 }
661
662 EGLBoolean eglTerminate(EGLDisplay dpy)
663 {
664     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
665
666     s_display.terminate();
667     return EGL_TRUE;
668 }
669
670 EGLint eglGetError()
671 {
672     EGLint error = getEGLThreadInfo()->eglError;
673     getEGLThreadInfo()->eglError = EGL_SUCCESS;
674     return error;
675 }
676
677 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
678 {
679     // search in EGL function table
680     for (int i=0; i<egl_num_funcs; i++) {
681         if (!strcmp(egl_funcs_by_name[i].name, procname)) {
682             return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
683         }
684     }
685
686     // look in gles client api's extensions table
687     return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
688
689     // Fail - function not found.
690     return NULL;
691 }
692
693 const char* eglQueryString(EGLDisplay dpy, EGLint name)
694 {
695     VALIDATE_DISPLAY_INIT(dpy, NULL);
696
697     return s_display.queryString(name);
698 }
699
700 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
701 {
702     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
703
704     if(!num_config) {
705         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
706     }
707
708     GLint numConfigs = s_display.getNumConfigs();
709     if (!configs) {
710         *num_config = numConfigs;
711         return EGL_TRUE;
712     }
713
714     EGLint i;
715     for (i = 0 ; i < numConfigs && i < config_size ; i++) {
716         *configs++ = (EGLConfig)(uintptr_t)i;
717     }
718     *num_config = i;
719     return EGL_TRUE;
720 }
721
722 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
723 {
724     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
725
726     int attribs_size = 0;
727     if (attrib_list) {
728         const EGLint * attrib_p = attrib_list;
729         while (attrib_p[0] != EGL_NONE) {
730             attribs_size += 2;
731             attrib_p += 2;
732         }
733         attribs_size++; //for the terminating EGL_NONE
734     }
735
736     uint32_t* tempConfigs[config_size];
737     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
738     *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
739     if (configs!=NULL) {
740         EGLint i=0;
741         for (i=0;i<(*num_config);i++) {
742              *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
743         }
744     }
745
746     if (*num_config <= 0)
747         return EGL_FALSE;
748     return EGL_TRUE;
749 }
750
751 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
752 {
753     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
754     VALIDATE_CONFIG(config, EGL_FALSE);
755
756     if (s_display.getConfigAttrib(config, attribute, value))
757     {
758         return EGL_TRUE;
759     }
760     else
761     {
762         RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
763     }
764 }
765
766 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
767 {
768     (void)attrib_list;
769
770     VALIDATE_DISPLAY_INIT(dpy, NULL);
771     VALIDATE_CONFIG(config, EGL_FALSE);
772     if (win == 0) {
773         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
774     }
775
776     EGLint surfaceType;
777     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
778
779     if (!(surfaceType & EGL_WINDOW_BIT)) {
780         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
781     }
782
783     if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
784         setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
785     }
786
787     egl_surface_t* surface = egl_window_surface_t::create(
788             &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
789     if (!surface) {
790         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
791     }
792
793     return surface;
794 }
795
796 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
797 {
798     VALIDATE_DISPLAY_INIT(dpy, NULL);
799     VALIDATE_CONFIG(config, EGL_FALSE);
800
801     EGLint surfaceType;
802     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
803
804     if (!(surfaceType & EGL_PBUFFER_BIT)) {
805         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
806     }
807
808     int32_t w = 0;
809     int32_t h = 0;
810     EGLint texFormat = EGL_NO_TEXTURE;
811     EGLint texTarget = EGL_NO_TEXTURE;
812     while (attrib_list[0] != EGL_NONE) {
813         switch (attrib_list[0]) {
814             case EGL_WIDTH:
815                 w = attrib_list[1];
816                 if (w < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
817                 break;
818             case EGL_HEIGHT:
819                 h = attrib_list[1];
820                 if (h < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
821                 break;
822             case EGL_TEXTURE_FORMAT:
823                 texFormat = attrib_list[1];
824                 break;
825             case EGL_TEXTURE_TARGET:
826                 texTarget = attrib_list[1];
827                 break;
828             // the followings are not supported
829             case EGL_LARGEST_PBUFFER:
830             case EGL_MIPMAP_TEXTURE:
831             case EGL_VG_ALPHA_FORMAT:
832             case EGL_VG_COLORSPACE:
833                 break;
834             default:
835                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
836         };
837         attrib_list+=2;
838     }
839     if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
840         ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
841         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
842     }
843     // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
844
845     GLenum pixelFormat;
846     if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
847         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
848
849     egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
850             EGL_PBUFFER_BIT, w, h, pixelFormat);
851     if (!surface) {
852         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
853     }
854
855     //setup attributes
856     surface->setTextureFormat(texFormat);
857     surface->setTextureTarget(texTarget);
858
859     return surface;
860 }
861
862 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
863 {
864     //XXX: Pixmap not supported. The host cannot render to a pixmap resource
865     //     located on host. In order to support Pixmaps we should either punt
866     //     to s/w rendering -or- let the host render to a buffer that will be
867     //     copied back to guest at some sync point. None of those methods not
868     //     implemented and pixmaps are not used with OpenGL anyway ...
869     VALIDATE_CONFIG(config, EGL_FALSE);
870     (void)dpy;
871     (void)pixmap;
872     (void)attrib_list;
873     return EGL_NO_SURFACE;
874 }
875
876 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
877 {
878     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
879     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
880
881     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
882     delete surface;
883
884     return EGL_TRUE;
885 }
886
887 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
888 {
889     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
890     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
891
892     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
893     EGLBoolean ret = EGL_TRUE;
894     switch (attribute) {
895         case EGL_CONFIG_ID:
896             ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
897             break;
898         case EGL_WIDTH:
899             *value = surface->getWidth();
900             break;
901         case EGL_HEIGHT:
902             *value = surface->getHeight();
903             break;
904         case EGL_TEXTURE_FORMAT:
905             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
906                 *value = surface->getTextureFormat();
907             }
908             break;
909         case EGL_TEXTURE_TARGET:
910             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
911                 *value = surface->getTextureTarget();
912             }
913             break;
914         case EGL_SWAP_BEHAVIOR:
915         {
916             EGLint surfaceType;
917             ret = s_display.getConfigAttrib(surface->config, EGL_SURFACE_TYPE,
918                     &surfaceType);
919             if (ret == EGL_TRUE) {
920                 if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
921                     *value = EGL_BUFFER_PRESERVED;
922                 } else {
923                     *value = EGL_BUFFER_DESTROYED;
924                 }
925             }
926             break;
927         }
928         case EGL_LARGEST_PBUFFER:
929             // not modified for a window or pixmap surface
930             // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
931             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
932             break;
933         case EGL_MIPMAP_TEXTURE:
934             // not modified for a window or pixmap surface
935             // and we ignore it when creating a PBuffer surface (default is 0)
936             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = false;
937             break;
938         case EGL_MIPMAP_LEVEL:
939             // not modified for a window or pixmap surface
940             // and we ignore it when creating a PBuffer surface (default is 0)
941             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
942             break;
943         case EGL_MULTISAMPLE_RESOLVE:
944             // ignored when creating the surface, return default
945             *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
946             break;
947         case EGL_HORIZONTAL_RESOLUTION:
948             // pixel/mm * EGL_DISPLAY_SCALING
949             // TODO: get the real resolution from avd config
950             *value = 1 * EGL_DISPLAY_SCALING;
951             break;
952         case EGL_VERTICAL_RESOLUTION:
953             // pixel/mm * EGL_DISPLAY_SCALING
954             // TODO: get the real resolution from avd config
955             *value = 1 * EGL_DISPLAY_SCALING;
956             break;
957         case EGL_PIXEL_ASPECT_RATIO:
958             // w / h * EGL_DISPLAY_SCALING
959             // Please don't ask why * EGL_DISPLAY_SCALING, the document says it
960             *value = 1 * EGL_DISPLAY_SCALING;
961             break;
962         case EGL_RENDER_BUFFER:
963             switch (surface->getSurfaceType()) {
964                 case EGL_PBUFFER_BIT:
965                     *value = EGL_BACK_BUFFER;
966                     break;
967                 case EGL_PIXMAP_BIT:
968                     *value = EGL_SINGLE_BUFFER;
969                     break;
970                 case EGL_WINDOW_BIT:
971                     // ignored when creating the surface, return default
972                     *value = EGL_BACK_BUFFER;
973                     break;
974                 default:
975                     ALOGE("eglQuerySurface %x unknown surface type %x",
976                             attribute, surface->getSurfaceType());
977                     ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
978                     break;
979             }
980             break;
981         case EGL_VG_COLORSPACE:
982             // ignored when creating the surface, return default
983             *value = EGL_VG_COLORSPACE_sRGB;
984             break;
985         case EGL_VG_ALPHA_FORMAT:
986             // ignored when creating the surface, return default
987             *value = EGL_VG_ALPHA_FORMAT_NONPRE;
988             break;
989         //TODO: complete other attributes
990         default:
991             ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
992             ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
993             break;
994     }
995
996     return ret;
997 }
998
999 EGLBoolean eglBindAPI(EGLenum api)
1000 {
1001     if (api != EGL_OPENGL_ES_API)
1002         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1003     return EGL_TRUE;
1004 }
1005
1006 EGLenum eglQueryAPI()
1007 {
1008     return EGL_OPENGL_ES_API;
1009 }
1010
1011 EGLBoolean eglWaitClient()
1012 {
1013     return eglWaitGL();
1014 }
1015
1016 EGLBoolean eglReleaseThread()
1017 {
1018     EGLThreadInfo *tInfo = getEGLThreadInfo();
1019     if (tInfo) {
1020         tInfo->eglError = EGL_SUCCESS;
1021         EGLContext_t* context = tInfo->currentContext;
1022         if (context) {
1023             // The following code is doing pretty much the same thing as
1024             // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
1025             // with the only issue that we do not require a valid display here.
1026             DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1027             rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
1028              if (context->version == 2) {
1029                 hostCon->gl2Encoder()->setClientState(NULL);
1030                 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
1031             }
1032             else {
1033                 hostCon->glEncoder()->setClientState(NULL);
1034                 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
1035             }
1036             context->flags &= ~EGLContext_t::IS_CURRENT;
1037
1038             if (context->deletePending) {
1039                 if (context->rcContext) {
1040                     rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1041                     context->rcContext = 0;
1042                 }
1043                 delete context;
1044             }
1045             tInfo->currentContext = 0;
1046         }
1047     }
1048     return EGL_TRUE;
1049 }
1050
1051 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
1052 {
1053     //TODO
1054     (void)dpy;
1055     (void)buftype;
1056     (void)buffer;
1057     (void)config;
1058     (void)attrib_list;
1059     ALOGW("%s not implemented", __FUNCTION__);
1060     return 0;
1061 }
1062
1063 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1064 {
1065     // Right now we don't do anything when using host GPU.
1066     // This is purely just to pass the data through
1067     // without issuing a warning. We may benefit from validating the
1068     // display and surface for debug purposes.
1069     // TODO: Find cases where we actually need to do something.
1070     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1071     VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
1072     if (surface == EGL_NO_SURFACE) {
1073         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1074     }
1075
1076     (void)value;
1077
1078     egl_surface_t* p_surface( static_cast<egl_surface_t*>(surface) );
1079     switch (attribute) {
1080     case EGL_MIPMAP_LEVEL:
1081         return true;
1082         break;
1083     case EGL_MULTISAMPLE_RESOLVE:
1084     {
1085         if (value == EGL_MULTISAMPLE_RESOLVE_BOX) {
1086             EGLint surface_type;
1087             s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1088             if (0 == (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) {
1089                 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1090             }
1091         }
1092         return true;
1093         break;
1094     }
1095     case EGL_SWAP_BEHAVIOR:
1096         if (value == EGL_BUFFER_PRESERVED) {
1097             EGLint surface_type;
1098             s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1099             if (0 == (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) {
1100                 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1101             }
1102         }
1103         return true;
1104         break;
1105     default:
1106         ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
1107         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1108     }
1109     return false;
1110 }
1111
1112 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
1113 {
1114     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1115     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1116     if (eglSurface == EGL_NO_SURFACE) {
1117         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1118     }
1119
1120     if (buffer != EGL_BACK_BUFFER) {
1121         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1122     }
1123
1124     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1125
1126     if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
1127         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1128     }
1129
1130     if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
1131         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1132     }
1133
1134     //It's now safe to cast to pbuffer surface
1135     egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
1136
1137     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1138     rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
1139
1140     return GL_TRUE;
1141 }
1142
1143 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1144 {
1145     //TODO
1146     (void)dpy;
1147     (void)surface;
1148     (void)buffer;
1149     ALOGW("%s not implemented", __FUNCTION__);
1150     return 0;
1151 }
1152
1153 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1154 {
1155     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1156     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1157
1158     EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
1159     if (!ctx) {
1160         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1161     }
1162     if (!ctx->draw) {
1163         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1164     }
1165     egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
1166     draw->setSwapInterval(interval);
1167
1168     rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
1169
1170     return EGL_TRUE;
1171 }
1172
1173 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
1174 {
1175     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
1176     VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
1177
1178     EGLint version = 1; //default
1179     while (attrib_list && attrib_list[0] != EGL_NONE) {
1180         if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
1181             version = attrib_list[1];
1182         } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
1183             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
1184         }
1185         attrib_list+=2;
1186     }
1187
1188     // Currently only support GLES1 and 2
1189     if (version != 1 && version != 2) {
1190         setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1191     }
1192
1193     uint32_t rcShareCtx = 0;
1194     EGLContext_t * shareCtx = NULL;
1195     if (share_context) {
1196         shareCtx = static_cast<EGLContext_t*>(share_context);
1197         rcShareCtx = shareCtx->rcContext;
1198         if (shareCtx->dpy != dpy)
1199             setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
1200     }
1201
1202     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
1203     // We've created EGL context. Disconnecting
1204     // would be dangerous at this point.
1205     hostCon->setGrallocOnly(false);
1206
1207     uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
1208     if (!rcContext) {
1209         ALOGE("rcCreateContext returned 0");
1210         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1211     }
1212
1213     EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
1214     if (!context)
1215         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1216
1217     context->version = version;
1218     context->rcContext = rcContext;
1219
1220
1221     return context;
1222 }
1223
1224 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1225 {
1226     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1227     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1228
1229     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1230
1231     if (!context) return EGL_TRUE;
1232
1233     if (getEGLThreadInfo()->currentContext == context) {
1234         getEGLThreadInfo()->currentContext->deletePending = 1;
1235         return EGL_TRUE;
1236     }
1237
1238     if (context->rcContext) {
1239         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1240         rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1241         context->rcContext = 0;
1242     }
1243
1244     delete context;
1245     return EGL_TRUE;
1246 }
1247
1248 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1249 {
1250     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1251     VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1252     VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1253
1254     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1255         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1256     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1257         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1258
1259     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1260     uint32_t ctxHandle = (context) ? context->rcContext : 0;
1261     egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1262     uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1263     egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1264     uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1265
1266     //
1267     // Nothing to do if no binding change has made
1268     //
1269     EGLThreadInfo *tInfo = getEGLThreadInfo();
1270
1271     if (tInfo->currentContext == context &&
1272         (context == NULL ||
1273         (context && context->draw == draw && context->read == read))) {
1274         return EGL_TRUE;
1275     }
1276
1277     if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1278         if (tInfo->currentContext != context) {
1279             EGLContext_t * contextToDelete = tInfo->currentContext;
1280             tInfo->currentContext = 0;
1281             eglDestroyContext(dpy, contextToDelete);
1282         }
1283     }
1284
1285     if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1286         //context is current to another thread
1287         setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1288     }
1289
1290     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1291     if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1292         ALOGE("rcMakeCurrent returned EGL_FALSE");
1293         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1294     }
1295
1296     //Now make the local bind
1297     if (context) {
1298         // This is a nontrivial context.
1299         // The thread cannot be gralloc-only anymore.
1300         hostCon->setGrallocOnly(false);
1301         context->draw = draw;
1302         context->read = read;
1303         context->flags |= EGLContext_t::IS_CURRENT;
1304         //set the client state
1305         if (context->version == 2) {
1306             hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
1307             hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1308         }
1309         else {
1310             hostCon->glEncoder()->setClientState(context->getClientState());
1311             hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1312         }
1313     }
1314     else if (tInfo->currentContext) {
1315         //release ClientState & SharedGroup
1316         if (tInfo->currentContext->version == 2) {
1317             hostCon->gl2Encoder()->setClientState(NULL);
1318             hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1319         }
1320         else {
1321             hostCon->glEncoder()->setClientState(NULL);
1322             hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1323         }
1324
1325     }
1326
1327     if (tInfo->currentContext)
1328         tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1329
1330     //Now make current
1331     tInfo->currentContext = context;
1332
1333     //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1334     if (tInfo->currentContext) {
1335         if (tInfo->currentContext->version == 2) {
1336             if (!hostCon->gl2Encoder()->isInitialized()) {
1337                 s_display.gles2_iface()->init();
1338                 hostCon->gl2Encoder()->setInitialized();
1339                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1340             }
1341         }
1342         else {
1343             if (!hostCon->glEncoder()->isInitialized()) {
1344                 s_display.gles_iface()->init();
1345                 hostCon->glEncoder()->setInitialized();
1346                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1347             }
1348         }
1349     }
1350
1351     return EGL_TRUE;
1352 }
1353
1354 EGLContext eglGetCurrentContext()
1355 {
1356     return getEGLThreadInfo()->currentContext;
1357 }
1358
1359 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1360 {
1361     EGLContext_t * context = getEGLThreadInfo()->currentContext;
1362     if (!context)
1363         return EGL_NO_SURFACE; //not an error
1364
1365     switch (readdraw) {
1366         case EGL_READ:
1367             return context->read;
1368         case EGL_DRAW:
1369             return context->draw;
1370         default:
1371             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1372     }
1373 }
1374
1375 EGLDisplay eglGetCurrentDisplay()
1376 {
1377     EGLContext_t * context = getEGLThreadInfo()->currentContext;
1378     if (!context)
1379         return EGL_NO_DISPLAY; //not an error
1380
1381     return context->dpy;
1382 }
1383
1384 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1385 {
1386     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1387     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1388
1389     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1390
1391     EGLBoolean ret = EGL_TRUE;
1392     switch (attribute) {
1393         case EGL_CONFIG_ID:
1394             ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1395             break;
1396         case EGL_CONTEXT_CLIENT_TYPE:
1397             *value = EGL_OPENGL_ES_API;
1398             break;
1399         case EGL_CONTEXT_CLIENT_VERSION:
1400             *value = context->version;
1401             break;
1402         case EGL_RENDER_BUFFER:
1403             if (!context->draw)
1404                 *value = EGL_NONE;
1405             else
1406                 *value = EGL_BACK_BUFFER; //single buffer not supported
1407             break;
1408         default:
1409             ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
1410             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1411             break;
1412     }
1413
1414     return ret;
1415 }
1416
1417 EGLBoolean eglWaitGL()
1418 {
1419     EGLThreadInfo *tInfo = getEGLThreadInfo();
1420     if (!tInfo || !tInfo->currentContext) {
1421         return EGL_FALSE;
1422     }
1423
1424     if (tInfo->currentContext->version == 2) {
1425         s_display.gles2_iface()->finish();
1426     }
1427     else {
1428         s_display.gles_iface()->finish();
1429     }
1430
1431     return EGL_TRUE;
1432 }
1433
1434 EGLBoolean eglWaitNative(EGLint engine)
1435 {
1436     (void)engine;
1437     return EGL_TRUE;
1438 }
1439
1440 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1441 {
1442     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1443     if (eglSurface == EGL_NO_SURFACE)
1444         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1445
1446     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1447
1448     egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1449     if (d->dpy != dpy)
1450         setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1451
1452     // post the surface
1453     d->swapBuffers();
1454
1455     hostCon->flush();
1456     return EGL_TRUE;
1457 }
1458
1459 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1460 {
1461     //TODO :later
1462     (void)dpy;
1463     (void)surface;
1464     (void)target;
1465     return 0;
1466 }
1467
1468 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1469 {
1470     //TODO later
1471     (void)display;
1472     (void)surface;
1473     (void)attrib_list;
1474     return 0;
1475 }
1476
1477 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1478 {
1479     //TODO later
1480     (void)display;
1481     (void)surface;
1482     return 0;
1483 }
1484
1485 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1486 {
1487     (void)attrib_list;
1488
1489     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1490
1491     if (target == EGL_NATIVE_BUFFER_ANDROID) {
1492         if (ctx != EGL_NO_CONTEXT) {
1493             setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1494         }
1495
1496         android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1497
1498         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1499             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1500
1501         if (native_buffer->common.version != sizeof(android_native_buffer_t))
1502             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1503
1504         cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1505
1506         switch (cb->format) {
1507             case HAL_PIXEL_FORMAT_RGBA_8888:
1508             case HAL_PIXEL_FORMAT_RGBX_8888:
1509             case HAL_PIXEL_FORMAT_RGB_888:
1510             case HAL_PIXEL_FORMAT_RGB_565:
1511             case HAL_PIXEL_FORMAT_YV12:
1512             case HAL_PIXEL_FORMAT_BGRA_8888:
1513                 break;
1514             default:
1515                 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1516         }
1517
1518         native_buffer->common.incRef(&native_buffer->common);
1519
1520         EGLImage_t *image = new EGLImage_t();
1521         image->dpy = dpy;
1522         image->target = target;
1523         image->native_buffer = native_buffer;
1524
1525         return (EGLImageKHR)image;
1526     }
1527     else if (target == EGL_GL_TEXTURE_2D_KHR) {
1528         VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1529
1530         EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1531         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1532
1533         uint32_t ctxHandle = (context) ? context->rcContext : 0;
1534         GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1535         uint32_t img = PUID_CMD(rcEnc, rcCreateClientImage, ctxHandle, target, texture);
1536         EGLImage_t *image = new EGLImage_t();
1537         image->dpy = dpy;
1538         image->target = target;
1539         image->host_egl_image = img;
1540
1541         return (EGLImageKHR)image;
1542     }
1543     
1544     setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1545 }
1546
1547 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1548 {
1549     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1550     EGLImage_t *image = (EGLImage_t*)img;
1551
1552     if (!image || image->dpy != dpy) {
1553         RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1554     }
1555
1556     if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1557         android_native_buffer_t* native_buffer = image->native_buffer;
1558
1559         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1560             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1561
1562         if (native_buffer->common.version != sizeof(android_native_buffer_t))
1563             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1564
1565         native_buffer->common.decRef(&native_buffer->common);
1566         delete image;
1567
1568         return EGL_TRUE;
1569     }
1570     else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1571         uint32_t host_egl_image = image->host_egl_image;
1572         delete image;
1573         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1574         return PUID_CMD(rcEnc, rcDestroyClientImage, host_egl_image);
1575     }
1576
1577     setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1578 }
1579
1580 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1581 #define MAX_EGL_SYNC_ATTRIBS 10
1582
1583 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1584         const EGLint *attrib_list)
1585 {
1586     VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1587     DPRINT("type for eglCreateSyncKHR: 0x%x", type);
1588
1589     DEFINE_HOST_CONNECTION;
1590
1591     if ((type != EGL_SYNC_FENCE_KHR &&
1592          type != EGL_SYNC_NATIVE_FENCE_ANDROID) ||
1593         (type != EGL_SYNC_FENCE_KHR &&
1594          !rcEnc->hasNativeSync())) {
1595         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1596     }
1597
1598     EGLThreadInfo *tInfo = getEGLThreadInfo();
1599     if (!tInfo || !tInfo->currentContext) {
1600         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1601     }
1602
1603     int num_actual_attribs = 0;
1604
1605     // If attrib_list is not NULL,
1606     // ensure attrib_list contains (key, value) pairs
1607     // followed by a single EGL_NONE.
1608     // Also validate attribs.
1609     int inputFenceFd = -1;
1610     if (attrib_list) {
1611         for (int i = 0; i < MAX_EGL_SYNC_ATTRIBS; i += 2) {
1612             if (attrib_list[i] == EGL_NONE) {
1613                 num_actual_attribs = i;
1614                 break;
1615             }
1616             if (i + 1 == MAX_EGL_SYNC_ATTRIBS) {
1617                 DPRINT("ERROR: attrib list without EGL_NONE");
1618                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1619             }
1620         }
1621
1622         // Validate and input attribs
1623         for (int i = 0; i < num_actual_attribs; i += 2) {
1624             if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
1625                 DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
1626             }
1627             if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
1628                 DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
1629             }
1630             if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
1631                 DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
1632             }
1633             EGLint attrib_key = attrib_list[i];
1634             EGLint attrib_val = attrib_list[i + 1];
1635             if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
1636                 if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
1637                     inputFenceFd = attrib_val;
1638                 }
1639             }
1640             DPRINT("attrib: 0x%x : 0x%x", attrib_key, attrib_val);
1641         }
1642     }
1643
1644     uint64_t sync_handle = 0;
1645     int newFenceFd = -1;
1646
1647     if (rcEnc->hasNativeSync()) {
1648         sync_handle =
1649             createNativeSync(type, attrib_list, num_actual_attribs,
1650                              false /* don't destroy when signaled on the host;
1651                                       let the guest clean this up,
1652                                       because the guest called eglCreateSyncKHR. */,
1653                              inputFenceFd,
1654                              &newFenceFd);
1655
1656     } else {
1657         // Just trigger a glFinish if the native sync on host
1658         // is unavailable.
1659         eglWaitClient();
1660     }
1661
1662     EGLSync_t* syncRes = new EGLSync_t(sync_handle);
1663
1664     if (type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
1665         syncRes->type = EGL_SYNC_NATIVE_FENCE_ANDROID;
1666
1667         if (inputFenceFd < 0) {
1668             syncRes->android_native_fence_fd = newFenceFd;
1669         } else {
1670             DPRINT("has input fence fd %d",
1671                     inputFenceFd);
1672             syncRes->android_native_fence_fd = inputFenceFd;
1673         }
1674     } else {
1675         syncRes->type = EGL_SYNC_FENCE_KHR;
1676         syncRes->android_native_fence_fd = -1;
1677     }
1678
1679     return (EGLSyncKHR)syncRes;
1680 }
1681
1682 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync)
1683 {
1684     (void)dpy;
1685
1686     if (!eglsync) {
1687         DPRINT("WARNING: null sync object")
1688         return EGL_TRUE;
1689     }
1690
1691     EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
1692
1693     if (sync && sync->android_native_fence_fd > 0) {
1694         close(sync->android_native_fence_fd);
1695         sync->android_native_fence_fd = -1;
1696     }
1697
1698     if (sync) {
1699         DEFINE_HOST_CONNECTION;
1700         if (rcEnc->hasNativeSync()) {
1701             rcEnc->rcDestroySyncKHR(rcEnc, sync->handle);
1702         }
1703         delete sync;
1704     }
1705
1706     return EGL_TRUE;
1707 }
1708
1709 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags,
1710         EGLTimeKHR timeout)
1711 {
1712     (void)dpy;
1713
1714     if (!eglsync) {
1715         DPRINT("WARNING: null sync object");
1716         return EGL_CONDITION_SATISFIED_KHR;
1717     }
1718
1719     EGLSync_t* sync = (EGLSync_t*)eglsync;
1720
1721     DPRINT("sync=0x%lx (handle=0x%lx) flags=0x%x timeout=0x%llx",
1722            sync, sync->handle, flags, timeout);
1723
1724     DEFINE_HOST_CONNECTION;
1725
1726     EGLint retval;
1727     if (rcEnc->hasNativeSync()) {
1728         retval = rcEnc->rcClientWaitSyncKHR
1729             (rcEnc, sync->handle, flags, timeout);
1730     } else {
1731         retval = EGL_CONDITION_SATISFIED_KHR;
1732     }
1733     EGLint res_status;
1734     switch (sync->type) {
1735         case EGL_SYNC_FENCE_KHR:
1736             res_status = EGL_SIGNALED_KHR;
1737             break;
1738         case EGL_SYNC_NATIVE_FENCE_ANDROID:
1739             res_status = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
1740             break;
1741         default:
1742             res_status = EGL_SIGNALED_KHR;
1743     }
1744     sync->status = res_status;
1745     return retval;
1746 }
1747
1748 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR eglsync,
1749         EGLint attribute, EGLint *value)
1750 {
1751     (void)dpy;
1752
1753     EGLSync_t* sync = (EGLSync_t*)eglsync;
1754
1755     switch (attribute) {
1756     case EGL_SYNC_TYPE_KHR:
1757         *value = sync->type;
1758         return EGL_TRUE;
1759     case EGL_SYNC_STATUS_KHR:
1760         *value = sync->status;
1761         return EGL_TRUE;
1762     case EGL_SYNC_CONDITION_KHR:
1763         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1764         return EGL_TRUE;
1765     default:
1766         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1767     }
1768 }
1769
1770 int eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR eglsync) {
1771     (void)dpy;
1772
1773     DPRINT("call");
1774
1775     EGLSync_t* sync = (EGLSync_t*)eglsync;
1776     if (sync && sync->android_native_fence_fd > 0) {
1777         int res = dup(sync->android_native_fence_fd);
1778         return res;
1779     } else {
1780         return -1;
1781     }
1782 }
1783
1784 // TODO: Implement EGL_KHR_wait_sync
1785 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {
1786     (void)dpy;
1787     (void)eglsync;
1788     (void)flags;
1789     return EGL_TRUE;
1790 }