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// ----------------------------------------------------------------------------
23namespace android {
24// ----------------------------------------------------------------------------
25
26egl_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
32egl_object_t::~egl_object_t() {
33}
34
35void 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
44void egl_object_t::destroy() {
45    if (decRef() == 1) {
46        delete this;
47    }
48}
49
50bool 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
58egl_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
83egl_surface_t::~egl_surface_t() {
84    if (win != NULL) {
85        disconnect();
86        win->decStrong(this);
87    }
88}
89
90void egl_surface_t::disconnect() {
91    if (win != NULL && 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
100EGLBoolean 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
146EGLBoolean 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
160EGLBoolean 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
190EGLBoolean 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
206EGLBoolean 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
214EGLBoolean 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
260EGLBoolean 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
274void egl_surface_t::terminate() {
275    disconnect();
276    egl_object_t::terminate();
277}
278
279// ----------------------------------------------------------------------------
280
281egl_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(0), draw(0), cnx(cnx), version(version) {
285}
286
287void egl_context_t::onLooseCurrent() {
288    read = NULL;
289    draw = NULL;
290}
291
292void 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