DisplayDevice.cpp revision eabe3140f11e515639e7a70a1286dd6af7352c9e
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 <gui/Surface.h>
31
32#include <GLES/gl.h>
33#include <EGL/egl.h>
34#include <EGL/eglext.h>
35
36#include <hardware/gralloc.h>
37
38#include "DisplayHardware/FramebufferSurface.h"
39#include "DisplayHardware/HWComposer.h"
40
41#include "clz.h"
42#include "DisplayDevice.h"
43#include "GLExtensions.h"
44#include "SurfaceFlinger.h"
45#include "LayerBase.h"
46
47// ----------------------------------------------------------------------------
48using namespace android;
49// ----------------------------------------------------------------------------
50
51static __attribute__((noinline))
52void checkGLErrors()
53{
54    do {
55        // there could be more than one error flag
56        GLenum error = glGetError();
57        if (error == GL_NO_ERROR)
58            break;
59        ALOGE("GL error 0x%04x", int(error));
60    } while(true);
61}
62
63// ----------------------------------------------------------------------------
64
65/*
66 * Initialize the display to the specified values.
67 *
68 */
69
70DisplayDevice::DisplayDevice(
71        const sp<SurfaceFlinger>& flinger,
72        DisplayType type,
73        bool isSecure,
74        const wp<IBinder>& displayToken,
75        const sp<ANativeWindow>& nativeWindow,
76        const sp<FramebufferSurface>& framebufferSurface,
77        EGLConfig config)
78    : mFlinger(flinger),
79      mType(type), mHwcDisplayId(-1),
80      mDisplayToken(displayToken),
81      mNativeWindow(nativeWindow),
82      mFramebufferSurface(framebufferSurface),
83      mDisplay(EGL_NO_DISPLAY),
84      mSurface(EGL_NO_SURFACE),
85      mContext(EGL_NO_CONTEXT),
86      mDisplayWidth(), mDisplayHeight(), mFormat(),
87      mFlags(),
88      mPageFlipCount(),
89      mIsSecure(isSecure),
90      mSecureLayerVisible(false),
91      mScreenAcquired(false),
92      mLayerStack(NO_LAYER_STACK),
93      mOrientation()
94{
95    init(config);
96}
97
98DisplayDevice::~DisplayDevice() {
99    if (mSurface != EGL_NO_SURFACE) {
100        eglDestroySurface(mDisplay, mSurface);
101        mSurface = EGL_NO_SURFACE;
102    }
103}
104
105bool DisplayDevice::isValid() const {
106    return mFlinger != NULL;
107}
108
109int DisplayDevice::getWidth() const {
110    return mDisplayWidth;
111}
112
113int DisplayDevice::getHeight() const {
114    return mDisplayHeight;
115}
116
117PixelFormat DisplayDevice::getFormat() const {
118    return mFormat;
119}
120
121EGLSurface DisplayDevice::getEGLSurface() const {
122    return mSurface;
123}
124
125void DisplayDevice::init(EGLConfig config)
126{
127    ANativeWindow* const window = mNativeWindow.get();
128
129    int format;
130    window->query(window, NATIVE_WINDOW_FORMAT, &format);
131
132    /*
133     * Create our display's surface
134     */
135
136    EGLSurface surface;
137    EGLint w, h;
138    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
139    surface = eglCreateWindowSurface(display, config, window, NULL);
140    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
141    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
142
143    mDisplay = display;
144    mSurface = surface;
145    mFormat  = format;
146    mPageFlipCount = 0;
147    mViewport.makeInvalid();
148    mFrame.makeInvalid();
149
150    // external displays are always considered enabled
151    mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
152
153    // get an h/w composer ID
154    mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
155
156    // Name the display.  The name will be replaced shortly if the display
157    // was created with createDisplay().
158    switch (mType) {
159        case DISPLAY_PRIMARY:
160            mDisplayName = "Built-in Screen";
161            break;
162        case DISPLAY_EXTERNAL:
163            mDisplayName = "HDMI Screen";
164            break;
165        default:
166            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
167            break;
168    }
169
170    // initialize the display orientation transform.
171    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
172}
173
174void DisplayDevice::setDisplayName(const String8& displayName) {
175    if (!displayName.isEmpty()) {
176        // never override the name with an empty name
177        mDisplayName = displayName;
178    }
179}
180
181uint32_t DisplayDevice::getPageFlipCount() const {
182    return mPageFlipCount;
183}
184
185status_t DisplayDevice::compositionComplete() const {
186    if (mFramebufferSurface == NULL) {
187        return NO_ERROR;
188    }
189    return mFramebufferSurface->compositionComplete();
190}
191
192void DisplayDevice::flip(const Region& dirty) const
193{
194    checkGLErrors();
195
196    EGLDisplay dpy = mDisplay;
197    EGLSurface surface = mSurface;
198
199#ifdef EGL_ANDROID_swap_rectangle
200    if (mFlags & SWAP_RECTANGLE) {
201        const Region newDirty(dirty.intersect(bounds()));
202        const Rect b(newDirty.getBounds());
203        eglSetSwapRectangleANDROID(dpy, surface,
204                b.left, b.top, b.width(), b.height());
205    }
206#endif
207
208    mPageFlipCount++;
209}
210
211void DisplayDevice::swapBuffers(HWComposer& hwc) const {
212    EGLBoolean success = EGL_TRUE;
213    if (hwc.initCheck() != NO_ERROR) {
214        // no HWC, we call eglSwapBuffers()
215        success = eglSwapBuffers(mDisplay, mSurface);
216    } else {
217        // We have a valid HWC, but not all displays can use it, in particular
218        // the virtual displays are on their own.
219        // TODO: HWC 1.2 will allow virtual displays
220        if (mType >= DisplayDevice::DISPLAY_VIRTUAL) {
221            // always call eglSwapBuffers() for virtual displays
222            success = eglSwapBuffers(mDisplay, mSurface);
223        } else if (hwc.supportsFramebufferTarget()) {
224            // as of hwc 1.1 we always call eglSwapBuffers if we have some
225            // GLES layers
226            if (hwc.hasGlesComposition(mType)) {
227                success = eglSwapBuffers(mDisplay, mSurface);
228            }
229        } else {
230            // HWC doesn't have the framebuffer target, we don't call
231            // eglSwapBuffers(), since this is handled by HWComposer::commit().
232        }
233    }
234
235    if (!success) {
236        EGLint error = eglGetError();
237        if (error == EGL_CONTEXT_LOST ||
238                mType == DisplayDevice::DISPLAY_PRIMARY) {
239            LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
240                    mDisplay, mSurface, error);
241        }
242    }
243}
244
245void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
246    if (hwc.initCheck() == NO_ERROR) {
247        if (hwc.supportsFramebufferTarget()) {
248            int fd = hwc.getAndResetReleaseFenceFd(mType);
249            mFramebufferSurface->setReleaseFenceFd(fd);
250        }
251    }
252}
253
254uint32_t DisplayDevice::getFlags() const
255{
256    return mFlags;
257}
258
259EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
260        const sp<const DisplayDevice>& hw, EGLContext ctx) {
261    EGLBoolean result = EGL_TRUE;
262    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
263    if (sur != hw->mSurface) {
264        result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
265        if (result == EGL_TRUE) {
266            setViewportAndProjection(hw);
267        }
268    }
269    return result;
270}
271
272void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw) {
273    GLsizei w = hw->mDisplayWidth;
274    GLsizei h = hw->mDisplayHeight;
275    glViewport(0, 0, w, h);
276    glMatrixMode(GL_PROJECTION);
277    glLoadIdentity();
278    // put the origin in the left-bottom corner
279    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
280    glMatrixMode(GL_MODELVIEW);
281}
282
283// ----------------------------------------------------------------------------
284
285void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
286    mVisibleLayersSortedByZ = layers;
287    mSecureLayerVisible = false;
288    size_t count = layers.size();
289    for (size_t i=0 ; i<count ; i++) {
290        const sp<LayerBase>& layer(layers[i]);
291        if (layer->isSecure()) {
292            mSecureLayerVisible = true;
293        }
294    }
295}
296
297const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const {
298    return mVisibleLayersSortedByZ;
299}
300
301bool DisplayDevice::getSecureLayerVisible() const {
302    return mSecureLayerVisible;
303}
304
305Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
306    Region dirty;
307    if (repaintEverything) {
308        dirty.set(getBounds());
309    } else {
310        const Transform& planeTransform(mGlobalTransform);
311        dirty = planeTransform.transform(this->dirtyRegion);
312        dirty.andSelf(getBounds());
313    }
314    return dirty;
315}
316
317// ----------------------------------------------------------------------------
318
319bool DisplayDevice::canDraw() const {
320    return mScreenAcquired;
321}
322
323void DisplayDevice::releaseScreen() const {
324    mScreenAcquired = false;
325}
326
327void DisplayDevice::acquireScreen() const {
328    mScreenAcquired = true;
329}
330
331bool DisplayDevice::isScreenAcquired() const {
332    return mScreenAcquired;
333}
334
335// ----------------------------------------------------------------------------
336
337void DisplayDevice::setLayerStack(uint32_t stack) {
338    mLayerStack = stack;
339    dirtyRegion.set(bounds());
340}
341
342// ----------------------------------------------------------------------------
343
344status_t DisplayDevice::orientationToTransfrom(
345        int orientation, int w, int h, Transform* tr)
346{
347    uint32_t flags = 0;
348    switch (orientation) {
349    case DisplayState::eOrientationDefault:
350        flags = Transform::ROT_0;
351        break;
352    case DisplayState::eOrientation90:
353        flags = Transform::ROT_90;
354        break;
355    case DisplayState::eOrientation180:
356        flags = Transform::ROT_180;
357        break;
358    case DisplayState::eOrientation270:
359        flags = Transform::ROT_270;
360        break;
361    default:
362        return BAD_VALUE;
363    }
364    tr->set(flags, w, h);
365    return NO_ERROR;
366}
367
368void DisplayDevice::setProjection(int orientation,
369        const Rect& newViewport, const Rect& newFrame) {
370    Rect viewport(newViewport);
371    Rect frame(newFrame);
372
373    const int w = mDisplayWidth;
374    const int h = mDisplayHeight;
375
376    Transform R;
377    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
378
379    if (!frame.isValid()) {
380        // the destination frame can be invalid if it has never been set,
381        // in that case we assume the whole display frame.
382        frame = Rect(w, h);
383    }
384
385    if (viewport.isEmpty()) {
386        // viewport can be invalid if it has never been set, in that case
387        // we assume the whole display size.
388        // it's also invalid to have an empty viewport, so we handle that
389        // case in the same way.
390        viewport = Rect(w, h);
391        if (R.getOrientation() & Transform::ROT_90) {
392            // viewport is always specified in the logical orientation
393            // of the display (ie: post-rotation).
394            swap(viewport.right, viewport.bottom);
395        }
396    }
397
398    dirtyRegion.set(getBounds());
399
400    Transform TL, TP, S;
401    float src_width  = viewport.width();
402    float src_height = viewport.height();
403    float dst_width  = frame.width();
404    float dst_height = frame.height();
405    if (src_width != dst_width || src_height != dst_height) {
406        float sx = dst_width  / src_width;
407        float sy = dst_height / src_height;
408        S.set(sx, 0, 0, sy);
409    }
410
411    float src_x = viewport.left;
412    float src_y = viewport.top;
413    float dst_x = frame.left;
414    float dst_y = frame.top;
415    TL.set(-src_x, -src_y);
416    TP.set(dst_x, dst_y);
417
418    // The viewport and frame are both in the logical orientation.
419    // Apply the logical translation, scale to physical size, apply the
420    // physical translation and finally rotate to the physical orientation.
421    mGlobalTransform = R * TP * S * TL;
422
423    const uint8_t type = mGlobalTransform.getType();
424    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
425            (type >= Transform::SCALE));
426
427    mScissor = mGlobalTransform.transform(viewport);
428    if (mScissor.isEmpty()) {
429        mScissor.set(getBounds());
430    }
431
432    mOrientation = orientation;
433    mViewport = viewport;
434    mFrame = frame;
435}
436
437void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
438    const Transform& tr(mGlobalTransform);
439    snprintf(buffer, SIZE,
440        "+ DisplayDevice: %s\n"
441        "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
442        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
443        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
444        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
445        mDisplayName.string(), mType,
446        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
447        mOrientation, tr.getType(), getPageFlipCount(),
448        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
449        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
450        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
451        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
452        tr[0][0], tr[1][0], tr[2][0],
453        tr[0][1], tr[1][1], tr[2][1],
454        tr[0][2], tr[1][2], tr[2][2]);
455
456    result.append(buffer);
457
458    String8 fbtargetDump;
459    if (mFramebufferSurface != NULL) {
460        mFramebufferSurface->dump(fbtargetDump);
461        result.append(fbtargetDump);
462    }
463}
464