xref: /aosp_15_r20/external/webrtc/sdk/android/api/org/webrtc/EglBase.java (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 package org.webrtc;
12 
13 import android.graphics.SurfaceTexture;
14 import android.view.Surface;
15 import androidx.annotation.Nullable;
16 import java.util.ArrayList;
17 import javax.microedition.khronos.egl.EGL10;
18 
19 /**
20  * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EGLDisplay,
21  * and an EGLSurface.
22  */
23 public interface EglBase {
24   // EGL wrapper for an actual EGLContext.
25   public interface Context {
26     public final static long NO_CONTEXT = 0;
27 
28     /**
29      * Returns an EGL context that can be used by native code. Returns NO_CONTEXT if the method is
30      * unsupported.
31      *
32      * @note This is currently only supported for EGL 1.4 and not for EGL 1.0.
33      */
getNativeEglContext()34     long getNativeEglContext();
35   }
36 
37   // According to the documentation, EGL can be used from multiple threads at the same time if each
38   // thread has its own EGLContext, but in practice it deadlocks on some devices when doing this.
39   // Therefore, synchronize on this global lock before calling dangerous EGL functions that might
40   // deadlock. See https://bugs.chromium.org/p/webrtc/issues/detail?id=5702 for more info.
41   public static final Object lock = new Object();
42 
43   // These constants are taken from EGL14.EGL_OPENGL_ES2_BIT and EGL14.EGL_CONTEXT_CLIENT_VERSION.
44   // https://android.googlesource.com/platform/frameworks/base/+/master/opengl/java/android/opengl/EGL14.java
45   // This is similar to how GlSurfaceView does:
46   // http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/opengl/GLSurfaceView.java#760
47   public static final int EGL_OPENGL_ES2_BIT = 4;
48   public static final int EGL_OPENGL_ES3_BIT = 0x40;
49   // Android-specific extension.
50   public static final int EGL_RECORDABLE_ANDROID = 0x3142;
51 
configBuilder()52   public static ConfigBuilder configBuilder() {
53     return new ConfigBuilder();
54   }
55 
56   public static class ConfigBuilder {
57     private int openGlesVersion = 2;
58     private boolean hasAlphaChannel;
59     private boolean supportsPixelBuffer;
60     private boolean isRecordable;
61 
setOpenGlesVersion(int version)62     public ConfigBuilder setOpenGlesVersion(int version) {
63       if (version < 1 || version > 3) {
64         throw new IllegalArgumentException("OpenGL ES version " + version + " not supported");
65       }
66       this.openGlesVersion = version;
67       return this;
68     }
69 
setHasAlphaChannel(boolean hasAlphaChannel)70     public ConfigBuilder setHasAlphaChannel(boolean hasAlphaChannel) {
71       this.hasAlphaChannel = hasAlphaChannel;
72       return this;
73     }
74 
setSupportsPixelBuffer(boolean supportsPixelBuffer)75     public ConfigBuilder setSupportsPixelBuffer(boolean supportsPixelBuffer) {
76       this.supportsPixelBuffer = supportsPixelBuffer;
77       return this;
78     }
79 
setIsRecordable(boolean isRecordable)80     public ConfigBuilder setIsRecordable(boolean isRecordable) {
81       this.isRecordable = isRecordable;
82       return this;
83     }
84 
createConfigAttributes()85     public int[] createConfigAttributes() {
86       ArrayList<Integer> list = new ArrayList<>();
87       list.add(EGL10.EGL_RED_SIZE);
88       list.add(8);
89       list.add(EGL10.EGL_GREEN_SIZE);
90       list.add(8);
91       list.add(EGL10.EGL_BLUE_SIZE);
92       list.add(8);
93       if (hasAlphaChannel) {
94         list.add(EGL10.EGL_ALPHA_SIZE);
95         list.add(8);
96       }
97       if (openGlesVersion == 2 || openGlesVersion == 3) {
98         list.add(EGL10.EGL_RENDERABLE_TYPE);
99         list.add(openGlesVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT);
100       }
101       if (supportsPixelBuffer) {
102         list.add(EGL10.EGL_SURFACE_TYPE);
103         list.add(EGL10.EGL_PBUFFER_BIT);
104       }
105       if (isRecordable) {
106         list.add(EGL_RECORDABLE_ANDROID);
107         list.add(1);
108       }
109       list.add(EGL10.EGL_NONE);
110 
111       final int[] res = new int[list.size()];
112       for (int i = 0; i < list.size(); ++i) {
113         res[i] = list.get(i);
114       }
115       return res;
116     }
117   }
118 
119   public static final int[] CONFIG_PLAIN = configBuilder().createConfigAttributes();
120   public static final int[] CONFIG_RGBA =
121       configBuilder().setHasAlphaChannel(true).createConfigAttributes();
122   public static final int[] CONFIG_PIXEL_BUFFER =
123       configBuilder().setSupportsPixelBuffer(true).createConfigAttributes();
124   public static final int[] CONFIG_PIXEL_RGBA_BUFFER = configBuilder()
125                                                            .setHasAlphaChannel(true)
126                                                            .setSupportsPixelBuffer(true)
127                                                            .createConfigAttributes();
128   public static final int[] CONFIG_RECORDABLE =
129       configBuilder().setIsRecordable(true).createConfigAttributes();
130 
getOpenGlesVersionFromConfig(int[] configAttributes)131   static int getOpenGlesVersionFromConfig(int[] configAttributes) {
132     for (int i = 0; i < configAttributes.length - 1; ++i) {
133       if (configAttributes[i] == EGL10.EGL_RENDERABLE_TYPE) {
134         switch (configAttributes[i + 1]) {
135           case EGL_OPENGL_ES2_BIT:
136             return 2;
137           case EGL_OPENGL_ES3_BIT:
138             return 3;
139           default:
140             return 1;
141         }
142       }
143     }
144     // Default to V1 if no renderable type is specified.
145     return 1;
146   }
147 
148   /**
149    * Create a new context with the specified config attributes, sharing data with `sharedContext`.
150    * If `sharedContext` is null, a root EGL 1.4 context is created.
151    */
create(@ullable Context sharedContext, int[] configAttributes)152   public static EglBase create(@Nullable Context sharedContext, int[] configAttributes) {
153     if (sharedContext == null) {
154       return createEgl14(configAttributes);
155     } else if (sharedContext instanceof EglBase14.Context) {
156       return createEgl14((EglBase14.Context) sharedContext, configAttributes);
157     } else if (sharedContext instanceof EglBase10.Context) {
158       return createEgl10((EglBase10.Context) sharedContext, configAttributes);
159     }
160     throw new IllegalArgumentException("Unrecognized Context");
161   }
162 
163   /**
164    * Helper function for creating a plain root context. This function will try to create an EGL 1.4
165    * context if possible, and an EGL 1.0 context otherwise.
166    */
create()167   public static EglBase create() {
168     return create(null /* shaderContext */, CONFIG_PLAIN);
169   }
170 
171   /**
172    * Helper function for creating a plain context, sharing data with `sharedContext`. This function
173    * will try to create an EGL 1.4 context if possible, and an EGL 1.0 context otherwise.
174    */
create(Context sharedContext)175   public static EglBase create(Context sharedContext) {
176     return create(sharedContext, CONFIG_PLAIN);
177   }
178 
179   /** Explicitly create a root EGl 1.0 context with the specified config attributes. */
createEgl10(int[] configAttributes)180   public static EglBase10 createEgl10(int[] configAttributes) {
181     return new EglBase10Impl(/* sharedContext= */ null, configAttributes);
182   }
183 
184   /**
185    * Explicitly create a root EGl 1.0 context with the specified config attributes and shared
186    * context.
187    */
createEgl10(EglBase10.Context sharedContext, int[] configAttributes)188   public static EglBase10 createEgl10(EglBase10.Context sharedContext, int[] configAttributes) {
189     return new EglBase10Impl(
190         sharedContext == null ? null : sharedContext.getRawContext(), configAttributes);
191   }
192 
193   /**
194    * Explicitly create a root EGl 1.0 context with the specified config attributes
195    * and shared context.
196    */
createEgl10( javax.microedition.khronos.egl.EGLContext sharedContext, int[] configAttributes)197   public static EglBase10 createEgl10(
198       javax.microedition.khronos.egl.EGLContext sharedContext, int[] configAttributes) {
199     return new EglBase10Impl(sharedContext, configAttributes);
200   }
201 
202   /** Explicitly create a root EGl 1.4 context with the specified config attributes. */
createEgl14(int[] configAttributes)203   public static EglBase14 createEgl14(int[] configAttributes) {
204     return new EglBase14Impl(/* sharedContext= */ null, configAttributes);
205   }
206 
207   /**
208    * Explicitly create a root EGl 1.4 context with the specified config attributes and shared
209    * context.
210    */
createEgl14(EglBase14.Context sharedContext, int[] configAttributes)211   public static EglBase14 createEgl14(EglBase14.Context sharedContext, int[] configAttributes) {
212     return new EglBase14Impl(
213         sharedContext == null ? null : sharedContext.getRawContext(), configAttributes);
214   }
215 
216   /**
217    * Explicitly create a root EGl 1.4 context with the specified config attributes
218    * and shared context.
219    */
createEgl14( android.opengl.EGLContext sharedContext, int[] configAttributes)220   public static EglBase14 createEgl14(
221       android.opengl.EGLContext sharedContext, int[] configAttributes) {
222     return new EglBase14Impl(sharedContext, configAttributes);
223   }
224 
createSurface(Surface surface)225   void createSurface(Surface surface);
226 
227   // Create EGLSurface from the Android SurfaceTexture.
createSurface(SurfaceTexture surfaceTexture)228   void createSurface(SurfaceTexture surfaceTexture);
229 
230   // Create dummy 1x1 pixel buffer surface so the context can be made current.
createDummyPbufferSurface()231   void createDummyPbufferSurface();
232 
createPbufferSurface(int width, int height)233   void createPbufferSurface(int width, int height);
234 
getEglBaseContext()235   Context getEglBaseContext();
236 
hasSurface()237   boolean hasSurface();
238 
surfaceWidth()239   int surfaceWidth();
240 
surfaceHeight()241   int surfaceHeight();
242 
releaseSurface()243   void releaseSurface();
244 
release()245   void release();
246 
makeCurrent()247   void makeCurrent();
248 
249   // Detach the current EGL context, so that it can be made current on another thread.
detachCurrent()250   void detachCurrent();
251 
swapBuffers()252   void swapBuffers();
253 
swapBuffers(long presentationTimeStampNs)254   void swapBuffers(long presentationTimeStampNs);
255 }
256