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,const EGLint * rects,EGLint n_rects)49 egl::Error SurfaceEGL::swapWithDamage(const gl::Context *context,
50 const EGLint *rects,
51 EGLint n_rects)
52 {
53 EGLBoolean success;
54 if (mHasSwapBuffersWithDamage)
55 {
56 success = mEGL->swapBuffersWithDamageKHR(mSurface, rects, n_rects);
57 }
58 else
59 {
60 success = mEGL->swapBuffers(mSurface);
61 }
62 if (success == EGL_FALSE)
63 {
64 return egl::Error(mEGL->getError(), "eglSwapBuffersWithDamageKHR failed");
65 }
66 return egl::NoError();
67 }
68
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)69 egl::Error SurfaceEGL::postSubBuffer(const gl::Context *context,
70 EGLint x,
71 EGLint y,
72 EGLint width,
73 EGLint height)
74 {
75 UNIMPLEMENTED();
76 return egl::EglBadSurface();
77 }
78
setPresentationTime(EGLnsecsANDROID time)79 egl::Error SurfaceEGL::setPresentationTime(EGLnsecsANDROID time)
80 {
81 EGLBoolean success = mEGL->presentationTimeANDROID(mSurface, time);
82 if (success == EGL_FALSE)
83 {
84 return egl::Error(mEGL->getError(), "eglPresentationTimeANDROID failed");
85 }
86 return egl::NoError();
87 }
88
querySurfacePointerANGLE(EGLint attribute,void ** value)89 egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value)
90 {
91 UNIMPLEMENTED();
92 return egl::EglBadSurface();
93 }
94
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)95 egl::Error SurfaceEGL::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
96 {
97 EGLBoolean success = mEGL->bindTexImage(mSurface, buffer);
98 if (success == EGL_FALSE)
99 {
100 return egl::Error(mEGL->getError(), "eglBindTexImage failed");
101 }
102 return egl::NoError();
103 }
104
releaseTexImage(const gl::Context * context,EGLint buffer)105 egl::Error SurfaceEGL::releaseTexImage(const gl::Context *context, EGLint buffer)
106 {
107 EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer);
108 if (success == EGL_FALSE)
109 {
110 return egl::Error(mEGL->getError(), "eglReleaseTexImage failed");
111 }
112 return egl::NoError();
113 }
114
setSwapInterval(EGLint interval)115 void SurfaceEGL::setSwapInterval(EGLint interval)
116 {
117 EGLBoolean success = mEGL->swapInterval(interval);
118 if (success == EGL_FALSE)
119 {
120 ERR() << "eglSwapInterval error " << egl::Error(mEGL->getError());
121 ASSERT(false);
122 }
123 }
124
getWidth() const125 EGLint SurfaceEGL::getWidth() const
126 {
127 EGLint value;
128 EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value);
129 ASSERT(success == EGL_TRUE);
130 return value;
131 }
132
getHeight() const133 EGLint SurfaceEGL::getHeight() const
134 {
135 EGLint value;
136 EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value);
137 ASSERT(success == EGL_TRUE);
138 return value;
139 }
140
isPostSubBufferSupported() const141 EGLint SurfaceEGL::isPostSubBufferSupported() const
142 {
143 UNIMPLEMENTED();
144 return 0;
145 }
146
getSwapBehavior() const147 EGLint SurfaceEGL::getSwapBehavior() const
148 {
149 EGLint value;
150 EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value);
151 ASSERT(success == EGL_TRUE);
152 return value;
153 }
154
getSurface() const155 EGLSurface SurfaceEGL::getSurface() const
156 {
157 return mSurface;
158 }
159
setTimestampsEnabled(bool enabled)160 void SurfaceEGL::setTimestampsEnabled(bool enabled)
161 {
162 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
163
164 EGLBoolean success =
165 mEGL->surfaceAttrib(mSurface, EGL_TIMESTAMPS_ANDROID, enabled ? EGL_TRUE : EGL_FALSE);
166 if (success == EGL_FALSE)
167 {
168 ERR() << "eglSurfaceAttribute failed: " << egl::Error(mEGL->getError());
169 }
170 }
171
getSupportedCompositorTimings() const172 egl::SupportedCompositorTimings SurfaceEGL::getSupportedCompositorTimings() const
173 {
174 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
175
176 egl::SupportedCompositorTimings result;
177 for (egl::CompositorTiming name : angle::AllEnums<egl::CompositorTiming>())
178 {
179 result[name] = mEGL->getCompositorTimingSupportedANDROID(mSurface, egl::ToEGLenum(name));
180 }
181 return result;
182 }
183
getCompositorTiming(EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values) const184 egl::Error SurfaceEGL::getCompositorTiming(EGLint numTimestamps,
185 const EGLint *names,
186 EGLnsecsANDROID *values) const
187 {
188 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
189
190 EGLBoolean success = mEGL->getCompositorTimingANDROID(mSurface, numTimestamps, names, values);
191 if (success == EGL_FALSE)
192 {
193 return egl::Error(mEGL->getError(), "eglGetCompositorTimingANDROID failed");
194 }
195 return egl::NoError();
196 }
197
getNextFrameId(EGLuint64KHR * frameId) const198 egl::Error SurfaceEGL::getNextFrameId(EGLuint64KHR *frameId) const
199 {
200 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
201
202 EGLBoolean success = mEGL->getNextFrameIdANDROID(mSurface, frameId);
203 if (success == EGL_FALSE)
204 {
205 return egl::Error(mEGL->getError(), "eglGetNextFrameId failed");
206 }
207 return egl::NoError();
208 }
209
getSupportedTimestamps() const210 egl::SupportedTimestamps SurfaceEGL::getSupportedTimestamps() const
211 {
212 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
213
214 egl::SupportedTimestamps result;
215 for (egl::Timestamp timestamp : angle::AllEnums<egl::Timestamp>())
216 {
217 result[timestamp] =
218 mEGL->getFrameTimestampSupportedANDROID(mSurface, egl::ToEGLenum(timestamp));
219 }
220 return result;
221 }
222
getFrameTimestamps(EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values) const223 egl::Error SurfaceEGL::getFrameTimestamps(EGLuint64KHR frameId,
224 EGLint numTimestamps,
225 const EGLint *timestamps,
226 EGLnsecsANDROID *values) const
227 {
228 ASSERT(mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps"));
229
230 // The driver may return EGL_BAD_ACCESS at any time if the requested frame is no longer stored.
231 EGLBoolean success =
232 mEGL->getFrameTimestampsANDROID(mSurface, frameId, numTimestamps, timestamps, values);
233 if (success == EGL_FALSE)
234 {
235 return egl::Error(mEGL->getError(), "eglGetFrameTimestampsANDROID failed");
236 }
237 return egl::NoError();
238 }
239
isExternal() const240 bool SurfaceEGL::isExternal() const
241 {
242 return false;
243 }
244
245 } // namespace rx
246