1441e847feb0e055ecb004802802cea07782ab228Andy McFadden/*
2441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Copyright 2013 The Android Open Source Project
3441e847feb0e055ecb004802802cea07782ab228Andy McFadden *
4441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License");
5441e847feb0e055ecb004802802cea07782ab228Andy McFadden * you may not use this file except in compliance with the License.
6441e847feb0e055ecb004802802cea07782ab228Andy McFadden * You may obtain a copy of the License at
7441e847feb0e055ecb004802802cea07782ab228Andy McFadden *
8441e847feb0e055ecb004802802cea07782ab228Andy McFadden *      http://www.apache.org/licenses/LICENSE-2.0
9441e847feb0e055ecb004802802cea07782ab228Andy McFadden *
10441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Unless required by applicable law or agreed to in writing, software
11441e847feb0e055ecb004802802cea07782ab228Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS,
12441e847feb0e055ecb004802802cea07782ab228Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13441e847feb0e055ecb004802802cea07782ab228Andy McFadden * See the License for the specific language governing permissions and
14441e847feb0e055ecb004802802cea07782ab228Andy McFadden * limitations under the License.
15441e847feb0e055ecb004802802cea07782ab228Andy McFadden */
16441e847feb0e055ecb004802802cea07782ab228Andy McFadden
17441e847feb0e055ecb004802802cea07782ab228Andy McFadden#define LOG_TAG "ScreenRecord"
18441e847feb0e055ecb004802802cea07782ab228Andy McFadden//#define LOG_NDEBUG 0
19441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <utils/Log.h>
20441e847feb0e055ecb004802802cea07782ab228Andy McFadden
21441e847feb0e055ecb004802802cea07782ab228Andy McFadden#define EGL_EGLEXT_PROTOTYPES
22441e847feb0e055ecb004802802cea07782ab228Andy McFadden
23441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <gui/BufferQueue.h>
24441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <gui/GraphicBufferAlloc.h>
25441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <gui/Surface.h>
26441e847feb0e055ecb004802802cea07782ab228Andy McFadden
27441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include "EglWindow.h"
28441e847feb0e055ecb004802802cea07782ab228Andy McFadden
29441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <EGL/egl.h>
30441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <EGL/eglext.h>
31441e847feb0e055ecb004802802cea07782ab228Andy McFadden
32441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <assert.h>
33441e847feb0e055ecb004802802cea07782ab228Andy McFadden
34441e847feb0e055ecb004802802cea07782ab228Andy McFaddenusing namespace android;
35441e847feb0e055ecb004802802cea07782ab228Andy McFadden
36441e847feb0e055ecb004802802cea07782ab228Andy McFadden
37441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t EglWindow::createWindow(const sp<IGraphicBufferProducer>& surface) {
38587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (mEglSurface != EGL_NO_SURFACE) {
39587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        ALOGE("surface already created");
40587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return UNKNOWN_ERROR;
41587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
42587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    status_t err = eglSetupContext(false);
43441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err != NO_ERROR) {
44441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return err;
45441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
46441e847feb0e055ecb004802802cea07782ab228Andy McFadden
47587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    // Cache the current dimensions.  We're not expecting these to change.
48441e847feb0e055ecb004802802cea07782ab228Andy McFadden    surface->query(NATIVE_WINDOW_WIDTH, &mWidth);
49441e847feb0e055ecb004802802cea07782ab228Andy McFadden    surface->query(NATIVE_WINDOW_HEIGHT, &mHeight);
50441e847feb0e055ecb004802802cea07782ab228Andy McFadden
51441e847feb0e055ecb004802802cea07782ab228Andy McFadden    // Output side (EGL surface to draw on).
52441e847feb0e055ecb004802802cea07782ab228Andy McFadden    sp<ANativeWindow> anw = new Surface(surface);
53441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, anw.get(),
54441e847feb0e055ecb004802802cea07782ab228Andy McFadden            NULL);
55441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglSurface == EGL_NO_SURFACE) {
56441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglCreateWindowSurface error: %#x", eglGetError());
57441e847feb0e055ecb004802802cea07782ab228Andy McFadden        eglRelease();
58441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
59441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
60441e847feb0e055ecb004802802cea07782ab228Andy McFadden
61441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
62441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
63441e847feb0e055ecb004802802cea07782ab228Andy McFadden
64587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFaddenstatus_t EglWindow::createPbuffer(int width, int height) {
65587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (mEglSurface != EGL_NO_SURFACE) {
66587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        ALOGE("surface already created");
67587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return UNKNOWN_ERROR;
68587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
69587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    status_t err = eglSetupContext(true);
70587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (err != NO_ERROR) {
71587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return err;
72587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
73587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
74587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    mWidth = width;
75587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    mHeight = height;
76587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
77587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    EGLint pbufferAttribs[] = {
78587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_WIDTH, width,
79587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_HEIGHT, height,
80587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_NONE
81587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    };
82587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    mEglSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, pbufferAttribs);
83587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (mEglSurface == EGL_NO_SURFACE) {
84587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        ALOGE("eglCreatePbufferSurface error: %#x", eglGetError());
85587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        eglRelease();
86587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return UNKNOWN_ERROR;
87587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
88587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
89587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    return NO_ERROR;
90587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden}
91587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
92441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t EglWindow::makeCurrent() const {
93441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
94441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglMakeCurrent failed: %#x", eglGetError());
95441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
96441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
97441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
98441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
99441e847feb0e055ecb004802802cea07782ab228Andy McFadden
100587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFaddenstatus_t EglWindow::eglSetupContext(bool forPbuffer) {
101441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLBoolean result;
102441e847feb0e055ecb004802802cea07782ab228Andy McFadden
103441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
104441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
105441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglGetDisplay failed: %#x", eglGetError());
106441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
107441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
108441e847feb0e055ecb004802802cea07782ab228Andy McFadden
109441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLint majorVersion, minorVersion;
110441e847feb0e055ecb004802802cea07782ab228Andy McFadden    result = eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
111441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (result != EGL_TRUE) {
112441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglInitialize failed: %#x", eglGetError());
113441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
114441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
115441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("Initialized EGL v%d.%d", majorVersion, minorVersion);
116441e847feb0e055ecb004802802cea07782ab228Andy McFadden
117441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLint numConfigs = 0;
118587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    EGLint windowConfigAttribs[] = {
119587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
120587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
121587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RECORDABLE_ANDROID, 1,
122587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RED_SIZE, 8,
123587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_GREEN_SIZE, 8,
124587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_BLUE_SIZE, 8,
125587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            // no alpha
126587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_NONE
127587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    };
128587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    EGLint pbufferConfigAttribs[] = {
129587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
130587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
131587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RED_SIZE, 8,
132587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_GREEN_SIZE, 8,
133587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_BLUE_SIZE, 8,
134587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_ALPHA_SIZE, 8,
135587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_NONE
136441e847feb0e055ecb004802802cea07782ab228Andy McFadden    };
137587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    result = eglChooseConfig(mEglDisplay,
138587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            forPbuffer ? pbufferConfigAttribs : windowConfigAttribs,
139587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            &mEglConfig, 1, &numConfigs);
140441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (result != EGL_TRUE) {
141441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglChooseConfig error: %#x", eglGetError());
142441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
143441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
144441e847feb0e055ecb004802802cea07782ab228Andy McFadden
145441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLint contextAttribs[] = {
146441e847feb0e055ecb004802802cea07782ab228Andy McFadden        EGL_CONTEXT_CLIENT_VERSION, 2,
147441e847feb0e055ecb004802802cea07782ab228Andy McFadden        EGL_NONE
148441e847feb0e055ecb004802802cea07782ab228Andy McFadden    };
149441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
150441e847feb0e055ecb004802802cea07782ab228Andy McFadden            contextAttribs);
151441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglContext == EGL_NO_CONTEXT) {
152441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglCreateContext error: %#x", eglGetError());
153441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
154441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
155441e847feb0e055ecb004802802cea07782ab228Andy McFadden
156441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
157441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
158441e847feb0e055ecb004802802cea07782ab228Andy McFadden
159441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid EglWindow::eglRelease() {
160441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("EglWindow::eglRelease");
161441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglDisplay != EGL_NO_DISPLAY) {
162441e847feb0e055ecb004802802cea07782ab228Andy McFadden        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
163441e847feb0e055ecb004802802cea07782ab228Andy McFadden                EGL_NO_CONTEXT);
164441e847feb0e055ecb004802802cea07782ab228Andy McFadden
165441e847feb0e055ecb004802802cea07782ab228Andy McFadden        if (mEglContext != EGL_NO_CONTEXT) {
166441e847feb0e055ecb004802802cea07782ab228Andy McFadden            eglDestroyContext(mEglDisplay, mEglContext);
167441e847feb0e055ecb004802802cea07782ab228Andy McFadden        }
168441e847feb0e055ecb004802802cea07782ab228Andy McFadden
169441e847feb0e055ecb004802802cea07782ab228Andy McFadden        if (mEglSurface != EGL_NO_SURFACE) {
170441e847feb0e055ecb004802802cea07782ab228Andy McFadden            eglDestroySurface(mEglDisplay, mEglSurface);
171441e847feb0e055ecb004802802cea07782ab228Andy McFadden        }
172441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
173441e847feb0e055ecb004802802cea07782ab228Andy McFadden
174441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglDisplay = EGL_NO_DISPLAY;
175441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglContext = EGL_NO_CONTEXT;
176441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglSurface = EGL_NO_SURFACE;
177441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglConfig = NULL;
178441e847feb0e055ecb004802802cea07782ab228Andy McFadden
179441e847feb0e055ecb004802802cea07782ab228Andy McFadden    eglReleaseThread();
180441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
181441e847feb0e055ecb004802802cea07782ab228Andy McFadden
182441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Sets the presentation time on the current EGL buffer.
183441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid EglWindow::presentationTime(nsecs_t whenNsec) const {
184441e847feb0e055ecb004802802cea07782ab228Andy McFadden    eglPresentationTimeANDROID(mEglDisplay, mEglSurface, whenNsec);
185441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
186441e847feb0e055ecb004802802cea07782ab228Andy McFadden
187441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Swaps the EGL buffer.
188441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid EglWindow::swapBuffers() const {
189441e847feb0e055ecb004802802cea07782ab228Andy McFadden    eglSwapBuffers(mEglDisplay, mEglSurface);
190441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
191