xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // SurfaceEGL.cpp: EGL implementation of egl::Surface
8 
9 #include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
10 
11 #include "common/debug.h"
12 #include "libANGLE/Display.h"
13 
14 namespace rx
15 {
16 
SurfaceEGL(const egl::SurfaceState & state,const FunctionsEGL * egl,EGLConfig config)17 SurfaceEGL::SurfaceEGL(const egl::SurfaceState &state, const FunctionsEGL *egl, EGLConfig config)
18     : SurfaceGL(state),
19       mEGL(egl),
20       mConfig(config),
21       mSurface(EGL_NO_SURFACE),
22       mHasSwapBuffersWithDamage(mEGL->hasExtension("EGL_KHR_swap_buffers_with_damage"))
23 {}
24 
~SurfaceEGL()25 SurfaceEGL::~SurfaceEGL()
26 {
27     if (mSurface != EGL_NO_SURFACE)
28     {
29         EGLBoolean success = mEGL->destroySurface(mSurface);
30         ASSERT(success == EGL_TRUE);
31     }
32 }
33 
makeCurrent(const gl::Context * context)34 egl::Error SurfaceEGL::makeCurrent(const gl::Context *context)
35 {
36     // Handling of makeCurrent is done in DisplayEGL
37     return egl::NoError();
38 }
39 
swap(const gl::Context * context)40 egl::Error SurfaceEGL::swap(const gl::Context *context)
41 {
42     egl::Display::GetCurrentThreadUnlockedTailCall()->add(
43         [egl = mEGL, surface = mSurface](void *resultOut) {
44             ANGLE_UNUSED_VARIABLE(resultOut);
45             *static_cast<EGLBoolean *>(resultOut) = egl->swapBuffers(surface);
46         });
47 
48     return egl::NoError();
49 }
50 
swapWithDamage(const gl::Context * context,const EGLint * rects,EGLint n_rects)51 egl::Error SurfaceEGL::swapWithDamage(const gl::Context *context,
52                                       const EGLint *rects,
53                                       EGLint n_rects)
54 {
55     if (mHasSwapBuffersWithDamage)
56     {
57         egl::Display::GetCurrentThreadUnlockedTailCall()->add(
58             [egl = mEGL, surface = mSurface, rects, n_rects](void *resultOut) {
59                 ANGLE_UNUSED_VARIABLE(resultOut);
60                 *static_cast<EGLBoolean *>(resultOut) =
61                     egl->swapBuffersWithDamageKHR(surface, rects, n_rects);
62             });
63     }
64     else
65     {
66         egl::Display::GetCurrentThreadUnlockedTailCall()->add(
67             [egl = mEGL, surface = mSurface](void *resultOut) {
68                 ANGLE_UNUSED_VARIABLE(resultOut);
69                 *static_cast<EGLBoolean *>(resultOut) = egl->swapBuffers(surface);
70             });
71     }
72 
73     return egl::NoError();
74 }
75 
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)76 egl::Error SurfaceEGL::postSubBuffer(const gl::Context *context,
77                                      EGLint x,
78                                      EGLint y,
79                                      EGLint width,
80                                      EGLint height)
81 {
82     UNIMPLEMENTED();
83     return egl::EglBadSurface();
84 }
85 
setPresentationTime(EGLnsecsANDROID time)86 egl::Error SurfaceEGL::setPresentationTime(EGLnsecsANDROID time)
87 {
88     EGLBoolean success = mEGL->presentationTimeANDROID(mSurface, time);
89     if (success == EGL_FALSE)
90     {
91         return egl::Error(mEGL->getError(), "eglPresentationTimeANDROID failed");
92     }
93     return egl::NoError();
94 }
95 
querySurfacePointerANGLE(EGLint attribute,void ** value)96 egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value)
97 {
98     UNIMPLEMENTED();
99     return egl::EglBadSurface();
100 }
101 
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)102 egl::Error SurfaceEGL::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
103 {
104     EGLBoolean success = mEGL->bindTexImage(mSurface, buffer);
105     if (success == EGL_FALSE)
106     {
107         return egl::Error(mEGL->getError(), "eglBindTexImage failed");
108     }
109     return egl::NoError();
110 }
111 
releaseTexImage(const gl::Context * context,EGLint buffer)112 egl::Error SurfaceEGL::releaseTexImage(const gl::Context *context, EGLint buffer)
113 {
114     EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer);
115     if (success == EGL_FALSE)
116     {
117         return egl::Error(mEGL->getError(), "eglReleaseTexImage failed");
118     }
119     return egl::NoError();
120 }
121 
setSwapInterval(const egl::Display * display,EGLint interval)122 void SurfaceEGL::setSwapInterval(const egl::Display *display, EGLint interval)
123 {
124     EGLBoolean success = mEGL->swapInterval(interval);
125     if (success == EGL_FALSE)
126     {
127         ERR() << "eglSwapInterval error " << egl::Error(mEGL->getError());
128         ASSERT(false);
129     }
130 }
131 
getWidth() const132 EGLint SurfaceEGL::getWidth() const
133 {
134     EGLint value;
135     EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value);
136     ASSERT(success == EGL_TRUE);
137     return value;
138 }
139 
getHeight() const140 EGLint SurfaceEGL::getHeight() const
141 {
142     EGLint value;
143     EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value);
144     ASSERT(success == EGL_TRUE);
145     return value;
146 }
147 
isPostSubBufferSupported() const148 EGLint SurfaceEGL::isPostSubBufferSupported() const
149 {
150     UNIMPLEMENTED();
151     return 0;
152 }
153 
getSwapBehavior() const154 EGLint SurfaceEGL::getSwapBehavior() const
155 {
156     EGLint value;
157     EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value);
158     ASSERT(success == EGL_TRUE);
159     return value;
160 }
161 
getSurface() const162 EGLSurface SurfaceEGL::getSurface() const
163 {
164     return mSurface;
165 }
166 
setTimestampsEnabled(bool enabled)167 void SurfaceEGL::setTimestampsEnabled(bool enabled)
168 {
169     ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
170 
171     EGLBoolean success =
172         mEGL->surfaceAttrib(mSurface, EGL_TIMESTAMPS_ANDROID, enabled ? EGL_TRUE : EGL_FALSE);
173     if (success == EGL_FALSE)
174     {
175         ERR() << "eglSurfaceAttribute failed: " << egl::Error(mEGL->getError());
176     }
177 }
178 
getSupportedCompositorTimings() const179 egl::SupportedCompositorTimings SurfaceEGL::getSupportedCompositorTimings() const
180 {
181     ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
182 
183     egl::SupportedCompositorTimings result;
184     for (egl::CompositorTiming name : angle::AllEnums<egl::CompositorTiming>())
185     {
186         result[name] = mEGL->getCompositorTimingSupportedANDROID(mSurface, egl::ToEGLenum(name));
187     }
188     return result;
189 }
190 
getCompositorTiming(EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values) const191 egl::Error SurfaceEGL::getCompositorTiming(EGLint numTimestamps,
192                                            const EGLint *names,
193                                            EGLnsecsANDROID *values) const
194 {
195     ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
196 
197     egl::Display::GetCurrentThreadUnlockedTailCall()->add(
198         [egl = mEGL, surface = mSurface, numTimestamps, names, values](void *resultOut) {
199             EGLBoolean success =
200                 egl->getCompositorTimingANDROID(surface, numTimestamps, names, values);
201             if (!success)
202             {
203                 ERR() << "eglGetCompositorTimingANDROID failed: " << egl::Error(egl->getError());
204             }
205             *static_cast<EGLBoolean *>(resultOut) = success;
206         });
207 
208     return egl::NoError();
209 }
210 
getNextFrameId(EGLuint64KHR * frameId) const211 egl::Error SurfaceEGL::getNextFrameId(EGLuint64KHR *frameId) const
212 {
213     ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
214 
215     EGLBoolean success = mEGL->getNextFrameIdANDROID(mSurface, frameId);
216     if (success == EGL_FALSE)
217     {
218         return egl::Error(mEGL->getError(), "eglGetNextFrameId failed");
219     }
220     return egl::NoError();
221 }
222 
getSupportedTimestamps() const223 egl::SupportedTimestamps SurfaceEGL::getSupportedTimestamps() const
224 {
225     ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
226 
227     egl::SupportedTimestamps result;
228     for (egl::Timestamp timestamp : angle::AllEnums<egl::Timestamp>())
229     {
230         result[timestamp] =
231             mEGL->getFrameTimestampSupportedANDROID(mSurface, egl::ToEGLenum(timestamp));
232     }
233     return result;
234 }
235 
getFrameTimestamps(EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values) const236 egl::Error SurfaceEGL::getFrameTimestamps(EGLuint64KHR frameId,
237                                           EGLint numTimestamps,
238                                           const EGLint *timestamps,
239                                           EGLnsecsANDROID *values) const
240 {
241     ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
242 
243     egl::Display::GetCurrentThreadUnlockedTailCall()->add([egl = mEGL, surface = mSurface, frameId,
244                                                            numTimestamps, timestamps,
245                                                            values](void *resultOut) {
246         EGLBoolean success =
247             egl->getFrameTimestampsANDROID(surface, frameId, numTimestamps, timestamps, values);
248         if (!success)
249         {
250             // The driver may return EGL_BAD_ACCESS at any time if the requested frame is no longer
251             // stored.
252             ERR() << "eglGetFrameTimestampsANDROID failed: " << egl::Error(egl->getError());
253         }
254         *static_cast<EGLBoolean *>(resultOut) = success;
255     });
256 
257     return egl::NoError();
258 }
259 
isExternal() const260 bool SurfaceEGL::isExternal() const
261 {
262     return false;
263 }
264 
265 }  // namespace rx
266