DisplayDevice.cpp revision 0f2f5ff75b7b48ceb64270655ee6b62d09bf4d00
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/DisplayInfo.h>
28#include <ui/PixelFormat.h>
29
30#include <GLES/gl.h>
31#include <EGL/egl.h>
32#include <EGL/eglext.h>
33
34#include <hardware/gralloc.h>
35
36#include "DisplayHardware/FramebufferSurface.h"
37#include "DisplayHardware/DisplayDeviceBase.h"
38#include "DisplayHardware/HWComposer.h"
39
40#include "DisplayDevice.h"
41#include "GLExtensions.h"
42#include "SurfaceFlinger.h"
43#include "LayerBase.h"
44
45// ----------------------------------------------------------------------------
46using namespace android;
47// ----------------------------------------------------------------------------
48
49static __attribute__((noinline))
50void checkGLErrors()
51{
52    do {
53        // there could be more than one error flag
54        GLenum error = glGetError();
55        if (error == GL_NO_ERROR)
56            break;
57        ALOGE("GL error 0x%04x", int(error));
58    } while(true);
59}
60
61static __attribute__((noinline))
62void checkEGLErrors(const char* token)
63{
64    struct EGLUtils {
65        static const char *strerror(EGLint err) {
66            switch (err){
67                case EGL_SUCCESS:           return "EGL_SUCCESS";
68                case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
69                case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
70                case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
71                case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
72                case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
73                case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
74                case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
75                case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
76                case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
77                case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
78                case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
79                case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
80                case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
81                case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
82                default: return "UNKNOWN";
83            }
84        }
85    };
86
87    EGLint error = eglGetError();
88    if (error && error != EGL_SUCCESS) {
89        ALOGE("%s: EGL error 0x%04x (%s)",
90                token, int(error), EGLUtils::strerror(error));
91    }
92}
93
94// ----------------------------------------------------------------------------
95
96/*
97 * Initialize the display to the specified values.
98 *
99 */
100
101DisplayDevice::DisplayDevice(
102        const sp<SurfaceFlinger>& flinger,
103        int display,
104        const sp<SurfaceTextureClient>& surface,
105        EGLConfig config)
106    : DisplayDeviceBase(display),
107      mFlinger(flinger),
108      mDisplayId(display),
109      mNativeWindow(surface),
110      mFlags(0),
111      mSecureLayerVisible(false),
112      mLayerStack(0)
113{
114    init(config);
115}
116
117DisplayDevice::~DisplayDevice() {
118}
119
120float DisplayDevice::getDpiX() const {
121    return mDpiX;
122}
123
124float DisplayDevice::getDpiY() const {
125    return mDpiY;
126}
127
128float DisplayDevice::getDensity() const {
129    return mDensity;
130}
131
132float DisplayDevice::getRefreshRate() const {
133    return mRefreshRate;
134}
135
136int DisplayDevice::getWidth() const {
137    return mDisplayWidth;
138}
139
140int DisplayDevice::getHeight() const {
141    return mDisplayHeight;
142}
143
144PixelFormat DisplayDevice::getFormat() const {
145    return mFormat;
146}
147
148EGLSurface DisplayDevice::getEGLSurface() const {
149    return mSurface;
150}
151
152status_t DisplayDevice::getInfo(DisplayInfo* info) const {
153    info->w = getWidth();
154    info->h = getHeight();
155    info->xdpi = getDpiX();
156    info->ydpi = getDpiY();
157    info->fps = getRefreshRate();
158    info->density = getDensity();
159    info->orientation = getOrientation();
160    // TODO: this needs to go away (currently needed only by webkit)
161    getPixelFormatInfo(getFormat(), &info->pixelFormatInfo);
162    return NO_ERROR;
163}
164
165void DisplayDevice::init(EGLConfig config)
166{
167    ANativeWindow* const window = mNativeWindow.get();
168
169    int concreteType;
170    window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &concreteType);
171    if (concreteType == NATIVE_WINDOW_FRAMEBUFFER) {
172        mFramebufferSurface = static_cast<FramebufferSurface *>(mNativeWindow.get());
173    }
174
175    int format;
176    window->query(window, NATIVE_WINDOW_FORMAT, &format);
177    mDpiX = window->xdpi;
178    mDpiY = window->ydpi;
179    if (mFramebufferSurface != NULL) {
180        mRefreshRate = mFramebufferSurface->getRefreshRate();
181    } else {
182        mRefreshRate = 60;
183    }
184    mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
185
186
187    // TODO: Not sure if display density should handled by SF any longer
188    class Density {
189        static int getDensityFromProperty(char const* propName) {
190            char property[PROPERTY_VALUE_MAX];
191            int density = 0;
192            if (property_get(propName, property, NULL) > 0) {
193                density = atoi(property);
194            }
195            return density;
196        }
197    public:
198        static int getEmuDensity() {
199            return getDensityFromProperty("qemu.sf.lcd_density"); }
200        static int getBuildDensity()  {
201            return getDensityFromProperty("ro.sf.lcd_density"); }
202    };
203    // The density of the device is provided by a build property
204    mDensity = Density::getBuildDensity() / 160.0f;
205    if (mDensity == 0) {
206        // the build doesn't provide a density -- this is wrong!
207        // use xdpi instead
208        ALOGE("ro.sf.lcd_density must be defined as a build property");
209        mDensity = mDpiX / 160.0f;
210    }
211    if (Density::getEmuDensity()) {
212        // if "qemu.sf.lcd_density" is specified, it overrides everything
213        mDpiX = mDpiY = mDensity = Density::getEmuDensity();
214        mDensity /= 160.0f;
215    }
216
217    /*
218     * Create our display's surface
219     */
220
221    EGLSurface surface;
222    EGLint w, h;
223    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
224    surface = eglCreateWindowSurface(display, config, window, NULL);
225    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
226    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
227
228    if (mFramebufferSurface != NULL) {
229        if (mFramebufferSurface->isUpdateOnDemand()) {
230            mFlags |= PARTIAL_UPDATES;
231            // if we have partial updates, we definitely don't need to
232            // preserve the backbuffer, which may be costly.
233            eglSurfaceAttrib(display, surface,
234                    EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
235        }
236    }
237
238    mDisplay = display;
239    mSurface = surface;
240    mFormat  = format;
241    mPageFlipCount = 0;
242
243    // initialize the display orientation transform.
244    DisplayDevice::setOrientation(ISurfaceComposer::eOrientationDefault);
245}
246
247uint32_t DisplayDevice::getPageFlipCount() const {
248    return mPageFlipCount;
249}
250
251nsecs_t DisplayDevice::getRefreshTimestamp() const {
252    // this returns the last refresh timestamp.
253    // if the last one is not available, we estimate it based on
254    // the refresh period and whatever closest timestamp we have.
255    Mutex::Autolock _l(mLock);
256    nsecs_t now = systemTime(CLOCK_MONOTONIC);
257    return now - ((now - mLastHwVSync) %  mRefreshPeriod);
258}
259
260nsecs_t DisplayDevice::getRefreshPeriod() const {
261    return mRefreshPeriod;
262}
263
264status_t DisplayDevice::compositionComplete() const {
265    if (mFramebufferSurface == NULL) {
266        return NO_ERROR;
267    }
268    return mFramebufferSurface->compositionComplete();
269}
270
271void DisplayDevice::onVSyncReceived(nsecs_t timestamp) {
272    Mutex::Autolock _l(mLock);
273    mLastHwVSync = timestamp;
274}
275
276void DisplayDevice::flip(const Region& dirty) const
277{
278    checkGLErrors();
279
280    EGLDisplay dpy = mDisplay;
281    EGLSurface surface = mSurface;
282
283#ifdef EGL_ANDROID_swap_rectangle
284    if (mFlags & SWAP_RECTANGLE) {
285        const Region newDirty(dirty.intersect(bounds()));
286        const Rect b(newDirty.getBounds());
287        eglSetSwapRectangleANDROID(dpy, surface,
288                b.left, b.top, b.width(), b.height());
289    }
290#endif
291
292    if (mFlags & PARTIAL_UPDATES) {
293        if (mFramebufferSurface != NULL) {
294            mFramebufferSurface->setUpdateRectangle(dirty.getBounds());
295        }
296    }
297
298    mPageFlipCount++;
299}
300
301uint32_t DisplayDevice::getFlags() const
302{
303    return mFlags;
304}
305
306void DisplayDevice::dump(String8& res) const
307{
308    if (mFramebufferSurface != NULL) {
309        mFramebufferSurface->dump(res);
310    }
311}
312
313void DisplayDevice::makeCurrent(const DisplayDevice& hw, EGLContext ctx) {
314    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
315    if (sur != hw.mSurface) {
316        EGLDisplay dpy = eglGetCurrentDisplay();
317        eglMakeCurrent(dpy, hw.mSurface, hw.mSurface, ctx);
318    }
319}
320
321// ----------------------------------------------------------------------------
322
323void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
324    mVisibleLayersSortedByZ = layers;
325    size_t count = layers.size();
326    for (size_t i=0 ; i<count ; i++) {
327        if (layers[i]->isSecure()) {
328            mSecureLayerVisible = true;
329        }
330    }
331}
332
333Vector< sp<LayerBase> > DisplayDevice::getVisibleLayersSortedByZ() const {
334    return mVisibleLayersSortedByZ;
335}
336
337bool DisplayDevice::getSecureLayerVisible() const {
338    return mSecureLayerVisible;
339}
340
341// ----------------------------------------------------------------------------
342
343status_t DisplayDevice::orientationToTransfrom(
344        int orientation, int w, int h, Transform* tr)
345{
346    uint32_t flags = 0;
347    switch (orientation) {
348    case ISurfaceComposer::eOrientationDefault:
349        flags = Transform::ROT_0;
350        break;
351    case ISurfaceComposer::eOrientation90:
352        flags = Transform::ROT_90;
353        break;
354    case ISurfaceComposer::eOrientation180:
355        flags = Transform::ROT_180;
356        break;
357    case ISurfaceComposer::eOrientation270:
358        flags = Transform::ROT_270;
359        break;
360    default:
361        return BAD_VALUE;
362    }
363    tr->set(flags, w, h);
364    return NO_ERROR;
365}
366
367status_t DisplayDevice::setOrientation(int orientation) {
368    int w = mDisplayWidth;
369    int h = mDisplayHeight;
370
371    DisplayDevice::orientationToTransfrom(
372            orientation, w, h, &mGlobalTransform);
373    if (orientation & ISurfaceComposer::eOrientationSwapMask) {
374        int tmp = w;
375        w = h;
376        h = tmp;
377    }
378    mOrientation = orientation;
379    return NO_ERROR;
380}
381