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 "HostConnection.h"
18#include "ThreadInfo.h"
19#include "eglDisplay.h"
20#include "egl_ftable.h"
21#include <cutils/log.h>
22#include "gralloc_cb.h"
23#include "GLClientState.h"
24#include "GLSharedGroup.h"
25#include "eglContext.h"
26#include "ClientAPIExts.h"
27
28#include "GLEncoder.h"
29#ifdef WITH_GLES2
30#include "GL2Encoder.h"
31#endif
32
33#include <system/window.h>
34
35template<typename T>
36static T setErrorFunc(GLint error, T returnValue) {
37    getEGLThreadInfo()->eglError = error;
38    return returnValue;
39}
40
41const char *  eglStrError(EGLint err)
42{
43    switch (err){
44        case EGL_SUCCESS:           return "EGL_SUCCESS";
45        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
46        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
47        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
48        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
49        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
50        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
51        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
52        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
53        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
54        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
55        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
56        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
57        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
58        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
59        default: return "UNKNOWN";
60    }
61}
62
63#define LOG_EGL_ERRORS 1
64
65#ifdef LOG_EGL_ERRORS
66
67#define setErrorReturn(error, retVal)     \
68    {                                                \
69        ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
70        return setErrorFunc(error, retVal);            \
71    }
72
73#define RETURN_ERROR(ret,err)           \
74    ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
75    getEGLThreadInfo()->eglError = err;    \
76    return ret;
77
78#else //!LOG_EGL_ERRORS
79
80#define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
81
82#define RETURN_ERROR(ret,err)           \
83    getEGLThreadInfo()->eglError = err; \
84    return ret;
85
86#endif //LOG_EGL_ERRORS
87
88#define VALIDATE_CONFIG(cfg,ret) \
89    if(((int)cfg<0)||((int)cfg>s_display.getNumConfigs())) { \
90        RETURN_ERROR(ret,EGL_BAD_CONFIG); \
91    }
92
93#define VALIDATE_DISPLAY(dpy,ret) \
94    if ((dpy) != (EGLDisplay)&s_display) { \
95        RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
96    }
97
98#define VALIDATE_DISPLAY_INIT(dpy,ret) \
99    VALIDATE_DISPLAY(dpy, ret)    \
100    if (!s_display.initialized()) {        \
101        RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
102    }
103
104#define DEFINE_HOST_CONNECTION \
105    HostConnection *hostCon = HostConnection::get(); \
106    renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
107
108#define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
109    HostConnection *hostCon = HostConnection::get(); \
110    if (!hostCon) { \
111        ALOGE("egl: Failed to get host connection\n"); \
112        return ret; \
113    } \
114    renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
115    if (!rcEnc) { \
116        ALOGE("egl: Failed to get renderControl encoder context\n"); \
117        return ret; \
118    }
119
120#define VALIDATE_CONTEXT_RETURN(context,ret)        \
121    if (!context) {                                    \
122        RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
123    }
124
125#define VALIDATE_SURFACE_RETURN(surface, ret)    \
126    if (surface != EGL_NO_SURFACE) {    \
127        egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
128        if (s->dpy != (EGLDisplay)&s_display)    \
129            setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
130    }
131
132
133EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
134    dpy(dpy),
135    config(config),
136    read(EGL_NO_SURFACE),
137    draw(EGL_NO_SURFACE),
138    shareCtx(shareCtx),
139    rcContext(0),
140    versionString(NULL),
141    vendorString(NULL),
142    rendererString(NULL),
143    extensionString(NULL)
144{
145    flags = 0;
146    version = 1;
147    clientState = new GLClientState();
148    if (shareCtx)
149        sharedGroup = shareCtx->getSharedGroup();
150    else
151        sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
152};
153
154EGLContext_t::~EGLContext_t()
155{
156    delete clientState;
157    delete [] versionString;
158    delete [] vendorString;
159    delete [] rendererString;
160    delete [] extensionString;
161}
162
163// ----------------------------------------------------------------------------
164//egl_surface_t
165
166//we don't need to handle depth since it's handled when window created on the host
167
168struct egl_surface_t {
169
170    EGLDisplay          dpy;
171    EGLConfig           config;
172
173
174    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
175    virtual     ~egl_surface_t();
176
177    virtual     void        setSwapInterval(int interval) = 0;
178    virtual     EGLBoolean  swapBuffers() = 0;
179
180    EGLint      getSwapBehavior() const;
181    uint32_t    getRcSurface()   { return rcSurface; }
182    EGLint      getSurfaceType() { return surfaceType; }
183
184    EGLint      getWidth(){ return width; }
185    EGLint      getHeight(){ return height; }
186    void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
187    EGLint      getTextureFormat() { return texFormat; }
188    void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
189    EGLint      getTextureTarget() { return texTarget; }
190
191private:
192    //
193    //Surface attributes
194    //
195    EGLint      width;
196    EGLint      height;
197    EGLint      texFormat;
198    EGLint      texTarget;
199
200protected:
201    void        setWidth(EGLint w)  { width = w;  }
202    void        setHeight(EGLint h) { height = h; }
203
204    EGLint      surfaceType;
205    uint32_t    rcSurface; //handle to surface created via remote control
206};
207
208egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
209    : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
210{
211    width = 0;
212    height = 0;
213    texFormat = EGL_NO_TEXTURE;
214    texTarget = EGL_NO_TEXTURE;
215}
216
217EGLint egl_surface_t::getSwapBehavior() const {
218    return EGL_BUFFER_PRESERVED;
219}
220
221egl_surface_t::~egl_surface_t()
222{
223}
224
225// ----------------------------------------------------------------------------
226// egl_window_surface_t
227
228struct egl_window_surface_t : public egl_surface_t {
229    static egl_window_surface_t* create(
230            EGLDisplay dpy, EGLConfig config, EGLint surfType,
231            ANativeWindow* window);
232
233    virtual ~egl_window_surface_t();
234
235    virtual void       setSwapInterval(int interval);
236    virtual EGLBoolean swapBuffers();
237
238private:
239    egl_window_surface_t(
240            EGLDisplay dpy, EGLConfig config, EGLint surfType,
241            ANativeWindow* window);
242    EGLBoolean init();
243
244    ANativeWindow*              nativeWindow;
245    android_native_buffer_t*    buffer;
246};
247
248egl_window_surface_t::egl_window_surface_t (
249        EGLDisplay dpy, EGLConfig config, EGLint surfType,
250        ANativeWindow* window)
251:   egl_surface_t(dpy, config, surfType),
252    nativeWindow(window),
253    buffer(NULL)
254{
255    // keep a reference on the window
256    nativeWindow->common.incRef(&nativeWindow->common);
257    EGLint w,h;
258    nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &w);
259    setWidth(w);
260    nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &h);
261    setHeight(h);
262}
263
264EGLBoolean egl_window_surface_t::init()
265{
266    if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
267        setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
268    }
269
270    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
271    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
272            getWidth(), getHeight());
273    if (!rcSurface) {
274        ALOGE("rcCreateWindowSurface returned 0");
275        return EGL_FALSE;
276    }
277    rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
278            ((cb_handle_t*)(buffer->handle))->hostHandle);
279
280    return EGL_TRUE;
281}
282
283egl_window_surface_t* egl_window_surface_t::create(
284        EGLDisplay dpy, EGLConfig config, EGLint surfType,
285        ANativeWindow* window)
286{
287    egl_window_surface_t* wnd = new egl_window_surface_t(
288            dpy, config, surfType, window);
289    if (wnd && !wnd->init()) {
290        delete wnd;
291        wnd = NULL;
292    }
293    return wnd;
294}
295
296egl_window_surface_t::~egl_window_surface_t() {
297    DEFINE_HOST_CONNECTION;
298    if (rcSurface && rcEnc) {
299        rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
300    }
301    if (buffer) {
302        nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
303    }
304    nativeWindow->common.decRef(&nativeWindow->common);
305}
306
307void egl_window_surface_t::setSwapInterval(int interval)
308{
309    nativeWindow->setSwapInterval(nativeWindow, interval);
310}
311
312EGLBoolean egl_window_surface_t::swapBuffers()
313{
314    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
315
316    rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
317
318    nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
319    if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
320        buffer = NULL;
321        setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
322    }
323
324    rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
325            ((cb_handle_t *)(buffer->handle))->hostHandle);
326
327    return EGL_TRUE;
328}
329
330// ----------------------------------------------------------------------------
331//egl_pbuffer_surface_t
332
333struct egl_pbuffer_surface_t : public egl_surface_t {
334    static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
335            EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
336
337    virtual ~egl_pbuffer_surface_t();
338
339    virtual void       setSwapInterval(int interval) {}
340    virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
341
342    uint32_t getRcColorBuffer() { return rcColorBuffer; }
343
344private:
345    egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
346            int32_t w, int32_t h);
347    EGLBoolean init(GLenum format);
348
349    uint32_t rcColorBuffer;
350};
351
352egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
353        EGLint surfType, int32_t w, int32_t h)
354:   egl_surface_t(dpy, config, surfType),
355    rcColorBuffer(0)
356{
357    setWidth(w);
358    setHeight(h);
359}
360
361egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
362{
363    DEFINE_HOST_CONNECTION;
364    if (rcEnc) {
365        if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
366        if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
367    }
368}
369
370EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
371{
372    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
373
374    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
375            getWidth(), getHeight());
376    if (!rcSurface) {
377        ALOGE("rcCreateWindowSurface returned 0");
378        return EGL_FALSE;
379    }
380
381    rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
382            pixelFormat);
383    if (!rcColorBuffer) {
384        ALOGE("rcCreateColorBuffer returned 0");
385        return EGL_FALSE;
386    }
387
388    rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
389
390    return EGL_TRUE;
391}
392
393egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
394        EGLConfig config, EGLint surfType, int32_t w, int32_t h,
395        GLenum pixelFormat)
396{
397    egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
398            w, h);
399    if (pb && !pb->init(pixelFormat)) {
400        delete pb;
401        pb = NULL;
402    }
403    return pb;
404}
405
406static const char *getGLString(int glEnum)
407{
408    EGLThreadInfo *tInfo = getEGLThreadInfo();
409    if (!tInfo || !tInfo->currentContext) {
410        return NULL;
411    }
412
413    const char** strPtr = NULL;
414
415#define GL_VENDOR                         0x1F00
416#define GL_RENDERER                       0x1F01
417#define GL_VERSION                        0x1F02
418#define GL_EXTENSIONS                     0x1F03
419
420    switch(glEnum) {
421        case GL_VERSION:
422            strPtr = &tInfo->currentContext->versionString;
423            break;
424        case GL_VENDOR:
425            strPtr = &tInfo->currentContext->vendorString;
426            break;
427        case GL_RENDERER:
428            strPtr = &tInfo->currentContext->rendererString;
429            break;
430        case GL_EXTENSIONS:
431            strPtr = &tInfo->currentContext->extensionString;
432            break;
433    }
434
435    if (!strPtr) {
436        return NULL;
437    }
438
439    if (*strPtr != NULL) {
440        //
441        // string is already cached
442        //
443        return *strPtr;
444    }
445
446    //
447    // first query of that string - need to query host
448    //
449    DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
450    char *hostStr = NULL;
451    int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
452    if (n < 0) {
453        hostStr = new char[-n+1];
454        n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
455        if (n <= 0) {
456            delete [] hostStr;
457            hostStr = NULL;
458        }
459    }
460
461    //
462    // keep the string in the context and return its value
463    //
464    *strPtr = hostStr;
465    return hostStr;
466}
467
468// ----------------------------------------------------------------------------
469
470// The one and only supported display object.
471static eglDisplay s_display;
472
473static EGLClient_eglInterface s_eglIface = {
474    getThreadInfo: getEGLThreadInfo,
475    getGLString: getGLString
476};
477
478#define DBG_FUNC DBG("%s\n", __FUNCTION__)
479EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
480{
481    //
482    // we support only EGL_DEFAULT_DISPLAY.
483    //
484    if (display_id != EGL_DEFAULT_DISPLAY) {
485        return EGL_NO_DISPLAY;
486    }
487
488    return (EGLDisplay)&s_display;
489}
490
491EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
492{
493    VALIDATE_DISPLAY(dpy,EGL_FALSE);
494
495    if (!s_display.initialize(&s_eglIface)) {
496        return EGL_FALSE;
497    }
498    if (major!=NULL)
499        *major = s_display.getVersionMajor();
500    if (minor!=NULL)
501        *minor = s_display.getVersionMinor();
502    return EGL_TRUE;
503}
504
505EGLBoolean eglTerminate(EGLDisplay dpy)
506{
507    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
508
509    s_display.terminate();
510    return EGL_TRUE;
511}
512
513EGLint eglGetError()
514{
515    EGLint error = getEGLThreadInfo()->eglError;
516    getEGLThreadInfo()->eglError = EGL_SUCCESS;
517    return error;
518}
519
520__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
521{
522    // search in EGL function table
523    for (int i=0; i<egl_num_funcs; i++) {
524        if (!strcmp(egl_funcs_by_name[i].name, procname)) {
525            return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
526        }
527    }
528
529    //
530    // Make sure display is initialized before searching in client APIs
531    //
532    if (!s_display.initialized()) {
533        if (!s_display.initialize(&s_eglIface)) {
534            return NULL;
535        }
536    }
537
538    // look in gles client api's extensions table
539    return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
540
541    // Fail - function not found.
542    return NULL;
543}
544
545const char* eglQueryString(EGLDisplay dpy, EGLint name)
546{
547    VALIDATE_DISPLAY_INIT(dpy, NULL);
548
549    return s_display.queryString(name);
550}
551
552EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
553{
554    VALIDATE_DISPLAY_INIT(dpy, NULL);
555
556    if(!num_config) {
557        RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
558    }
559
560    GLint numConfigs = s_display.getNumConfigs();
561    if (!configs) {
562        *num_config = numConfigs;
563        return EGL_TRUE;
564    }
565
566    int i=0;
567    for (i=0 ; i<numConfigs && i<config_size ; i++) {
568        *configs++ = (EGLConfig)i;
569    }
570    *num_config = i;
571    return EGL_TRUE;
572}
573
574EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
575{
576    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
577
578    int attribs_size = 0;
579    if (attrib_list) {
580        const EGLint * attrib_p = attrib_list;
581        while (attrib_p[0] != EGL_NONE) {
582            attribs_size += 2;
583            attrib_p += 2;
584        }
585        attribs_size++; //for the terminating EGL_NONE
586    }
587
588    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
589    *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)configs, config_size);
590
591    return EGL_TRUE;
592}
593
594EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
595{
596    VALIDATE_DISPLAY_INIT(dpy, NULL);
597    VALIDATE_CONFIG(config, EGL_FALSE);
598
599    if (s_display.getConfigAttrib(config, attribute, value))
600    {
601        return EGL_TRUE;
602    }
603    else
604    {
605        RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
606    }
607}
608
609EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
610{
611    VALIDATE_DISPLAY_INIT(dpy, NULL);
612    VALIDATE_CONFIG(config, EGL_FALSE);
613    if (win == 0) {
614        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
615    }
616
617    EGLint surfaceType;
618    if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
619
620    if (!(surfaceType & EGL_WINDOW_BIT)) {
621        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
622    }
623
624    if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
625        setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
626    }
627
628    egl_surface_t* surface = egl_window_surface_t::create(
629            &s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
630    if (!surface) {
631        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
632    }
633
634    return surface;
635}
636
637EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
638{
639    VALIDATE_DISPLAY_INIT(dpy, NULL);
640    VALIDATE_CONFIG(config, EGL_FALSE);
641
642    EGLint surfaceType;
643    if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
644
645    if (!(surfaceType & EGL_PBUFFER_BIT)) {
646        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
647    }
648
649    int32_t w = 0;
650    int32_t h = 0;
651    EGLint texFormat = EGL_NO_TEXTURE;
652    EGLint texTarget = EGL_NO_TEXTURE;
653    while (attrib_list[0]) {
654        switch (attrib_list[0]) {
655            case EGL_WIDTH:
656                w = attrib_list[1];
657                break;
658            case EGL_HEIGHT:
659                h = attrib_list[1];
660                break;
661            case EGL_TEXTURE_FORMAT:
662                texFormat = attrib_list[1];
663                break;
664            case EGL_TEXTURE_TARGET:
665                texTarget = attrib_list[1];
666                break;
667            default:
668                break;
669        };
670        attrib_list+=2;
671    }
672    if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
673        ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
674        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
675    }
676    // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
677
678    GLenum pixelFormat;
679    if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
680        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
681
682    egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
683            surfaceType, w, h, pixelFormat);
684    if (!surface) {
685        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
686    }
687
688    //setup attributes
689    surface->setTextureFormat(texFormat);
690    surface->setTextureTarget(texTarget);
691
692    return surface;
693}
694
695EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
696{
697    //XXX: Pixmap not supported. The host cannot render to a pixmap resource
698    //     located on host. In order to support Pixmaps we should either punt
699    //     to s/w rendering -or- let the host render to a buffer that will be
700    //     copied back to guest at some sync point. None of those methods not
701    //     implemented and pixmaps are not used with OpenGL anyway ...
702    return EGL_NO_SURFACE;
703}
704
705EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
706{
707    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
708    VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
709
710    egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
711    delete surface;
712
713    return EGL_TRUE;
714}
715
716EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
717{
718    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
719    VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
720
721    egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
722    EGLBoolean ret = EGL_TRUE;
723    switch (attribute) {
724        case EGL_CONFIG_ID:
725            ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
726            break;
727        case EGL_WIDTH:
728            *value = surface->getWidth();
729            break;
730        case EGL_HEIGHT:
731            *value = surface->getHeight();
732            break;
733        case EGL_TEXTURE_FORMAT:
734            *value = surface->getTextureFormat();
735            break;
736        case EGL_TEXTURE_TARGET:
737            *value = surface->getTextureTarget();
738            break;
739        case EGL_SWAP_BEHAVIOR:
740            *value = surface->getSwapBehavior();
741            break;
742        case EGL_LARGEST_PBUFFER:
743            // not modified for a window or pixmap surface
744            // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
745            if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
746            break;
747        //TODO: complete other attributes
748        default:
749            ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
750            ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
751            break;
752    }
753
754    return ret;
755}
756
757EGLBoolean eglBindAPI(EGLenum api)
758{
759    if (api != EGL_OPENGL_ES_API)
760        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
761    return EGL_TRUE;
762}
763
764EGLenum eglQueryAPI()
765{
766    return EGL_OPENGL_ES_API;
767}
768
769EGLBoolean eglWaitClient()
770{
771    return eglWaitGL();
772}
773
774EGLBoolean eglReleaseThread()
775{
776    EGLThreadInfo *tInfo = getEGLThreadInfo();
777    if (tInfo && tInfo->currentContext) {
778        return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
779    }
780    return EGL_TRUE;
781}
782
783EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
784{
785    //TODO
786    ALOGW("%s not implemented", __FUNCTION__);
787    return 0;
788}
789
790EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
791{
792    //TODO
793    ALOGW("%s not implemented", __FUNCTION__);
794    return 0;
795}
796
797EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
798{
799    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
800    VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
801    if (eglSurface == EGL_NO_SURFACE) {
802        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
803    }
804
805    if (buffer != EGL_BACK_BUFFER) {
806        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
807    }
808
809    egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
810
811    if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
812        setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
813    }
814
815    if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
816        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
817    }
818
819    //It's now safe to cast to pbuffer surface
820    egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
821
822    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
823    rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
824
825    return GL_TRUE;
826}
827
828EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
829{
830    //TODO
831    ALOGW("%s not implemented", __FUNCTION__);
832    return 0;
833}
834
835EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
836{
837    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
838    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
839
840    EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
841    if (!ctx) {
842        setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
843    }
844    if (!ctx->draw) {
845        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
846    }
847    egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
848    draw->setSwapInterval(interval);
849
850    rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
851
852    return EGL_TRUE;
853}
854
855EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
856{
857    VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
858    VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
859
860    EGLint version = 1; //default
861    while (attrib_list && attrib_list[0]) {
862        if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
863        attrib_list+=2;
864    }
865
866    uint32_t rcShareCtx = 0;
867    EGLContext_t * shareCtx = NULL;
868    if (share_context) {
869        shareCtx = static_cast<EGLContext_t*>(share_context);
870        rcShareCtx = shareCtx->rcContext;
871        if (shareCtx->dpy != dpy)
872            setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
873    }
874
875    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
876    uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uint32_t)config, rcShareCtx, version);
877    if (!rcContext) {
878        ALOGE("rcCreateContext returned 0");
879        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
880    }
881
882    EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
883    if (!context)
884        setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
885
886    context->version = version;
887    context->rcContext = rcContext;
888
889
890    return context;
891}
892
893EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
894{
895    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
896    VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
897
898    EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
899
900    if (getEGLThreadInfo()->currentContext == context)
901    {
902        eglMakeCurrent(dpy, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
903    }
904
905    if (context->rcContext) {
906        DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
907        rcEnc->rcDestroyContext(rcEnc, context->rcContext);
908        context->rcContext = 0;
909    }
910
911    delete context;
912    return EGL_TRUE;
913}
914
915EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
916{
917    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
918    VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
919    VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
920
921    if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
922        setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
923    if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
924        setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
925
926    EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
927    uint32_t ctxHandle = (context) ? context->rcContext : 0;
928    egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
929    uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
930    egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
931    uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
932
933    //
934    // Nothing to do if no binding change has made
935    //
936    EGLThreadInfo *tInfo = getEGLThreadInfo();
937    if (tInfo->currentContext == context &&
938        (context == NULL ||
939        (context && context->draw == draw && context->read == read))) {
940        return EGL_TRUE;
941    }
942
943    if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
944        //context is current to another thread
945        setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
946    }
947
948    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
949    if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
950        ALOGE("rcMakeCurrent returned EGL_FALSE");
951        setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
952    }
953
954    //Now make the local bind
955    if (context) {
956        context->draw = draw;
957        context->read = read;
958        context->flags |= EGLContext_t::IS_CURRENT;
959        //set the client state
960        if (context->version == 2) {
961            hostCon->gl2Encoder()->setClientState(context->getClientState());
962            hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
963        }
964        else {
965            hostCon->glEncoder()->setClientState(context->getClientState());
966            hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
967        }
968    }
969    else {
970        //release ClientState & SharedGroup
971        if (tInfo->currentContext->version == 2) {
972            hostCon->gl2Encoder()->setClientState(NULL);
973            hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
974        }
975        else {
976            hostCon->glEncoder()->setClientState(NULL);
977            hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
978        }
979
980    }
981
982    if (tInfo->currentContext)
983        tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
984
985    //Now make current
986    tInfo->currentContext = context;
987
988    //Check maybe we need to init the encoder, if it's first eglMakeCurrent
989    if (tInfo->currentContext) {
990        if (tInfo->currentContext->version == 2) {
991            if (!hostCon->gl2Encoder()->isInitialized()) {
992                s_display.gles2_iface()->init();
993                hostCon->gl2Encoder()->setInitialized();
994                ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
995            }
996        }
997        else {
998            if (!hostCon->glEncoder()->isInitialized()) {
999                s_display.gles_iface()->init();
1000                hostCon->glEncoder()->setInitialized();
1001                ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1002            }
1003        }
1004    }
1005
1006    return EGL_TRUE;
1007}
1008
1009EGLContext eglGetCurrentContext()
1010{
1011    return getEGLThreadInfo()->currentContext;
1012}
1013
1014EGLSurface eglGetCurrentSurface(EGLint readdraw)
1015{
1016    EGLContext_t * context = getEGLThreadInfo()->currentContext;
1017    if (!context)
1018        return EGL_NO_SURFACE; //not an error
1019
1020    switch (readdraw) {
1021        case EGL_READ:
1022            return context->read;
1023        case EGL_DRAW:
1024            return context->draw;
1025        default:
1026            setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1027    }
1028}
1029
1030EGLDisplay eglGetCurrentDisplay()
1031{
1032    EGLContext_t * context = getEGLThreadInfo()->currentContext;
1033    if (!context)
1034        return EGL_NO_DISPLAY; //not an error
1035
1036    return context->dpy;
1037}
1038
1039EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1040{
1041    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1042    VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1043
1044    EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1045
1046    EGLBoolean ret = EGL_TRUE;
1047    switch (attribute) {
1048        case EGL_CONFIG_ID:
1049            ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1050            break;
1051        case EGL_CONTEXT_CLIENT_TYPE:
1052            *value = EGL_OPENGL_ES_API;
1053            break;
1054        case EGL_CONTEXT_CLIENT_VERSION:
1055            *value = context->version;
1056            break;
1057        case EGL_RENDER_BUFFER:
1058            if (!context->draw)
1059                *value = EGL_NONE;
1060            else
1061                *value = EGL_BACK_BUFFER; //single buffer not supported
1062            break;
1063        default:
1064            ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
1065            setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1066            break;
1067    }
1068
1069    return ret;
1070}
1071
1072EGLBoolean eglWaitGL()
1073{
1074    EGLThreadInfo *tInfo = getEGLThreadInfo();
1075    if (!tInfo || !tInfo->currentContext) {
1076        return EGL_FALSE;
1077    }
1078
1079    if (tInfo->currentContext->version == 2) {
1080        s_display.gles2_iface()->finish();
1081    }
1082    else {
1083        s_display.gles_iface()->finish();
1084    }
1085
1086    return EGL_TRUE;
1087}
1088
1089EGLBoolean eglWaitNative(EGLint engine)
1090{
1091    return EGL_TRUE;
1092}
1093
1094EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1095{
1096    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1097    if (eglSurface == EGL_NO_SURFACE)
1098        setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1099
1100    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1101
1102    egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1103    if (d->dpy != dpy)
1104        setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1105
1106    // post the surface
1107    d->swapBuffers();
1108
1109    hostCon->flush();
1110    return EGL_TRUE;
1111}
1112
1113EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1114{
1115    //TODO :later
1116    return 0;
1117}
1118
1119EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1120{
1121    //TODO later
1122    return 0;
1123}
1124
1125EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1126{
1127    //TODO later
1128    return 0;
1129}
1130
1131EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1132{
1133    VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1134    if (ctx != EGL_NO_CONTEXT) {
1135        setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1136    }
1137    if (target != EGL_NATIVE_BUFFER_ANDROID) {
1138        setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1139    }
1140
1141    android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1142
1143    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1144        setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1145
1146    if (native_buffer->common.version != sizeof(android_native_buffer_t))
1147        setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1148
1149    cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1150
1151    switch (cb->format) {
1152        case HAL_PIXEL_FORMAT_RGBA_8888:
1153        case HAL_PIXEL_FORMAT_RGBX_8888:
1154        case HAL_PIXEL_FORMAT_RGB_888:
1155        case HAL_PIXEL_FORMAT_RGB_565:
1156        case HAL_PIXEL_FORMAT_BGRA_8888:
1157        case HAL_PIXEL_FORMAT_RGBA_5551:
1158        case HAL_PIXEL_FORMAT_RGBA_4444:
1159            break;
1160        default:
1161            setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1162    }
1163
1164    native_buffer->common.incRef(&native_buffer->common);
1165    return (EGLImageKHR)native_buffer;
1166}
1167
1168EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1169{
1170    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1171    android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
1172
1173    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1174        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1175
1176    if (native_buffer->common.version != sizeof(android_native_buffer_t))
1177        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1178
1179    native_buffer->common.decRef(&native_buffer->common);
1180
1181    return EGL_TRUE;
1182}
1183
1184#define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1185
1186EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1187        const EGLint *attrib_list)
1188{
1189    // TODO: This implementation could be faster. We should require the host EGL
1190    // to support KHR_fence_sync, or at least pipe the fence command to the host
1191    // and wait for it (probably involving a glFinish on the host) in
1192    // eglClientWaitSyncKHR.
1193
1194    VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1195
1196    if (type != EGL_SYNC_FENCE_KHR ||
1197            (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
1198        setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1199    }
1200
1201    EGLThreadInfo *tInfo = getEGLThreadInfo();
1202    if (!tInfo || !tInfo->currentContext) {
1203        setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1204    }
1205
1206    if (tInfo->currentContext->version == 2) {
1207        s_display.gles2_iface()->finish();
1208    } else {
1209        s_display.gles_iface()->finish();
1210    }
1211
1212    return FENCE_SYNC_HANDLE;
1213}
1214
1215EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1216{
1217    if (sync != FENCE_SYNC_HANDLE) {
1218        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1219    }
1220
1221    return EGL_TRUE;
1222}
1223
1224EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
1225        EGLTimeKHR timeout)
1226{
1227    if (sync != FENCE_SYNC_HANDLE) {
1228        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1229    }
1230
1231    return EGL_CONDITION_SATISFIED_KHR;
1232}
1233
1234EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1235        EGLint attribute, EGLint *value)
1236{
1237    if (sync != FENCE_SYNC_HANDLE) {
1238        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1239    }
1240
1241    switch (attribute) {
1242    case EGL_SYNC_TYPE_KHR:
1243        *value = EGL_SYNC_FENCE_KHR;
1244        return EGL_TRUE;
1245    case EGL_SYNC_STATUS_KHR:
1246        *value = EGL_SIGNALED_KHR;
1247        return EGL_TRUE;
1248    case EGL_SYNC_CONDITION_KHR:
1249        *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1250        return EGL_TRUE;
1251    default:
1252        setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1253    }
1254}
1255