| // |
| // Copyright 2016 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // SurfaceEGL.cpp: EGL implementation of egl::Surface |
| |
| #include "libANGLE/renderer/gl/egl/SurfaceEGL.h" |
| |
| #include "common/debug.h" |
| |
| namespace rx |
| { |
| |
| SurfaceEGL::SurfaceEGL(const egl::SurfaceState &state, const FunctionsEGL *egl, EGLConfig config) |
| : SurfaceGL(state), |
| mEGL(egl), |
| mConfig(config), |
| mSurface(EGL_NO_SURFACE), |
| mHasSwapBuffersWithDamage(mEGL->hasExtension("EGL_KHR_swap_buffers_with_damage")) |
| {} |
| |
| SurfaceEGL::~SurfaceEGL() |
| { |
| if (mSurface != EGL_NO_SURFACE) |
| { |
| EGLBoolean success = mEGL->destroySurface(mSurface); |
| ASSERT(success == EGL_TRUE); |
| } |
| } |
| |
| egl::Error SurfaceEGL::makeCurrent(const gl::Context *context) |
| { |
| // Handling of makeCurrent is done in DisplayEGL |
| return egl::NoError(); |
| } |
| |
| egl::Error SurfaceEGL::swap(const gl::Context *context) |
| { |
| EGLBoolean success = mEGL->swapBuffers(mSurface); |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglSwapBuffers failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| egl::Error SurfaceEGL::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects) |
| { |
| EGLBoolean success; |
| if (mHasSwapBuffersWithDamage) |
| { |
| success = mEGL->swapBuffersWithDamageKHR(mSurface, rects, n_rects); |
| } |
| else |
| { |
| success = mEGL->swapBuffers(mSurface); |
| } |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglSwapBuffersWithDamageKHR failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| egl::Error SurfaceEGL::postSubBuffer(const gl::Context *context, |
| EGLint x, |
| EGLint y, |
| EGLint width, |
| EGLint height) |
| { |
| UNIMPLEMENTED(); |
| return egl::EglBadSurface(); |
| } |
| |
| egl::Error SurfaceEGL::setPresentationTime(EGLnsecsANDROID time) |
| { |
| EGLBoolean success = mEGL->presentationTimeANDROID(mSurface, time); |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglPresentationTimeANDROID failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value) |
| { |
| UNIMPLEMENTED(); |
| return egl::EglBadSurface(); |
| } |
| |
| egl::Error SurfaceEGL::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer) |
| { |
| EGLBoolean success = mEGL->bindTexImage(mSurface, buffer); |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglBindTexImage failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| egl::Error SurfaceEGL::releaseTexImage(const gl::Context *context, EGLint buffer) |
| { |
| EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer); |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglReleaseTexImage failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| void SurfaceEGL::setSwapInterval(EGLint interval) |
| { |
| EGLBoolean success = mEGL->swapInterval(interval); |
| if (success == EGL_FALSE) |
| { |
| ERR() << "eglSwapInterval error " << egl::Error(mEGL->getError()); |
| ASSERT(false); |
| } |
| } |
| |
| EGLint SurfaceEGL::getWidth() const |
| { |
| EGLint value; |
| EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value); |
| ASSERT(success == EGL_TRUE); |
| return value; |
| } |
| |
| EGLint SurfaceEGL::getHeight() const |
| { |
| EGLint value; |
| EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value); |
| ASSERT(success == EGL_TRUE); |
| return value; |
| } |
| |
| EGLint SurfaceEGL::isPostSubBufferSupported() const |
| { |
| UNIMPLEMENTED(); |
| return 0; |
| } |
| |
| EGLint SurfaceEGL::getSwapBehavior() const |
| { |
| EGLint value; |
| EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value); |
| ASSERT(success == EGL_TRUE); |
| return value; |
| } |
| |
| EGLSurface SurfaceEGL::getSurface() const |
| { |
| return mSurface; |
| } |
| |
| void SurfaceEGL::setTimestampsEnabled(bool enabled) |
| { |
| ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps")); |
| |
| EGLBoolean success = |
| mEGL->surfaceAttrib(mSurface, EGL_TIMESTAMPS_ANDROID, enabled ? EGL_TRUE : EGL_FALSE); |
| if (success == EGL_FALSE) |
| { |
| ERR() << "eglSurfaceAttribute failed: " << egl::Error(mEGL->getError()); |
| } |
| } |
| |
| egl::SupportedCompositorTimings SurfaceEGL::getSupportedCompositorTimings() const |
| { |
| ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps")); |
| |
| egl::SupportedCompositorTimings result; |
| for (egl::CompositorTiming name : angle::AllEnums<egl::CompositorTiming>()) |
| { |
| result[name] = mEGL->getCompositorTimingSupportedANDROID(mSurface, egl::ToEGLenum(name)); |
| } |
| return result; |
| } |
| |
| egl::Error SurfaceEGL::getCompositorTiming(EGLint numTimestamps, |
| const EGLint *names, |
| EGLnsecsANDROID *values) const |
| { |
| ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps")); |
| |
| EGLBoolean success = mEGL->getCompositorTimingANDROID(mSurface, numTimestamps, names, values); |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglGetCompositorTimingANDROID failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| egl::Error SurfaceEGL::getNextFrameId(EGLuint64KHR *frameId) const |
| { |
| ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps")); |
| |
| EGLBoolean success = mEGL->getNextFrameIdANDROID(mSurface, frameId); |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglGetNextFrameId failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| egl::SupportedTimestamps SurfaceEGL::getSupportedTimestamps() const |
| { |
| ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps")); |
| |
| egl::SupportedTimestamps result; |
| for (egl::Timestamp timestamp : angle::AllEnums<egl::Timestamp>()) |
| { |
| result[timestamp] = |
| mEGL->getFrameTimestampSupportedANDROID(mSurface, egl::ToEGLenum(timestamp)); |
| } |
| return result; |
| } |
| |
| egl::Error SurfaceEGL::getFrameTimestamps(EGLuint64KHR frameId, |
| EGLint numTimestamps, |
| const EGLint *timestamps, |
| EGLnsecsANDROID *values) const |
| { |
| ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps")); |
| |
| // The driver may return EGL_BAD_ACCESS at any time if the requested frame is no longer stored. |
| EGLBoolean success = |
| mEGL->getFrameTimestampsANDROID(mSurface, frameId, numTimestamps, timestamps, values); |
| if (success == EGL_FALSE) |
| { |
| return egl::Error(mEGL->getError(), "eglGetFrameTimestampsANDROID failed"); |
| } |
| return egl::NoError(); |
| } |
| |
| } // namespace rx |