DisplayDevice.cpp revision 92a979a92c34b7de609ce2b1662c73bb8a2728b9
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    : mId(0),
102      mDisplay(EGL_NO_DISPLAY),
103      mSurface(EGL_NO_SURFACE),
104      mContext(EGL_NO_CONTEXT)
105{
106}
107
108DisplayDevice::DisplayDevice(
109        const sp<SurfaceFlinger>& flinger,
110        int display,
111        const sp<SurfaceTextureClient>& surface,
112        EGLConfig config)
113    : mFlinger(flinger),
114      mId(display),
115      mNativeWindow(surface),
116      mDisplay(EGL_NO_DISPLAY),
117      mSurface(EGL_NO_SURFACE),
118      mContext(EGL_NO_CONTEXT),
119      mDpiX(), mDpiY(),
120      mRefreshRate(),
121      mDensity(),
122      mDisplayWidth(), mDisplayHeight(), mFormat(),
123      mFlags(),
124      mPageFlipCount(),
125      mRefreshPeriod(),
126      mSecureLayerVisible(false),
127      mScreenAcquired(false),
128      mOrientation(),
129      mLayerStack(0)
130{
131    init(config);
132}
133
134DisplayDevice::~DisplayDevice() {
135    // DO NOT call terminate() from here, because we create
136    // temporaries of this class (on the stack typically), and we don't
137    // want to destroy the EGLSurface in that case
138}
139
140void DisplayDevice::terminate() {
141    if (mSurface != EGL_NO_SURFACE) {
142        eglDestroySurface(mDisplay, mSurface);
143        mSurface = EGL_NO_SURFACE;
144    }
145}
146
147bool DisplayDevice::isValid() const {
148    return mFlinger != NULL;
149}
150
151float DisplayDevice::getDpiX() const {
152    return mDpiX;
153}
154
155float DisplayDevice::getDpiY() const {
156    return mDpiY;
157}
158
159float DisplayDevice::getDensity() const {
160    return mDensity;
161}
162
163float DisplayDevice::getRefreshRate() const {
164    return mRefreshRate;
165}
166
167int DisplayDevice::getWidth() const {
168    return mDisplayWidth;
169}
170
171int DisplayDevice::getHeight() const {
172    return mDisplayHeight;
173}
174
175PixelFormat DisplayDevice::getFormat() const {
176    return mFormat;
177}
178
179EGLSurface DisplayDevice::getEGLSurface() const {
180    return mSurface;
181}
182
183status_t DisplayDevice::getInfo(DisplayInfo* info) const {
184    info->w = getWidth();
185    info->h = getHeight();
186    info->xdpi = getDpiX();
187    info->ydpi = getDpiY();
188    info->fps = getRefreshRate();
189    info->density = getDensity();
190    info->orientation = getOrientation();
191    // TODO: this needs to go away (currently needed only by webkit)
192    getPixelFormatInfo(getFormat(), &info->pixelFormatInfo);
193    return NO_ERROR;
194}
195
196void DisplayDevice::init(EGLConfig config)
197{
198    ANativeWindow* const window = mNativeWindow.get();
199
200    int concreteType;
201    window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &concreteType);
202    if (concreteType == NATIVE_WINDOW_FRAMEBUFFER) {
203        mFramebufferSurface = static_cast<FramebufferSurface *>(mNativeWindow.get());
204    }
205
206    int format;
207    window->query(window, NATIVE_WINDOW_FORMAT, &format);
208    mDpiX = window->xdpi;
209    mDpiY = window->ydpi;
210    if (mFramebufferSurface != NULL) {
211        mRefreshRate = mFramebufferSurface->getRefreshRate();
212    } else {
213        mRefreshRate = 60;
214    }
215    mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
216
217
218    // TODO: Not sure if display density should handled by SF any longer
219    class Density {
220        static int getDensityFromProperty(char const* propName) {
221            char property[PROPERTY_VALUE_MAX];
222            int density = 0;
223            if (property_get(propName, property, NULL) > 0) {
224                density = atoi(property);
225            }
226            return density;
227        }
228    public:
229        static int getEmuDensity() {
230            return getDensityFromProperty("qemu.sf.lcd_density"); }
231        static int getBuildDensity()  {
232            return getDensityFromProperty("ro.sf.lcd_density"); }
233    };
234    // The density of the device is provided by a build property
235    mDensity = Density::getBuildDensity() / 160.0f;
236    if (mDensity == 0) {
237        // the build doesn't provide a density -- this is wrong!
238        // use xdpi instead
239        ALOGE("ro.sf.lcd_density must be defined as a build property");
240        mDensity = mDpiX / 160.0f;
241    }
242    if (Density::getEmuDensity()) {
243        // if "qemu.sf.lcd_density" is specified, it overrides everything
244        mDpiX = mDpiY = mDensity = Density::getEmuDensity();
245        mDensity /= 160.0f;
246    }
247
248    /*
249     * Create our display's surface
250     */
251
252    EGLSurface surface;
253    EGLint w, h;
254    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
255    surface = eglCreateWindowSurface(display, config, window, NULL);
256    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
257    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
258
259    if (mFramebufferSurface != NULL) {
260        if (mFramebufferSurface->isUpdateOnDemand()) {
261            mFlags |= PARTIAL_UPDATES;
262            // if we have partial updates, we definitely don't need to
263            // preserve the backbuffer, which may be costly.
264            eglSurfaceAttrib(display, surface,
265                    EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
266        }
267    }
268
269    mDisplay = display;
270    mSurface = surface;
271    mFormat  = format;
272    mPageFlipCount = 0;
273
274    // initialize the display orientation transform.
275    DisplayDevice::setOrientation(ISurfaceComposer::eOrientationDefault);
276}
277
278uint32_t DisplayDevice::getPageFlipCount() const {
279    return mPageFlipCount;
280}
281
282nsecs_t DisplayDevice::getRefreshPeriod() const {
283    return mRefreshPeriod;
284}
285
286status_t DisplayDevice::compositionComplete() const {
287    if (mFramebufferSurface == NULL) {
288        return NO_ERROR;
289    }
290    return mFramebufferSurface->compositionComplete();
291}
292
293void DisplayDevice::flip(const Region& dirty) const
294{
295    checkGLErrors();
296
297    EGLDisplay dpy = mDisplay;
298    EGLSurface surface = mSurface;
299
300#ifdef EGL_ANDROID_swap_rectangle
301    if (mFlags & SWAP_RECTANGLE) {
302        const Region newDirty(dirty.intersect(bounds()));
303        const Rect b(newDirty.getBounds());
304        eglSetSwapRectangleANDROID(dpy, surface,
305                b.left, b.top, b.width(), b.height());
306    }
307#endif
308
309    if (mFlags & PARTIAL_UPDATES) {
310        if (mFramebufferSurface != NULL) {
311            mFramebufferSurface->setUpdateRectangle(dirty.getBounds());
312        }
313    }
314
315    mPageFlipCount++;
316}
317
318uint32_t DisplayDevice::getFlags() const
319{
320    return mFlags;
321}
322
323void DisplayDevice::dump(String8& res) const
324{
325    if (mFramebufferSurface != NULL) {
326        mFramebufferSurface->dump(res);
327    }
328}
329
330void DisplayDevice::makeCurrent(const DisplayDevice& hw, EGLContext ctx) {
331    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
332    if (sur != hw.mSurface) {
333        EGLDisplay dpy = eglGetCurrentDisplay();
334        eglMakeCurrent(dpy, hw.mSurface, hw.mSurface, ctx);
335    }
336}
337
338// ----------------------------------------------------------------------------
339
340void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
341    mVisibleLayersSortedByZ = layers;
342    size_t count = layers.size();
343    for (size_t i=0 ; i<count ; i++) {
344        if (layers[i]->isSecure()) {
345            mSecureLayerVisible = true;
346        }
347    }
348}
349
350Vector< sp<LayerBase> > DisplayDevice::getVisibleLayersSortedByZ() const {
351    return mVisibleLayersSortedByZ;
352}
353
354bool DisplayDevice::getSecureLayerVisible() const {
355    return mSecureLayerVisible;
356}
357
358// ----------------------------------------------------------------------------
359
360bool DisplayDevice::canDraw() const {
361    return mScreenAcquired;
362}
363
364void DisplayDevice::releaseScreen() const {
365    mScreenAcquired = false;
366}
367
368void DisplayDevice::acquireScreen() const {
369    mScreenAcquired = true;
370}
371
372bool DisplayDevice::isScreenAcquired() const {
373    return mScreenAcquired;
374}
375
376// ----------------------------------------------------------------------------
377
378status_t DisplayDevice::orientationToTransfrom(
379        int orientation, int w, int h, Transform* tr)
380{
381    uint32_t flags = 0;
382    switch (orientation) {
383    case ISurfaceComposer::eOrientationDefault:
384        flags = Transform::ROT_0;
385        break;
386    case ISurfaceComposer::eOrientation90:
387        flags = Transform::ROT_90;
388        break;
389    case ISurfaceComposer::eOrientation180:
390        flags = Transform::ROT_180;
391        break;
392    case ISurfaceComposer::eOrientation270:
393        flags = Transform::ROT_270;
394        break;
395    default:
396        return BAD_VALUE;
397    }
398    tr->set(flags, w, h);
399    return NO_ERROR;
400}
401
402status_t DisplayDevice::setOrientation(int orientation) {
403    int w = mDisplayWidth;
404    int h = mDisplayHeight;
405
406    DisplayDevice::orientationToTransfrom(
407            orientation, w, h, &mGlobalTransform);
408    if (orientation & ISurfaceComposer::eOrientationSwapMask) {
409        int tmp = w;
410        w = h;
411        h = tmp;
412    }
413    mOrientation = orientation;
414    dirtyRegion.set(bounds());
415    return NO_ERROR;
416}
417