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> 37 static T setErrorFunc(GLint error, T returnValue) { 38 getEGLThreadInfo()->eglError = error; 39 return returnValue; 40 } 41 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 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 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; 185 uint32_t getRcSurface() { return rcSurface; } 186 EGLint getSurfaceType() { return surfaceType; } 187 188 EGLint getWidth(){ return width; } 189 EGLint getHeight(){ return height; } 190 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; } 191 EGLint getTextureFormat() { return texFormat; } 192 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; } 193 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: 205 void setWidth(EGLint w) { width = w; } 206 void setHeight(EGLint h) { height = h; } 207 208 EGLint surfaceType; 209 uint32_t rcSurface; //handle to surface created via remote control 210 }; 211 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 221 EGLint egl_surface_t::getSwapBehavior() const { 222 return EGL_BUFFER_PRESERVED; 223 } 224 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 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 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 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 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 308 void egl_window_surface_t::setSwapInterval(int interval) 309 { 310 nativeWindow->setSwapInterval(nativeWindow, interval); 311 } 312 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 343 virtual void setSwapInterval(int interval) { (void)interval; } 344 virtual EGLBoolean swapBuffers() { return EGL_TRUE; } 345 346 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 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 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 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 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 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__) 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 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 513 EGLBoolean eglTerminate(EGLDisplay dpy) 514 { 515 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 516 517 s_display.terminate(); 518 return EGL_TRUE; 519 } 520 521 EGLint eglGetError() 522 { 523 EGLint error = getEGLThreadInfo()->eglError; 524 getEGLThreadInfo()->eglError = EGL_SUCCESS; 525 return error; 526 } 527 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 544 const char* eglQueryString(EGLDisplay dpy, EGLint name) 545 { 546 VALIDATE_DISPLAY_INIT(dpy, NULL); 547 548 return s_display.queryString(name); 549 } 550 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 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 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 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 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 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 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 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 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 787 EGLenum eglQueryAPI() 788 { 789 return EGL_OPENGL_ES_API; 790 } 791 792 EGLBoolean eglWaitClient() 793 { 794 return eglWaitGL(); 795 } 796 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 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 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 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 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 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 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 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 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 1076 EGLContext eglGetCurrentContext() 1077 { 1078 return getEGLThreadInfo()->currentContext; 1079 } 1080 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 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 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 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 1156 EGLBoolean eglWaitNative(EGLint engine) 1157 { 1158 (void)engine; 1159 return EGL_TRUE; 1160 } 1161 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 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 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 1199 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface) 1200 { 1201 //TODO later 1202 (void)display; 1203 (void)surface; 1204 return 0; 1205 } 1206 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 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 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 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 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 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