1 /*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17 #include "egl_object.h"
18
19 #include <sstream>
20
21 namespace android {
22
egl_object_t(egl_display_t * disp)23 egl_object_t::egl_object_t(egl_display_t* disp) : display(disp), count(1) {
24 // NOTE: this does an implicit incRef
25 display->addObject(this);
26 }
27
~egl_object_t()28 egl_object_t::~egl_object_t() {}
29
terminate()30 void egl_object_t::terminate() {
31 // this marks the object as "terminated"
32 display->removeObject(this);
33 if (decRef() == 1) {
34 // shouldn't happen because this is called from LocalRef
35 ALOGE("egl_object_t::terminate() removed the last reference!");
36 }
37 }
38
destroy()39 void egl_object_t::destroy() {
40 if (decRef() == 1) {
41 delete this;
42 }
43 }
44
get(egl_display_t const * display,egl_object_t * object)45 bool egl_object_t::get(egl_display_t const* display, egl_object_t* object) {
46 // used by LocalRef, this does an incRef() atomically with
47 // checking that the object is valid.
48 return display->getObject(object);
49 }
50
egl_surface_t(egl_display_t * dpy,EGLConfig config,EGLNativeWindowType win,EGLSurface surface,EGLint colorSpace,egl_connection_t const * cnx)51 egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win,
52 EGLSurface surface, EGLint colorSpace, egl_connection_t const* cnx)
53 : egl_object_t(dpy),
54 surface(surface),
55 config(config),
56 win(win),
57 cnx(cnx),
58 connected(true),
59 colorSpace(colorSpace),
60 egl_smpte2086_dirty(false),
61 egl_cta861_3_dirty(false) {
62 egl_smpte2086_metadata.displayPrimaryRed = {EGL_DONT_CARE, EGL_DONT_CARE};
63 egl_smpte2086_metadata.displayPrimaryGreen = {EGL_DONT_CARE, EGL_DONT_CARE};
64 egl_smpte2086_metadata.displayPrimaryBlue = {EGL_DONT_CARE, EGL_DONT_CARE};
65 egl_smpte2086_metadata.whitePoint = {EGL_DONT_CARE, EGL_DONT_CARE};
66 egl_smpte2086_metadata.maxLuminance = EGL_DONT_CARE;
67 egl_smpte2086_metadata.minLuminance = EGL_DONT_CARE;
68 egl_cta861_3_metadata.maxFrameAverageLightLevel = EGL_DONT_CARE;
69 egl_cta861_3_metadata.maxContentLightLevel = EGL_DONT_CARE;
70
71 if (win) {
72 win->incStrong(this);
73 }
74 }
75
~egl_surface_t()76 egl_surface_t::~egl_surface_t() {
77 if (win != nullptr) {
78 disconnect();
79 win->decStrong(this);
80 }
81 }
82
disconnect()83 void egl_surface_t::disconnect() {
84 if (win != nullptr && connected) {
85 // NOTE: When using Vulkan backend, the Vulkan runtime makes all the
86 // native_window_* calls, so don't do them here.
87 if (!cnx->angleLoaded) {
88 native_window_set_buffers_format(win, 0);
89 if (native_window_api_disconnect(win, NATIVE_WINDOW_API_EGL)) {
90 ALOGW("EGLNativeWindowType %p disconnect failed", win);
91 }
92 }
93 connected = false;
94 }
95 }
96
setSmpte2086Attribute(EGLint attribute,EGLint value)97 EGLBoolean egl_surface_t::setSmpte2086Attribute(EGLint attribute, EGLint value) {
98 switch (attribute) {
99 case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
100 egl_smpte2086_metadata.displayPrimaryRed.x = value;
101 egl_smpte2086_dirty = true;
102 return EGL_TRUE;
103 case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
104 egl_smpte2086_metadata.displayPrimaryRed.y = value;
105 egl_smpte2086_dirty = true;
106 return EGL_TRUE;
107 case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
108 egl_smpte2086_metadata.displayPrimaryGreen.x = value;
109 egl_smpte2086_dirty = true;
110 return EGL_TRUE;
111 case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
112 egl_smpte2086_metadata.displayPrimaryGreen.y = value;
113 egl_smpte2086_dirty = true;
114 return EGL_TRUE;
115 case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
116 egl_smpte2086_metadata.displayPrimaryBlue.x = value;
117 egl_smpte2086_dirty = true;
118 return EGL_TRUE;
119 case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
120 egl_smpte2086_metadata.displayPrimaryBlue.y = value;
121 egl_smpte2086_dirty = true;
122 return EGL_TRUE;
123 case EGL_SMPTE2086_WHITE_POINT_X_EXT:
124 egl_smpte2086_metadata.whitePoint.x = value;
125 egl_smpte2086_dirty = true;
126 return EGL_TRUE;
127 case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
128 egl_smpte2086_metadata.whitePoint.y = value;
129 egl_smpte2086_dirty = true;
130 return EGL_TRUE;
131 case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
132 egl_smpte2086_metadata.maxLuminance = value;
133 egl_smpte2086_dirty = true;
134 return EGL_TRUE;
135 case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
136 egl_smpte2086_metadata.minLuminance = value;
137 egl_smpte2086_dirty = true;
138 return EGL_TRUE;
139 }
140 return EGL_FALSE;
141 }
142
setCta8613Attribute(EGLint attribute,EGLint value)143 EGLBoolean egl_surface_t::setCta8613Attribute(EGLint attribute, EGLint value) {
144 switch (attribute) {
145 case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
146 egl_cta861_3_metadata.maxContentLightLevel = value;
147 egl_cta861_3_dirty = true;
148 return EGL_TRUE;
149 case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
150 egl_cta861_3_metadata.maxFrameAverageLightLevel = value;
151 egl_cta861_3_dirty = true;
152 return EGL_TRUE;
153 }
154 return EGL_FALSE;
155 }
156
getSmpte2086Metadata(android_smpte2086_metadata & metadata) const157 EGLBoolean egl_surface_t::getSmpte2086Metadata(android_smpte2086_metadata& metadata) const {
158 if (!egl_smpte2086_dirty) return EGL_FALSE;
159 if (egl_smpte2086_metadata.displayPrimaryRed.x == EGL_DONT_CARE ||
160 egl_smpte2086_metadata.displayPrimaryRed.y == EGL_DONT_CARE ||
161 egl_smpte2086_metadata.displayPrimaryGreen.x == EGL_DONT_CARE ||
162 egl_smpte2086_metadata.displayPrimaryGreen.y == EGL_DONT_CARE ||
163 egl_smpte2086_metadata.displayPrimaryBlue.x == EGL_DONT_CARE ||
164 egl_smpte2086_metadata.displayPrimaryBlue.y == EGL_DONT_CARE ||
165 egl_smpte2086_metadata.whitePoint.x == EGL_DONT_CARE ||
166 egl_smpte2086_metadata.whitePoint.y == EGL_DONT_CARE ||
167 egl_smpte2086_metadata.maxLuminance == EGL_DONT_CARE ||
168 egl_smpte2086_metadata.minLuminance == EGL_DONT_CARE) {
169 ALOGW("egl_surface_t: incomplete SMPTE 2086 metadata!");
170 return EGL_FALSE;
171 }
172
173 metadata.displayPrimaryRed.x = static_cast<float>(egl_smpte2086_metadata.displayPrimaryRed.x) /
174 EGL_METADATA_SCALING_EXT;
175 metadata.displayPrimaryRed.y = static_cast<float>(egl_smpte2086_metadata.displayPrimaryRed.y) /
176 EGL_METADATA_SCALING_EXT;
177 metadata.displayPrimaryGreen.x =
178 static_cast<float>(egl_smpte2086_metadata.displayPrimaryGreen.x) /
179 EGL_METADATA_SCALING_EXT;
180 metadata.displayPrimaryGreen.y =
181 static_cast<float>(egl_smpte2086_metadata.displayPrimaryGreen.y) /
182 EGL_METADATA_SCALING_EXT;
183 metadata.displayPrimaryBlue.x =
184 static_cast<float>(egl_smpte2086_metadata.displayPrimaryBlue.x) /
185 EGL_METADATA_SCALING_EXT;
186 metadata.displayPrimaryBlue.y =
187 static_cast<float>(egl_smpte2086_metadata.displayPrimaryBlue.y) /
188 EGL_METADATA_SCALING_EXT;
189 metadata.whitePoint.x =
190 static_cast<float>(egl_smpte2086_metadata.whitePoint.x) / EGL_METADATA_SCALING_EXT;
191 metadata.whitePoint.y =
192 static_cast<float>(egl_smpte2086_metadata.whitePoint.y) / EGL_METADATA_SCALING_EXT;
193 metadata.maxLuminance =
194 static_cast<float>(egl_smpte2086_metadata.maxLuminance) / EGL_METADATA_SCALING_EXT;
195 metadata.minLuminance =
196 static_cast<float>(egl_smpte2086_metadata.minLuminance) / EGL_METADATA_SCALING_EXT;
197
198 return EGL_TRUE;
199 }
200
getCta8613Metadata(android_cta861_3_metadata & metadata) const201 EGLBoolean egl_surface_t::getCta8613Metadata(android_cta861_3_metadata& metadata) const {
202 if (!egl_cta861_3_dirty) return EGL_FALSE;
203
204 if (egl_cta861_3_metadata.maxContentLightLevel == EGL_DONT_CARE ||
205 egl_cta861_3_metadata.maxFrameAverageLightLevel == EGL_DONT_CARE) {
206 ALOGW("egl_surface_t: incomplete CTA861.3 metadata!");
207 return EGL_FALSE;
208 }
209
210 metadata.maxContentLightLevel = static_cast<float>(egl_cta861_3_metadata.maxContentLightLevel) /
211 EGL_METADATA_SCALING_EXT;
212 metadata.maxFrameAverageLightLevel =
213 static_cast<float>(egl_cta861_3_metadata.maxFrameAverageLightLevel) /
214 EGL_METADATA_SCALING_EXT;
215
216 return EGL_TRUE;
217 }
218
getColorSpaceAttribute(EGLint attribute,EGLint * value) const219 EGLBoolean egl_surface_t::getColorSpaceAttribute(EGLint attribute, EGLint* value) const {
220 if (attribute == EGL_GL_COLORSPACE_KHR) {
221 *value = colorSpace;
222 return EGL_TRUE;
223 }
224 return EGL_FALSE;
225 }
226
getSmpte2086Attribute(EGLint attribute,EGLint * value) const227 EGLBoolean egl_surface_t::getSmpte2086Attribute(EGLint attribute, EGLint* value) const {
228 switch (attribute) {
229 case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
230 *value = egl_smpte2086_metadata.displayPrimaryRed.x;
231 return EGL_TRUE;
232 break;
233 case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
234 *value = egl_smpte2086_metadata.displayPrimaryRed.y;
235 return EGL_TRUE;
236 break;
237 case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
238 *value = egl_smpte2086_metadata.displayPrimaryGreen.x;
239 return EGL_TRUE;
240 break;
241 case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
242 *value = egl_smpte2086_metadata.displayPrimaryGreen.y;
243 return EGL_TRUE;
244 break;
245 case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
246 *value = egl_smpte2086_metadata.displayPrimaryBlue.x;
247 return EGL_TRUE;
248 break;
249 case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
250 *value = egl_smpte2086_metadata.displayPrimaryBlue.y;
251 return EGL_TRUE;
252 break;
253 case EGL_SMPTE2086_WHITE_POINT_X_EXT:
254 *value = egl_smpte2086_metadata.whitePoint.x;
255 return EGL_TRUE;
256 break;
257 case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
258 *value = egl_smpte2086_metadata.whitePoint.y;
259 return EGL_TRUE;
260 break;
261 case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
262 *value = egl_smpte2086_metadata.maxLuminance;
263 return EGL_TRUE;
264 break;
265 case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
266 *value = egl_smpte2086_metadata.minLuminance;
267 return EGL_TRUE;
268 break;
269 }
270 return EGL_FALSE;
271 }
272
getCta8613Attribute(EGLint attribute,EGLint * value) const273 EGLBoolean egl_surface_t::getCta8613Attribute(EGLint attribute, EGLint* value) const {
274 switch (attribute) {
275 case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
276 *value = egl_cta861_3_metadata.maxContentLightLevel;
277 return EGL_TRUE;
278 break;
279 case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
280 *value = egl_cta861_3_metadata.maxFrameAverageLightLevel;
281 return EGL_TRUE;
282 break;
283 }
284 return EGL_FALSE;
285 }
286
terminate()287 void egl_surface_t::terminate() {
288 disconnect();
289 egl_object_t::terminate();
290 }
291
egl_context_t(EGLDisplay dpy,EGLContext context,EGLConfig config,egl_connection_t const * cnx,int version)292 egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
293 egl_connection_t const* cnx, int version)
294 : egl_object_t(get_display(dpy)),
295 dpy(dpy),
296 context(context),
297 config(config),
298 read(nullptr),
299 draw(nullptr),
300 cnx(cnx),
301 version(version) {}
302
onLooseCurrent()303 void egl_context_t::onLooseCurrent() {
304 read = nullptr;
305 draw = nullptr;
306 }
307
onMakeCurrent(EGLSurface draw,EGLSurface read)308 void egl_context_t::onMakeCurrent(EGLSurface draw, EGLSurface read) {
309 this->read = read;
310 this->draw = draw;
311
312 /*
313 * Here we cache the GL_EXTENSIONS string for this context and we
314 * add the extensions always handled by the wrapper
315 */
316 if (!gl_extensions.empty()) return;
317
318 // call the implementation's glGetString(GL_EXTENSIONS)
319 const char* exts = (const char*)gEGLImpl.hooks[version]->gl.glGetString(GL_EXTENSIONS);
320 if (!exts) return;
321
322 // If this context is sharing with another context, and the other context was reset
323 // e.g. due to robustness failure, this context might also be reset and glGetString can
324 // return NULL.
325 gl_extensions = exts;
326 if (gl_extensions.find("GL_EXT_debug_marker") == std::string::npos) {
327 gl_extensions.insert(0, "GL_EXT_debug_marker ");
328 // eglGetProcAddress could return function pointers to these
329 // functions while they actually don't work. Fix them now.
330 __eglMustCastToProperFunctionPointerType* f;
331 f = (__eglMustCastToProperFunctionPointerType*)&gEGLImpl.hooks[version]
332 ->gl.glInsertEventMarkerEXT;
333 if (*f != gl_noop) *f = gl_noop;
334 f = (__eglMustCastToProperFunctionPointerType*)&gEGLImpl.hooks[version]
335 ->gl.glPushGroupMarkerEXT;
336 if (*f != gl_noop) *f = gl_noop;
337 f = (__eglMustCastToProperFunctionPointerType*)&gEGLImpl.hooks[version]
338 ->gl.glPopGroupMarkerEXT;
339 if (*f != gl_noop) *f = gl_noop;
340 }
341
342 // tokenize the supported extensions for the glGetStringi() wrapper
343 std::stringstream ss;
344 std::string str;
345 ss << gl_extensions;
346 while (ss >> str) {
347 tokenized_gl_extensions.push_back(str);
348 }
349 }
350
351 }; // namespace android
352