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