DisplayDevice.cpp revision 076b1cc3a9b90aa5b381a1ed268ca0b548444c9b
1/*
2 * Copyright (C) 2007 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#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20#include <math.h>
21
22#include <cutils/properties.h>
23
24#include <utils/RefBase.h>
25#include <utils/Log.h>
26
27#include <ui/PixelFormat.h>
28#include <ui/EGLNativeWindowSurface.h>
29
30#include <GLES/gl.h>
31#include <EGL/egl.h>
32#include <EGL/eglext.h>
33#include <EGL/android_natives.h>
34
35#include <pixelflinger/pixelflinger.h>
36
37#include "DisplayHardware/DisplayHardware.h"
38
39#include <hardware/copybit.h>
40#include <hardware/overlay.h>
41#include <hardware/gralloc.h>
42
43using namespace android;
44
45static __attribute__((noinline))
46const char *egl_strerror(EGLint err)
47{
48    switch (err){
49        case EGL_SUCCESS:           return "EGL_SUCCESS";
50        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
51        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
52        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
53        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
54        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
55        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
56        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
57        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
58        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
59        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
60        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
61        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
62        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
63        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
64        default: return "UNKNOWN";
65    }
66}
67
68static __attribute__((noinline))
69void checkGLErrors()
70{
71    GLenum error = glGetError();
72    if (error != GL_NO_ERROR)
73        LOGE("GL error 0x%04x", int(error));
74}
75
76static __attribute__((noinline))
77void checkEGLErrors(const char* token)
78{
79    EGLint error = eglGetError();
80    // GLESonGL seems to be returning 0 when there is no errors?
81    if (error && error != EGL_SUCCESS)
82        LOGE("%s error 0x%04x (%s)",
83                token, int(error), egl_strerror(error));
84}
85
86
87/*
88 * Initialize the display to the specified values.
89 *
90 */
91
92DisplayHardware::DisplayHardware(
93        const sp<SurfaceFlinger>& flinger,
94        uint32_t dpy)
95    : DisplayHardwareBase(flinger, dpy)
96{
97    init(dpy);
98}
99
100DisplayHardware::~DisplayHardware()
101{
102    fini();
103}
104
105float DisplayHardware::getDpiX() const          { return mDpiX; }
106float DisplayHardware::getDpiY() const          { return mDpiY; }
107float DisplayHardware::getDensity() const       { return mDensity; }
108float DisplayHardware::getRefreshRate() const   { return mRefreshRate; }
109int DisplayHardware::getWidth() const           { return mWidth; }
110int DisplayHardware::getHeight() const          { return mHeight; }
111PixelFormat DisplayHardware::getFormat() const  { return mFormat; }
112
113void DisplayHardware::init(uint32_t dpy)
114{
115    hw_module_t const* module;
116
117    mNativeWindow = new FramebufferNativeWindow();
118
119    mOverlayEngine = NULL;
120    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
121        overlay_control_open(module, &mOverlayEngine);
122    }
123
124    framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
125
126    PixelFormatInfo fbFormatInfo;
127    getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo);
128
129    // initialize EGL
130    const EGLint attribs[] = {
131            EGL_BUFFER_SIZE,    fbFormatInfo.bitsPerPixel,
132            EGL_DEPTH_SIZE,     0,
133            EGL_NONE
134    };
135    EGLint w, h, dummy;
136    EGLint numConfigs=0, n=0;
137    EGLSurface surface;
138    EGLContext context;
139    mFlags = 0;
140
141    // TODO: all the extensions below should be queried through
142    // eglGetProcAddress().
143
144    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
145    eglInitialize(display, NULL, NULL);
146    eglGetConfigs(display, NULL, 0, &numConfigs);
147
148    // Get all the "potential match" configs...
149    EGLConfig* const configs = new EGLConfig[numConfigs];
150    eglChooseConfig(display, attribs, configs, numConfigs, &n);
151    LOGE_IF(n<=0, "no EGLConfig available!");
152    EGLConfig config = configs[0];
153    if (n > 1) {
154        // if there is more than one candidate, go through the list
155        // and pick one that matches our framebuffer format
156        int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);
157        int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);
158        int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);
159        int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE);
160        for (int i=0 ; i<n ; i++) {
161            EGLint r,g,b,a;
162            eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE,   &r);
163            eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g);
164            eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE,  &b);
165            eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a);
166            if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
167                config = configs[i];
168            }
169        }
170    }
171    delete [] configs;
172
173    /*
174     * Gather EGL extensions
175     */
176
177    const char* const egl_extensions = eglQueryString(
178            display, EGL_EXTENSIONS);
179
180    LOGI("EGL informations:");
181    LOGI("# of configs : %d", numConfigs);
182    LOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
183    LOGI("version   : %s", eglQueryString(display, EGL_VERSION));
184    LOGI("extensions: %s", egl_extensions);
185    LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
186
187    // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
188    // FIXME: mFlags |= UPDATE_ON_DEMAND;
189
190    if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
191        if (dummy == EGL_SLOW_CONFIG)
192            mFlags |= SLOW_CONFIG;
193    }
194
195    /*
196     * Create our main surface
197     */
198
199
200    surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
201    checkEGLErrors("eglCreateDisplaySurfaceANDROID");
202
203
204    if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
205        if (dummy == EGL_BUFFER_PRESERVED) {
206            mFlags |= BUFFER_PRESERVED;
207        }
208    }
209
210    mDpiX = mNativeWindow->xdpi;
211    mDpiX = mNativeWindow->ydpi;
212    mRefreshRate = mNativeWindow->getDevice()->fps;
213
214    char property[PROPERTY_VALUE_MAX];
215    if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
216        LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
217        strcpy(property, "160");
218    }
219    mDensity = atoi(property) * (1.0f/160.0f);
220
221
222    /*
223     * Create our OpenGL ES context
224     */
225
226    context = eglCreateContext(display, config, NULL, NULL);
227    //checkEGLErrors("eglCreateContext");
228
229    eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
230    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
231
232
233    /*
234     * Gather OpenGL ES extensions
235     */
236
237    eglMakeCurrent(display, surface, surface, context);
238    const char* const  gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
239    LOGI("OpenGL informations:");
240    LOGI("vendor    : %s", glGetString(GL_VENDOR));
241    LOGI("renderer  : %s", glGetString(GL_RENDERER));
242    LOGI("version   : %s", glGetString(GL_VERSION));
243    LOGI("extensions: %s", gl_extensions);
244
245    if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
246        mFlags |= NPOT_EXTENSION;
247    }
248    if (strstr(gl_extensions, "GL_OES_draw_texture")) {
249        mFlags |= DRAW_TEXTURE_EXTENSION;
250    }
251    if (strstr( gl_extensions, "GL_OES_EGL_image") &&
252        (strstr(egl_extensions, "KHR_image_base") ||
253                strstr(egl_extensions, "EGL_KHR_image")) &&
254        strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
255        mFlags |= DIRECT_TEXTURE;
256    }
257
258    // Unbind the context from this thread
259    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
260
261    mDisplay = display;
262    mConfig  = config;
263    mSurface = surface;
264    mContext = context;
265    mFormat  = fbDev->format;
266    mPageFlipCount = 0;
267}
268
269/*
270 * Clean up.  Throw out our local state.
271 *
272 * (It's entirely possible we'll never get here, since this is meant
273 * for real hardware, which doesn't restart.)
274 */
275
276void DisplayHardware::fini()
277{
278    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
279    eglTerminate(mDisplay);
280    overlay_control_close(mOverlayEngine);
281}
282
283void DisplayHardware::releaseScreen() const
284{
285    DisplayHardwareBase::releaseScreen();
286}
287
288void DisplayHardware::acquireScreen() const
289{
290    DisplayHardwareBase::acquireScreen();
291}
292
293uint32_t DisplayHardware::getPageFlipCount() const {
294    return mPageFlipCount;
295}
296
297/*
298 * "Flip" the front and back buffers.
299 */
300
301void DisplayHardware::flip(const Region& dirty) const
302{
303    checkGLErrors();
304
305    EGLDisplay dpy = mDisplay;
306    EGLSurface surface = mSurface;
307
308    Region newDirty(dirty);
309    newDirty.andSelf(Rect(mWidth, mHeight));
310
311    if (mFlags & BUFFER_PRESERVED) {
312        mDirty = newDirty;
313    }
314
315    const Rect& b(newDirty.bounds());
316    mNativeWindow->android_native_window_t::setSwapRectangle(
317            mNativeWindow.get(), b.left, b.top, b.width(), b.height());
318
319    mPageFlipCount++;
320    eglSwapBuffers(dpy, surface);
321    checkEGLErrors("eglSwapBuffers");
322
323    // for debugging
324    //glClearColor(1,0,0,0);
325    //glClear(GL_COLOR_BUFFER_BIT);
326}
327
328uint32_t DisplayHardware::getFlags() const
329{
330    return mFlags;
331}
332
333void DisplayHardware::makeCurrent() const
334{
335    eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
336}
337
338void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
339    // FIXME: we need to get rid of this
340}
341
342void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
343    // FIXME: we need to get rid of this
344}
345