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 22 // ---------------------------------------------------------------------------- 23 namespace android { 24 // ---------------------------------------------------------------------------- 25 26 egl_object_t::egl_object_t(egl_display_t* disp) : 27 display(disp), count(1) { 28 // NOTE: this does an implicit incRef 29 display->addObject(this); 30 } 31 32 egl_object_t::~egl_object_t() { 33 } 34 35 void egl_object_t::terminate() { 36 // this marks the object as "terminated" 37 display->removeObject(this); 38 if (decRef() == 1) { 39 // shouldn't happen because this is called from LocalRef 40 ALOGE("egl_object_t::terminate() removed the last reference!"); 41 } 42 } 43 44 void egl_object_t::destroy() { 45 if (decRef() == 1) { 46 delete this; 47 } 48 } 49 50 bool egl_object_t::get(egl_display_t const* display, egl_object_t* object) { 51 // used by LocalRef, this does an incRef() atomically with 52 // checking that the object is valid. 53 return display->getObject(object); 54 } 55 56 // ---------------------------------------------------------------------------- 57 58 egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, 59 EGLSurface surface, EGLint colorSpace, egl_connection_t const* cnx) 60 : egl_object_t(dpy), 61 surface(surface), 62 config(config), 63 win(win), 64 cnx(cnx), 65 connected(true), 66 colorSpace(colorSpace), 67 egl_smpte2086_dirty(false), 68 egl_cta861_3_dirty(false) { 69 egl_smpte2086_metadata.displayPrimaryRed = { EGL_DONT_CARE, EGL_DONT_CARE }; 70 egl_smpte2086_metadata.displayPrimaryGreen = { EGL_DONT_CARE, EGL_DONT_CARE }; 71 egl_smpte2086_metadata.displayPrimaryBlue = { EGL_DONT_CARE, EGL_DONT_CARE }; 72 egl_smpte2086_metadata.whitePoint = { EGL_DONT_CARE, EGL_DONT_CARE }; 73 egl_smpte2086_metadata.maxLuminance = EGL_DONT_CARE; 74 egl_smpte2086_metadata.minLuminance = EGL_DONT_CARE; 75 egl_cta861_3_metadata.maxFrameAverageLightLevel = EGL_DONT_CARE; 76 egl_cta861_3_metadata.maxContentLightLevel = EGL_DONT_CARE; 77 78 if (win) { 79 win->incStrong(this); 80 } 81 } 82 83 egl_surface_t::~egl_surface_t() { 84 if (win != nullptr) { 85 disconnect(); 86 win->decStrong(this); 87 } 88 } 89 90 void egl_surface_t::disconnect() { 91 if (win != nullptr && connected) { 92 native_window_set_buffers_format(win, 0); 93 if (native_window_api_disconnect(win, NATIVE_WINDOW_API_EGL)) { 94 ALOGW("EGLNativeWindowType %p disconnect failed", win); 95 } 96 connected = false; 97 } 98 } 99 100 EGLBoolean egl_surface_t::setSmpte2086Attribute(EGLint attribute, EGLint value) { 101 switch (attribute) { 102 case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT: 103 egl_smpte2086_metadata.displayPrimaryRed.x = value; 104 egl_smpte2086_dirty = true; 105 return EGL_TRUE; 106 case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT: 107 egl_smpte2086_metadata.displayPrimaryRed.y = value; 108 egl_smpte2086_dirty = true; 109 return EGL_TRUE; 110 case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT: 111 egl_smpte2086_metadata.displayPrimaryGreen.x = value; 112 egl_smpte2086_dirty = true; 113 return EGL_TRUE; 114 case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT: 115 egl_smpte2086_metadata.displayPrimaryGreen.y = value; 116 egl_smpte2086_dirty = true; 117 return EGL_TRUE; 118 case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT: 119 egl_smpte2086_metadata.displayPrimaryBlue.x = value; 120 egl_smpte2086_dirty = true; 121 return EGL_TRUE; 122 case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT: 123 egl_smpte2086_metadata.displayPrimaryBlue.y = value; 124 egl_smpte2086_dirty = true; 125 return EGL_TRUE; 126 case EGL_SMPTE2086_WHITE_POINT_X_EXT: 127 egl_smpte2086_metadata.whitePoint.x = value; 128 egl_smpte2086_dirty = true; 129 return EGL_TRUE; 130 case EGL_SMPTE2086_WHITE_POINT_Y_EXT: 131 egl_smpte2086_metadata.whitePoint.y = value; 132 egl_smpte2086_dirty = true; 133 return EGL_TRUE; 134 case EGL_SMPTE2086_MAX_LUMINANCE_EXT: 135 egl_smpte2086_metadata.maxLuminance = value; 136 egl_smpte2086_dirty = true; 137 return EGL_TRUE; 138 case EGL_SMPTE2086_MIN_LUMINANCE_EXT: 139 egl_smpte2086_metadata.minLuminance = value; 140 egl_smpte2086_dirty = true; 141 return EGL_TRUE; 142 } 143 return EGL_FALSE; 144 } 145 146 EGLBoolean egl_surface_t::setCta8613Attribute(EGLint attribute, EGLint value) { 147 switch (attribute) { 148 case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT: 149 egl_cta861_3_metadata.maxContentLightLevel = value; 150 egl_cta861_3_dirty = true; 151 return EGL_TRUE; 152 case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT: 153 egl_cta861_3_metadata.maxFrameAverageLightLevel = value; 154 egl_cta861_3_dirty = true; 155 return EGL_TRUE; 156 } 157 return EGL_FALSE; 158 } 159 160 EGLBoolean egl_surface_t::getSmpte2086Metadata(android_smpte2086_metadata& metadata) const { 161 if (!egl_smpte2086_dirty) return EGL_FALSE; 162 if (egl_smpte2086_metadata.displayPrimaryRed.x == EGL_DONT_CARE || 163 egl_smpte2086_metadata.displayPrimaryRed.y == EGL_DONT_CARE || 164 egl_smpte2086_metadata.displayPrimaryGreen.x == EGL_DONT_CARE || 165 egl_smpte2086_metadata.displayPrimaryGreen.y == EGL_DONT_CARE || 166 egl_smpte2086_metadata.displayPrimaryBlue.x == EGL_DONT_CARE || 167 egl_smpte2086_metadata.displayPrimaryBlue.y == EGL_DONT_CARE || 168 egl_smpte2086_metadata.whitePoint.x == EGL_DONT_CARE || 169 egl_smpte2086_metadata.whitePoint.y == EGL_DONT_CARE || 170 egl_smpte2086_metadata.maxLuminance == EGL_DONT_CARE || 171 egl_smpte2086_metadata.minLuminance == EGL_DONT_CARE) { 172 ALOGW("egl_surface_t: incomplete SMPTE 2086 metadata!"); 173 return EGL_FALSE; 174 } 175 176 metadata.displayPrimaryRed.x = static_cast<float>(egl_smpte2086_metadata.displayPrimaryRed.x) / EGL_METADATA_SCALING_EXT; 177 metadata.displayPrimaryRed.y = static_cast<float>(egl_smpte2086_metadata.displayPrimaryRed.y) / EGL_METADATA_SCALING_EXT; 178 metadata.displayPrimaryGreen.x = static_cast<float>(egl_smpte2086_metadata.displayPrimaryGreen.x) / EGL_METADATA_SCALING_EXT; 179 metadata.displayPrimaryGreen.y = static_cast<float>(egl_smpte2086_metadata.displayPrimaryGreen.y) / EGL_METADATA_SCALING_EXT; 180 metadata.displayPrimaryBlue.x = static_cast<float>(egl_smpte2086_metadata.displayPrimaryBlue.x) / EGL_METADATA_SCALING_EXT; 181 metadata.displayPrimaryBlue.y = static_cast<float>(egl_smpte2086_metadata.displayPrimaryBlue.y) / EGL_METADATA_SCALING_EXT; 182 metadata.whitePoint.x = static_cast<float>(egl_smpte2086_metadata.whitePoint.x) / EGL_METADATA_SCALING_EXT; 183 metadata.whitePoint.y = static_cast<float>(egl_smpte2086_metadata.whitePoint.y) / EGL_METADATA_SCALING_EXT; 184 metadata.maxLuminance = static_cast<float>(egl_smpte2086_metadata.maxLuminance) / EGL_METADATA_SCALING_EXT; 185 metadata.minLuminance = static_cast<float>(egl_smpte2086_metadata.minLuminance) / EGL_METADATA_SCALING_EXT; 186 187 return EGL_TRUE; 188 } 189 190 EGLBoolean egl_surface_t::getCta8613Metadata(android_cta861_3_metadata& metadata) const { 191 if (!egl_cta861_3_dirty) return EGL_FALSE; 192 193 if (egl_cta861_3_metadata.maxContentLightLevel == EGL_DONT_CARE || 194 egl_cta861_3_metadata.maxFrameAverageLightLevel == EGL_DONT_CARE) { 195 ALOGW("egl_surface_t: incomplete CTA861.3 metadata!"); 196 return EGL_FALSE; 197 } 198 199 metadata.maxContentLightLevel = static_cast<float>(egl_cta861_3_metadata.maxContentLightLevel) / EGL_METADATA_SCALING_EXT; 200 metadata.maxFrameAverageLightLevel = static_cast<float>(egl_cta861_3_metadata.maxFrameAverageLightLevel) / EGL_METADATA_SCALING_EXT; 201 202 return EGL_TRUE; 203 } 204 205 206 EGLBoolean egl_surface_t::getColorSpaceAttribute(EGLint attribute, EGLint* value) const { 207 if (attribute == EGL_GL_COLORSPACE_KHR) { 208 *value = colorSpace; 209 return EGL_TRUE; 210 } 211 return EGL_FALSE; 212 } 213 214 EGLBoolean egl_surface_t::getSmpte2086Attribute(EGLint attribute, EGLint *value) const { 215 switch (attribute) { 216 case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT: 217 *value = egl_smpte2086_metadata.displayPrimaryRed.x; 218 return EGL_TRUE; 219 break; 220 case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT: 221 *value = egl_smpte2086_metadata.displayPrimaryRed.y; 222 return EGL_TRUE; 223 break; 224 case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT: 225 *value = egl_smpte2086_metadata.displayPrimaryGreen.x; 226 return EGL_TRUE; 227 break; 228 case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT: 229 *value = egl_smpte2086_metadata.displayPrimaryGreen.y; 230 return EGL_TRUE; 231 break; 232 case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT: 233 *value = egl_smpte2086_metadata.displayPrimaryBlue.x; 234 return EGL_TRUE; 235 break; 236 case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT: 237 *value = egl_smpte2086_metadata.displayPrimaryBlue.y; 238 return EGL_TRUE; 239 break; 240 case EGL_SMPTE2086_WHITE_POINT_X_EXT: 241 *value = egl_smpte2086_metadata.whitePoint.x; 242 return EGL_TRUE; 243 break; 244 case EGL_SMPTE2086_WHITE_POINT_Y_EXT: 245 *value = egl_smpte2086_metadata.whitePoint.y; 246 return EGL_TRUE; 247 break; 248 case EGL_SMPTE2086_MAX_LUMINANCE_EXT: 249 *value = egl_smpte2086_metadata.maxLuminance; 250 return EGL_TRUE; 251 break; 252 case EGL_SMPTE2086_MIN_LUMINANCE_EXT: 253 *value = egl_smpte2086_metadata.minLuminance; 254 return EGL_TRUE; 255 break; 256 } 257 return EGL_FALSE; 258 } 259 260 EGLBoolean egl_surface_t::getCta8613Attribute(EGLint attribute, EGLint *value) const { 261 switch (attribute) { 262 case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT: 263 *value = egl_cta861_3_metadata.maxContentLightLevel; 264 return EGL_TRUE; 265 break; 266 case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT: 267 *value = egl_cta861_3_metadata.maxFrameAverageLightLevel; 268 return EGL_TRUE; 269 break; 270 } 271 return EGL_FALSE; 272 } 273 274 void egl_surface_t::terminate() { 275 disconnect(); 276 egl_object_t::terminate(); 277 } 278 279 // ---------------------------------------------------------------------------- 280 281 egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config, 282 egl_connection_t const* cnx, int version) : 283 egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context), 284 config(config), read(nullptr), draw(nullptr), cnx(cnx), version(version) { 285 } 286 287 void egl_context_t::onLooseCurrent() { 288 read = nullptr; 289 draw = nullptr; 290 } 291 292 void egl_context_t::onMakeCurrent(EGLSurface draw, EGLSurface read) { 293 this->read = read; 294 this->draw = draw; 295 296 /* 297 * Here we cache the GL_EXTENSIONS string for this context and we 298 * add the extensions always handled by the wrapper 299 */ 300 301 if (gl_extensions.empty()) { 302 // call the implementation's glGetString(GL_EXTENSIONS) 303 const char* exts = (const char *)gEGLImpl.hooks[version]->gl.glGetString(GL_EXTENSIONS); 304 305 // If this context is sharing with another context, and the other context was reset 306 // e.g. due to robustness failure, this context might also be reset and glGetString can 307 // return NULL. 308 if (exts) { 309 gl_extensions = exts; 310 if (gl_extensions.find("GL_EXT_debug_marker") == std::string::npos) { 311 gl_extensions.insert(0, "GL_EXT_debug_marker "); 312 } 313 314 // tokenize the supported extensions for the glGetStringi() wrapper 315 std::stringstream ss; 316 std::string str; 317 ss << gl_extensions; 318 while (ss >> str) { 319 tokenized_gl_extensions.push_back(str); 320 } 321 } 322 } 323 } 324 325 // ---------------------------------------------------------------------------- 326 }; // namespace android 327 // ---------------------------------------------------------------------------- 328