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 #ifndef ANDROID_EGL_OBJECT_H
18 #define ANDROID_EGL_OBJECT_H
19
20 #include <EGL/egl.h>
21 #include <EGL/eglext.h>
22 #include <log/log.h>
23 #include <stddef.h>
24 #include <stdint.h>
25 #include <system/window.h>
26
27 #include <atomic>
28 #include <string>
29 #include <vector>
30
31 #include "egl_display.h"
32
33 namespace android {
34
35 class egl_display_t;
36
37 class egl_object_t {
38 egl_display_t* display;
39 mutable std::atomic_size_t count;
40
41 protected:
42 virtual ~egl_object_t();
43 virtual void terminate();
44
45 public:
46 explicit egl_object_t(egl_display_t* display);
47 void destroy();
48
incRef()49 inline void incRef() { count.fetch_add(1, std::memory_order_relaxed); }
decRef()50 inline size_t decRef() { return count.fetch_sub(1, std::memory_order_acq_rel); }
getDisplay()51 inline egl_display_t* getDisplay() const { return display; }
52
53 private:
54 static bool get(egl_display_t const* display, egl_object_t* object);
55
56 public:
57 template <typename N, typename T>
58 class LocalRef {
59 egl_object_t* ref;
60 LocalRef() = delete;
61 LocalRef(const LocalRef* rhs) = delete;
62
63 public:
64 ~LocalRef();
65 explicit LocalRef(egl_object_t* rhs);
LocalRef(egl_display_t const * display,T o)66 explicit LocalRef(egl_display_t const* display, T o) : ref(nullptr) {
67 egl_object_t* native = reinterpret_cast<N*>(o);
68 if (o && egl_object_t::get(display, native)) {
69 ref = native;
70 }
71 }
get()72 inline N* get() { return static_cast<N*>(ref); }
73 void acquire() const;
74 void release() const;
75 void terminate();
76 };
77 template <typename N, typename T>
78 friend class LocalRef;
79 };
80
81 template <typename N, typename T>
LocalRef(egl_object_t * rhs)82 egl_object_t::LocalRef<N, T>::LocalRef(egl_object_t* rhs) : ref(rhs) {
83 if (ref) {
84 ref->incRef();
85 }
86 }
87
88 template <typename N, typename T>
~LocalRef()89 egl_object_t::LocalRef<N, T>::~LocalRef() {
90 if (ref) {
91 ref->destroy();
92 }
93 }
94
95 template <typename N, typename T>
acquire()96 void egl_object_t::LocalRef<N, T>::acquire() const {
97 if (ref) {
98 ref->incRef();
99 }
100 }
101
102 template <typename N, typename T>
release()103 void egl_object_t::LocalRef<N, T>::release() const {
104 if (ref) {
105 if (ref->decRef() == 1) {
106 // shouldn't happen because this is called from LocalRef
107 ALOGE("LocalRef::release() removed the last reference!");
108 }
109 }
110 }
111
112 template <typename N, typename T>
terminate()113 void egl_object_t::LocalRef<N, T>::terminate() {
114 if (ref) {
115 ref->terminate();
116 }
117 }
118
119 // ----------------------------------------------------------------------------
120
121 class egl_surface_t : public egl_object_t {
122 protected:
123 ~egl_surface_t();
124 void terminate() override;
125
126 public:
127 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
128
129 egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, EGLSurface surface,
130 EGLint colorSpace, egl_connection_t const* cnx);
131
getNativeWindow()132 ANativeWindow* getNativeWindow() { return win; }
getNativeWindow()133 ANativeWindow* getNativeWindow() const { return win; }
getColorSpace()134 EGLint getColorSpace() const { return colorSpace; }
135 EGLBoolean setSmpte2086Attribute(EGLint attribute, EGLint value);
136 EGLBoolean setCta8613Attribute(EGLint attribute, EGLint value);
137 EGLBoolean getColorSpaceAttribute(EGLint attribute, EGLint* value) const;
138 EGLBoolean getSmpte2086Attribute(EGLint attribute, EGLint* value) const;
139 EGLBoolean getCta8613Attribute(EGLint attribute, EGLint* value) const;
140 EGLBoolean getSmpte2086Metadata(android_smpte2086_metadata& smpte2086) const;
141 EGLBoolean getCta8613Metadata(android_cta861_3_metadata& cta861_3) const;
resetSmpte2086Metadata()142 void resetSmpte2086Metadata() { egl_smpte2086_dirty = false; }
resetCta8613Metadata()143 void resetCta8613Metadata() { egl_cta861_3_dirty = false; }
144
145 // Try to keep the order of these fields and size unchanged. It's not public API, but
146 // it's not hard to imagine native games accessing them.
147 EGLSurface surface;
148 EGLConfig config;
149
150 private:
151 ANativeWindow* win;
152
153 public:
154 egl_connection_t const* cnx;
155
156 private:
157 bool connected;
158 void disconnect();
159 EGLint colorSpace;
160
161 struct egl_xy_color {
162 EGLint x;
163 EGLint y;
164 };
165
166 struct egl_smpte2086_metadata {
167 struct egl_xy_color displayPrimaryRed;
168 struct egl_xy_color displayPrimaryGreen;
169 struct egl_xy_color displayPrimaryBlue;
170 struct egl_xy_color whitePoint;
171 EGLint maxLuminance;
172 EGLint minLuminance;
173 };
174
175 struct egl_cta861_3_metadata {
176 EGLint maxContentLightLevel;
177 EGLint maxFrameAverageLightLevel;
178 };
179
180 bool egl_smpte2086_dirty;
181 bool egl_cta861_3_dirty;
182
183 egl_smpte2086_metadata egl_smpte2086_metadata;
184 egl_cta861_3_metadata egl_cta861_3_metadata;
185 };
186
187 class egl_context_t : public egl_object_t {
188 protected:
~egl_context_t()189 ~egl_context_t() {}
190
191 public:
192 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
193
194 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config, egl_connection_t const* cnx,
195 int version);
196
197 void onLooseCurrent();
198 void onMakeCurrent(EGLSurface draw, EGLSurface read);
199
200 EGLDisplay dpy;
201 EGLContext context;
202 EGLConfig config;
203 EGLSurface read;
204 EGLSurface draw;
205 egl_connection_t const* cnx;
206 int version;
207 std::string gl_extensions;
208 std::vector<std::string> tokenized_gl_extensions;
209 };
210
211 typedef egl_surface_t::Ref SurfaceRef;
212 typedef egl_context_t::Ref ContextRef;
213
214 template <typename NATIVE, typename EGL>
egl_to_native_cast(EGL arg)215 static inline NATIVE* egl_to_native_cast(EGL arg) {
216 return reinterpret_cast<NATIVE*>(arg);
217 }
218
get_surface(EGLSurface surface)219 static inline egl_surface_t* get_surface(EGLSurface surface) {
220 return egl_to_native_cast<egl_surface_t>(surface);
221 }
222
get_context(EGLContext context)223 static inline egl_context_t* get_context(EGLContext context) {
224 return egl_to_native_cast<egl_context_t>(context);
225 }
226
227 }; // namespace android
228
229 #endif // ANDROID_EGL_OBJECT_H
230