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/Surface.h>
25441e847feb0e055ecb004802802cea07782ab228Andy McFadden
26441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include "EglWindow.h"
27441e847feb0e055ecb004802802cea07782ab228Andy McFadden
28441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <EGL/egl.h>
29441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <EGL/eglext.h>
30441e847feb0e055ecb004802802cea07782ab228Andy McFadden
31441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <assert.h>
32441e847feb0e055ecb004802802cea07782ab228Andy McFadden
33441e847feb0e055ecb004802802cea07782ab228Andy McFaddenusing namespace android;
34441e847feb0e055ecb004802802cea07782ab228Andy McFadden
35441e847feb0e055ecb004802802cea07782ab228Andy McFadden
36441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t EglWindow::createWindow(const sp<IGraphicBufferProducer>& surface) {
37587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (mEglSurface != EGL_NO_SURFACE) {
38587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        ALOGE("surface already created");
39587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return UNKNOWN_ERROR;
40587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
41587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    status_t err = eglSetupContext(false);
42441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err != NO_ERROR) {
43441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return err;
44441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
45441e847feb0e055ecb004802802cea07782ab228Andy McFadden
46587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    // Cache the current dimensions.  We're not expecting these to change.
47441e847feb0e055ecb004802802cea07782ab228Andy McFadden    surface->query(NATIVE_WINDOW_WIDTH, &mWidth);
48441e847feb0e055ecb004802802cea07782ab228Andy McFadden    surface->query(NATIVE_WINDOW_HEIGHT, &mHeight);
49441e847feb0e055ecb004802802cea07782ab228Andy McFadden
50441e847feb0e055ecb004802802cea07782ab228Andy McFadden    // Output side (EGL surface to draw on).
51441e847feb0e055ecb004802802cea07782ab228Andy McFadden    sp<ANativeWindow> anw = new Surface(surface);
52441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, anw.get(),
53441e847feb0e055ecb004802802cea07782ab228Andy McFadden            NULL);
54441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglSurface == EGL_NO_SURFACE) {
55441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglCreateWindowSurface error: %#x", eglGetError());
56441e847feb0e055ecb004802802cea07782ab228Andy McFadden        eglRelease();
57441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
58441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
59441e847feb0e055ecb004802802cea07782ab228Andy McFadden
60441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
61441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
62441e847feb0e055ecb004802802cea07782ab228Andy McFadden
63587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFaddenstatus_t EglWindow::createPbuffer(int width, int height) {
64587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (mEglSurface != EGL_NO_SURFACE) {
65587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        ALOGE("surface already created");
66587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return UNKNOWN_ERROR;
67587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
68587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    status_t err = eglSetupContext(true);
69587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (err != NO_ERROR) {
70587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return err;
71587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
72587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
73587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    mWidth = width;
74587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    mHeight = height;
75587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
76587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    EGLint pbufferAttribs[] = {
77587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_WIDTH, width,
78587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_HEIGHT, height,
79587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_NONE
80587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    };
81587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    mEglSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, pbufferAttribs);
82587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (mEglSurface == EGL_NO_SURFACE) {
83587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        ALOGE("eglCreatePbufferSurface error: %#x", eglGetError());
84587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        eglRelease();
85587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        return UNKNOWN_ERROR;
86587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
87587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
88587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    return NO_ERROR;
89587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden}
90587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden
91441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t EglWindow::makeCurrent() const {
92441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
93441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglMakeCurrent failed: %#x", eglGetError());
94441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
95441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
96441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
97441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
98441e847feb0e055ecb004802802cea07782ab228Andy McFadden
99587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFaddenstatus_t EglWindow::eglSetupContext(bool forPbuffer) {
100441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLBoolean result;
101441e847feb0e055ecb004802802cea07782ab228Andy McFadden
102441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
103441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
104441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglGetDisplay failed: %#x", eglGetError());
105441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
106441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
107441e847feb0e055ecb004802802cea07782ab228Andy McFadden
108441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLint majorVersion, minorVersion;
109441e847feb0e055ecb004802802cea07782ab228Andy McFadden    result = eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
110441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (result != EGL_TRUE) {
111441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglInitialize failed: %#x", eglGetError());
112441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
113441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
114441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("Initialized EGL v%d.%d", majorVersion, minorVersion);
115441e847feb0e055ecb004802802cea07782ab228Andy McFadden
116441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLint numConfigs = 0;
117587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    EGLint windowConfigAttribs[] = {
118587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
119587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
120587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RECORDABLE_ANDROID, 1,
121587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RED_SIZE, 8,
122587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_GREEN_SIZE, 8,
123587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_BLUE_SIZE, 8,
124587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            // no alpha
125587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_NONE
126587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    };
127587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    EGLint pbufferConfigAttribs[] = {
128587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
129587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
130587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_RED_SIZE, 8,
131587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_GREEN_SIZE, 8,
132587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_BLUE_SIZE, 8,
133587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_ALPHA_SIZE, 8,
134587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            EGL_NONE
135441e847feb0e055ecb004802802cea07782ab228Andy McFadden    };
136587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    result = eglChooseConfig(mEglDisplay,
137587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            forPbuffer ? pbufferConfigAttribs : windowConfigAttribs,
138587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden            &mEglConfig, 1, &numConfigs);
139441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (result != EGL_TRUE) {
140441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglChooseConfig error: %#x", eglGetError());
141441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
142441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
143441e847feb0e055ecb004802802cea07782ab228Andy McFadden
144441e847feb0e055ecb004802802cea07782ab228Andy McFadden    EGLint contextAttribs[] = {
145441e847feb0e055ecb004802802cea07782ab228Andy McFadden        EGL_CONTEXT_CLIENT_VERSION, 2,
146441e847feb0e055ecb004802802cea07782ab228Andy McFadden        EGL_NONE
147441e847feb0e055ecb004802802cea07782ab228Andy McFadden    };
148441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
149441e847feb0e055ecb004802802cea07782ab228Andy McFadden            contextAttribs);
150441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglContext == EGL_NO_CONTEXT) {
151441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("eglCreateContext error: %#x", eglGetError());
152441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
153441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
154441e847feb0e055ecb004802802cea07782ab228Andy McFadden
155441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
156441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
157441e847feb0e055ecb004802802cea07782ab228Andy McFadden
158441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid EglWindow::eglRelease() {
159441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("EglWindow::eglRelease");
160441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mEglDisplay != EGL_NO_DISPLAY) {
161441e847feb0e055ecb004802802cea07782ab228Andy McFadden        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
162441e847feb0e055ecb004802802cea07782ab228Andy McFadden                EGL_NO_CONTEXT);
163441e847feb0e055ecb004802802cea07782ab228Andy McFadden
164441e847feb0e055ecb004802802cea07782ab228Andy McFadden        if (mEglContext != EGL_NO_CONTEXT) {
165441e847feb0e055ecb004802802cea07782ab228Andy McFadden            eglDestroyContext(mEglDisplay, mEglContext);
166441e847feb0e055ecb004802802cea07782ab228Andy McFadden        }
167441e847feb0e055ecb004802802cea07782ab228Andy McFadden
168441e847feb0e055ecb004802802cea07782ab228Andy McFadden        if (mEglSurface != EGL_NO_SURFACE) {
169441e847feb0e055ecb004802802cea07782ab228Andy McFadden            eglDestroySurface(mEglDisplay, mEglSurface);
170441e847feb0e055ecb004802802cea07782ab228Andy McFadden        }
171441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
172441e847feb0e055ecb004802802cea07782ab228Andy McFadden
173441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglDisplay = EGL_NO_DISPLAY;
174441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglContext = EGL_NO_CONTEXT;
175441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglSurface = EGL_NO_SURFACE;
176441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mEglConfig = NULL;
177441e847feb0e055ecb004802802cea07782ab228Andy McFadden
178441e847feb0e055ecb004802802cea07782ab228Andy McFadden    eglReleaseThread();
179441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
180441e847feb0e055ecb004802802cea07782ab228Andy McFadden
181441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Sets the presentation time on the current EGL buffer.
182441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid EglWindow::presentationTime(nsecs_t whenNsec) const {
183441e847feb0e055ecb004802802cea07782ab228Andy McFadden    eglPresentationTimeANDROID(mEglDisplay, mEglSurface, whenNsec);
184441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
185441e847feb0e055ecb004802802cea07782ab228Andy McFadden
186441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Swaps the EGL buffer.
187441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid EglWindow::swapBuffers() const {
188441e847feb0e055ecb004802802cea07782ab228Andy McFadden    eglSwapBuffers(mEglDisplay, mEglSurface);
189441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
190