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 <cutils/properties.h>
25#include "goldfish_sync.h"
26#include "gralloc_cb.h"
27#include "GLClientState.h"
28#include "GLSharedGroup.h"
29#include "eglContext.h"
30#include "ClientAPIExts.h"
31#include "EGLImage.h"
32#include "ProcessPipe.h"
33
34#include "GLEncoder.h"
35#ifdef WITH_GLES2
36#include "GL2Encoder.h"
37#endif
38
39#include <GLES3/gl31.h>
40
41#if PLATFORM_SDK_VERSION < 18
42#define override
43#endif
44
45#if PLATFORM_SDK_VERSION >= 16
46#include <system/window.h>
47#else // PLATFORM_SDK_VERSION >= 16
48#include <private/ui/android_natives_priv.h>
49#endif // PLATFORM_SDK_VERSION >= 16
50
51#if PLATFORM_SDK_VERSION <= 16
52#define queueBuffer_DEPRECATED queueBuffer
53#define dequeueBuffer_DEPRECATED dequeueBuffer
54#define cancelBuffer_DEPRECATED cancelBuffer
55#endif // PLATFORM_SDK_VERSION <= 16
56
57#define DEBUG_EGL 0
58
59#if DEBUG_EGL
60#define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
61#else
62#define DPRINT(...)
63#endif
64
65template<typename T>
66static T setErrorFunc(GLint error, T returnValue) {
67    getEGLThreadInfo()->eglError = error;
68    return returnValue;
69}
70
71const char *  eglStrError(EGLint err)
72{
73    switch (err){
74        case EGL_SUCCESS:           return "EGL_SUCCESS";
75        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
76        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
77        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
78        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
79        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
80        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
81        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
82        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
83        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
84        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
85        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
86        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
87        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
88        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
89        default: return "UNKNOWN";
90    }
91}
92
93#define LOG_EGL_ERRORS 1
94
95#ifdef LOG_EGL_ERRORS
96
97#define setErrorReturn(error, retVal)     \
98    {                                                \
99        ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
100        return setErrorFunc(error, retVal);            \
101    }
102
103#define RETURN_ERROR(ret,err)           \
104    ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
105    getEGLThreadInfo()->eglError = err;    \
106    return ret;
107
108#else //!LOG_EGL_ERRORS
109
110#define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
111
112#define RETURN_ERROR(ret,err)           \
113    getEGLThreadInfo()->eglError = err; \
114    return ret;
115
116#endif //LOG_EGL_ERRORS
117
118#define VALIDATE_CONFIG(cfg,ret) \
119    if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
120        RETURN_ERROR(ret,EGL_BAD_CONFIG); \
121    }
122
123#define VALIDATE_DISPLAY(dpy,ret) \
124    if ((dpy) != (EGLDisplay)&s_display) { \
125        RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
126    }
127
128#define VALIDATE_DISPLAY_INIT(dpy,ret) \
129    VALIDATE_DISPLAY(dpy, ret)    \
130    if (!s_display.initialized()) {        \
131        RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
132    }
133
134#define DEFINE_HOST_CONNECTION \
135    HostConnection *hostCon = HostConnection::get(); \
136    ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
137
138#define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
139    HostConnection *hostCon = HostConnection::get(); \
140    if (!hostCon) { \
141        ALOGE("egl: Failed to get host connection\n"); \
142        return ret; \
143    } \
144    ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
145    if (!rcEnc) { \
146        ALOGE("egl: Failed to get renderControl encoder context\n"); \
147        return ret; \
148    }
149
150#define DEFINE_AND_VALIDATE_HOST_CONNECTION_FOR_TLS(ret, tls) \
151    HostConnection *hostCon = HostConnection::getWithThreadInfo(tls); \
152    if (!hostCon) { \
153        ALOGE("egl: Failed to get host connection\n"); \
154        return ret; \
155    } \
156    ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
157    if (!rcEnc) { \
158        ALOGE("egl: Failed to get renderControl encoder context\n"); \
159        return ret; \
160    }
161
162#define VALIDATE_CONTEXT_RETURN(context,ret)  \
163    if (!(context) || !s_display.isContext((context))) {                         \
164        RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
165    }
166
167#define VALIDATE_SURFACE_RETURN(surface, ret)    \
168    if ((surface) != EGL_NO_SURFACE) {    \
169        if (!s_display.isSurface((surface))) \
170            setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); \
171        egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
172        if (s->dpy != (EGLDisplay)&s_display)    \
173            setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
174    }
175
176// The one and only supported display object.
177static eglDisplay s_display;
178
179// Extra defines not in the official EGL spec yet,
180// but required in Android CTS.
181
182#define EGL_TIMESTAMPS_ANDROID 0x314D
183
184EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx, int maj, int min) :
185    dpy(dpy),
186    config(config),
187    read(EGL_NO_SURFACE),
188    draw(EGL_NO_SURFACE),
189    shareCtx(shareCtx),
190    rcContext(0),
191    versionString(NULL),
192    majorVersion(maj),
193    minorVersion(min),
194    vendorString(NULL) ,
195    rendererString(NULL),
196    shaderVersionString(NULL),
197    extensionString(NULL),
198    deletePending(0),
199    goldfishSyncFd(-1)
200{
201
202    DEFINE_HOST_CONNECTION;
203    switch (rcEnc->getGLESMaxVersion()) {
204        case GLES_MAX_VERSION_3_0:
205            deviceMajorVersion = 3;
206            deviceMinorVersion = 0;
207            break;
208        case GLES_MAX_VERSION_3_1:
209            deviceMajorVersion = 3;
210            deviceMinorVersion = 1;
211            break;
212        case GLES_MAX_VERSION_3_2:
213            deviceMajorVersion = 3;
214            deviceMinorVersion = 2;
215            break;
216        default:
217            deviceMajorVersion = 2;
218            deviceMinorVersion = 0;
219            break;
220    }
221
222    flags = 0;
223    clientState = new GLClientState(majorVersion, minorVersion);
224     if (shareCtx)
225        sharedGroup = shareCtx->getSharedGroup();
226    else
227        sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
228    assert(dpy == (EGLDisplay)&s_display);
229    s_display.onCreateContext((EGLContext)this);
230};
231
232int EGLContext_t::getGoldfishSyncFd() {
233    if (goldfishSyncFd < 0) {
234        goldfishSyncFd = goldfish_sync_open();
235    }
236    return goldfishSyncFd;
237}
238
239EGLContext_t::~EGLContext_t()
240{
241    if (goldfishSyncFd > 0) {
242        goldfish_sync_close(goldfishSyncFd);
243        goldfishSyncFd = -1;
244    }
245    assert(dpy == (EGLDisplay)&s_display);
246    s_display.onDestroyContext((EGLContext)this);
247    delete clientState;
248    delete [] versionString;
249    delete [] vendorString;
250    delete [] rendererString;
251    delete [] shaderVersionString;
252    delete [] extensionString;
253}
254
255// ----------------------------------------------------------------------------
256//egl_surface_t
257
258//we don't need to handle depth since it's handled when window created on the host
259
260struct egl_surface_t {
261
262    EGLDisplay          dpy;
263    EGLConfig           config;
264
265
266    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
267    virtual     ~egl_surface_t();
268
269    virtual     void        setSwapInterval(int interval) = 0;
270    virtual     EGLBoolean  swapBuffers() = 0;
271
272    EGLint      getSwapBehavior() const;
273    uint32_t    getRcSurface()   { return rcSurface; }
274    EGLint      getSurfaceType() { return surfaceType; }
275
276    EGLint      getWidth(){ return width; }
277    EGLint      getHeight(){ return height; }
278    EGLint      getNativeWidth(){ return nativeWidth; }
279    EGLint      getNativeHeight(){ return nativeHeight; }
280    void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
281    EGLint      getTextureFormat() { return texFormat; }
282    void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
283    EGLint      getTextureTarget() { return texTarget; }
284
285    virtual     void setCollectingTimestamps(EGLint collect) { }
286    virtual     EGLint isCollectingTimestamps() const { return EGL_FALSE; }
287    EGLint      deletePending;
288    void        setIsCurrent(bool isCurrent) { mIsCurrent = isCurrent; }
289    bool        isCurrent() const { return mIsCurrent;}
290private:
291    //
292    //Surface attributes
293    //
294    EGLint      width;
295    EGLint      height;
296    EGLint      texFormat;
297    EGLint      texTarget;
298
299    // Width of the actual window being presented (not the EGL texture)
300    // Give it some default values.
301    int nativeWidth;
302    int nativeHeight;
303    bool mIsCurrent;
304protected:
305    void        setWidth(EGLint w)  { width = w;  }
306    void        setHeight(EGLint h) { height = h; }
307    void        setNativeWidth(int w)  { nativeWidth = w;  }
308    void        setNativeHeight(int h) { nativeHeight = h; }
309
310    EGLint      surfaceType;
311    uint32_t    rcSurface; //handle to surface created via remote control
312};
313
314egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
315    : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0),
316      deletePending(0), mIsCurrent(false)
317{
318    width = 0;
319    height = 0;
320    // prevent div by 0 in EGL_(HORIZONTAL|VERTICAL)_RESOLUTION queries.
321    nativeWidth = 1;
322    nativeHeight = 1;
323    texFormat = EGL_NO_TEXTURE;
324    texTarget = EGL_NO_TEXTURE;
325    assert(dpy == (EGLDisplay)&s_display);
326    s_display.onCreateSurface((EGLSurface)this);
327}
328
329EGLint egl_surface_t::getSwapBehavior() const {
330    return EGL_BUFFER_PRESERVED;
331}
332
333egl_surface_t::~egl_surface_t()
334{
335    assert(dpy == (EGLDisplay)&s_display);
336    s_display.onDestroySurface((EGLSurface)this);
337}
338
339// ----------------------------------------------------------------------------
340// egl_window_surface_t
341
342struct egl_window_surface_t : public egl_surface_t {
343    static egl_window_surface_t* create(
344            EGLDisplay dpy, EGLConfig config, EGLint surfType,
345            ANativeWindow* window);
346
347    virtual ~egl_window_surface_t();
348
349    virtual void       setSwapInterval(int interval);
350    virtual EGLBoolean swapBuffers();
351
352    virtual     void        setCollectingTimestamps(EGLint collect)
353        override { collectingTimestamps = (collect == EGL_TRUE) ? true : false; }
354    virtual     EGLint isCollectingTimestamps() const override { return collectingTimestamps ? EGL_TRUE : EGL_FALSE; }
355
356
357private:
358    egl_window_surface_t(
359            EGLDisplay dpy, EGLConfig config, EGLint surfType,
360            ANativeWindow* window);
361    EGLBoolean init();
362
363    ANativeWindow*              nativeWindow;
364    android_native_buffer_t*    buffer;
365    bool collectingTimestamps;
366};
367
368egl_window_surface_t::egl_window_surface_t (
369        EGLDisplay dpy, EGLConfig config, EGLint surfType,
370        ANativeWindow* window)
371:   egl_surface_t(dpy, config, surfType),
372    nativeWindow(window),
373    buffer(NULL),
374    collectingTimestamps(false)
375{
376    // keep a reference on the window
377    nativeWindow->common.incRef(&nativeWindow->common);
378}
379
380
381EGLBoolean egl_window_surface_t::init()
382{
383    if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
384        setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
385    }
386    setWidth(buffer->width);
387    setHeight(buffer->height);
388
389    int nativeWidth, nativeHeight;
390          nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &nativeWidth);
391          nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &nativeHeight);
392
393    setNativeWidth(nativeWidth);
394    setNativeHeight(nativeHeight);
395
396    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
397    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
398            getWidth(), getHeight());
399    if (!rcSurface) {
400        ALOGE("rcCreateWindowSurface returned 0");
401        return EGL_FALSE;
402    }
403    rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
404            ((cb_handle_t*)(buffer->handle))->hostHandle);
405
406    return EGL_TRUE;
407}
408
409egl_window_surface_t* egl_window_surface_t::create(
410        EGLDisplay dpy, EGLConfig config, EGLint surfType,
411        ANativeWindow* window)
412{
413    egl_window_surface_t* wnd = new egl_window_surface_t(
414            dpy, config, surfType, window);
415    if (wnd && !wnd->init()) {
416        delete wnd;
417        wnd = NULL;
418    }
419    return wnd;
420}
421
422egl_window_surface_t::~egl_window_surface_t() {
423    DEFINE_HOST_CONNECTION;
424    if (rcSurface && rcEnc) {
425        rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
426    }
427    if (buffer) {
428        nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
429    }
430    nativeWindow->common.decRef(&nativeWindow->common);
431}
432
433void egl_window_surface_t::setSwapInterval(int interval)
434{
435    nativeWindow->setSwapInterval(nativeWindow, interval);
436}
437
438// createNativeSync() creates an OpenGL sync object on the host
439// using rcCreateSyncKHR. If necessary, a native fence FD will
440// also be created through the goldfish sync device.
441// Returns a handle to the host-side FenceSync object.
442static uint64_t createNativeSync(EGLenum type,
443                                 const EGLint* attrib_list,
444                                 int num_actual_attribs,
445                                 bool destroy_when_signaled,
446                                 int fd_in,
447                                 int* fd_out) {
448    DEFINE_HOST_CONNECTION;
449
450    uint64_t sync_handle;
451    uint64_t thread_handle;
452
453    EGLint* actual_attribs =
454        (EGLint*)(num_actual_attribs == 0 ? NULL : attrib_list);
455
456    rcEnc->rcCreateSyncKHR(rcEnc, type,
457                           actual_attribs,
458                           num_actual_attribs * sizeof(EGLint),
459                           destroy_when_signaled,
460                           &sync_handle,
461                           &thread_handle);
462
463    if (type == EGL_SYNC_NATIVE_FENCE_ANDROID && fd_in < 0) {
464        int queue_work_err =
465            goldfish_sync_queue_work(
466                    getEGLThreadInfo()->currentContext->getGoldfishSyncFd(),
467                    sync_handle,
468                    thread_handle,
469                    fd_out);
470
471        DPRINT("got native fence fd=%d queue_work_err=%d",
472               *fd_out, queue_work_err);
473    }
474
475    return sync_handle;
476}
477
478// createGoldfishOpenGLNativeSync() is for creating host-only sync objects
479// that are needed by only this goldfish opengl driver,
480// such as in swapBuffers().
481// The guest will not see any of these, and these sync objects will be
482// destroyed on the host when signaled.
483// A native fence FD is possibly returned.
484static void createGoldfishOpenGLNativeSync(int* fd_out) {
485    createNativeSync(EGL_SYNC_NATIVE_FENCE_ANDROID,
486                     NULL /* empty attrib list */,
487                     0 /* 0 attrib count */,
488                     true /* destroy when signaled. this is host-only
489                             and there will only be one waiter */,
490                     -1 /* we want a new fd */,
491                     fd_out);
492}
493
494EGLBoolean egl_window_surface_t::swapBuffers()
495{
496
497    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
498
499    // Follow up flushWindowColorBuffer with a fence command.
500    // When the fence command finishes,
501    // we're sure that the buffer on the host
502    // has been blitted.
503    //
504    // |presentFenceFd| guards the presentation of the
505    // current frame with a goldfish sync fence fd.
506    //
507    // When |presentFenceFd| is signaled, the recipient
508    // of the buffer that was sent through queueBuffer
509    // can be sure that the buffer is current.
510    //
511    // If we don't take care of this synchronization,
512    // an old frame can be processed by surfaceflinger,
513    // resulting in out of order frames.
514
515    int presentFenceFd = -1;
516
517    if (buffer == NULL) {
518        ALOGE("egl_window_surface_t::swapBuffers called with NULL buffer");
519        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
520    }
521
522#if PLATFORM_SDK_VERSION <= 16
523    rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
524    // equivalent to glFinish if no native sync
525    eglWaitClient();
526    nativeWindow->queueBuffer(nativeWindow, buffer);
527#else
528    if (rcEnc->hasNativeSync()) {
529        rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
530        createGoldfishOpenGLNativeSync(&presentFenceFd);
531    } else {
532        rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
533        // equivalent to glFinish if no native sync
534        eglWaitClient();
535    }
536
537    DPRINT("queueBuffer with fence %d", presentFenceFd);
538    nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
539#endif
540
541    DPRINT("calling dequeueBuffer...");
542
543#if PLATFORM_SDK_VERSION <= 16
544    if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
545        buffer = NULL;
546        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
547    }
548#else
549    int acquireFenceFd = -1;
550    if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &acquireFenceFd)) {
551        buffer = NULL;
552        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
553    }
554
555    DPRINT("dequeueBuffer with fence %d", acquireFenceFd);
556
557    if (acquireFenceFd > 0) {
558        close(acquireFenceFd);
559    }
560#endif
561
562    rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
563            ((cb_handle_t *)(buffer->handle))->hostHandle);
564
565    setWidth(buffer->width);
566    setHeight(buffer->height);
567
568    return EGL_TRUE;
569}
570
571// ----------------------------------------------------------------------------
572//egl_pbuffer_surface_t
573
574struct egl_pbuffer_surface_t : public egl_surface_t {
575    static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
576            EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
577
578    virtual ~egl_pbuffer_surface_t();
579
580    virtual void       setSwapInterval(int interval) { (void)interval; }
581    virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
582
583    uint32_t getRcColorBuffer() { return rcColorBuffer; }
584
585private:
586    egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
587            int32_t w, int32_t h);
588    EGLBoolean init(GLenum format);
589
590    uint32_t rcColorBuffer;
591};
592
593egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
594        EGLint surfType, int32_t w, int32_t h)
595:   egl_surface_t(dpy, config, surfType),
596    rcColorBuffer(0)
597{
598    setWidth(w);
599    setHeight(h);
600}
601
602egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
603{
604    DEFINE_HOST_CONNECTION;
605    if (rcEnc) {
606        if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
607        if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
608    }
609}
610
611// Destroy a pending surface and set it to NULL.
612
613static void s_destroyPendingSurfaceAndSetNull(EGLSurface* surface) {
614    if (!s_display.isSurface(surface)) {
615        *surface = NULL;
616        return;
617    }
618
619    egl_surface_t* surf = static_cast<egl_surface_t *>(*surface);
620    if (surf && surf->deletePending) {
621        delete surf;
622        *surface = NULL;
623    }
624}
625
626static void s_destroyPendingSurfacesInContext(EGLContext_t* context) {
627    if (context->read == context->draw) {
628        // If they are the same, delete it only once
629        s_destroyPendingSurfaceAndSetNull(&context->draw);
630        if (context->draw == NULL) {
631            context->read = NULL;
632        }
633    } else {
634        s_destroyPendingSurfaceAndSetNull(&context->draw);
635        s_destroyPendingSurfaceAndSetNull(&context->read);
636    }
637}
638
639EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
640{
641    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
642
643    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
644            getWidth(), getHeight());
645    if (!rcSurface) {
646        ALOGE("rcCreateWindowSurface returned 0");
647        return EGL_FALSE;
648    }
649
650    rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), pixelFormat);
651    if (!rcColorBuffer) {
652        ALOGE("rcCreateColorBuffer returned 0");
653        return EGL_FALSE;
654    }
655
656    rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
657
658    return EGL_TRUE;
659}
660
661egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
662        EGLConfig config, EGLint surfType, int32_t w, int32_t h,
663        GLenum pixelFormat)
664{
665    egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
666            w, h);
667    if (pb && !pb->init(pixelFormat)) {
668        delete pb;
669        pb = NULL;
670    }
671    return pb;
672}
673
674// Required for Skia.
675static const char kOESEGLImageExternalEssl3[] = "GL_OES_EGL_image_external_essl3";
676
677static bool sWantES30OrAbove(const char* exts) {
678    if (strstr(exts, kGLESMaxVersion_3_0) ||
679        strstr(exts, kGLESMaxVersion_3_1) ||
680        strstr(exts, kGLESMaxVersion_3_2)) {
681        return true;
682    }
683    return false;
684}
685
686static std::vector<std::string> getExtStringArray() {
687    std::vector<std::string> res;
688
689    EGLThreadInfo *tInfo = getEGLThreadInfo();
690    if (!tInfo || !tInfo->currentContext) {
691        return res;
692    }
693
694#define GL_EXTENSIONS                     0x1F03
695
696    DEFINE_AND_VALIDATE_HOST_CONNECTION(res);
697
698    char *hostStr = NULL;
699    int n = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, NULL, 0);
700    if (n < 0) {
701        hostStr = new char[-n+1];
702        n = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, hostStr, -n);
703        if (n <= 0) {
704            delete [] hostStr;
705            hostStr = NULL;
706        }
707    }
708
709    if (!hostStr || !strlen(hostStr)) { return res; }
710
711    // find the number of extensions
712    int extStart = 0;
713    int extEnd = 0;
714    int currentExtIndex = 0;
715    int numExts = 0;
716
717    if (sWantES30OrAbove(hostStr) &&
718        !strstr(hostStr, kOESEGLImageExternalEssl3)) {
719        res.push_back(kOESEGLImageExternalEssl3);
720    }
721
722    while (extEnd < strlen(hostStr)) {
723        if (hostStr[extEnd] == ' ') {
724            int extSz = extEnd - extStart;
725            res.push_back(std::string(hostStr + extStart, extSz));
726            currentExtIndex++;
727            extStart = extEnd + 1;
728        }
729        extEnd++;
730    }
731
732    delete [] hostStr;
733    return res;
734}
735
736static const char *getGLString(int glEnum)
737{
738    EGLThreadInfo *tInfo = getEGLThreadInfo();
739    if (!tInfo || !tInfo->currentContext) {
740        return NULL;
741    }
742
743    const char** strPtr = NULL;
744
745#define GL_VENDOR                         0x1F00
746#define GL_RENDERER                       0x1F01
747#define GL_VERSION                        0x1F02
748#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
749#define GL_EXTENSIONS                     0x1F03
750
751    switch(glEnum) {
752        case GL_VERSION:
753            strPtr = &tInfo->currentContext->versionString;
754            break;
755        case GL_VENDOR:
756            strPtr = &tInfo->currentContext->vendorString;
757            break;
758        case GL_RENDERER:
759            strPtr = &tInfo->currentContext->rendererString;
760            break;
761        case GL_SHADING_LANGUAGE_VERSION:
762            strPtr = &tInfo->currentContext->shaderVersionString;
763            break;
764        case GL_EXTENSIONS:
765            strPtr = &tInfo->currentContext->extensionString;
766            break;
767    }
768
769    if (!strPtr) {
770        return NULL;
771    }
772
773    char* hostStr = NULL;
774
775    if (glEnum == GL_EXTENSIONS) {
776
777        std::vector<std::string> exts = getExtStringArray();
778
779        int totalSz = 1; // null terminator
780        for (int i = 0; i < exts.size(); i++) {
781            totalSz += exts[i].size() + 1; // for space
782        }
783
784        if (totalSz == 1) return NULL;
785
786        hostStr = new char[totalSz];
787        memset(hostStr, 0, totalSz);
788
789        char* current = hostStr;
790        for (int i = 0; i < exts.size(); i++) {
791            memcpy(current, exts[i].c_str(), exts[i].size());
792            current += exts[i].size();
793            *current = ' ';
794            ++current;
795        }
796    } else {
797        //
798        // first query of that string - need to query host
799        //
800        DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
801        int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
802        if (n < 0) {
803            hostStr = new char[-n+1];
804            n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
805            if (n <= 0) {
806                delete [] hostStr;
807                hostStr = NULL;
808            }
809        }
810    }
811
812    //
813    // keep the string in the context and return its value
814    //
815    *strPtr = hostStr;
816    return hostStr;
817}
818
819// ----------------------------------------------------------------------------
820
821static EGLClient_eglInterface s_eglIface = {
822    getThreadInfo: getEGLThreadInfo,
823    getGLString: getGLString,
824};
825
826#define DBG_FUNC DBG("%s\n", __FUNCTION__)
827EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
828{
829    //
830    // we support only EGL_DEFAULT_DISPLAY.
831    //
832    if (display_id != EGL_DEFAULT_DISPLAY) {
833        return EGL_NO_DISPLAY;
834    }
835
836    return (EGLDisplay)&s_display;
837}
838
839EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
840{
841    VALIDATE_DISPLAY(dpy,EGL_FALSE);
842
843    if (!s_display.initialize(&s_eglIface)) {
844        return EGL_FALSE;
845    }
846    if (major!=NULL)
847        *major = s_display.getVersionMajor();
848    if (minor!=NULL)
849        *minor = s_display.getVersionMinor();
850    return EGL_TRUE;
851}
852
853EGLBoolean eglTerminate(EGLDisplay dpy)
854{
855    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
856
857    s_display.terminate();
858    return EGL_TRUE;
859}
860
861EGLint eglGetError()
862{
863    EGLint error = getEGLThreadInfo()->eglError;
864    getEGLThreadInfo()->eglError = EGL_SUCCESS;
865    return error;
866}
867
868__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
869{
870    // search in EGL function table
871    for (int i=0; i<egl_num_funcs; i++) {
872        if (!strcmp(egl_funcs_by_name[i].name, procname)) {
873            return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
874        }
875    }
876
877    // look in gles client api's extensions table
878    return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
879
880    // Fail - function not found.
881    return NULL;
882}
883
884const char* eglQueryString(EGLDisplay dpy, EGLint name)
885{
886    VALIDATE_DISPLAY_INIT(dpy, NULL);
887
888    return s_display.queryString(name);
889}
890
891EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
892{
893    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
894
895    if(!num_config) {
896        RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
897    }
898
899    GLint numConfigs = s_display.getNumConfigs();
900    if (!configs) {
901        *num_config = numConfigs;
902        return EGL_TRUE;
903    }
904
905    EGLint i;
906    for (i = 0 ; i < numConfigs && i < config_size ; i++) {
907        *configs++ = (EGLConfig)(uintptr_t)i;
908    }
909    *num_config = i;
910    return EGL_TRUE;
911}
912
913EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
914{
915    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
916
917    if (!num_config) {
918        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
919    }
920
921    int attribs_size = 0;
922    if (attrib_list) {
923        const EGLint * attrib_p = attrib_list;
924        while (attrib_p[0] != EGL_NONE) {
925            attribs_size += 2;
926            attrib_p += 2;
927        }
928        attribs_size++; //for the terminating EGL_NONE
929    }
930
931    // API 19 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
932    // while the host never supports it.
933    // We remove the bit here.
934    EGLint* local_attrib_list = NULL;
935    if (PLATFORM_SDK_VERSION <= 19) {
936        local_attrib_list = new EGLint[attribs_size];
937        memcpy(local_attrib_list, attrib_list, attribs_size * sizeof(EGLint));
938        EGLint* local_attrib_p = local_attrib_list;
939        while (local_attrib_p[0] != EGL_NONE) {
940            if (local_attrib_p[0] == EGL_SURFACE_TYPE) {
941                local_attrib_p[1] &= ~(EGLint)EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
942            }
943            local_attrib_p += 2;
944        }
945    }
946
947    uint32_t* tempConfigs[config_size];
948    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
949    *num_config = rcEnc->rcChooseConfig(rcEnc,
950            local_attrib_list ? local_attrib_list:(EGLint*)attrib_list,
951            attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
952
953    if (local_attrib_list) delete [] local_attrib_list;
954    if (*num_config <= 0) {
955        EGLint err = -(*num_config);
956        *num_config = 0;
957        switch (err) {
958            case EGL_BAD_ATTRIBUTE:
959                setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
960            default:
961                return EGL_FALSE;
962        }
963    }
964
965    if (configs!=NULL) {
966        EGLint i=0;
967        for (i=0;i<(*num_config);i++) {
968             *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
969        }
970    }
971
972    return EGL_TRUE;
973}
974
975EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
976{
977    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
978    VALIDATE_CONFIG(config, EGL_FALSE);
979
980    if (s_display.getConfigAttrib(config, attribute, value))
981    {
982        return EGL_TRUE;
983    }
984    else
985    {
986        ALOGD("%s: bad attrib 0x%x", __FUNCTION__, attribute);
987        RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
988    }
989}
990
991EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
992{
993    (void)attrib_list;
994
995    VALIDATE_DISPLAY_INIT(dpy, NULL);
996    VALIDATE_CONFIG(config, EGL_FALSE);
997    if (win == 0) {
998        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
999    }
1000
1001    EGLint surfaceType;
1002    if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
1003
1004    if (!(surfaceType & EGL_WINDOW_BIT)) {
1005        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
1006    }
1007
1008    if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
1009        setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
1010    }
1011
1012    egl_surface_t* surface = egl_window_surface_t::create(
1013            &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
1014    if (!surface) {
1015        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
1016    }
1017
1018    return surface;
1019}
1020
1021EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
1022{
1023    VALIDATE_DISPLAY_INIT(dpy, NULL);
1024    VALIDATE_CONFIG(config, EGL_FALSE);
1025
1026    EGLint surfaceType;
1027    if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
1028
1029    if (!(surfaceType & EGL_PBUFFER_BIT)) {
1030        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
1031    }
1032
1033    int32_t w = 0;
1034    int32_t h = 0;
1035    EGLint texFormat = EGL_NO_TEXTURE;
1036    EGLint texTarget = EGL_NO_TEXTURE;
1037    while (attrib_list[0] != EGL_NONE) {
1038        switch (attrib_list[0]) {
1039            case EGL_WIDTH:
1040                w = attrib_list[1];
1041                if (w < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1042                break;
1043            case EGL_HEIGHT:
1044                h = attrib_list[1];
1045                if (h < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1046                break;
1047            case EGL_TEXTURE_FORMAT:
1048                texFormat = attrib_list[1];
1049                break;
1050            case EGL_TEXTURE_TARGET:
1051                texTarget = attrib_list[1];
1052                break;
1053            // the followings are not supported
1054            case EGL_LARGEST_PBUFFER:
1055            case EGL_MIPMAP_TEXTURE:
1056            case EGL_VG_ALPHA_FORMAT:
1057            case EGL_VG_COLORSPACE:
1058                break;
1059            default:
1060                setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
1061        };
1062        attrib_list+=2;
1063    }
1064    if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
1065        ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
1066        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
1067    }
1068    // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
1069
1070    GLenum pixelFormat;
1071    if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
1072        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
1073
1074    egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
1075            EGL_PBUFFER_BIT, w, h, pixelFormat);
1076    if (!surface) {
1077        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
1078    }
1079
1080    //setup attributes
1081    surface->setTextureFormat(texFormat);
1082    surface->setTextureTarget(texTarget);
1083
1084    return surface;
1085}
1086
1087EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
1088{
1089    //XXX: Pixmap not supported. The host cannot render to a pixmap resource
1090    //     located on host. In order to support Pixmaps we should either punt
1091    //     to s/w rendering -or- let the host render to a buffer that will be
1092    //     copied back to guest at some sync point. None of those methods not
1093    //     implemented and pixmaps are not used with OpenGL anyway ...
1094    VALIDATE_CONFIG(config, EGL_FALSE);
1095    (void)dpy;
1096    (void)pixmap;
1097    (void)attrib_list;
1098    return EGL_NO_SURFACE;
1099}
1100
1101EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
1102{
1103    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1104    VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1105
1106    EGLThreadInfo* tInfo = getEGLThreadInfo();
1107    egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
1108    if (surface->isCurrent()) {
1109        surface->deletePending = 1;
1110    } else {
1111        delete surface;
1112    }
1113
1114    return EGL_TRUE;
1115}
1116
1117static float s_getNativeDpi() {
1118    float nativeDPI = 560.0f;
1119    const char* dpiPropName = "qemu.sf.lcd_density";
1120    char dpiProp[PROPERTY_VALUE_MAX];
1121    if (property_get(dpiPropName, dpiProp, NULL) > 0) {
1122        nativeDPI = atof(dpiProp);
1123    }
1124    return nativeDPI;
1125}
1126
1127EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
1128{
1129    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1130    VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1131
1132    egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1133
1134    // Parameters involved in queries of EGL_(HORIZONTAL|VERTICAL)_RESOLUTION
1135    float currWidth, currHeight, scaledResolution, effectiveSurfaceDPI;
1136    EGLBoolean ret = EGL_TRUE;
1137    switch (attribute) {
1138        case EGL_CONFIG_ID:
1139            ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
1140            break;
1141        case EGL_WIDTH:
1142            *value = surface->getWidth();
1143            break;
1144        case EGL_HEIGHT:
1145            *value = surface->getHeight();
1146            break;
1147        case EGL_TEXTURE_FORMAT:
1148            if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
1149                *value = surface->getTextureFormat();
1150            }
1151            break;
1152        case EGL_TEXTURE_TARGET:
1153            if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
1154                *value = surface->getTextureTarget();
1155            }
1156            break;
1157        case EGL_SWAP_BEHAVIOR:
1158        {
1159            EGLint surfaceType;
1160            ret = s_display.getConfigAttrib(surface->config, EGL_SURFACE_TYPE,
1161                    &surfaceType);
1162            if (ret == EGL_TRUE) {
1163                if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
1164                    *value = EGL_BUFFER_PRESERVED;
1165                } else {
1166                    *value = EGL_BUFFER_DESTROYED;
1167                }
1168            }
1169            break;
1170        }
1171        case EGL_LARGEST_PBUFFER:
1172            // not modified for a window or pixmap surface
1173            // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
1174            if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
1175            break;
1176        case EGL_MIPMAP_TEXTURE:
1177            // not modified for a window or pixmap surface
1178            // and we ignore it when creating a PBuffer surface (default is 0)
1179            if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = false;
1180            break;
1181        case EGL_MIPMAP_LEVEL:
1182            // not modified for a window or pixmap surface
1183            // and we ignore it when creating a PBuffer surface (default is 0)
1184            if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
1185            break;
1186        case EGL_MULTISAMPLE_RESOLVE:
1187            // ignored when creating the surface, return default
1188            *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
1189            break;
1190        case EGL_HORIZONTAL_RESOLUTION:
1191            // pixel/mm * EGL_DISPLAY_SCALING
1192            // TODO: get the DPI from avd config
1193            currWidth = surface->getWidth();
1194            scaledResolution = currWidth / surface->getNativeWidth();
1195            effectiveSurfaceDPI =
1196                scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
1197            *value = (EGLint)(effectiveSurfaceDPI);
1198            break;
1199        case EGL_VERTICAL_RESOLUTION:
1200            // pixel/mm * EGL_DISPLAY_SCALING
1201            // TODO: get the real DPI from avd config
1202            currHeight = surface->getHeight();
1203            scaledResolution = currHeight / surface->getNativeHeight();
1204            effectiveSurfaceDPI =
1205                scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
1206            *value = (EGLint)(effectiveSurfaceDPI);
1207            break;
1208        case EGL_PIXEL_ASPECT_RATIO:
1209            // w / h * EGL_DISPLAY_SCALING
1210            // Please don't ask why * EGL_DISPLAY_SCALING, the document says it
1211            *value = 1 * EGL_DISPLAY_SCALING;
1212            break;
1213        case EGL_RENDER_BUFFER:
1214            switch (surface->getSurfaceType()) {
1215                case EGL_PBUFFER_BIT:
1216                    *value = EGL_BACK_BUFFER;
1217                    break;
1218                case EGL_PIXMAP_BIT:
1219                    *value = EGL_SINGLE_BUFFER;
1220                    break;
1221                case EGL_WINDOW_BIT:
1222                    // ignored when creating the surface, return default
1223                    *value = EGL_BACK_BUFFER;
1224                    break;
1225                default:
1226                    ALOGE("eglQuerySurface %x unknown surface type %x",
1227                            attribute, surface->getSurfaceType());
1228                    ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1229                    break;
1230            }
1231            break;
1232        case EGL_VG_COLORSPACE:
1233            // ignored when creating the surface, return default
1234            *value = EGL_VG_COLORSPACE_sRGB;
1235            break;
1236        case EGL_VG_ALPHA_FORMAT:
1237            // ignored when creating the surface, return default
1238            *value = EGL_VG_ALPHA_FORMAT_NONPRE;
1239            break;
1240        case EGL_TIMESTAMPS_ANDROID:
1241            *value = surface->isCollectingTimestamps();
1242            break;
1243        //TODO: complete other attributes
1244        default:
1245            ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
1246            ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1247            break;
1248    }
1249
1250    return ret;
1251}
1252
1253EGLBoolean eglBindAPI(EGLenum api)
1254{
1255    if (api != EGL_OPENGL_ES_API)
1256        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1257    return EGL_TRUE;
1258}
1259
1260EGLenum eglQueryAPI()
1261{
1262    return EGL_OPENGL_ES_API;
1263}
1264
1265EGLBoolean eglWaitClient()
1266{
1267    return eglWaitGL();
1268}
1269
1270// We may need to trigger this directly from the TLS destructor.
1271static EGLBoolean s_eglReleaseThreadImpl(EGLThreadInfo* tInfo) {
1272    if (!tInfo) return EGL_TRUE;
1273
1274    tInfo->eglError = EGL_SUCCESS;
1275    EGLContext_t* context = tInfo->currentContext;
1276
1277    if (!context || !s_display.isContext(context)) return EGL_TRUE;
1278
1279    // The following code is doing pretty much the same thing as
1280    // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
1281    // with the only issue that we do not require a valid display here.
1282    DEFINE_AND_VALIDATE_HOST_CONNECTION_FOR_TLS(EGL_FALSE, tInfo);
1283    // We are going to call makeCurrent on the null context and surface
1284    // anyway once we are on the host, so skip rcMakeCurrent here.
1285    // rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
1286    context->flags &= ~EGLContext_t::IS_CURRENT;
1287
1288    s_destroyPendingSurfacesInContext(context);
1289
1290    if (context->deletePending) {
1291        if (context->rcContext) {
1292            rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1293            context->rcContext = 0;
1294        }
1295        delete context;
1296    }
1297    tInfo->currentContext = 0;
1298
1299    return EGL_TRUE;
1300}
1301
1302EGLBoolean eglReleaseThread()
1303{
1304    return s_eglReleaseThreadImpl(getEGLThreadInfo());
1305}
1306
1307EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
1308{
1309    //TODO
1310    (void)dpy;
1311    (void)buftype;
1312    (void)buffer;
1313    (void)config;
1314    (void)attrib_list;
1315    ALOGW("%s not implemented", __FUNCTION__);
1316    return 0;
1317}
1318
1319EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1320{
1321    // Right now we don't do anything when using host GPU.
1322    // This is purely just to pass the data through
1323    // without issuing a warning. We may benefit from validating the
1324    // display and surface for debug purposes.
1325    // TODO: Find cases where we actually need to do something.
1326    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1327    VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
1328    if (surface == EGL_NO_SURFACE) {
1329        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1330    }
1331
1332    (void)value;
1333
1334    egl_surface_t* p_surface( static_cast<egl_surface_t*>(surface) );
1335    switch (attribute) {
1336    case EGL_MIPMAP_LEVEL:
1337        return true;
1338    case EGL_MULTISAMPLE_RESOLVE:
1339    {
1340        if (value == EGL_MULTISAMPLE_RESOLVE_BOX) {
1341            EGLint surface_type;
1342            s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1343            if (0 == (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) {
1344                setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1345            }
1346        }
1347        return true;
1348    }
1349    case EGL_SWAP_BEHAVIOR:
1350        if (value == EGL_BUFFER_PRESERVED) {
1351            EGLint surface_type;
1352            s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1353            if (0 == (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) {
1354                setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1355            }
1356        }
1357        return true;
1358    case EGL_TIMESTAMPS_ANDROID:
1359        ALOGD("%s: set frame timestamps collecting %d\n", __func__, value);
1360        p_surface->setCollectingTimestamps(value);
1361        return true;
1362    default:
1363        ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
1364        setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1365    }
1366    return false;
1367}
1368
1369EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
1370{
1371    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1372    VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1373    if (eglSurface == EGL_NO_SURFACE) {
1374        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1375    }
1376
1377    if (buffer != EGL_BACK_BUFFER) {
1378        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1379    }
1380
1381    egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1382
1383    if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
1384        setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1385    }
1386
1387    if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
1388        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1389    }
1390
1391    //It's now safe to cast to pbuffer surface
1392    egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
1393
1394    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1395    rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
1396
1397    return GL_TRUE;
1398}
1399
1400EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1401{
1402    //TODO
1403    (void)dpy;
1404    (void)surface;
1405    (void)buffer;
1406    ALOGW("%s not implemented", __FUNCTION__);
1407    return 0;
1408}
1409
1410EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1411{
1412    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1413    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1414
1415    EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
1416    if (!ctx) {
1417        setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1418    }
1419    if (!ctx->draw) {
1420        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1421    }
1422    egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
1423    draw->setSwapInterval(interval);
1424
1425    rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
1426
1427    return EGL_TRUE;
1428}
1429
1430EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
1431{
1432    VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
1433    VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
1434
1435    EGLint majorVersion = 1; //default
1436    EGLint minorVersion = 0;
1437    EGLint context_flags = 0;
1438    EGLint profile_mask = 0;
1439    EGLint reset_notification_strategy = 0;
1440
1441    bool wantedMajorVersion = false;
1442    bool wantedMinorVersion = false;
1443
1444    while (attrib_list && attrib_list[0] != EGL_NONE) {
1445           EGLint attrib_val = attrib_list[1];
1446        switch(attrib_list[0]) {
1447        case EGL_CONTEXT_MAJOR_VERSION_KHR:
1448            majorVersion = attrib_val;
1449            wantedMajorVersion = true;
1450            break;
1451        case EGL_CONTEXT_MINOR_VERSION_KHR:
1452            minorVersion = attrib_val;
1453            wantedMinorVersion = true;
1454            break;
1455        case EGL_CONTEXT_FLAGS_KHR:
1456            if ((attrib_val | EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) ||
1457                (attrib_val | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)  ||
1458                (attrib_val | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
1459                context_flags = attrib_val;
1460            } else {
1461                RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
1462            }
1463            break;
1464        case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
1465            if ((attrib_val | EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) ||
1466                (attrib_val | EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR)) {
1467                profile_mask = attrib_val;
1468            } else {
1469                RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
1470            }
1471            break;
1472        case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
1473            // According to the spec, we are allowed not to honor this hint.
1474            // https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt
1475            break;
1476        default:
1477            ALOGV("eglCreateContext unsupported attrib 0x%x", attrib_list[0]);
1478            setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
1479        }
1480        attrib_list+=2;
1481    }
1482
1483    // Support up to GLES 3.2 depending on advertised version from the host system.
1484    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
1485    if (rcEnc->getGLESMaxVersion() >= GLES_MAX_VERSION_3_0) {
1486        if (!wantedMajorVersion) {
1487            majorVersion = 1;
1488            wantedMinorVersion = false;
1489        }
1490
1491        if (wantedMajorVersion &&
1492            majorVersion == 2) {
1493            majorVersion = 3;
1494            wantedMinorVersion = false;
1495        }
1496
1497        if (majorVersion == 3 && !wantedMinorVersion) {
1498            switch (rcEnc->getGLESMaxVersion()) {
1499                case GLES_MAX_VERSION_3_0:
1500                    minorVersion = 0;
1501                    break;
1502                case GLES_MAX_VERSION_3_1:
1503                    minorVersion = 1;
1504                    break;
1505                case GLES_MAX_VERSION_3_2:
1506                    minorVersion = 2;
1507                    break;
1508                default:
1509                    minorVersion = 0;
1510                    break;
1511            }
1512        }
1513    } else {
1514        if (!wantedMajorVersion) {
1515            majorVersion = 1;
1516        }
1517    }
1518
1519    switch (majorVersion) {
1520    case 1:
1521    case 2:
1522        break;
1523    case 3:
1524        if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_0) {
1525            ALOGE("%s: EGL_BAD_CONFIG: no ES 3 support", __FUNCTION__);
1526            setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1527        }
1528        switch (minorVersion) {
1529            case 0:
1530                break;
1531            case 1:
1532                if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_1) {
1533                    ALOGE("%s: EGL_BAD_CONFIG: no ES 3.1 support", __FUNCTION__);
1534                    setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1535                }
1536                break;
1537            case 2:
1538                if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_2) {
1539                    ALOGE("%s: EGL_BAD_CONFIG: no ES 3.2 support", __FUNCTION__);
1540                    setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1541                }
1542                break;
1543            default:
1544                ALOGE("%s: EGL_BAD_CONFIG: Unknown ES version %d.%d",
1545                      __FUNCTION__, majorVersion, minorVersion);
1546                setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1547        }
1548        break;
1549    default:
1550        setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1551    }
1552
1553    uint32_t rcShareCtx = 0;
1554    EGLContext_t * shareCtx = NULL;
1555    if (share_context) {
1556        shareCtx = static_cast<EGLContext_t*>(share_context);
1557        rcShareCtx = shareCtx->rcContext;
1558        if (shareCtx->dpy != dpy)
1559            setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
1560    }
1561
1562    // We've created EGL context. Disconnecting
1563    // would be dangerous at this point.
1564    hostCon->setGrallocOnly(false);
1565
1566    int rcMajorVersion = majorVersion;
1567    if (majorVersion == 3 && minorVersion == 1) {
1568        rcMajorVersion = 4;
1569    }
1570    if (majorVersion == 3 && minorVersion == 2) {
1571        rcMajorVersion = 4;
1572    }
1573    uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, rcMajorVersion);
1574    if (!rcContext) {
1575        ALOGE("rcCreateContext returned 0");
1576        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1577    }
1578
1579    EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx, majorVersion, minorVersion);
1580    ALOGD("%s: %p: maj %d min %d rcv %d", __FUNCTION__, context, majorVersion, minorVersion, rcMajorVersion);
1581    if (!context) {
1582        ALOGE("could not alloc egl context!");
1583        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1584    }
1585
1586    context->rcContext = rcContext;
1587    return context;
1588}
1589
1590EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1591{
1592    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1593    VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1594
1595    EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1596
1597    if (context->flags & EGLContext_t::IS_CURRENT) {
1598        context->deletePending = 1;
1599        return EGL_TRUE;
1600    }
1601
1602    if (context->rcContext) {
1603        DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1604        rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1605        context->rcContext = 0;
1606    }
1607
1608    delete context;
1609    return EGL_TRUE;
1610}
1611
1612EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1613{
1614    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1615    VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1616    VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1617
1618    // Only place to initialize the TLS destructor; any
1619    // thread can suddenly jump in any eglMakeCurrent
1620    setTlsDestructor((tlsDtorCallback)s_eglReleaseThreadImpl);
1621
1622    if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1623        setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1624    if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1625        setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1626
1627    EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1628    uint32_t ctxHandle = (context) ? context->rcContext : 0;
1629    egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1630    uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1631    egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1632    uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1633
1634    //
1635    // Nothing to do if no binding change has made
1636    //
1637    EGLThreadInfo *tInfo = getEGLThreadInfo();
1638
1639    if (tInfo->currentContext == context &&
1640        (context == NULL ||
1641        (context && (context->draw == draw) && (context->read == read)))) {
1642        return EGL_TRUE;
1643    }
1644
1645    if (tInfo->currentContext) {
1646        EGLContext_t* prevCtx = tInfo->currentContext;
1647
1648        if (prevCtx->draw) {
1649            static_cast<egl_surface_t *>(prevCtx->draw)->setIsCurrent(false);
1650        }
1651        if (prevCtx->read) {
1652            static_cast<egl_surface_t *>(prevCtx->read)->setIsCurrent(false);
1653        }
1654        s_destroyPendingSurfacesInContext(tInfo->currentContext);
1655
1656        if (prevCtx->deletePending && prevCtx != context) {
1657            tInfo->currentContext = 0;
1658            eglDestroyContext(dpy, prevCtx);
1659        }
1660    }
1661
1662    if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1663        // context is current to another thread
1664        ALOGE("%s: error: EGL_BAD_ACCESS: context %p current to another thread!\n", __FUNCTION__, context);
1665        setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1666    }
1667
1668    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1669    if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1670        ALOGE("rcMakeCurrent returned EGL_FALSE");
1671        setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1672    }
1673
1674    //Now make the local bind
1675    if (context) {
1676
1677        ALOGD("%s: %p: ver %d %d (tinfo %p)", __FUNCTION__, context, context->majorVersion, context->minorVersion, tInfo);
1678        // This is a nontrivial context.
1679        // The thread cannot be gralloc-only anymore.
1680        hostCon->setGrallocOnly(false);
1681        context->draw = draw;
1682        context->read = read;
1683        if (drawSurf) {
1684            drawSurf->setIsCurrent(true);
1685        }
1686        if (readSurf) {
1687            readSurf->setIsCurrent(true);
1688        }
1689        context->flags |= EGLContext_t::IS_CURRENT;
1690        GLClientState* contextState =
1691            context->getClientState();
1692
1693        if (!hostCon->gl2Encoder()->isInitialized()) {
1694            s_display.gles2_iface()->init();
1695            hostCon->gl2Encoder()->setInitialized();
1696            ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1697        }
1698        if (contextState->needsInitFromCaps()) {
1699            // Need to set the version first if
1700            // querying caps, or validation will trip incorrectly.
1701            hostCon->gl2Encoder()->setVersion(
1702                context->majorVersion,
1703                context->minorVersion,
1704                context->deviceMajorVersion,
1705                context->deviceMinorVersion);
1706            // Get caps for indexed buffers from host.
1707            // Some need a current context.
1708            int max_transform_feedback_separate_attribs = 0;
1709            int max_uniform_buffer_bindings = 0;
1710            int max_atomic_counter_buffer_bindings = 0;
1711            int max_shader_storage_buffer_bindings = 0;
1712            int max_vertex_attrib_bindings = 0;
1713            int max_color_attachments = 1;
1714            int max_draw_buffers = 1;
1715            if (context->majorVersion > 2) {
1716                s_display.gles2_iface()->getIntegerv(
1717                        GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);
1718                s_display.gles2_iface()->getIntegerv(
1719                        GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_uniform_buffer_bindings);
1720                if (context->minorVersion > 0) {
1721                    s_display.gles2_iface()->getIntegerv(
1722                            GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &max_atomic_counter_buffer_bindings);
1723                    s_display.gles2_iface()->getIntegerv(
1724                            GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &max_shader_storage_buffer_bindings);
1725                    s_display.gles2_iface()->getIntegerv(
1726                            GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_vertex_attrib_bindings);
1727                }
1728                s_display.gles2_iface()->getIntegerv(
1729                        GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
1730                s_display.gles2_iface()->getIntegerv(
1731                        GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
1732            }
1733            contextState->initFromCaps(
1734                    max_transform_feedback_separate_attribs,
1735                    max_uniform_buffer_bindings,
1736                    max_atomic_counter_buffer_bindings,
1737                    max_shader_storage_buffer_bindings,
1738                    max_vertex_attrib_bindings,
1739                    max_color_attachments,
1740                    max_draw_buffers);
1741        }
1742
1743        // update the client state, share group, and version
1744        if (context->majorVersion > 1) {
1745            hostCon->gl2Encoder()->setClientStateMakeCurrent(
1746                    contextState,
1747                    context->majorVersion,
1748                    context->minorVersion,
1749                    context->deviceMajorVersion,
1750                    context->deviceMinorVersion);
1751            hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1752        }
1753        else {
1754            hostCon->glEncoder()->setClientState(context->getClientState());
1755            hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1756        }
1757    }
1758    else if (tInfo->currentContext) {
1759        //release ClientState & SharedGroup
1760        if (tInfo->currentContext->majorVersion > 1) {
1761            hostCon->gl2Encoder()->setClientState(NULL);
1762            hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1763        }
1764        else {
1765            hostCon->glEncoder()->setClientState(NULL);
1766            hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1767        }
1768
1769    }
1770
1771    if (tInfo->currentContext && (tInfo->currentContext != context)) {
1772        tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1773    }
1774
1775    //Now make current
1776    tInfo->currentContext = context;
1777
1778    //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1779    if (tInfo->currentContext) {
1780        if (tInfo->currentContext->majorVersion  > 1) {
1781            if (!hostCon->gl2Encoder()->isInitialized()) {
1782                s_display.gles2_iface()->init();
1783                hostCon->gl2Encoder()->setInitialized();
1784                ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1785            }
1786            const char* exts = getGLString(GL_EXTENSIONS);
1787            if (exts) {
1788                hostCon->gl2Encoder()->setExtensions(exts, getExtStringArray());
1789            }
1790        }
1791        else {
1792            if (!hostCon->glEncoder()->isInitialized()) {
1793                s_display.gles_iface()->init();
1794                hostCon->glEncoder()->setInitialized();
1795                ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1796            }
1797        }
1798    }
1799
1800    return EGL_TRUE;
1801}
1802
1803EGLContext eglGetCurrentContext()
1804{
1805    return getEGLThreadInfo()->currentContext;
1806}
1807
1808EGLSurface eglGetCurrentSurface(EGLint readdraw)
1809{
1810    EGLContext_t * context = getEGLThreadInfo()->currentContext;
1811    if (!context)
1812        return EGL_NO_SURFACE; //not an error
1813
1814    switch (readdraw) {
1815        case EGL_READ:
1816            return context->read;
1817        case EGL_DRAW:
1818            return context->draw;
1819        default:
1820            setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1821    }
1822}
1823
1824EGLDisplay eglGetCurrentDisplay()
1825{
1826    EGLContext_t * context = getEGLThreadInfo()->currentContext;
1827    if (!context)
1828        return EGL_NO_DISPLAY; //not an error
1829
1830    return context->dpy;
1831}
1832
1833EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1834{
1835    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1836    VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1837
1838    EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1839
1840    EGLBoolean ret = EGL_TRUE;
1841    switch (attribute) {
1842        case EGL_CONFIG_ID:
1843            ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1844            break;
1845        case EGL_CONTEXT_CLIENT_TYPE:
1846            *value = EGL_OPENGL_ES_API;
1847            break;
1848        case EGL_CONTEXT_CLIENT_VERSION:
1849            *value = context->majorVersion;
1850            break;
1851        case EGL_RENDER_BUFFER:
1852            if (!context->draw)
1853                *value = EGL_NONE;
1854            else
1855                *value = EGL_BACK_BUFFER; //single buffer not supported
1856            break;
1857        default:
1858            ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
1859            setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1860            break;
1861    }
1862
1863    return ret;
1864}
1865
1866EGLBoolean eglWaitGL()
1867{
1868    EGLThreadInfo *tInfo = getEGLThreadInfo();
1869    if (!tInfo || !tInfo->currentContext) {
1870        return EGL_FALSE;
1871    }
1872
1873    if (tInfo->currentContext->majorVersion > 1) {
1874        s_display.gles2_iface()->finish();
1875    }
1876    else {
1877        s_display.gles_iface()->finish();
1878    }
1879
1880    return EGL_TRUE;
1881}
1882
1883EGLBoolean eglWaitNative(EGLint engine)
1884{
1885    (void)engine;
1886    return EGL_TRUE;
1887}
1888
1889EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1890{
1891    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1892    if (eglSurface == EGL_NO_SURFACE)
1893        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1894
1895    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1896
1897    egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1898    if (d->dpy != dpy)
1899        setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1900
1901    // post the surface
1902    EGLBoolean ret = d->swapBuffers();
1903
1904    hostCon->flush();
1905    return ret;
1906}
1907
1908EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1909{
1910    //TODO :later
1911    (void)dpy;
1912    (void)surface;
1913    (void)target;
1914    return 0;
1915}
1916
1917EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1918{
1919    //TODO later
1920    (void)display;
1921    (void)surface;
1922    (void)attrib_list;
1923    return 0;
1924}
1925
1926EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1927{
1928    //TODO later
1929    (void)display;
1930    (void)surface;
1931    return 0;
1932}
1933
1934EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1935{
1936    (void)attrib_list;
1937
1938    VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1939
1940    if (target == EGL_NATIVE_BUFFER_ANDROID) {
1941        if (ctx != EGL_NO_CONTEXT) {
1942            setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1943        }
1944
1945        android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1946
1947        if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1948            setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1949
1950        if (native_buffer->common.version != sizeof(android_native_buffer_t))
1951            setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1952
1953        cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1954
1955        switch (cb->format) {
1956            case HAL_PIXEL_FORMAT_RGBA_8888:
1957            case HAL_PIXEL_FORMAT_RGBX_8888:
1958            case HAL_PIXEL_FORMAT_RGB_888:
1959            case HAL_PIXEL_FORMAT_RGB_565:
1960            case HAL_PIXEL_FORMAT_YV12:
1961            case HAL_PIXEL_FORMAT_BGRA_8888:
1962            case HAL_PIXEL_FORMAT_RGBA_FP16:
1963            case HAL_PIXEL_FORMAT_RGBA_1010102:
1964                break;
1965            default:
1966                setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1967        }
1968
1969        native_buffer->common.incRef(&native_buffer->common);
1970
1971        EGLImage_t *image = new EGLImage_t();
1972        image->dpy = dpy;
1973        image->target = target;
1974        image->native_buffer = native_buffer;
1975
1976        return (EGLImageKHR)image;
1977    }
1978    else if (target == EGL_GL_TEXTURE_2D_KHR) {
1979        VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1980
1981        EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1982        DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1983
1984        uint32_t ctxHandle = (context) ? context->rcContext : 0;
1985        GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1986        uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1987        EGLImage_t *image = new EGLImage_t();
1988        image->dpy = dpy;
1989        image->target = target;
1990        image->host_egl_image = img;
1991
1992        return (EGLImageKHR)image;
1993    }
1994
1995    setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1996}
1997
1998EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1999{
2000    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
2001    EGLImage_t *image = (EGLImage_t*)img;
2002
2003    if (!image || image->dpy != dpy) {
2004        RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
2005    }
2006
2007    if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
2008        android_native_buffer_t* native_buffer = image->native_buffer;
2009
2010        if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2011            setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
2012
2013        if (native_buffer->common.version != sizeof(android_native_buffer_t))
2014            setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
2015
2016        native_buffer->common.decRef(&native_buffer->common);
2017        delete image;
2018
2019        return EGL_TRUE;
2020    }
2021    else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
2022        uint32_t host_egl_image = image->host_egl_image;
2023        delete image;
2024        DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
2025        return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
2026    }
2027
2028    setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
2029}
2030
2031#define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
2032#define MAX_EGL_SYNC_ATTRIBS 10
2033
2034EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
2035        const EGLint *attrib_list)
2036{
2037    VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
2038    DPRINT("type for eglCreateSyncKHR: 0x%x", type);
2039
2040    DEFINE_HOST_CONNECTION;
2041
2042    if ((type != EGL_SYNC_FENCE_KHR &&
2043         type != EGL_SYNC_NATIVE_FENCE_ANDROID) ||
2044        (type != EGL_SYNC_FENCE_KHR &&
2045         !rcEnc->hasNativeSync())) {
2046        setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
2047    }
2048
2049    EGLThreadInfo *tInfo = getEGLThreadInfo();
2050    if (!tInfo || !tInfo->currentContext) {
2051        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
2052    }
2053
2054    int num_actual_attribs = 0;
2055
2056    // If attrib_list is not NULL,
2057    // ensure attrib_list contains (key, value) pairs
2058    // followed by a single EGL_NONE.
2059    // Also validate attribs.
2060    int inputFenceFd = -1;
2061    if (attrib_list) {
2062        for (int i = 0; i < MAX_EGL_SYNC_ATTRIBS; i += 2) {
2063            if (attrib_list[i] == EGL_NONE) {
2064                num_actual_attribs = i;
2065                break;
2066            }
2067            if (i + 1 == MAX_EGL_SYNC_ATTRIBS) {
2068                DPRINT("ERROR: attrib list without EGL_NONE");
2069                setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
2070            }
2071        }
2072
2073        // Validate and input attribs
2074        for (int i = 0; i < num_actual_attribs; i += 2) {
2075            if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
2076                DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
2077            }
2078            if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
2079                DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
2080            }
2081            if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
2082                DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
2083            }
2084            EGLint attrib_key = attrib_list[i];
2085            EGLint attrib_val = attrib_list[i + 1];
2086            if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
2087                if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
2088                    inputFenceFd = attrib_val;
2089                }
2090            }
2091            DPRINT("attrib: 0x%x : 0x%x", attrib_key, attrib_val);
2092        }
2093    }
2094
2095    uint64_t sync_handle = 0;
2096    int newFenceFd = -1;
2097
2098    if (rcEnc->hasNativeSync()) {
2099        sync_handle =
2100            createNativeSync(type, attrib_list, num_actual_attribs,
2101                             false /* don't destroy when signaled on the host;
2102                                      let the guest clean this up,
2103                                      because the guest called eglCreateSyncKHR. */,
2104                             inputFenceFd,
2105                             &newFenceFd);
2106
2107    } else {
2108        // Just trigger a glFinish if the native sync on host
2109        // is unavailable.
2110        eglWaitClient();
2111    }
2112
2113    EGLSync_t* syncRes = new EGLSync_t(sync_handle);
2114
2115    if (type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
2116        syncRes->type = EGL_SYNC_NATIVE_FENCE_ANDROID;
2117
2118        if (inputFenceFd < 0) {
2119            syncRes->android_native_fence_fd = newFenceFd;
2120        } else {
2121            DPRINT("has input fence fd %d",
2122                    inputFenceFd);
2123            syncRes->android_native_fence_fd = inputFenceFd;
2124        }
2125    } else {
2126        syncRes->type = EGL_SYNC_FENCE_KHR;
2127        syncRes->android_native_fence_fd = -1;
2128        if (!rcEnc->hasNativeSync()) {
2129            syncRes->status = EGL_SIGNALED_KHR;
2130        }
2131    }
2132
2133    return (EGLSyncKHR)syncRes;
2134}
2135
2136EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync)
2137{
2138    (void)dpy;
2139
2140    if (!eglsync) {
2141        DPRINT("WARNING: null sync object")
2142        return EGL_TRUE;
2143    }
2144
2145    EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
2146
2147    if (sync && sync->android_native_fence_fd > 0) {
2148        close(sync->android_native_fence_fd);
2149        sync->android_native_fence_fd = -1;
2150    }
2151
2152    if (sync) {
2153        DEFINE_HOST_CONNECTION;
2154        if (rcEnc->hasNativeSync()) {
2155            rcEnc->rcDestroySyncKHR(rcEnc, sync->handle);
2156        }
2157        delete sync;
2158    }
2159
2160    return EGL_TRUE;
2161}
2162
2163EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags,
2164        EGLTimeKHR timeout)
2165{
2166    (void)dpy;
2167
2168    if (!eglsync) {
2169        DPRINT("WARNING: null sync object");
2170        return EGL_CONDITION_SATISFIED_KHR;
2171    }
2172
2173    EGLSync_t* sync = (EGLSync_t*)eglsync;
2174
2175    DPRINT("sync=0x%lx (handle=0x%lx) flags=0x%x timeout=0x%llx",
2176           sync, sync->handle, flags, timeout);
2177
2178    DEFINE_HOST_CONNECTION;
2179
2180    EGLint retval;
2181    if (rcEnc->hasNativeSync()) {
2182        retval = rcEnc->rcClientWaitSyncKHR
2183            (rcEnc, sync->handle, flags, timeout);
2184    } else {
2185        retval = EGL_CONDITION_SATISFIED_KHR;
2186    }
2187    EGLint res_status;
2188    switch (sync->type) {
2189        case EGL_SYNC_FENCE_KHR:
2190            res_status = EGL_SIGNALED_KHR;
2191            break;
2192        case EGL_SYNC_NATIVE_FENCE_ANDROID:
2193            res_status = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
2194            break;
2195        default:
2196            res_status = EGL_SIGNALED_KHR;
2197    }
2198    sync->status = res_status;
2199    return retval;
2200}
2201
2202EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR eglsync,
2203        EGLint attribute, EGLint *value)
2204{
2205    (void)dpy;
2206
2207    EGLSync_t* sync = (EGLSync_t*)eglsync;
2208
2209    switch (attribute) {
2210    case EGL_SYNC_TYPE_KHR:
2211        *value = sync->type;
2212        return EGL_TRUE;
2213    case EGL_SYNC_STATUS_KHR:
2214        *value = sync->status;
2215        return EGL_TRUE;
2216    case EGL_SYNC_CONDITION_KHR:
2217        *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
2218        return EGL_TRUE;
2219    default:
2220        setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
2221    }
2222}
2223
2224int eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR eglsync) {
2225    (void)dpy;
2226
2227    DPRINT("call");
2228
2229    EGLSync_t* sync = (EGLSync_t*)eglsync;
2230    if (sync && sync->android_native_fence_fd > 0) {
2231        int res = dup(sync->android_native_fence_fd);
2232        return res;
2233    } else {
2234        return -1;
2235    }
2236}
2237
2238EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {
2239    (void)dpy;
2240
2241    if (!eglsync) {
2242        ALOGE("%s: null sync object!", __FUNCTION__);
2243        return EGL_FALSE;
2244    }
2245
2246    if (flags) {
2247        ALOGE("%s: flags must be 0, got 0x%x", __FUNCTION__, flags);
2248        return EGL_FALSE;
2249    }
2250
2251    DEFINE_HOST_CONNECTION;
2252    if (rcEnc->hasNativeSyncV3()) {
2253        EGLSync_t* sync = (EGLSync_t*)eglsync;
2254        rcEnc->rcWaitSyncKHR(rcEnc, sync->handle, flags);
2255    }
2256
2257    return EGL_TRUE;
2258}
2259