status_t GLConsumer::doGLFenceWaitLocked() const { EGLDisplay dpy = eglGetCurrentDisplay(); EGLContext ctx = eglGetCurrentContext(); if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) { ST_LOGE("doGLFenceWait: invalid current EGLDisplay"); return INVALID_OPERATION; } if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) { ST_LOGE("doGLFenceWait: invalid current EGLContext"); return INVALID_OPERATION; } if (mCurrentFence->isValid()) { if (SyncFeatures::getInstance().useWaitSync()) { // Create an EGLSyncKHR from the current fence. int fenceFd = mCurrentFence->dup(); if (fenceFd == -1) { ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno); return -errno; } EGLint attribs[] = { EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE }; EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); if (sync == EGL_NO_SYNC_KHR) { close(fenceFd); ST_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError()); return UNKNOWN_ERROR; } // XXX: The spec draft is inconsistent as to whether this should // return an EGLint or void. Ignore the return value for now, as // it's not strictly needed. eglWaitSyncKHR(dpy, sync, 0); EGLint eglErr = eglGetError(); eglDestroySyncKHR(dpy, sync); if (eglErr != EGL_SUCCESS) { ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr); return UNKNOWN_ERROR; } } else { status_t err = mCurrentFence->waitForever( "GLConsumer::doGLFenceWaitLocked"); if (err != NO_ERROR) { ST_LOGE("doGLFenceWait: error waiting for fence: %d", err); return err; } } } return NO_ERROR; }
static int EGLFenceWait(EGLDisplay egl_display, int acquireFenceFd) { int ret = 0; EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, acquireFenceFd, EGL_NONE}; EGLSyncKHR egl_sync = eglCreateSyncKHR(egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); if (egl_sync == EGL_NO_SYNC_KHR) { ALOGE("Failed to make EGLSyncKHR from acquireFenceFd: %s", GetEGLError()); close(acquireFenceFd); return 1; } EGLint success = eglWaitSyncKHR(egl_display, egl_sync, 0); if (success == EGL_FALSE) { ALOGE("Failed to wait for acquire: %s", GetEGLError()); ret = 1; } eglDestroySyncKHR(egl_display, egl_sync); return ret; }
void ContextSwitchRenderer::drawWorkload() { SCOPED_TRACE(); if (mWorkload > 8) { return; // This test does not support higher workloads. } // Set the background clear color to black. glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // No culling of back faces glDisable(GL_CULL_FACE); // No depth testing glDisable(GL_DEPTH_TEST); EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL); const int TOTAL_NUM_CONTEXTS = NUM_WORKER_CONTEXTS + 1; const float TRANSLATION = 0.9f - (TOTAL_NUM_CONTEXTS * 0.2f); for (int i = 0; i < TOTAL_NUM_CONTEXTS; i++) { eglWaitSyncKHR(mEglDisplay, fence, 0); eglDestroySyncKHR(mEglDisplay, fence); glUseProgram(mProgramId); // Set the texture. glActiveTexture (GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTextureId); glUniform1i(mTextureUniformHandle, 0); // Set the x translate. glUniform1f(mTranslateUniformHandle, (i * 0.2f) + TRANSLATION); glEnableVertexAttribArray(mPositionHandle); glEnableVertexAttribArray(mTexCoordHandle); glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, false, 0, CS_VERTICES); glVertexAttribPointer(mTexCoordHandle, 2, GL_FLOAT, false, 0, CS_TEX_COORDS); glDrawArrays(GL_TRIANGLES, 0, CS_NUM_VERTICES); fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL); // Switch to next context. if (i < (mWorkload - 1)) { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i]); // Switch to FBO and re-attach. if (mOffscreen) { glBindFramebuffer(GL_FRAMEBUFFER, mFboIds[i]); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mFboDepthId); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFboTexId, 0); glViewport(0, 0, mFboWidth, mFboHeight); } } GLuint err = glGetError(); if (err != GL_NO_ERROR) { ALOGE("GLError %d in drawWorkload", err); break; } } eglWaitSyncKHR(mEglDisplay, fence, 0); eglDestroySyncKHR(mEglDisplay, fence); // Switch back to the main context. eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); if (mOffscreen) { glBindFramebuffer(GL_FRAMEBUFFER, mFboId); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mFboDepthId); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFboTexId, 0); glViewport(0, 0, mFboWidth, mFboHeight); } }