2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "HostConnection.h"
19 #include "ThreadInfo.h"
20 #include "eglDisplay.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"
32 #include "ProcessPipe.h"
34 #include "GLEncoder.h"
36 #include "GL2Encoder.h"
39 #include <GLES3/gl31.h>
41 #if PLATFORM_SDK_VERSION >= 16
42 #include <system/window.h>
43 #else // PLATFORM_SDK_VERSION >= 16
44 #include <private/ui/android_natives_priv.h>
45 #endif // PLATFORM_SDK_VERSION >= 16
47 #if PLATFORM_SDK_VERSION <= 16
48 #define queueBuffer_DEPRECATED queueBuffer
49 #define dequeueBuffer_DEPRECATED dequeueBuffer
50 #define cancelBuffer_DEPRECATED cancelBuffer
51 #endif // PLATFORM_SDK_VERSION <= 16
56 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
62 static T setErrorFunc(GLint error, T returnValue) {
63 getEGLThreadInfo()->eglError = error;
67 const char * eglStrError(EGLint err)
70 case EGL_SUCCESS: return "EGL_SUCCESS";
71 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
72 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
73 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
74 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
75 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
76 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
77 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
78 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
79 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
80 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
81 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
82 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
83 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
84 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
85 default: return "UNKNOWN";
89 #define LOG_EGL_ERRORS 1
93 #define setErrorReturn(error, retVal) \
95 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
96 return setErrorFunc(error, retVal); \
99 #define RETURN_ERROR(ret,err) \
100 ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
101 getEGLThreadInfo()->eglError = err; \
104 #else //!LOG_EGL_ERRORS
106 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
108 #define RETURN_ERROR(ret,err) \
109 getEGLThreadInfo()->eglError = err; \
112 #endif //LOG_EGL_ERRORS
114 #define VALIDATE_CONFIG(cfg,ret) \
115 if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
116 RETURN_ERROR(ret,EGL_BAD_CONFIG); \
119 #define VALIDATE_DISPLAY(dpy,ret) \
120 if ((dpy) != (EGLDisplay)&s_display) { \
121 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
124 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
125 VALIDATE_DISPLAY(dpy, ret) \
126 if (!s_display.initialized()) { \
127 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
130 #define DEFINE_HOST_CONNECTION \
131 HostConnection *hostCon = HostConnection::get(); \
132 ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
134 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
135 HostConnection *hostCon = HostConnection::get(); \
137 ALOGE("egl: Failed to get host connection\n"); \
140 ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
142 ALOGE("egl: Failed to get renderControl encoder context\n"); \
146 #define VALIDATE_CONTEXT_RETURN(context,ret) \
148 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
151 #define VALIDATE_SURFACE_RETURN(surface, ret) \
152 if ((surface) != EGL_NO_SURFACE) { \
153 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
154 if (s->dpy != (EGLDisplay)&s_display) \
155 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
158 // The one and only supported display object.
159 static eglDisplay s_display;
161 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx, int maj, int min) :
164 read(EGL_NO_SURFACE),
165 draw(EGL_NO_SURFACE),
172 rendererString(NULL),
173 shaderVersionString(NULL),
174 extensionString(NULL),
179 clientState = new GLClientState(majorVersion, minorVersion);
181 sharedGroup = shareCtx->getSharedGroup();
183 sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
184 assert(dpy == (EGLDisplay)&s_display);
185 s_display.onCreateContext((EGLContext)this);
188 int EGLContext_t::getGoldfishSyncFd() {
189 if (goldfishSyncFd < 0) {
190 goldfishSyncFd = goldfish_sync_open();
192 return goldfishSyncFd;
195 EGLContext_t::~EGLContext_t()
197 if (goldfishSyncFd > 0) {
198 goldfish_sync_close(goldfishSyncFd);
201 assert(dpy == (EGLDisplay)&s_display);
202 s_display.onDestroyContext((EGLContext)this);
204 delete [] versionString;
205 delete [] vendorString;
206 delete [] rendererString;
207 delete [] shaderVersionString;
208 delete [] extensionString;
211 // ----------------------------------------------------------------------------
214 //we don't need to handle depth since it's handled when window created on the host
216 struct egl_surface_t {
222 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
223 virtual ~egl_surface_t();
225 virtual void setSwapInterval(int interval) = 0;
226 virtual EGLBoolean swapBuffers() = 0;
228 EGLint getSwapBehavior() const;
229 uint32_t getRcSurface() { return rcSurface; }
230 EGLint getSurfaceType() { return surfaceType; }
232 EGLint getWidth(){ return width; }
233 EGLint getHeight(){ return height; }
234 EGLint getNativeWidth(){ return nativeWidth; }
235 EGLint getNativeHeight(){ return nativeHeight; }
236 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
237 EGLint getTextureFormat() { return texFormat; }
238 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
239 EGLint getTextureTarget() { return texTarget; }
250 // Width of the actual window being presented (not the EGL texture)
251 // Give it some default values.
256 void setWidth(EGLint w) { width = w; }
257 void setHeight(EGLint h) { height = h; }
258 void setNativeWidth(int w) { nativeWidth = w; }
259 void setNativeHeight(int h) { nativeHeight = h; }
262 uint32_t rcSurface; //handle to surface created via remote control
265 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
266 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
270 // prevent div by 0 in EGL_(HORIZONTAL|VERTICAL)_RESOLUTION queries.
273 texFormat = EGL_NO_TEXTURE;
274 texTarget = EGL_NO_TEXTURE;
275 assert(dpy == (EGLDisplay)&s_display);
276 s_display.onCreateSurface((EGLSurface)this);
279 EGLint egl_surface_t::getSwapBehavior() const {
280 return EGL_BUFFER_PRESERVED;
283 egl_surface_t::~egl_surface_t()
285 assert(dpy == (EGLDisplay)&s_display);
286 s_display.onDestroySurface((EGLSurface)this);
289 // ----------------------------------------------------------------------------
290 // egl_window_surface_t
292 struct egl_window_surface_t : public egl_surface_t {
293 static egl_window_surface_t* create(
294 EGLDisplay dpy, EGLConfig config, EGLint surfType,
295 ANativeWindow* window);
297 virtual ~egl_window_surface_t();
299 virtual void setSwapInterval(int interval);
300 virtual EGLBoolean swapBuffers();
303 egl_window_surface_t(
304 EGLDisplay dpy, EGLConfig config, EGLint surfType,
305 ANativeWindow* window);
308 ANativeWindow* nativeWindow;
309 android_native_buffer_t* buffer;
312 egl_window_surface_t::egl_window_surface_t (
313 EGLDisplay dpy, EGLConfig config, EGLint surfType,
314 ANativeWindow* window)
315 : egl_surface_t(dpy, config, surfType),
316 nativeWindow(window),
319 // keep a reference on the window
320 nativeWindow->common.incRef(&nativeWindow->common);
324 EGLBoolean egl_window_surface_t::init()
326 if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
327 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
329 setWidth(buffer->width);
330 setHeight(buffer->height);
332 int nativeWidth, nativeHeight;
333 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &nativeWidth);
334 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &nativeHeight);
336 setNativeWidth(nativeWidth);
337 setNativeHeight(nativeHeight);
339 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
340 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
341 getWidth(), getHeight());
343 ALOGE("rcCreateWindowSurface returned 0");
346 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
347 ((cb_handle_t*)(buffer->handle))->hostHandle);
352 egl_window_surface_t* egl_window_surface_t::create(
353 EGLDisplay dpy, EGLConfig config, EGLint surfType,
354 ANativeWindow* window)
356 egl_window_surface_t* wnd = new egl_window_surface_t(
357 dpy, config, surfType, window);
358 if (wnd && !wnd->init()) {
365 egl_window_surface_t::~egl_window_surface_t() {
366 DEFINE_HOST_CONNECTION;
367 if (rcSurface && rcEnc) {
368 rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
371 nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
373 nativeWindow->common.decRef(&nativeWindow->common);
376 void egl_window_surface_t::setSwapInterval(int interval)
378 nativeWindow->setSwapInterval(nativeWindow, interval);
381 // createNativeSync() creates an OpenGL sync object on the host
382 // using rcCreateSyncKHR. If necessary, a native fence FD will
383 // also be created through the goldfish sync device.
384 // Returns a handle to the host-side FenceSync object.
385 static uint64_t createNativeSync(EGLenum type,
386 const EGLint* attrib_list,
387 int num_actual_attribs,
388 bool destroy_when_signaled,
391 DEFINE_HOST_CONNECTION;
393 uint64_t sync_handle;
394 uint64_t thread_handle;
396 EGLint* actual_attribs =
397 (EGLint*)(num_actual_attribs == 0 ? NULL : attrib_list);
399 rcEnc->rcCreateSyncKHR(rcEnc, type,
401 num_actual_attribs * sizeof(EGLint),
402 destroy_when_signaled,
406 if (type == EGL_SYNC_NATIVE_FENCE_ANDROID && fd_in < 0) {
408 goldfish_sync_queue_work(
409 getEGLThreadInfo()->currentContext->getGoldfishSyncFd(),
414 DPRINT("got native fence fd=%d queue_work_err=%d",
415 *fd_out, queue_work_err);
421 // createGoldfishOpenGLNativeSync() is for creating host-only sync objects
422 // that are needed by only this goldfish opengl driver,
423 // such as in swapBuffers().
424 // The guest will not see any of these, and these sync objects will be
425 // destroyed on the host when signaled.
426 // A native fence FD is possibly returned.
427 static void createGoldfishOpenGLNativeSync(int* fd_out) {
428 createNativeSync(EGL_SYNC_NATIVE_FENCE_ANDROID,
429 NULL /* empty attrib list */,
430 0 /* 0 attrib count */,
431 true /* destroy when signaled. this is host-only
432 and there will only be one waiter */,
433 -1 /* we want a new fd */,
437 EGLBoolean egl_window_surface_t::swapBuffers()
440 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
442 // Follow up flushWindowColorBuffer with a fence command.
443 // When the fence command finishes,
444 // we're sure that the buffer on the host
447 // |presentFenceFd| guards the presentation of the
448 // current frame with a goldfish sync fence fd.
450 // When |presentFenceFd| is signaled, the recipient
451 // of the buffer that was sent through queueBuffer
452 // can be sure that the buffer is current.
454 // If we don't take care of this synchronization,
455 // an old frame can be processed by surfaceflinger,
456 // resulting in out of order frames.
458 int presentFenceFd = -1;
460 if (buffer == NULL) {
461 ALOGE("egl_window_surface_t::swapBuffers called with NULL buffer");
462 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
465 #if PLATFORM_SDK_VERSION <= 16
466 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
467 // equivalent to glFinish if no native sync
469 nativeWindow->queueBuffer(nativeWindow, buffer);
471 if (rcEnc->hasNativeSync()) {
472 rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
473 createGoldfishOpenGLNativeSync(&presentFenceFd);
475 rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
476 // equivalent to glFinish if no native sync
480 DPRINT("queueBuffer with fence %d", presentFenceFd);
481 nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
484 DPRINT("calling dequeueBuffer...");
486 #if PLATFORM_SDK_VERSION <= 16
487 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
489 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
492 int acquireFenceFd = -1;
493 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &acquireFenceFd)) {
495 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
498 DPRINT("dequeueBuffer with fence %d", acquireFenceFd);
500 if (acquireFenceFd > 0) {
501 close(acquireFenceFd);
505 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
506 ((cb_handle_t *)(buffer->handle))->hostHandle);
508 setWidth(buffer->width);
509 setHeight(buffer->height);
514 // ----------------------------------------------------------------------------
515 //egl_pbuffer_surface_t
517 struct egl_pbuffer_surface_t : public egl_surface_t {
518 static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
519 EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
521 virtual ~egl_pbuffer_surface_t();
523 virtual void setSwapInterval(int interval) { (void)interval; }
524 virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
526 uint32_t getRcColorBuffer() { return rcColorBuffer; }
529 egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
530 int32_t w, int32_t h);
531 EGLBoolean init(GLenum format);
533 uint32_t rcColorBuffer;
536 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
537 EGLint surfType, int32_t w, int32_t h)
538 : egl_surface_t(dpy, config, surfType),
545 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
547 DEFINE_HOST_CONNECTION;
549 if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
550 if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
554 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
556 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
558 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
559 getWidth(), getHeight());
561 ALOGE("rcCreateWindowSurface returned 0");
565 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), pixelFormat);
566 if (!rcColorBuffer) {
567 ALOGE("rcCreateColorBuffer returned 0");
571 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
576 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
577 EGLConfig config, EGLint surfType, int32_t w, int32_t h,
580 egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
582 if (pb && !pb->init(pixelFormat)) {
589 static const char *getGLString(int glEnum)
591 EGLThreadInfo *tInfo = getEGLThreadInfo();
592 if (!tInfo || !tInfo->currentContext) {
596 const char** strPtr = NULL;
598 #define GL_VENDOR 0x1F00
599 #define GL_RENDERER 0x1F01
600 #define GL_VERSION 0x1F02
601 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
602 #define GL_EXTENSIONS 0x1F03
606 strPtr = &tInfo->currentContext->versionString;
609 strPtr = &tInfo->currentContext->vendorString;
612 strPtr = &tInfo->currentContext->rendererString;
614 case GL_SHADING_LANGUAGE_VERSION:
615 strPtr = &tInfo->currentContext->shaderVersionString;
618 strPtr = &tInfo->currentContext->extensionString;
627 // first query of that string - need to query host
629 DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
630 char *hostStr = NULL;
631 int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
633 hostStr = new char[-n+1];
634 n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
642 // keep the string in the context and return its value
648 // ----------------------------------------------------------------------------
650 static EGLClient_eglInterface s_eglIface = {
651 getThreadInfo: getEGLThreadInfo,
652 getGLString: getGLString
655 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
656 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
659 // we support only EGL_DEFAULT_DISPLAY.
661 if (display_id != EGL_DEFAULT_DISPLAY) {
662 return EGL_NO_DISPLAY;
665 return (EGLDisplay)&s_display;
668 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
670 VALIDATE_DISPLAY(dpy,EGL_FALSE);
672 if (!s_display.initialize(&s_eglIface)) {
676 *major = s_display.getVersionMajor();
678 *minor = s_display.getVersionMinor();
682 EGLBoolean eglTerminate(EGLDisplay dpy)
684 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
686 s_display.terminate();
692 EGLint error = getEGLThreadInfo()->eglError;
693 getEGLThreadInfo()->eglError = EGL_SUCCESS;
697 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
699 // search in EGL function table
700 for (int i=0; i<egl_num_funcs; i++) {
701 if (!strcmp(egl_funcs_by_name[i].name, procname)) {
702 return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
706 // look in gles client api's extensions table
707 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
709 // Fail - function not found.
713 const char* eglQueryString(EGLDisplay dpy, EGLint name)
715 VALIDATE_DISPLAY_INIT(dpy, NULL);
717 return s_display.queryString(name);
720 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
722 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
725 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
728 GLint numConfigs = s_display.getNumConfigs();
730 *num_config = numConfigs;
735 for (i = 0 ; i < numConfigs && i < config_size ; i++) {
736 *configs++ = (EGLConfig)(uintptr_t)i;
742 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
744 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
747 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
750 int attribs_size = 0;
752 const EGLint * attrib_p = attrib_list;
753 while (attrib_p[0] != EGL_NONE) {
757 attribs_size++; //for the terminating EGL_NONE
760 // API 19 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
761 // while the host never supports it.
762 // We remove the bit here.
763 EGLint* local_attrib_list = NULL;
764 if (PLATFORM_SDK_VERSION <= 19) {
765 local_attrib_list = new EGLint[attribs_size];
766 memcpy(local_attrib_list, attrib_list, attribs_size * sizeof(EGLint));
767 EGLint* local_attrib_p = local_attrib_list;
768 while (local_attrib_p[0] != EGL_NONE) {
769 if (local_attrib_p[0] == EGL_SURFACE_TYPE) {
770 local_attrib_p[1] &= ~(EGLint)EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
776 uint32_t* tempConfigs[config_size];
777 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
778 *num_config = rcEnc->rcChooseConfig(rcEnc,
779 local_attrib_list ? local_attrib_list:(EGLint*)attrib_list,
780 attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
782 if (local_attrib_list) delete [] local_attrib_list;
783 if (*num_config <= 0) {
784 EGLint err = -(*num_config);
787 case EGL_BAD_ATTRIBUTE:
788 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
796 for (i=0;i<(*num_config);i++) {
797 *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
804 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
806 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
807 VALIDATE_CONFIG(config, EGL_FALSE);
809 if (s_display.getConfigAttrib(config, attribute, value))
815 ALOGD("%s: bad attrib 0x%x", __FUNCTION__, attribute);
816 RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
820 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
824 VALIDATE_DISPLAY_INIT(dpy, NULL);
825 VALIDATE_CONFIG(config, EGL_FALSE);
827 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
831 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
833 if (!(surfaceType & EGL_WINDOW_BIT)) {
834 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
837 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
838 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
841 egl_surface_t* surface = egl_window_surface_t::create(
842 &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
844 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
850 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
852 VALIDATE_DISPLAY_INIT(dpy, NULL);
853 VALIDATE_CONFIG(config, EGL_FALSE);
856 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
858 if (!(surfaceType & EGL_PBUFFER_BIT)) {
859 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
864 EGLint texFormat = EGL_NO_TEXTURE;
865 EGLint texTarget = EGL_NO_TEXTURE;
866 while (attrib_list[0] != EGL_NONE) {
867 switch (attrib_list[0]) {
870 if (w < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
874 if (h < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
876 case EGL_TEXTURE_FORMAT:
877 texFormat = attrib_list[1];
879 case EGL_TEXTURE_TARGET:
880 texTarget = attrib_list[1];
882 // the followings are not supported
883 case EGL_LARGEST_PBUFFER:
884 case EGL_MIPMAP_TEXTURE:
885 case EGL_VG_ALPHA_FORMAT:
886 case EGL_VG_COLORSPACE:
889 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
893 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
894 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
895 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
897 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
900 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
901 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
903 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
904 EGL_PBUFFER_BIT, w, h, pixelFormat);
906 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
910 surface->setTextureFormat(texFormat);
911 surface->setTextureTarget(texTarget);
916 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
918 //XXX: Pixmap not supported. The host cannot render to a pixmap resource
919 // located on host. In order to support Pixmaps we should either punt
920 // to s/w rendering -or- let the host render to a buffer that will be
921 // copied back to guest at some sync point. None of those methods not
922 // implemented and pixmaps are not used with OpenGL anyway ...
923 VALIDATE_CONFIG(config, EGL_FALSE);
927 return EGL_NO_SURFACE;
930 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
932 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
933 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
935 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
941 static float s_getNativeDpi() {
942 float nativeDPI = 560.0f;
943 const char* dpiPropName = "qemu.sf.lcd_density";
944 char dpiProp[PROPERTY_VALUE_MAX];
945 if (property_get(dpiPropName, dpiProp, NULL) > 0) {
946 nativeDPI = atof(dpiProp);
951 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
953 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
954 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
956 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
958 // Parameters involved in queries of EGL_(HORIZONTAL|VERTICAL)_RESOLUTION
959 float currWidth, currHeight, scaledResolution, effectiveSurfaceDPI;
960 EGLBoolean ret = EGL_TRUE;
963 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
966 *value = surface->getWidth();
969 *value = surface->getHeight();
971 case EGL_TEXTURE_FORMAT:
972 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
973 *value = surface->getTextureFormat();
976 case EGL_TEXTURE_TARGET:
977 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
978 *value = surface->getTextureTarget();
981 case EGL_SWAP_BEHAVIOR:
984 ret = s_display.getConfigAttrib(surface->config, EGL_SURFACE_TYPE,
986 if (ret == EGL_TRUE) {
987 if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
988 *value = EGL_BUFFER_PRESERVED;
990 *value = EGL_BUFFER_DESTROYED;
995 case EGL_LARGEST_PBUFFER:
996 // not modified for a window or pixmap surface
997 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
998 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
1000 case EGL_MIPMAP_TEXTURE:
1001 // not modified for a window or pixmap surface
1002 // and we ignore it when creating a PBuffer surface (default is 0)
1003 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = false;
1005 case EGL_MIPMAP_LEVEL:
1006 // not modified for a window or pixmap surface
1007 // and we ignore it when creating a PBuffer surface (default is 0)
1008 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
1010 case EGL_MULTISAMPLE_RESOLVE:
1011 // ignored when creating the surface, return default
1012 *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
1014 case EGL_HORIZONTAL_RESOLUTION:
1015 // pixel/mm * EGL_DISPLAY_SCALING
1016 // TODO: get the DPI from avd config
1017 currWidth = surface->getWidth();
1018 scaledResolution = currWidth / surface->getNativeWidth();
1019 effectiveSurfaceDPI =
1020 scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
1021 *value = (EGLint)(effectiveSurfaceDPI);
1023 case EGL_VERTICAL_RESOLUTION:
1024 // pixel/mm * EGL_DISPLAY_SCALING
1025 // TODO: get the real DPI from avd config
1026 currHeight = surface->getHeight();
1027 scaledResolution = currHeight / surface->getNativeHeight();
1028 effectiveSurfaceDPI =
1029 scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
1030 *value = (EGLint)(effectiveSurfaceDPI);
1032 case EGL_PIXEL_ASPECT_RATIO:
1033 // w / h * EGL_DISPLAY_SCALING
1034 // Please don't ask why * EGL_DISPLAY_SCALING, the document says it
1035 *value = 1 * EGL_DISPLAY_SCALING;
1037 case EGL_RENDER_BUFFER:
1038 switch (surface->getSurfaceType()) {
1039 case EGL_PBUFFER_BIT:
1040 *value = EGL_BACK_BUFFER;
1042 case EGL_PIXMAP_BIT:
1043 *value = EGL_SINGLE_BUFFER;
1045 case EGL_WINDOW_BIT:
1046 // ignored when creating the surface, return default
1047 *value = EGL_BACK_BUFFER;
1050 ALOGE("eglQuerySurface %x unknown surface type %x",
1051 attribute, surface->getSurfaceType());
1052 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1056 case EGL_VG_COLORSPACE:
1057 // ignored when creating the surface, return default
1058 *value = EGL_VG_COLORSPACE_sRGB;
1060 case EGL_VG_ALPHA_FORMAT:
1061 // ignored when creating the surface, return default
1062 *value = EGL_VG_ALPHA_FORMAT_NONPRE;
1064 //TODO: complete other attributes
1066 ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
1067 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1074 EGLBoolean eglBindAPI(EGLenum api)
1076 if (api != EGL_OPENGL_ES_API)
1077 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1081 EGLenum eglQueryAPI()
1083 return EGL_OPENGL_ES_API;
1086 EGLBoolean eglWaitClient()
1091 EGLBoolean eglReleaseThread()
1093 EGLThreadInfo *tInfo = getEGLThreadInfo();
1095 tInfo->eglError = EGL_SUCCESS;
1096 EGLContext_t* context = tInfo->currentContext;
1098 // The following code is doing pretty much the same thing as
1099 // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
1100 // with the only issue that we do not require a valid display here.
1101 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1102 rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
1103 if (context->majorVersion > 1) {
1104 hostCon->gl2Encoder()->setClientState(NULL);
1105 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
1108 hostCon->glEncoder()->setClientState(NULL);
1109 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
1111 context->flags &= ~EGLContext_t::IS_CURRENT;
1113 if (context->deletePending) {
1114 if (context->rcContext) {
1115 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1116 context->rcContext = 0;
1120 tInfo->currentContext = 0;
1126 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
1134 ALOGW("%s not implemented", __FUNCTION__);
1138 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1140 // Right now we don't do anything when using host GPU.
1141 // This is purely just to pass the data through
1142 // without issuing a warning. We may benefit from validating the
1143 // display and surface for debug purposes.
1144 // TODO: Find cases where we actually need to do something.
1145 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1146 VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
1147 if (surface == EGL_NO_SURFACE) {
1148 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1153 egl_surface_t* p_surface( static_cast<egl_surface_t*>(surface) );
1154 switch (attribute) {
1155 case EGL_MIPMAP_LEVEL:
1158 case EGL_MULTISAMPLE_RESOLVE:
1160 if (value == EGL_MULTISAMPLE_RESOLVE_BOX) {
1161 EGLint surface_type;
1162 s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1163 if (0 == (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) {
1164 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1170 case EGL_SWAP_BEHAVIOR:
1171 if (value == EGL_BUFFER_PRESERVED) {
1172 EGLint surface_type;
1173 s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
1174 if (0 == (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) {
1175 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1181 ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
1182 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1187 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
1189 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1190 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
1191 if (eglSurface == EGL_NO_SURFACE) {
1192 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1195 if (buffer != EGL_BACK_BUFFER) {
1196 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1199 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1201 if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
1202 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1205 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
1206 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1209 //It's now safe to cast to pbuffer surface
1210 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
1212 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1213 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
1218 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1224 ALOGW("%s not implemented", __FUNCTION__);
1228 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1230 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1231 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1233 EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
1235 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1238 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1240 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
1241 draw->setSwapInterval(interval);
1243 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
1248 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
1250 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
1251 VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
1253 EGLint majorVersion = 1; //default
1254 EGLint minorVersion = 0;
1255 EGLint context_flags = 0;
1256 EGLint profile_mask = 0;
1257 EGLint reset_notification_strategy = 0;
1259 bool wantedMajorVersion = false;
1260 bool wantedMinorVersion = false;
1262 while (attrib_list && attrib_list[0] != EGL_NONE) {
1263 EGLint attrib_val = attrib_list[1];
1264 switch(attrib_list[0]) {
1265 case EGL_CONTEXT_MAJOR_VERSION_KHR:
1266 majorVersion = attrib_val;
1267 wantedMajorVersion = true;
1269 case EGL_CONTEXT_MINOR_VERSION_KHR:
1270 minorVersion = attrib_val;
1271 wantedMinorVersion = true;
1273 case EGL_CONTEXT_FLAGS_KHR:
1274 if ((attrib_val | EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) ||
1275 (attrib_val | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) ||
1276 (attrib_val | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
1277 context_flags = attrib_val;
1279 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
1282 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
1283 if ((attrib_val | EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) ||
1284 (attrib_val | EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR)) {
1285 profile_mask = attrib_val;
1287 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
1290 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
1291 switch (attrib_val) {
1292 case EGL_NO_RESET_NOTIFICATION_KHR:
1293 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
1296 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
1298 reset_notification_strategy = attrib_val;
1301 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
1306 if (!wantedMajorVersion) {
1310 // Support up to GLES 3.2 depending on advertised version from the host system.
1311 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
1312 switch (majorVersion) {
1317 if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_0) {
1318 ALOGE("%s: EGL_BAD_CONFIG: no ES 3 support", __FUNCTION__);
1319 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1321 switch (minorVersion) {
1325 if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_1) {
1326 ALOGE("%s: EGL_BAD_CONFIG: no ES 3.1 support", __FUNCTION__);
1327 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1331 if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_2) {
1332 ALOGE("%s: EGL_BAD_CONFIG: no ES 3.2 support", __FUNCTION__);
1333 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1337 ALOGE("%s: EGL_BAD_CONFIG: Unknown ES version %d.%d",
1338 __FUNCTION__, majorVersion, minorVersion);
1339 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1343 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
1346 uint32_t rcShareCtx = 0;
1347 EGLContext_t * shareCtx = NULL;
1348 if (share_context) {
1349 shareCtx = static_cast<EGLContext_t*>(share_context);
1350 rcShareCtx = shareCtx->rcContext;
1351 if (shareCtx->dpy != dpy)
1352 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
1355 // We've created EGL context. Disconnecting
1356 // would be dangerous at this point.
1357 hostCon->setGrallocOnly(false);
1359 int rcMajorVersion = majorVersion;
1360 if (majorVersion == 3 && minorVersion == 1) {
1363 if (majorVersion == 3 && minorVersion == 2) {
1366 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, rcMajorVersion);
1368 ALOGE("rcCreateContext returned 0");
1369 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1372 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx, majorVersion, minorVersion);
1373 ALOGD("%s: %p: maj %d min %d rcv %d", __FUNCTION__, context, majorVersion, minorVersion, rcMajorVersion);
1375 ALOGE("could not alloc egl context!");
1376 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1379 context->rcContext = rcContext;
1383 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1385 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1386 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1388 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1390 if (!context) return EGL_TRUE;
1392 if (getEGLThreadInfo()->currentContext == context) {
1393 getEGLThreadInfo()->currentContext->deletePending = 1;
1397 if (context->rcContext) {
1398 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1399 rcEnc->rcDestroyContext(rcEnc, context->rcContext);
1400 context->rcContext = 0;
1407 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1409 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1410 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
1411 VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
1413 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1414 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1415 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1416 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
1418 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1419 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1420 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
1421 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
1422 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
1423 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
1426 // Nothing to do if no binding change has made
1428 EGLThreadInfo *tInfo = getEGLThreadInfo();
1430 if (tInfo->currentContext == context &&
1432 (context && context->draw == draw && context->read == read))) {
1436 if (tInfo->currentContext && tInfo->currentContext->deletePending) {
1437 if (tInfo->currentContext != context) {
1438 EGLContext_t * contextToDelete = tInfo->currentContext;
1439 tInfo->currentContext = 0;
1440 eglDestroyContext(dpy, contextToDelete);
1444 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
1445 //context is current to another thread
1446 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
1449 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1450 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
1451 ALOGE("rcMakeCurrent returned EGL_FALSE");
1452 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
1455 //Now make the local bind
1458 ALOGD("%s: %p: ver %d %d", __FUNCTION__, context, context->majorVersion, context->minorVersion);
1459 // This is a nontrivial context.
1460 // The thread cannot be gralloc-only anymore.
1461 hostCon->setGrallocOnly(false);
1462 context->draw = draw;
1463 context->read = read;
1464 context->flags |= EGLContext_t::IS_CURRENT;
1465 GLClientState* contextState =
1466 context->getClientState();
1468 if (!hostCon->gl2Encoder()->isInitialized()) {
1469 s_display.gles2_iface()->init();
1470 hostCon->gl2Encoder()->setInitialized();
1471 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1473 if (contextState->needsInitFromCaps()) {
1474 // Get caps for indexed buffers from host.
1475 // Some need a current context.
1476 int max_transform_feedback_separate_attribs = 0;
1477 int max_uniform_buffer_bindings = 0;
1478 int max_atomic_counter_buffer_bindings = 0;
1479 int max_shader_storage_buffer_bindings = 0;
1480 int max_vertex_attrib_bindings = 0;
1481 int max_color_attachments = 1;
1482 int max_draw_buffers = 1;
1483 if (context->majorVersion > 2) {
1484 s_display.gles2_iface()->getIntegerv(
1485 GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);
1486 s_display.gles2_iface()->getIntegerv(
1487 GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_uniform_buffer_bindings);
1488 if (context->minorVersion > 0) {
1489 s_display.gles2_iface()->getIntegerv(
1490 GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &max_atomic_counter_buffer_bindings);
1491 s_display.gles2_iface()->getIntegerv(
1492 GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &max_shader_storage_buffer_bindings);
1493 s_display.gles2_iface()->getIntegerv(
1494 GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_vertex_attrib_bindings);
1496 s_display.gles2_iface()->getIntegerv(
1497 GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
1498 s_display.gles2_iface()->getIntegerv(
1499 GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
1501 contextState->initFromCaps(
1502 max_transform_feedback_separate_attribs,
1503 max_uniform_buffer_bindings,
1504 max_atomic_counter_buffer_bindings,
1505 max_shader_storage_buffer_bindings,
1506 max_vertex_attrib_bindings,
1507 max_color_attachments,
1511 //set the client state
1512 if (context->majorVersion > 1) {
1513 hostCon->gl2Encoder()->setClientStateMakeCurrent(
1515 context->majorVersion,
1516 context->minorVersion);
1517 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
1520 hostCon->glEncoder()->setClientState(context->getClientState());
1521 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
1524 else if (tInfo->currentContext) {
1525 //release ClientState & SharedGroup
1526 if (tInfo->currentContext->majorVersion > 1) {
1527 hostCon->gl2Encoder()->setClientState(NULL);
1528 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1531 hostCon->glEncoder()->setClientState(NULL);
1532 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
1537 if (tInfo->currentContext)
1538 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
1541 tInfo->currentContext = context;
1543 //Check maybe we need to init the encoder, if it's first eglMakeCurrent
1544 if (tInfo->currentContext) {
1545 if (tInfo->currentContext->majorVersion > 1) {
1546 if (!hostCon->gl2Encoder()->isInitialized()) {
1547 s_display.gles2_iface()->init();
1548 hostCon->gl2Encoder()->setInitialized();
1549 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
1553 if (!hostCon->glEncoder()->isInitialized()) {
1554 s_display.gles_iface()->init();
1555 hostCon->glEncoder()->setInitialized();
1556 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
1564 EGLContext eglGetCurrentContext()
1566 return getEGLThreadInfo()->currentContext;
1569 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1571 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1573 return EGL_NO_SURFACE; //not an error
1577 return context->read;
1579 return context->draw;
1581 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1585 EGLDisplay eglGetCurrentDisplay()
1587 EGLContext_t * context = getEGLThreadInfo()->currentContext;
1589 return EGL_NO_DISPLAY; //not an error
1591 return context->dpy;
1594 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1596 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1597 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
1599 EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
1601 EGLBoolean ret = EGL_TRUE;
1602 switch (attribute) {
1604 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
1606 case EGL_CONTEXT_CLIENT_TYPE:
1607 *value = EGL_OPENGL_ES_API;
1609 case EGL_CONTEXT_CLIENT_VERSION:
1610 *value = context->majorVersion;
1612 case EGL_RENDER_BUFFER:
1616 *value = EGL_BACK_BUFFER; //single buffer not supported
1619 ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
1620 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1627 EGLBoolean eglWaitGL()
1629 EGLThreadInfo *tInfo = getEGLThreadInfo();
1630 if (!tInfo || !tInfo->currentContext) {
1634 if (tInfo->currentContext->majorVersion > 1) {
1635 s_display.gles2_iface()->finish();
1638 s_display.gles_iface()->finish();
1644 EGLBoolean eglWaitNative(EGLint engine)
1650 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
1652 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1653 if (eglSurface == EGL_NO_SURFACE)
1654 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
1656 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1658 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
1660 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
1663 EGLBoolean ret = d->swapBuffers();
1669 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1678 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
1687 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
1695 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1699 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
1701 if (target == EGL_NATIVE_BUFFER_ANDROID) {
1702 if (ctx != EGL_NO_CONTEXT) {
1703 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1706 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1708 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1709 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1711 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1712 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1714 cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
1716 switch (cb->format) {
1717 case HAL_PIXEL_FORMAT_RGBA_8888:
1718 case HAL_PIXEL_FORMAT_RGBX_8888:
1719 case HAL_PIXEL_FORMAT_RGB_888:
1720 case HAL_PIXEL_FORMAT_RGB_565:
1721 case HAL_PIXEL_FORMAT_YV12:
1722 case HAL_PIXEL_FORMAT_BGRA_8888:
1725 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1728 native_buffer->common.incRef(&native_buffer->common);
1730 EGLImage_t *image = new EGLImage_t();
1732 image->target = target;
1733 image->native_buffer = native_buffer;
1735 return (EGLImageKHR)image;
1737 else if (target == EGL_GL_TEXTURE_2D_KHR) {
1738 VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
1740 EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
1741 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
1743 uint32_t ctxHandle = (context) ? context->rcContext : 0;
1744 GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
1745 uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
1746 EGLImage_t *image = new EGLImage_t();
1748 image->target = target;
1749 image->host_egl_image = img;
1751 return (EGLImageKHR)image;
1754 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1757 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1759 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
1760 EGLImage_t *image = (EGLImage_t*)img;
1762 if (!image || image->dpy != dpy) {
1763 RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
1766 if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
1767 android_native_buffer_t* native_buffer = image->native_buffer;
1769 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1770 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1772 if (native_buffer->common.version != sizeof(android_native_buffer_t))
1773 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1775 native_buffer->common.decRef(&native_buffer->common);
1780 else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
1781 uint32_t host_egl_image = image->host_egl_image;
1783 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
1784 return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
1787 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
1790 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
1791 #define MAX_EGL_SYNC_ATTRIBS 10
1793 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
1794 const EGLint *attrib_list)
1796 VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
1797 DPRINT("type for eglCreateSyncKHR: 0x%x", type);
1799 DEFINE_HOST_CONNECTION;
1801 if ((type != EGL_SYNC_FENCE_KHR &&
1802 type != EGL_SYNC_NATIVE_FENCE_ANDROID) ||
1803 (type != EGL_SYNC_FENCE_KHR &&
1804 !rcEnc->hasNativeSync())) {
1805 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1808 EGLThreadInfo *tInfo = getEGLThreadInfo();
1809 if (!tInfo || !tInfo->currentContext) {
1810 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1813 int num_actual_attribs = 0;
1815 // If attrib_list is not NULL,
1816 // ensure attrib_list contains (key, value) pairs
1817 // followed by a single EGL_NONE.
1818 // Also validate attribs.
1819 int inputFenceFd = -1;
1821 for (int i = 0; i < MAX_EGL_SYNC_ATTRIBS; i += 2) {
1822 if (attrib_list[i] == EGL_NONE) {
1823 num_actual_attribs = i;
1826 if (i + 1 == MAX_EGL_SYNC_ATTRIBS) {
1827 DPRINT("ERROR: attrib list without EGL_NONE");
1828 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1832 // Validate and input attribs
1833 for (int i = 0; i < num_actual_attribs; i += 2) {
1834 if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
1835 DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
1837 if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
1838 DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
1840 if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
1841 DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
1843 EGLint attrib_key = attrib_list[i];
1844 EGLint attrib_val = attrib_list[i + 1];
1845 if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
1846 if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
1847 inputFenceFd = attrib_val;
1850 DPRINT("attrib: 0x%x : 0x%x", attrib_key, attrib_val);
1854 uint64_t sync_handle = 0;
1855 int newFenceFd = -1;
1857 if (rcEnc->hasNativeSync()) {
1859 createNativeSync(type, attrib_list, num_actual_attribs,
1860 false /* don't destroy when signaled on the host;
1861 let the guest clean this up,
1862 because the guest called eglCreateSyncKHR. */,
1867 // Just trigger a glFinish if the native sync on host
1872 EGLSync_t* syncRes = new EGLSync_t(sync_handle);
1874 if (type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
1875 syncRes->type = EGL_SYNC_NATIVE_FENCE_ANDROID;
1877 if (inputFenceFd < 0) {
1878 syncRes->android_native_fence_fd = newFenceFd;
1880 DPRINT("has input fence fd %d",
1882 syncRes->android_native_fence_fd = inputFenceFd;
1885 syncRes->type = EGL_SYNC_FENCE_KHR;
1886 syncRes->android_native_fence_fd = -1;
1887 if (!rcEnc->hasNativeSync()) {
1888 syncRes->status = EGL_SIGNALED_KHR;
1892 return (EGLSyncKHR)syncRes;
1895 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync)
1900 DPRINT("WARNING: null sync object")
1904 EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
1906 if (sync && sync->android_native_fence_fd > 0) {
1907 close(sync->android_native_fence_fd);
1908 sync->android_native_fence_fd = -1;
1912 DEFINE_HOST_CONNECTION;
1913 if (rcEnc->hasNativeSync()) {
1914 rcEnc->rcDestroySyncKHR(rcEnc, sync->handle);
1922 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags,
1928 DPRINT("WARNING: null sync object");
1929 return EGL_CONDITION_SATISFIED_KHR;
1932 EGLSync_t* sync = (EGLSync_t*)eglsync;
1934 DPRINT("sync=0x%lx (handle=0x%lx) flags=0x%x timeout=0x%llx",
1935 sync, sync->handle, flags, timeout);
1937 DEFINE_HOST_CONNECTION;
1940 if (rcEnc->hasNativeSync()) {
1941 retval = rcEnc->rcClientWaitSyncKHR
1942 (rcEnc, sync->handle, flags, timeout);
1944 retval = EGL_CONDITION_SATISFIED_KHR;
1947 switch (sync->type) {
1948 case EGL_SYNC_FENCE_KHR:
1949 res_status = EGL_SIGNALED_KHR;
1951 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1952 res_status = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
1955 res_status = EGL_SIGNALED_KHR;
1957 sync->status = res_status;
1961 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR eglsync,
1962 EGLint attribute, EGLint *value)
1966 EGLSync_t* sync = (EGLSync_t*)eglsync;
1968 switch (attribute) {
1969 case EGL_SYNC_TYPE_KHR:
1970 *value = sync->type;
1972 case EGL_SYNC_STATUS_KHR:
1973 *value = sync->status;
1975 case EGL_SYNC_CONDITION_KHR:
1976 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1979 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1983 int eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR eglsync) {
1988 EGLSync_t* sync = (EGLSync_t*)eglsync;
1989 if (sync && sync->android_native_fence_fd > 0) {
1990 int res = dup(sync->android_native_fence_fd);
1997 // TODO: Implement EGL_KHR_wait_sync
1998 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {