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
13 namespace rx
14 {
15
SurfaceEGL(const egl::SurfaceState & state,const FunctionsEGL * egl,EGLConfig config)16 SurfaceEGL::SurfaceEGL(const egl::SurfaceState &state, const FunctionsEGL *egl, EGLConfig config)
17 : SurfaceGL(state),
18 mEGL(egl),
19 mConfig(config),
20 mSurface(EGL_NO_SURFACE),
21 mHasSwapBuffersWithDamage(mEGL->hasExtension("EGL_KHR_swap_buffers_with_damage"))
22 {}
23
~SurfaceEGL()24 SurfaceEGL::~SurfaceEGL()
25 {
26 if (mSurface != EGL_NO_SURFACE)
27 {
28 EGLBoolean success = mEGL->destroySurface(mSurface);
29 ASSERT(success == EGL_TRUE);
30 }
31 }
32
makeCurrent(const gl::Context * context)33 egl::Error SurfaceEGL::makeCurrent(const gl::Context *context)
34 {
35 // Handling of makeCurrent is done in DisplayEGL
36 return egl::NoError();
37 }
38
swap(const gl::Context * context)39 egl::Error SurfaceEGL::swap(const gl::Context *context)
40 {
41 EGLBoolean success = mEGL->swapBuffers(mSurface);
42 if (success == EGL_FALSE)
43 {
44 return egl::Error(mEGL->getError(), "eglSwapBuffers failed");
45 }
46 return egl::NoError();
47 }
48
swapWithDamage(const gl::Context * context,EGLint * rects,EGLint n_rects)49 egl::Error SurfaceEGL::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects)
50 {
51 EGLBoolean success;
52 if (mHasSwapBuffersWithDamage)
53 {
54 success = mEGL->swapBuffersWithDamageKHR(mSurface, rects, n_rects);
55 }
56 else
57 {
58 success = mEGL->swapBuffers(mSurface);
59 }
60 if (success == EGL_FALSE)
61 {
62 return egl::Error(mEGL->getError(), "eglSwapBuffersWithDamageKHR failed");
63 }
64 return egl::NoError();
65 }
66
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)67 egl::Error SurfaceEGL::postSubBuffer(const gl::Context *context,
68 EGLint x,
69 EGLint y,
70 EGLint width,
71 EGLint height)
72 {
73 UNIMPLEMENTED();
74 return egl::EglBadSurface();
75 }
76
setPresentationTime(EGLnsecsANDROID time)77 egl::Error SurfaceEGL::setPresentationTime(EGLnsecsANDROID time)
78 {
79 EGLBoolean success = mEGL->presentationTimeANDROID(mSurface, time);
80 if (success == EGL_FALSE)
81 {
82 return egl::Error(mEGL->getError(), "eglPresentationTimeANDROID failed");
83 }
84 return egl::NoError();
85 }
86
querySurfacePointerANGLE(EGLint attribute,void ** value)87 egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value)
88 {
89 UNIMPLEMENTED();
90 return egl::EglBadSurface();
91 }
92
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)93 egl::Error SurfaceEGL::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
94 {
95 EGLBoolean success = mEGL->bindTexImage(mSurface, buffer);
96 if (success == EGL_FALSE)
97 {
98 return egl::Error(mEGL->getError(), "eglBindTexImage failed");
99 }
100 return egl::NoError();
101 }
102
releaseTexImage(const gl::Context * context,EGLint buffer)103 egl::Error SurfaceEGL::releaseTexImage(const gl::Context *context, EGLint buffer)
104 {
105 EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer);
106 if (success == EGL_FALSE)
107 {
108 return egl::Error(mEGL->getError(), "eglReleaseTexImage failed");
109 }
110 return egl::NoError();
111 }
112
setSwapInterval(EGLint interval)113 void SurfaceEGL::setSwapInterval(EGLint interval)
114 {
115 EGLBoolean success = mEGL->swapInterval(interval);
116 if (success == EGL_FALSE)
117 {
118 ERR() << "eglSwapInterval error " << egl::Error(mEGL->getError());
119 ASSERT(false);
120 }
121 }
122
getWidth() const123 EGLint SurfaceEGL::getWidth() const
124 {
125 EGLint value;
126 EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value);
127 ASSERT(success == EGL_TRUE);
128 return value;
129 }
130
getHeight() const131 EGLint SurfaceEGL::getHeight() const
132 {
133 EGLint value;
134 EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value);
135 ASSERT(success == EGL_TRUE);
136 return value;
137 }
138
isPostSubBufferSupported() const139 EGLint SurfaceEGL::isPostSubBufferSupported() const
140 {
141 UNIMPLEMENTED();
142 return 0;
143 }
144
getSwapBehavior() const145 EGLint SurfaceEGL::getSwapBehavior() const
146 {
147 EGLint value;
148 EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value);
149 ASSERT(success == EGL_TRUE);
150 return value;
151 }
152
getSurface() const153 EGLSurface SurfaceEGL::getSurface() const
154 {
155 return mSurface;
156 }
157
setTimestampsEnabled(bool enabled)158 void SurfaceEGL::setTimestampsEnabled(bool enabled)
159 {
160 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
161
162 EGLBoolean success =
163 mEGL->surfaceAttrib(mSurface, EGL_TIMESTAMPS_ANDROID, enabled ? EGL_TRUE : EGL_FALSE);
164 if (success == EGL_FALSE)
165 {
166 ERR() << "eglSurfaceAttribute failed: " << egl::Error(mEGL->getError());
167 }
168 }
169
getSupportedCompositorTimings() const170 egl::SupportedCompositorTimings SurfaceEGL::getSupportedCompositorTimings() const
171 {
172 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
173
174 egl::SupportedCompositorTimings result;
175 for (egl::CompositorTiming name : angle::AllEnums<egl::CompositorTiming>())
176 {
177 result[name] = mEGL->getCompositorTimingSupportedANDROID(mSurface, egl::ToEGLenum(name));
178 }
179 return result;
180 }
181
getCompositorTiming(EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values) const182 egl::Error SurfaceEGL::getCompositorTiming(EGLint numTimestamps,
183 const EGLint *names,
184 EGLnsecsANDROID *values) const
185 {
186 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
187
188 EGLBoolean success = mEGL->getCompositorTimingANDROID(mSurface, numTimestamps, names, values);
189 if (success == EGL_FALSE)
190 {
191 return egl::Error(mEGL->getError(), "eglGetCompositorTimingANDROID failed");
192 }
193 return egl::NoError();
194 }
195
getNextFrameId(EGLuint64KHR * frameId) const196 egl::Error SurfaceEGL::getNextFrameId(EGLuint64KHR *frameId) const
197 {
198 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
199
200 EGLBoolean success = mEGL->getNextFrameIdANDROID(mSurface, frameId);
201 if (success == EGL_FALSE)
202 {
203 return egl::Error(mEGL->getError(), "eglGetNextFrameId failed");
204 }
205 return egl::NoError();
206 }
207
getSupportedTimestamps() const208 egl::SupportedTimestamps SurfaceEGL::getSupportedTimestamps() const
209 {
210 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
211
212 egl::SupportedTimestamps result;
213 for (egl::Timestamp timestamp : angle::AllEnums<egl::Timestamp>())
214 {
215 result[timestamp] =
216 mEGL->getFrameTimestampSupportedANDROID(mSurface, egl::ToEGLenum(timestamp));
217 }
218 return result;
219 }
220
getFrameTimestamps(EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values) const221 egl::Error SurfaceEGL::getFrameTimestamps(EGLuint64KHR frameId,
222 EGLint numTimestamps,
223 const EGLint *timestamps,
224 EGLnsecsANDROID *values) const
225 {
226 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
227
228 // The driver may return EGL_BAD_ACCESS at any time if the requested frame is no longer stored.
229 EGLBoolean success =
230 mEGL->getFrameTimestampsANDROID(mSurface, frameId, numTimestamps, timestamps, values);
231 if (success == EGL_FALSE)
232 {
233 return egl::Error(mEGL->getError(), "eglGetFrameTimestampsANDROID failed");
234 }
235 return egl::NoError();
236 }
237
238 } // namespace rx
239