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