1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw;
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.annotation.TargetApi;
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.SurfaceTexture;
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.media.MediaRecorder;
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.opengl.GLES20;
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.opengl.GLUtils;
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Build.VERSION;
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log;
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.Surface;
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.SurfaceHolder;
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer;
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashMap;
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.microedition.khronos.egl.EGL10;
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.microedition.khronos.egl.EGLConfig;
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.microedition.khronos.egl.EGLContext;
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.microedition.khronos.egl.EGLDisplay;
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.microedition.khronos.egl.EGLSurface;
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic final class RenderTarget {
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final int EGL_OPENGL_ES2_BIT = 4;
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    // Pre-HC devices do not necessarily support multiple display surfaces.
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static boolean mSupportsMultipleDisplaySurfaces = (VERSION.SDK_INT >= 11);
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** A Map that tracks which objects are wrapped by EGLSurfaces */
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static HashMap<Object, EGLSurface> mSurfaceSources = new HashMap<Object, EGLSurface>();
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** A Map for performing reference counting over shared objects across RenderTargets */
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static HashMap<Object, Integer> mRefCounts = new HashMap<Object, Integer>();
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Stores the RenderTarget that is focused on the current thread. */
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static ThreadLocal<RenderTarget> mCurrentTarget = new ThreadLocal<RenderTarget>();
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The source for the surface used in this target (if any) */
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Object mSurfaceSource = null;
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The cached EGLConfig instance. */
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static EGLConfig mEglConfig = null;
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The display for which the EGLConfig was chosen. We expect only one. */
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static EGLDisplay mConfiguredDisplay;
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private EGL10 mEgl;
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private EGLDisplay mDisplay;
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private EGLContext mContext;
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private EGLSurface mSurface;
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private int mFbo;
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mOwnsContext;
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mOwnsSurface;
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static HashMap<EGLContext, ImageShader> mIdShaders
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        = new HashMap<EGLContext, ImageShader>();
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static HashMap<EGLContext, EGLSurface> mDisplaySurfaces
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        = new HashMap<EGLContext, EGLSurface>();
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int sRedSize = 8;
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int sGreenSize = 8;
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int sBlueSize = 8;
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int sAlphaSize = 8;
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int sDepthSize = 0;
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int sStencilSize = 0;
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static RenderTarget newTarget(int width, int height) {
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGL10 egl = (EGL10) EGLContext.getEGL();
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLDisplay eglDisplay = createDefaultDisplay(egl);
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLConfig eglConfig = chooseEglConfig(egl, eglDisplay);
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLContext eglContext = createContext(egl, eglDisplay, eglConfig);
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLSurface eglSurface = createSurface(egl, eglDisplay, width, height);
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        RenderTarget result = new RenderTarget(eglDisplay, eglContext, eglSurface, 0, true, true);
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        result.addReferenceTo(eglSurface);
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return result;
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static RenderTarget currentTarget() {
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // As RenderTargets are immutable, we can safely return the last focused instance on this
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // thread, as we know it cannot have changed, and therefore must be current.
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mCurrentTarget.get();
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public RenderTarget forTexture(TextureSource texture, int width, int height) {
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // NOTE: We do not need to lookup any previous bindings of this texture to an FBO, as
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // multiple FBOs to a single texture is valid.
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int fbo = GLToolbox.generateFbo();
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo);
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GLToolbox.checkGlError("glBindFramebuffer");
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                      GLES20.GL_COLOR_ATTACHMENT0,
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                      texture.getTarget(),
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                      texture.getTextureId(),
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                      0);
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GLToolbox.checkGlError("glFramebufferTexture2D");
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return new RenderTarget(mDisplay, mContext, surface(), fbo, false, false);
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public RenderTarget forSurfaceHolder(SurfaceHolder surfaceHolder) {
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLConfig eglConfig = chooseEglConfig(mEgl, mDisplay);
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLSurface eglSurf = null;
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mSurfaceSources) {
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            eglSurf = mSurfaceSources.get(surfaceHolder);
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (eglSurf == null) {
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                eglSurf = mEgl.eglCreateWindowSurface(mDisplay, eglConfig, surfaceHolder, null);
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mSurfaceSources.put(surfaceHolder, eglSurf);
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkEglError(mEgl, "eglCreateWindowSurface");
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkSurface(mEgl, eglSurf);
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        RenderTarget result = new RenderTarget(mDisplay, mContext, eglSurf, 0, false, true);
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        result.addReferenceTo(eglSurf);
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        result.setSurfaceSource(surfaceHolder);
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return result;
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @TargetApi(11)
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public RenderTarget forSurfaceTexture(SurfaceTexture surfaceTexture) {
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLConfig eglConfig = chooseEglConfig(mEgl, mDisplay);
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLSurface eglSurf = null;
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mSurfaceSources) {
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            eglSurf = mSurfaceSources.get(surfaceTexture);
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (eglSurf == null) {
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                eglSurf = mEgl.eglCreateWindowSurface(mDisplay, eglConfig, surfaceTexture, null);
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mSurfaceSources.put(surfaceTexture, eglSurf);
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkEglError(mEgl, "eglCreateWindowSurface");
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkSurface(mEgl, eglSurf);
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        RenderTarget result = new RenderTarget(mDisplay, mContext, eglSurf, 0, false, true);
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        result.setSurfaceSource(surfaceTexture);
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        result.addReferenceTo(eglSurf);
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return result;
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @TargetApi(11)
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public RenderTarget forSurface(Surface surface) {
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLConfig eglConfig = chooseEglConfig(mEgl, mDisplay);
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLSurface eglSurf = null;
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mSurfaceSources) {
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            eglSurf = mSurfaceSources.get(surface);
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (eglSurf == null) {
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                eglSurf = mEgl.eglCreateWindowSurface(mDisplay, eglConfig, surface, null);
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mSurfaceSources.put(surface, eglSurf);
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkEglError(mEgl, "eglCreateWindowSurface");
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkSurface(mEgl, eglSurf);
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        RenderTarget result = new RenderTarget(mDisplay, mContext, eglSurf, 0, false, true);
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        result.setSurfaceSource(surface);
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        result.addReferenceTo(eglSurf);
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return result;
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static RenderTarget forMediaRecorder(MediaRecorder mediaRecorder) {
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        throw new RuntimeException("Not yet implemented MediaRecorder -> RenderTarget!");
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static void setEGLConfigChooser(int redSize, int greenSize, int blueSize, int alphaSize,
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int depthSize, int stencilSize) {
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        sRedSize = redSize;
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        sGreenSize = greenSize;
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        sBlueSize = blueSize;
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        sAlphaSize = alphaSize;
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        sDepthSize = depthSize;
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        sStencilSize = stencilSize;
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void registerAsDisplaySurface() {
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!mSupportsMultipleDisplaySurfaces) {
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // Note that while this does in effect change RenderTarget instances (by modifying
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // their returned EGLSurface), breaking the immutability requirement, it does not modify
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // the current target. This is important so that the instance returned in
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // currentTarget() remains accurate.
194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            EGLSurface currentSurface = mDisplaySurfaces.get(mContext);
195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (currentSurface != null && !currentSurface.equals(mSurface)) {
196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("This device supports only a single display surface!");
197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mDisplaySurfaces.put(mContext, mSurface);
199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void unregisterAsDisplaySurface() {
204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!mSupportsMultipleDisplaySurfaces) {
205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mDisplaySurfaces.put(mContext, null);
206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void focus() {
210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        RenderTarget current = mCurrentTarget.get();
211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // We assume RenderTargets are immutable, so that we do not need to focus if the current
212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // RenderTarget has not changed.
213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (current != this) {
214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mEgl.eglMakeCurrent(mDisplay, surface(), surface(), mContext);
215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mCurrentTarget.set(this);
216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (getCurrentFbo() != mFbo) {
218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFbo);
219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            GLToolbox.checkGlError("glBindFramebuffer");
220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static void focusNone() {
224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGL10 egl = (EGL10) EGLContext.getEGL();
225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        egl.eglMakeCurrent(egl.eglGetCurrentDisplay(),
226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           EGL10.EGL_NO_SURFACE,
227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           EGL10.EGL_NO_SURFACE,
228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           EGL10.EGL_NO_CONTEXT);
229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mCurrentTarget.set(null);
230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkEglError(egl, "eglMakeCurrent");
231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void swapBuffers() {
234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mEgl.eglSwapBuffers(mDisplay, surface());
235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public EGLContext getContext() {
238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mContext;
239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static EGLContext currentContext() {
242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        RenderTarget current = RenderTarget.currentTarget();
243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return current != null ? current.getContext() : EGL10.EGL_NO_CONTEXT;
244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void release() {
247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mOwnsContext) {
248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mEgl.eglDestroyContext(mDisplay, mContext);
249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mContext = EGL10.EGL_NO_CONTEXT;
250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mOwnsSurface) {
252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            synchronized (mSurfaceSources) {
253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (removeReferenceTo(mSurface)) {
254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mEgl.eglDestroySurface(mDisplay, mSurface);
255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mSurface = EGL10.EGL_NO_SURFACE;
256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mSurfaceSources.remove(mSurfaceSource);
257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mFbo != 0) {
261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks           GLToolbox.deleteFbo(mFbo);
262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks       }
263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void readPixelData(ByteBuffer pixels, int width, int height) {
266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GLToolbox.readTarget(this, pixels, width, height);
267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public ByteBuffer getPixelData(int width, int height) {
270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        ByteBuffer pixels = ByteBuffer.allocateDirect(width * height * 4);
271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GLToolbox.readTarget(this, pixels, width, height);
272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return pixels;
273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns an identity shader for this context.
277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * You must not modify this shader. Use {@link ImageShader#createIdentity()} if you need to
278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * modify an identity shader.
279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public ImageShader getIdentityShader() {
281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        ImageShader idShader = mIdShaders.get(mContext);
282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (idShader == null) {
283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            idShader = ImageShader.createIdentity();
284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mIdShaders.put(mContext, idShader);
285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return idShader;
287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @Override
290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public String toString() {
291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return "RenderTarget(" + mDisplay + ", " + mContext + ", " + mSurface + ", " + mFbo + ")";
292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void setSurfaceSource(Object source) {
295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mSurfaceSource = source;
296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void addReferenceTo(Object object) {
299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Integer refCount = mRefCounts.get(object);
300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (refCount != null) {
301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRefCounts.put(object, refCount + 1);
302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRefCounts.put(object, 1);
304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean removeReferenceTo(Object object) {
308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Integer refCount = mRefCounts.get(object);
309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (refCount != null && refCount > 0) {
310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            --refCount;
311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRefCounts.put(object, refCount);
312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return refCount == 0;
313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Log.e("RenderTarget", "Removing reference of already released: " + object + "!");
315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static EGLConfig chooseEglConfig(EGL10 egl, EGLDisplay display) {
320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mEglConfig == null || !display.equals(mConfiguredDisplay)) {
321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int[] configsCount = new int[1];
322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            EGLConfig[] configs = new EGLConfig[1];
323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int[] configSpec = getDesiredConfig();
324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (!egl.eglChooseConfig(display, configSpec, configs, 1, configsCount)) {
325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new IllegalArgumentException("EGL Error: eglChooseConfig failed " +
326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        getEGLErrorString(egl, egl.eglGetError()));
327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (configsCount[0] > 0) {
328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mEglConfig = configs[0];
329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mConfiguredDisplay = display;
330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mEglConfig;
333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int[] getDesiredConfig() {
336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return new int[] {
337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_RED_SIZE, sRedSize,
339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_GREEN_SIZE, sGreenSize,
340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_BLUE_SIZE, sBlueSize,
341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_ALPHA_SIZE, sAlphaSize,
342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_DEPTH_SIZE, sDepthSize,
343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_STENCIL_SIZE, sStencilSize,
344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                EGL10.EGL_NONE
345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        };
346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private RenderTarget(EGLDisplay display, EGLContext context, EGLSurface surface, int fbo,
349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                         boolean ownsContext, boolean ownsSurface) {
350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mEgl = (EGL10) EGLContext.getEGL();
351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mDisplay = display;
352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mContext = context;
353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mSurface = surface;
354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFbo = fbo;
355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mOwnsContext = ownsContext;
356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mOwnsSurface = ownsSurface;
357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private EGLSurface surface() {
360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mSupportsMultipleDisplaySurfaces) {
361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mSurface;
362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            EGLSurface displaySurface = mDisplaySurfaces.get(mContext);
364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return displaySurface != null ? displaySurface : mSurface;
365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static void initEgl(EGL10 egl, EGLDisplay display) {
369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int[] version = new int[2];
370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!egl.eglInitialize(display, version)) {
371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("EGL Error: eglInitialize failed " +
372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    getEGLErrorString(egl, egl.eglGetError()));
373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static EGLDisplay createDefaultDisplay(EGL10 egl) {
377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkDisplay(egl, display);
379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        initEgl(egl, display);
380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return display;
381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLContext ctxt = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, attrib_list);
386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        checkContext(egl, ctxt);
387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return ctxt;
388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static EGLSurface createSurface(EGL10 egl, EGLDisplay display, int width, int height) {
391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        EGLConfig eglConfig = chooseEglConfig(egl, display);
392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int[] attribs = { EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, EGL10.EGL_NONE };
393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return egl.eglCreatePbufferSurface(display, eglConfig, attribs);
394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int getCurrentFbo() {
397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int[] result = new int[1];
398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, result, 0);
399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return result[0];
400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static void checkDisplay(EGL10 egl, EGLDisplay display) {
403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (display == EGL10.EGL_NO_DISPLAY) {
404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("EGL Error: Bad display: "
405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + getEGLErrorString(egl, egl.eglGetError()));
406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static void checkContext(EGL10 egl, EGLContext context) {
410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (context == EGL10.EGL_NO_CONTEXT) {
411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("EGL Error: Bad context: "
412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + getEGLErrorString(egl, egl.eglGetError()));
413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static void checkSurface(EGL10 egl, EGLSurface surface) {
417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (surface == EGL10.EGL_NO_SURFACE) {
418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("EGL Error: Bad surface: "
419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + getEGLErrorString(egl, egl.eglGetError()));
420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static void checkEglError(EGL10 egl, String command) {
424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int error = egl.eglGetError();
425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (error != EGL10.EGL_SUCCESS) {
426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("Error executing " + command + "! EGL error = 0x"
427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                + Integer.toHexString(error));
428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static String getEGLErrorString(EGL10 egl, int eglError) {
432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (VERSION.SDK_INT >= 14) {
433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return getEGLErrorStringICS(egl, eglError);
434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return "EGL Error 0x" + Integer.toHexString(eglError);
436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @TargetApi(14)
440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static String getEGLErrorStringICS(EGL10 egl, int eglError) {
441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return GLUtils.getEGLErrorString(egl.eglGetError());
442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
445