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