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