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 
egl_object_t(egl_display_t * disp)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 
~egl_object_t()32 egl_object_t::~egl_object_t() {
33 }
34 
terminate()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 
destroy()44 void egl_object_t::destroy() {
45     if (decRef() == 1) {
46         delete this;
47     }
48 }
49 
get(egl_display_t const * display,egl_object_t * object)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 
egl_surface_t(egl_display_t * dpy,EGLConfig config,EGLNativeWindowType win,EGLSurface surface,EGLint colorSpace,egl_connection_t const * cnx)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 
~egl_surface_t()83 egl_surface_t::~egl_surface_t() {
84     if (win != nullptr) {
85         disconnect();
86         win->decStrong(this);
87     }
88 }
89 
disconnect()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 
setSmpte2086Attribute(EGLint attribute,EGLint value)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 
setCta8613Attribute(EGLint attribute,EGLint value)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 
getSmpte2086Metadata(android_smpte2086_metadata & metadata) const160 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 
getCta8613Metadata(android_cta861_3_metadata & metadata) const190 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 
getColorSpaceAttribute(EGLint attribute,EGLint * value) const206 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 
getSmpte2086Attribute(EGLint attribute,EGLint * value) const214 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 
getCta8613Attribute(EGLint attribute,EGLint * value) const260 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 
terminate()274 void egl_surface_t::terminate() {
275     disconnect();
276     egl_object_t::terminate();
277 }
278 
279 // ----------------------------------------------------------------------------
280 
egl_context_t(EGLDisplay dpy,EGLContext context,EGLConfig config,egl_connection_t const * cnx,int version)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 
onLooseCurrent()287 void egl_context_t::onLooseCurrent() {
288     read = nullptr;
289     draw = nullptr;
290 }
291 
onMakeCurrent(EGLSurface draw,EGLSurface read)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