void EglManager::createContext() { EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE }; TIME_LOG("eglCreateContext", mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs)); LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, "Failed to create context, error = %s", egl_error_str()); EGL_LOGD("Created EGL context (%p)", mEglContext); }
bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) { if (CC_UNLIKELY(Properties::waitForGpuCompletion)) { ATRACE_NAME("Finishing GPU work"); fence(); } EGLint rects[4]; frame.map(screenDirty, rects); eglSwapBuffersWithDamageKHR(mEglDisplay, frame.mSurface, rects, screenDirty.isEmpty() ? 0 : 1); EGLint err = eglGetError(); if (CC_LIKELY(err == EGL_SUCCESS)) { return true; } if (err == EGL_BAD_SURFACE || err == EGL_BAD_NATIVE_WINDOW) { // For some reason our surface was destroyed out from under us // This really shouldn't happen, but if it does we can recover easily // by just not trying to use the surface anymore ALOGW("swapBuffers encountered EGL error %d on %p, halting rendering...", err, frame.mSurface); return false; } LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering", err, egl_error_str(err)); // Impossible to hit this, but the compiler doesn't know that return false; }
EGLSurface EglManager::createSurface(EGLNativeWindowType window) { initialize(); EGLSurface surface; TIME_LOG("eglCreateWindowSurface", surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL)); LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, "Failed to create EGLSurface for window %p, eglErr = %s", (void*) window, egl_error_str()); return surface; }
void EglManager::destroySurface(EGLSurface surface) { if (isCurrent(surface)) { makeCurrent(EGL_NO_SURFACE); } EGLBoolean success; TIME_LOG("eglDestroySurface", success = eglDestroySurface(mEglDisplay, surface)); if (!success) { ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str()); } }
bool EglManager::enableDirtyRegions(EGLSurface surface) { if (!mRequestDirtyRegions) return false; if (mCanSetDirtyRegions) { EGLBoolean success; TIME_LOG("eglSurfaceAttrib", success = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)); if (!success) { ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", (void*) surface, egl_error_str()); return false; } return true; } // Perhaps it is already enabled? EGLint value; EGLBoolean success; TIME_LOG("eglQuerySurface", success = eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)); if (!success) { ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", (void*) surface, egl_error_str()); return false; } return value == EGL_BUFFER_PRESERVED; }
bool EglManager::makeCurrent(EGLSurface surface) { if (isCurrent(surface)) return false; if (surface == EGL_NO_SURFACE) { // If we are setting EGL_NO_SURFACE we don't care about any of the potential // return errors, which would only happen if mEglDisplay had already been // destroyed in which case the current context is already NO_CONTEXT TIME_LOG("eglMakeCurrent", eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); } else { EGLBoolean success; TIME_LOG("eglMakeCurrent", success = eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)); if (!success) { LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", (void*)surface, egl_error_str()); } } mCurrentSurface = surface; return true; }
bool EglManager::swapBuffers(EGLSurface surface) { /// M: use basic because driver has added systrace for it nsecs_t duration; TIME_LOG_BASIC("eglSwapBuffers", eglSwapBuffers(mEglDisplay, surface), duration); EGLint err = eglGetError(); if (CC_LIKELY(err == EGL_SUCCESS)) { return true; } if (err == EGL_BAD_SURFACE) { // For some reason our surface was destroyed out from under us // This really shouldn't happen, but if it does we can recover easily // by just not trying to use the surface anymore ALOGW("swapBuffers encountered EGL_BAD_SURFACE on %p, halting rendering...", surface); return false; } LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering", err, egl_error_str(err)); // Impossible to hit this, but the compiler doesn't know that return false; }
bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) { if (isCurrent(surface)) return false; if (surface == EGL_NO_SURFACE) { // Ensure we always have a valid surface & context surface = mPBufferSurface; } if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) { if (errOut) { *errOut = eglGetError(); ALOGW("Failed to make current on surface %p, error=%s", (void*)surface, egl_error_str(*errOut)); } else { LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", (void*)surface, eglErrorString()); } } mCurrentSurface = surface; if (Properties::disableVsync) { eglSwapInterval(mEglDisplay, 0); } return true; }