Home | History | Annotate | Download | only in screenrecord
      1 /*
      2  * Copyright 2013 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 #define LOG_TAG "ScreenRecord"
     18 //#define LOG_NDEBUG 0
     19 #include <utils/Log.h>
     20 
     21 #define EGL_EGLEXT_PROTOTYPES
     22 
     23 #include <gui/BufferQueue.h>
     24 #include <gui/Surface.h>
     25 
     26 #include "EglWindow.h"
     27 
     28 #include <EGL/egl.h>
     29 #include <EGL/eglext.h>
     30 
     31 #include <assert.h>
     32 
     33 using namespace android;
     34 
     35 
     36 status_t EglWindow::createWindow(const sp<IGraphicBufferProducer>& surface) {
     37     if (mEglSurface != EGL_NO_SURFACE) {
     38         ALOGE("surface already created");
     39         return UNKNOWN_ERROR;
     40     }
     41     status_t err = eglSetupContext(false);
     42     if (err != NO_ERROR) {
     43         return err;
     44     }
     45 
     46     // Cache the current dimensions.  We're not expecting these to change.
     47     surface->query(NATIVE_WINDOW_WIDTH, &mWidth);
     48     surface->query(NATIVE_WINDOW_HEIGHT, &mHeight);
     49 
     50     // Output side (EGL surface to draw on).
     51     sp<ANativeWindow> anw = new Surface(surface);
     52     mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, anw.get(),
     53             NULL);
     54     if (mEglSurface == EGL_NO_SURFACE) {
     55         ALOGE("eglCreateWindowSurface error: %#x", eglGetError());
     56         eglRelease();
     57         return UNKNOWN_ERROR;
     58     }
     59 
     60     return NO_ERROR;
     61 }
     62 
     63 status_t EglWindow::createPbuffer(int width, int height) {
     64     if (mEglSurface != EGL_NO_SURFACE) {
     65         ALOGE("surface already created");
     66         return UNKNOWN_ERROR;
     67     }
     68     status_t err = eglSetupContext(true);
     69     if (err != NO_ERROR) {
     70         return err;
     71     }
     72 
     73     mWidth = width;
     74     mHeight = height;
     75 
     76     EGLint pbufferAttribs[] = {
     77             EGL_WIDTH, width,
     78             EGL_HEIGHT, height,
     79             EGL_NONE
     80     };
     81     mEglSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, pbufferAttribs);
     82     if (mEglSurface == EGL_NO_SURFACE) {
     83         ALOGE("eglCreatePbufferSurface error: %#x", eglGetError());
     84         eglRelease();
     85         return UNKNOWN_ERROR;
     86     }
     87 
     88     return NO_ERROR;
     89 }
     90 
     91 status_t EglWindow::makeCurrent() const {
     92     if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
     93         ALOGE("eglMakeCurrent failed: %#x", eglGetError());
     94         return UNKNOWN_ERROR;
     95     }
     96     return NO_ERROR;
     97 }
     98 
     99 status_t EglWindow::eglSetupContext(bool forPbuffer) {
    100     EGLBoolean result;
    101 
    102     mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    103     if (mEglDisplay == EGL_NO_DISPLAY) {
    104         ALOGE("eglGetDisplay failed: %#x", eglGetError());
    105         return UNKNOWN_ERROR;
    106     }
    107 
    108     EGLint majorVersion, minorVersion;
    109     result = eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
    110     if (result != EGL_TRUE) {
    111         ALOGE("eglInitialize failed: %#x", eglGetError());
    112         return UNKNOWN_ERROR;
    113     }
    114     ALOGV("Initialized EGL v%d.%d", majorVersion, minorVersion);
    115 
    116     EGLint numConfigs = 0;
    117     EGLint windowConfigAttribs[] = {
    118             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    119             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    120             EGL_RECORDABLE_ANDROID, 1,
    121             EGL_RED_SIZE, 8,
    122             EGL_GREEN_SIZE, 8,
    123             EGL_BLUE_SIZE, 8,
    124             // no alpha
    125             EGL_NONE
    126     };
    127     EGLint pbufferConfigAttribs[] = {
    128             EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
    129             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    130             EGL_RED_SIZE, 8,
    131             EGL_GREEN_SIZE, 8,
    132             EGL_BLUE_SIZE, 8,
    133             EGL_ALPHA_SIZE, 8,
    134             EGL_NONE
    135     };
    136     result = eglChooseConfig(mEglDisplay,
    137             forPbuffer ? pbufferConfigAttribs : windowConfigAttribs,
    138             &mEglConfig, 1, &numConfigs);
    139     if (result != EGL_TRUE) {
    140         ALOGE("eglChooseConfig error: %#x", eglGetError());
    141         return UNKNOWN_ERROR;
    142     }
    143 
    144     EGLint contextAttribs[] = {
    145         EGL_CONTEXT_CLIENT_VERSION, 2,
    146         EGL_NONE
    147     };
    148     mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
    149             contextAttribs);
    150     if (mEglContext == EGL_NO_CONTEXT) {
    151         ALOGE("eglCreateContext error: %#x", eglGetError());
    152         return UNKNOWN_ERROR;
    153     }
    154 
    155     return NO_ERROR;
    156 }
    157 
    158 void EglWindow::eglRelease() {
    159     ALOGV("EglWindow::eglRelease");
    160     if (mEglDisplay != EGL_NO_DISPLAY) {
    161         eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
    162                 EGL_NO_CONTEXT);
    163 
    164         if (mEglContext != EGL_NO_CONTEXT) {
    165             eglDestroyContext(mEglDisplay, mEglContext);
    166         }
    167 
    168         if (mEglSurface != EGL_NO_SURFACE) {
    169             eglDestroySurface(mEglDisplay, mEglSurface);
    170         }
    171     }
    172 
    173     mEglDisplay = EGL_NO_DISPLAY;
    174     mEglContext = EGL_NO_CONTEXT;
    175     mEglSurface = EGL_NO_SURFACE;
    176     mEglConfig = NULL;
    177 
    178     eglReleaseThread();
    179 }
    180 
    181 // Sets the presentation time on the current EGL buffer.
    182 void EglWindow::presentationTime(nsecs_t whenNsec) const {
    183     eglPresentationTimeANDROID(mEglDisplay, mEglSurface, whenNsec);
    184 }
    185 
    186 // Swaps the EGL buffer.
    187 void EglWindow::swapBuffers() const {
    188     eglSwapBuffers(mEglDisplay, mEglSurface);
    189 }
    190