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 #include "HostConnection.h" 17 #include "ThreadInfo.h" 18 #include "eglDisplay.h" 19 #include "egl_ftable.h" 20 #include <cutils/log.h> 21 #include "gralloc_cb.h" 22 #include "GLClientState.h" 23 #include "GLSharedGroup.h" 24 #include "eglContext.h" 25 #include "ClientAPIExts.h" 26 27 #include "GLEncoder.h" 28 #ifdef WITH_GLES2 29 #include "GL2Encoder.h" 30 #endif 31 32 #include <private/ui/android_natives_priv.h> 33 34 template<typename T> 35 static T setErrorFunc(GLint error, T returnValue) { 36 getEGLThreadInfo()->eglError = error; 37 return returnValue; 38 } 39 40 const char * eglStrError(EGLint err) 41 { 42 switch (err){ 43 case EGL_SUCCESS: return "EGL_SUCCESS"; 44 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 45 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 46 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 47 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 48 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 49 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 50 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 51 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 52 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 53 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 54 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 55 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 56 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 57 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 58 default: return "UNKNOWN"; 59 } 60 } 61 62 #define LOG_EGL_ERRORS 1 63 64 #ifdef LOG_EGL_ERRORS 65 66 #define setErrorReturn(error, retVal) \ 67 { \ 68 LOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \ 69 return setErrorFunc(error, retVal); \ 70 } 71 72 #define RETURN_ERROR(ret,err) \ 73 LOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \ 74 getEGLThreadInfo()->eglError = err; \ 75 return ret; 76 77 #else //!LOG_EGL_ERRORS 78 79 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal); 80 81 #define RETURN_ERROR(ret,err) \ 82 getEGLThreadInfo()->eglError = err; \ 83 return ret; 84 85 #endif //LOG_EGL_ERRORS 86 87 #define VALIDATE_CONFIG(cfg,ret) \ 88 if(((int)cfg<0)||((int)cfg>s_display.getNumConfigs())) { \ 89 RETURN_ERROR(ret,EGL_BAD_CONFIG); \ 90 } 91 92 #define VALIDATE_DISPLAY(dpy,ret) \ 93 if ((dpy) != (EGLDisplay)&s_display) { \ 94 RETURN_ERROR(ret, EGL_BAD_DISPLAY); \ 95 } 96 97 #define VALIDATE_DISPLAY_INIT(dpy,ret) \ 98 VALIDATE_DISPLAY(dpy, ret) \ 99 if (!s_display.initialized()) { \ 100 RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \ 101 } 102 103 #define DEFINE_HOST_CONNECTION \ 104 HostConnection *hostCon = HostConnection::get(); \ 105 renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL) 106 107 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \ 108 HostConnection *hostCon = HostConnection::get(); \ 109 if (!hostCon) { \ 110 LOGE("egl: Failed to get host connection\n"); \ 111 return ret; \ 112 } \ 113 renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \ 114 if (!rcEnc) { \ 115 LOGE("egl: Failed to get renderControl encoder context\n"); \ 116 return ret; \ 117 } 118 119 #define VALIDATE_CONTEXT_RETURN(context,ret) \ 120 if (!context) { \ 121 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \ 122 } 123 124 #define VALIDATE_SURFACE_RETURN(surface, ret) \ 125 if (surface != EGL_NO_SURFACE) { \ 126 egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \ 127 if (s->dpy != (EGLDisplay)&s_display) \ 128 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \ 129 } 130 131 132 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) : 133 dpy(dpy), 134 config(config), 135 read(EGL_NO_SURFACE), 136 draw(EGL_NO_SURFACE), 137 shareCtx(shareCtx), 138 rcContext(0), 139 versionString(NULL), 140 vendorString(NULL), 141 rendererString(NULL), 142 extensionString(NULL) 143 { 144 flags = 0; 145 version = 1; 146 clientState = new GLClientState(); 147 if (shareCtx) 148 sharedGroup = shareCtx->getSharedGroup(); 149 else 150 sharedGroup = GLSharedGroupPtr(new GLSharedGroup()); 151 }; 152 153 EGLContext_t::~EGLContext_t() 154 { 155 delete clientState; 156 delete [] versionString; 157 delete [] vendorString; 158 delete [] rendererString; 159 delete [] extensionString; 160 } 161 162 // ---------------------------------------------------------------------------- 163 //egl_surface_t 164 165 //we don't need to handle depth since it's handled when window created on the host 166 167 struct egl_surface_t { 168 169 EGLDisplay dpy; 170 EGLConfig config; 171 172 173 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType); 174 virtual ~egl_surface_t(); 175 176 virtual void setSwapInterval(int interval) = 0; 177 virtual EGLBoolean swapBuffers() = 0; 178 179 EGLint getSwapBehavior() const; 180 uint32_t getRcSurface() { return rcSurface; } 181 EGLint getSurfaceType() { return surfaceType; } 182 183 EGLint getWidth(){ return width; } 184 EGLint getHeight(){ return height; } 185 void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; } 186 EGLint getTextureFormat() { return texFormat; } 187 void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; } 188 EGLint getTextureTarget() { return texTarget; } 189 190 private: 191 // 192 //Surface attributes 193 // 194 EGLint width; 195 EGLint height; 196 EGLint texFormat; 197 EGLint texTarget; 198 199 protected: 200 void setWidth(EGLint w) { width = w; } 201 void setHeight(EGLint h) { height = h; } 202 203 EGLint surfaceType; 204 uint32_t rcSurface; //handle to surface created via remote control 205 }; 206 207 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType) 208 : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0) 209 { 210 width = 0; 211 height = 0; 212 texFormat = EGL_NO_TEXTURE; 213 texTarget = EGL_NO_TEXTURE; 214 } 215 216 EGLint egl_surface_t::getSwapBehavior() const { 217 return EGL_BUFFER_PRESERVED; 218 } 219 220 egl_surface_t::~egl_surface_t() 221 { 222 } 223 224 // ---------------------------------------------------------------------------- 225 // egl_window_surface_t 226 227 struct egl_window_surface_t : public egl_surface_t { 228 static egl_window_surface_t* create( 229 EGLDisplay dpy, EGLConfig config, EGLint surfType, 230 ANativeWindow* window); 231 232 virtual ~egl_window_surface_t(); 233 234 virtual void setSwapInterval(int interval); 235 virtual EGLBoolean swapBuffers(); 236 237 private: 238 egl_window_surface_t( 239 EGLDisplay dpy, EGLConfig config, EGLint surfType, 240 ANativeWindow* window); 241 EGLBoolean init(); 242 243 ANativeWindow* nativeWindow; 244 android_native_buffer_t* buffer; 245 }; 246 247 egl_window_surface_t::egl_window_surface_t ( 248 EGLDisplay dpy, EGLConfig config, EGLint surfType, 249 ANativeWindow* window) 250 : egl_surface_t(dpy, config, surfType), 251 nativeWindow(window), 252 buffer(NULL) 253 { 254 // keep a reference on the window 255 nativeWindow->common.incRef(&nativeWindow->common); 256 EGLint w,h; 257 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &w); 258 setWidth(w); 259 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &h); 260 setHeight(h); 261 } 262 263 EGLBoolean egl_window_surface_t::init() 264 { 265 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) { 266 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE); 267 } 268 nativeWindow->lockBuffer(nativeWindow, buffer); 269 270 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 271 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config, 272 getWidth(), getHeight()); 273 if (!rcSurface) { 274 LOGE("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 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 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(nativeWindow, buffer); 303 } 304 nativeWindow->common.decRef(&nativeWindow->common); 305 } 306 307 void egl_window_surface_t::setSwapInterval(int interval) 308 { 309 nativeWindow->setSwapInterval(nativeWindow, interval); 310 } 311 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(nativeWindow, buffer); 319 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) { 320 buffer = NULL; 321 setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE); 322 } 323 nativeWindow->lockBuffer(nativeWindow, buffer); 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 340 virtual void setSwapInterval(int interval) {} 341 virtual EGLBoolean swapBuffers() { return EGL_TRUE; } 342 343 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 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 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 371 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat) 372 { 373 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 374 375 rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config, 376 getWidth(), getHeight()); 377 if (!rcSurface) { 378 LOGE("rcCreateWindowSurface returned 0"); 379 return EGL_FALSE; 380 } 381 382 rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), 383 pixelFormat); 384 if (!rcColorBuffer) { 385 LOGE("rcCreateColorBuffer returned 0"); 386 return EGL_FALSE; 387 } 388 389 rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer); 390 391 return EGL_TRUE; 392 } 393 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 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__) 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 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 506 EGLBoolean eglTerminate(EGLDisplay dpy) 507 { 508 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 509 510 s_display.terminate(); 511 return EGL_TRUE; 512 } 513 514 EGLint eglGetError() 515 { 516 EGLint error = getEGLThreadInfo()->eglError; 517 getEGLThreadInfo()->eglError = EGL_SUCCESS; 518 return error; 519 } 520 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 // 531 // Make sure display is initialized before searching in client APIs 532 // 533 if (!s_display.initialized()) { 534 if (!s_display.initialize(&s_eglIface)) { 535 return NULL; 536 } 537 } 538 539 // look in gles client api's extensions table 540 return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname); 541 542 // Fail - function not found. 543 return NULL; 544 } 545 546 const char* eglQueryString(EGLDisplay dpy, EGLint name) 547 { 548 VALIDATE_DISPLAY_INIT(dpy, NULL); 549 550 return s_display.queryString(name); 551 } 552 553 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) 554 { 555 VALIDATE_DISPLAY_INIT(dpy, NULL); 556 557 if(!num_config) { 558 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); 559 } 560 561 GLint numConfigs = s_display.getNumConfigs(); 562 if (!configs) { 563 *num_config = numConfigs; 564 return EGL_TRUE; 565 } 566 567 int i=0; 568 for (i=0 ; i<numConfigs && i<config_size ; i++) { 569 *configs++ = (EGLConfig)i; 570 } 571 *num_config = i; 572 return EGL_TRUE; 573 } 574 575 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) 576 { 577 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 578 579 int attribs_size = 0; 580 if (attrib_list) { 581 const EGLint * attrib_p = attrib_list; 582 while (attrib_p[0] != EGL_NONE) { 583 attribs_size += 2; 584 attrib_p += 2; 585 } 586 attribs_size++; //for the terminating EGL_NONE 587 } 588 589 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 590 *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)configs, config_size); 591 592 return EGL_TRUE; 593 } 594 595 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) 596 { 597 VALIDATE_DISPLAY_INIT(dpy, NULL); 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 610 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) 611 { 612 VALIDATE_DISPLAY_INIT(dpy, NULL); 613 VALIDATE_CONFIG(config, EGL_FALSE); 614 if (win == 0) { 615 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE); 616 } 617 618 EGLint surfaceType; 619 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE; 620 621 if (!(surfaceType & EGL_WINDOW_BIT)) { 622 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE); 623 } 624 625 if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { 626 setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 627 } 628 629 egl_surface_t* surface = egl_window_surface_t::create( 630 &s_display, config, surfaceType, static_cast<ANativeWindow*>(win)); 631 if (!surface) { 632 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE); 633 } 634 635 return surface; 636 } 637 638 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) 639 { 640 VALIDATE_DISPLAY_INIT(dpy, NULL); 641 VALIDATE_CONFIG(config, EGL_FALSE); 642 643 EGLint surfaceType; 644 if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE; 645 646 if (!(surfaceType & EGL_PBUFFER_BIT)) { 647 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE); 648 } 649 650 int32_t w = 0; 651 int32_t h = 0; 652 EGLint texFormat = EGL_NO_TEXTURE; 653 EGLint texTarget = EGL_NO_TEXTURE; 654 while (attrib_list[0]) { 655 switch (attrib_list[0]) { 656 case EGL_WIDTH: 657 w = attrib_list[1]; 658 break; 659 case EGL_HEIGHT: 660 h = attrib_list[1]; 661 break; 662 case EGL_TEXTURE_FORMAT: 663 texFormat = attrib_list[1]; 664 break; 665 case EGL_TEXTURE_TARGET: 666 texTarget = attrib_list[1]; 667 break; 668 default: 669 break; 670 }; 671 attrib_list+=2; 672 } 673 if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) || 674 ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) { 675 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE); 676 } 677 // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage 678 679 GLenum pixelFormat; 680 if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE) 681 setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE); 682 683 egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config, 684 surfaceType, w, h, pixelFormat); 685 if (!surface) { 686 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE); 687 } 688 689 //setup attributes 690 surface->setTextureFormat(texFormat); 691 surface->setTextureTarget(texTarget); 692 693 return surface; 694 } 695 696 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) 697 { 698 //XXX: Pixmap not supported. The host cannot render to a pixmap resource 699 // located on host. In order to support Pixmaps we should either punt 700 // to s/w rendering -or- let the host render to a buffer that will be 701 // copied back to guest at some sync point. None of those methods not 702 // implemented and pixmaps are not used with OpenGL anyway ... 703 return EGL_NO_SURFACE; 704 } 705 706 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) 707 { 708 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 709 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE); 710 711 egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface)); 712 delete surface; 713 714 return EGL_TRUE; 715 } 716 717 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value) 718 { 719 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 720 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE); 721 722 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) ); 723 EGLBoolean ret = EGL_TRUE; 724 switch (attribute) { 725 case EGL_CONFIG_ID: 726 ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value); 727 break; 728 case EGL_WIDTH: 729 *value = surface->getWidth(); 730 break; 731 case EGL_HEIGHT: 732 *value = surface->getHeight(); 733 break; 734 case EGL_TEXTURE_FORMAT: 735 *value = surface->getTextureFormat(); 736 break; 737 case EGL_TEXTURE_TARGET: 738 *value = surface->getTextureTarget(); 739 break; 740 case EGL_SWAP_BEHAVIOR: 741 *value = surface->getSwapBehavior(); 742 break; 743 case EGL_LARGEST_PBUFFER: 744 // not modified for a window or pixmap surface 745 // and we ignore it when creating a PBuffer surface (default is EGL_FALSE) 746 if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE; 747 break; 748 //TODO: complete other attributes 749 default: 750 LOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute); 751 ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE); 752 break; 753 } 754 755 return ret; 756 } 757 758 EGLBoolean eglBindAPI(EGLenum api) 759 { 760 if (api != EGL_OPENGL_ES_API) 761 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE); 762 return EGL_TRUE; 763 } 764 765 EGLenum eglQueryAPI() 766 { 767 return EGL_OPENGL_ES_API; 768 } 769 770 EGLBoolean eglWaitClient() 771 { 772 return eglWaitGL(); 773 } 774 775 EGLBoolean eglReleaseThread() 776 { 777 EGLThreadInfo *tInfo = getEGLThreadInfo(); 778 if (tInfo && tInfo->currentContext) { 779 return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); 780 } 781 return EGL_TRUE; 782 } 783 784 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) 785 { 786 //TODO 787 LOGW("%s not implemented", __FUNCTION__); 788 return 0; 789 } 790 791 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 792 { 793 //TODO 794 LOGW("%s not implemented", __FUNCTION__); 795 return 0; 796 } 797 798 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer) 799 { 800 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 801 VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE); 802 if (eglSurface == EGL_NO_SURFACE) { 803 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); 804 } 805 806 if (buffer != EGL_BACK_BUFFER) { 807 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE); 808 } 809 810 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) ); 811 812 if (surface->getTextureFormat() == EGL_NO_TEXTURE) { 813 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE); 814 } 815 816 if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) { 817 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); 818 } 819 820 //It's now safe to cast to pbuffer surface 821 egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface; 822 823 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 824 rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer()); 825 826 return GL_TRUE; 827 } 828 829 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 830 { 831 //TODO 832 LOGW("%s not implemented", __FUNCTION__); 833 return 0; 834 } 835 836 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 837 { 838 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 839 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 840 841 EGLContext_t* ctx = getEGLThreadInfo()->currentContext; 842 if (!ctx) { 843 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE); 844 } 845 if (!ctx->draw) { 846 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); 847 } 848 egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw)); 849 draw->setSwapInterval(interval); 850 851 rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host 852 853 return EGL_TRUE; 854 } 855 856 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) 857 { 858 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT); 859 VALIDATE_CONFIG(config, EGL_NO_CONTEXT); 860 861 EGLint version = 1; //default 862 while (attrib_list && attrib_list[0]) { 863 if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1]; 864 attrib_list+=2; 865 } 866 867 uint32_t rcShareCtx = 0; 868 EGLContext_t * shareCtx = NULL; 869 if (share_context) { 870 shareCtx = static_cast<EGLContext_t*>(share_context); 871 rcShareCtx = shareCtx->rcContext; 872 if (shareCtx->dpy != dpy) 873 setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT); 874 } 875 876 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT); 877 uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uint32_t)config, rcShareCtx, version); 878 if (!rcContext) { 879 LOGE("rcCreateContext returned 0"); 880 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT); 881 } 882 883 EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx); 884 if (!context) 885 setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT); 886 887 context->version = version; 888 context->rcContext = rcContext; 889 890 891 return context; 892 } 893 894 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 895 { 896 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 897 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE); 898 899 EGLContext_t * context = static_cast<EGLContext_t*>(ctx); 900 901 if (getEGLThreadInfo()->currentContext == context) 902 { 903 eglMakeCurrent(dpy, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); 904 } 905 906 if (context->rcContext) { 907 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 908 rcEnc->rcDestroyContext(rcEnc, context->rcContext); 909 context->rcContext = 0; 910 } 911 912 delete context; 913 return EGL_TRUE; 914 } 915 916 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) 917 { 918 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 919 VALIDATE_SURFACE_RETURN(draw, EGL_FALSE); 920 VALIDATE_SURFACE_RETURN(read, EGL_FALSE); 921 922 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) 923 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE); 924 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT)) 925 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE); 926 927 EGLContext_t * context = static_cast<EGLContext_t*>(ctx); 928 uint32_t ctxHandle = (context) ? context->rcContext : 0; 929 egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw); 930 uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0; 931 egl_surface_t * readSurf = static_cast<egl_surface_t *>(read); 932 uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0; 933 934 // 935 // Nothing to do if no binding change has made 936 // 937 EGLThreadInfo *tInfo = getEGLThreadInfo(); 938 if (tInfo->currentContext == context && 939 (context == NULL || 940 (context && context->draw == draw && context->read == read))) { 941 return EGL_TRUE; 942 } 943 944 if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) { 945 //context is current to another thread 946 setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE); 947 } 948 949 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 950 if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) { 951 LOGE("rcMakeCurrent returned EGL_FALSE"); 952 setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE); 953 } 954 955 //Now make the local bind 956 if (context) { 957 context->draw = draw; 958 context->read = read; 959 context->flags |= EGLContext_t::IS_CURRENT; 960 //set the client state 961 if (context->version == 2) { 962 hostCon->gl2Encoder()->setClientState(context->getClientState()); 963 hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup()); 964 } 965 else { 966 hostCon->glEncoder()->setClientState(context->getClientState()); 967 hostCon->glEncoder()->setSharedGroup(context->getSharedGroup()); 968 } 969 } 970 else { 971 //release ClientState & SharedGroup 972 if (tInfo->currentContext->version == 2) { 973 hostCon->gl2Encoder()->setClientState(NULL); 974 hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL)); 975 } 976 else { 977 hostCon->glEncoder()->setClientState(NULL); 978 hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL)); 979 } 980 981 } 982 983 if (tInfo->currentContext) 984 tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT; 985 986 //Now make current 987 tInfo->currentContext = context; 988 989 //Check maybe we need to init the encoder, if it's first eglMakeCurrent 990 if (tInfo->currentContext) { 991 if (tInfo->currentContext->version == 2) { 992 if (!hostCon->gl2Encoder()->isInitialized()) { 993 s_display.gles2_iface()->init(); 994 hostCon->gl2Encoder()->setInitialized(); 995 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1); 996 } 997 } 998 else { 999 if (!hostCon->glEncoder()->isInitialized()) { 1000 s_display.gles_iface()->init(); 1001 hostCon->glEncoder()->setInitialized(); 1002 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0); 1003 } 1004 } 1005 } 1006 1007 return EGL_TRUE; 1008 } 1009 1010 EGLContext eglGetCurrentContext() 1011 { 1012 return getEGLThreadInfo()->currentContext; 1013 } 1014 1015 EGLSurface eglGetCurrentSurface(EGLint readdraw) 1016 { 1017 EGLContext_t * context = getEGLThreadInfo()->currentContext; 1018 if (!context) 1019 return EGL_NO_SURFACE; //not an error 1020 1021 switch (readdraw) { 1022 case EGL_READ: 1023 return context->read; 1024 case EGL_DRAW: 1025 return context->draw; 1026 default: 1027 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1028 } 1029 } 1030 1031 EGLDisplay eglGetCurrentDisplay() 1032 { 1033 EGLContext_t * context = getEGLThreadInfo()->currentContext; 1034 if (!context) 1035 return EGL_NO_DISPLAY; //not an error 1036 1037 return context->dpy; 1038 } 1039 1040 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) 1041 { 1042 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 1043 VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE); 1044 1045 EGLContext_t * context = static_cast<EGLContext_t*>(ctx); 1046 1047 EGLBoolean ret = EGL_TRUE; 1048 switch (attribute) { 1049 case EGL_CONFIG_ID: 1050 ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value); 1051 break; 1052 case EGL_CONTEXT_CLIENT_TYPE: 1053 *value = EGL_OPENGL_ES_API; 1054 break; 1055 case EGL_CONTEXT_CLIENT_VERSION: 1056 *value = context->version; 1057 break; 1058 case EGL_RENDER_BUFFER: 1059 if (!context->draw) 1060 *value = EGL_NONE; 1061 else 1062 *value = EGL_BACK_BUFFER; //single buffer not supported 1063 break; 1064 default: 1065 LOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute); 1066 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1067 break; 1068 } 1069 1070 return ret; 1071 } 1072 1073 EGLBoolean eglWaitGL() 1074 { 1075 EGLThreadInfo *tInfo = getEGLThreadInfo(); 1076 if (!tInfo || !tInfo->currentContext) { 1077 return EGL_FALSE; 1078 } 1079 1080 if (tInfo->currentContext->version == 2) { 1081 s_display.gles2_iface()->finish(); 1082 } 1083 else { 1084 s_display.gles_iface()->finish(); 1085 } 1086 1087 return EGL_TRUE; 1088 } 1089 1090 EGLBoolean eglWaitNative(EGLint engine) 1091 { 1092 return EGL_TRUE; 1093 } 1094 1095 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface) 1096 { 1097 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 1098 if (eglSurface == EGL_NO_SURFACE) 1099 setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); 1100 1101 DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); 1102 1103 egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface); 1104 if (d->dpy != dpy) 1105 setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); 1106 1107 // post the surface 1108 d->swapBuffers(); 1109 1110 hostCon->flush(); 1111 return EGL_TRUE; 1112 } 1113 1114 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) 1115 { 1116 //TODO :later 1117 return 0; 1118 } 1119 1120 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list) 1121 { 1122 //TODO later 1123 return 0; 1124 } 1125 1126 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface) 1127 { 1128 //TODO later 1129 return 0; 1130 } 1131 1132 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) 1133 { 1134 VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR); 1135 if (ctx != EGL_NO_CONTEXT) { 1136 setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1137 } 1138 if (target != EGL_NATIVE_BUFFER_ANDROID) { 1139 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1140 } 1141 1142 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer; 1143 1144 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) 1145 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1146 1147 if (native_buffer->common.version != sizeof(android_native_buffer_t)) 1148 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1149 1150 switch (native_buffer->format) { 1151 case HAL_PIXEL_FORMAT_RGBA_8888: 1152 case HAL_PIXEL_FORMAT_RGBX_8888: 1153 case HAL_PIXEL_FORMAT_RGB_888: 1154 case HAL_PIXEL_FORMAT_RGB_565: 1155 case HAL_PIXEL_FORMAT_BGRA_8888: 1156 case HAL_PIXEL_FORMAT_RGBA_5551: 1157 case HAL_PIXEL_FORMAT_RGBA_4444: 1158 break; 1159 default: 1160 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1161 } 1162 1163 native_buffer->common.incRef(&native_buffer->common); 1164 return (EGLImageKHR)native_buffer; 1165 } 1166 1167 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1168 { 1169 VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); 1170 android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; 1171 1172 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) 1173 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE); 1174 1175 if (native_buffer->common.version != sizeof(android_native_buffer_t)) 1176 setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE); 1177 1178 native_buffer->common.decRef(&native_buffer->common); 1179 1180 return EGL_TRUE; 1181 } 1182 1183 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1184 { 1185 //TODO later 1186 return 0; 1187 } 1188 1189 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1190 { 1191 //TODO later 1192 return 0; 1193 } 1194 1195 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 1196 { 1197 //TODO 1198 return 0; 1199 } 1200 1201 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) 1202 { 1203 //TODO later 1204 return 0; 1205 } 1206 1207 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 1208 { 1209 //TODO later 1210 return 0; 1211 } 1212