DisplayDevice.cpp revision 47e45405d1533aa73307014f7bf371e118695cf3
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 <hardware/gralloc.h>
33
34#include "DisplayHardware/DisplaySurface.h"
35#include "DisplayHardware/HWComposer.h"
36#include "RenderEngine/RenderEngine.h"
37
38#include "clz.h"
39#include "DisplayDevice.h"
40#include "SurfaceFlinger.h"
41#include "Layer.h"
42
43// ----------------------------------------------------------------------------
44using namespace android;
45// ----------------------------------------------------------------------------
46
47/*
48 * Initialize the display to the specified values.
49 *
50 */
51
52DisplayDevice::DisplayDevice(
53        const sp<SurfaceFlinger>& flinger,
54        DisplayType type,
55        int32_t hwcId,
56        int format,
57        bool isSecure,
58        const wp<IBinder>& displayToken,
59        const sp<DisplaySurface>& displaySurface,
60        const sp<IGraphicBufferProducer>& producer,
61        EGLConfig config)
62    : mFlinger(flinger),
63      mType(type), mHwcDisplayId(hwcId),
64      mDisplayToken(displayToken),
65      mDisplaySurface(displaySurface),
66      mDisplay(EGL_NO_DISPLAY),
67      mSurface(EGL_NO_SURFACE),
68      mDisplayWidth(), mDisplayHeight(), mFormat(),
69      mFlags(),
70      mPageFlipCount(),
71      mIsSecure(isSecure),
72      mSecureLayerVisible(false),
73      mLayerStack(NO_LAYER_STACK),
74      mOrientation(),
75      mPowerMode(HWC_POWER_MODE_OFF),
76      mActiveConfig(0)
77{
78    mNativeWindow = new Surface(producer, false);
79    ANativeWindow* const window = mNativeWindow.get();
80
81    /*
82     * Create our display's surface
83     */
84
85    EGLSurface surface;
86    EGLint w, h;
87    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
88    if (config == EGL_NO_CONFIG) {
89        config = RenderEngine::chooseEglConfig(display, format);
90    }
91    surface = eglCreateWindowSurface(display, config, window, NULL);
92    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
93    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
94
95    // Make sure that composition can never be stalled by a virtual display
96    // consumer that isn't processing buffers fast enough. We have to do this
97    // in two places:
98    // * Here, in case the display is composed entirely by HWC.
99    // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
100    //   window's swap interval in eglMakeCurrent, so they'll override the
101    //   interval we set here.
102    if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
103        window->setSwapInterval(window, 0);
104
105    mConfig = config;
106    mDisplay = display;
107    mSurface = surface;
108    mFormat  = format;
109    mPageFlipCount = 0;
110    mViewport.makeInvalid();
111    mFrame.makeInvalid();
112
113    // virtual displays are always considered enabled
114    mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
115                  HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
116
117    // Name the display.  The name will be replaced shortly if the display
118    // was created with createDisplay().
119    switch (mType) {
120        case DISPLAY_PRIMARY:
121            mDisplayName = "Built-in Screen";
122            break;
123        case DISPLAY_EXTERNAL:
124            mDisplayName = "HDMI Screen";
125            break;
126        default:
127            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
128            break;
129    }
130
131    // initialize the display orientation transform.
132    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
133}
134
135DisplayDevice::~DisplayDevice() {
136    if (mSurface != EGL_NO_SURFACE) {
137        eglDestroySurface(mDisplay, mSurface);
138        mSurface = EGL_NO_SURFACE;
139    }
140}
141
142void DisplayDevice::disconnect(HWComposer& hwc) {
143    if (mHwcDisplayId >= 0) {
144        hwc.disconnectDisplay(mHwcDisplayId);
145        if (mHwcDisplayId >= DISPLAY_VIRTUAL)
146            hwc.freeDisplayId(mHwcDisplayId);
147        mHwcDisplayId = -1;
148    }
149}
150
151bool DisplayDevice::isValid() const {
152    return mFlinger != NULL;
153}
154
155int DisplayDevice::getWidth() const {
156    return mDisplayWidth;
157}
158
159int DisplayDevice::getHeight() const {
160    return mDisplayHeight;
161}
162
163PixelFormat DisplayDevice::getFormat() const {
164    return mFormat;
165}
166
167EGLSurface DisplayDevice::getEGLSurface() const {
168    return mSurface;
169}
170
171void DisplayDevice::setDisplayName(const String8& displayName) {
172    if (!displayName.isEmpty()) {
173        // never override the name with an empty name
174        mDisplayName = displayName;
175    }
176}
177
178uint32_t DisplayDevice::getPageFlipCount() const {
179    return mPageFlipCount;
180}
181
182status_t DisplayDevice::compositionComplete() const {
183    return mDisplaySurface->compositionComplete();
184}
185
186void DisplayDevice::flip(const Region& dirty) const
187{
188    mFlinger->getRenderEngine().checkErrors();
189
190    EGLDisplay dpy = mDisplay;
191    EGLSurface surface = mSurface;
192
193#ifdef EGL_ANDROID_swap_rectangle
194    if (mFlags & SWAP_RECTANGLE) {
195        const Region newDirty(dirty.intersect(bounds()));
196        const Rect b(newDirty.getBounds());
197        eglSetSwapRectangleANDROID(dpy, surface,
198                b.left, b.top, b.width(), b.height());
199    }
200#else
201    (void) dirty; // Eliminate unused parameter warning
202#endif
203
204    mPageFlipCount++;
205}
206
207status_t DisplayDevice::beginFrame(bool mustRecompose) const {
208    return mDisplaySurface->beginFrame(mustRecompose);
209}
210
211status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
212    DisplaySurface::CompositionType compositionType;
213    bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
214    bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
215    if (haveGles && haveHwc) {
216        compositionType = DisplaySurface::COMPOSITION_MIXED;
217    } else if (haveGles) {
218        compositionType = DisplaySurface::COMPOSITION_GLES;
219    } else if (haveHwc) {
220        compositionType = DisplaySurface::COMPOSITION_HWC;
221    } else {
222        // Nothing to do -- when turning the screen off we get a frame like
223        // this. Call it a HWC frame since we won't be doing any GLES work but
224        // will do a prepare/set cycle.
225        compositionType = DisplaySurface::COMPOSITION_HWC;
226    }
227    return mDisplaySurface->prepareFrame(compositionType);
228}
229
230void DisplayDevice::swapBuffers(HWComposer& hwc) const {
231    // We need to call eglSwapBuffers() if:
232    //  (1) we don't have a hardware composer, or
233    //  (2) we did GLES composition this frame, and either
234    //    (a) we have framebuffer target support (not present on legacy
235    //        devices, where HWComposer::commit() handles things); or
236    //    (b) this is a virtual display
237    if (hwc.initCheck() != NO_ERROR ||
238            (hwc.hasGlesComposition(mHwcDisplayId) &&
239             (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
240        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
241        if (!success) {
242            EGLint error = eglGetError();
243            if (error == EGL_CONTEXT_LOST ||
244                    mType == DisplayDevice::DISPLAY_PRIMARY) {
245                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
246                        mDisplay, mSurface, error);
247            } else {
248                ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
249                        mDisplay, mSurface, error);
250            }
251        }
252    }
253
254    status_t result = mDisplaySurface->advanceFrame();
255    if (result != NO_ERROR) {
256        ALOGE("[%s] failed pushing new frame to HWC: %d",
257                mDisplayName.string(), result);
258    }
259}
260
261void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
262    if (hwc.initCheck() == NO_ERROR) {
263        mDisplaySurface->onFrameCommitted();
264    }
265}
266
267uint32_t DisplayDevice::getFlags() const
268{
269    return mFlags;
270}
271
272EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
273    EGLBoolean result = EGL_TRUE;
274    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
275    if (sur != mSurface) {
276        result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
277        if (result == EGL_TRUE) {
278            if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
279                eglSwapInterval(dpy, 0);
280        }
281    }
282    setViewportAndProjection();
283    return result;
284}
285
286void DisplayDevice::setViewportAndProjection() const {
287    size_t w = mDisplayWidth;
288    size_t h = mDisplayHeight;
289    Rect sourceCrop(0, 0, w, h);
290    mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, false);
291}
292
293// ----------------------------------------------------------------------------
294
295void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
296    mVisibleLayersSortedByZ = layers;
297    mSecureLayerVisible = false;
298    size_t count = layers.size();
299    for (size_t i=0 ; i<count ; i++) {
300        const sp<Layer>& layer(layers[i]);
301        if (layer->isSecure()) {
302            mSecureLayerVisible = true;
303        }
304    }
305}
306
307const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
308    return mVisibleLayersSortedByZ;
309}
310
311bool DisplayDevice::getSecureLayerVisible() const {
312    return mSecureLayerVisible;
313}
314
315Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
316    Region dirty;
317    if (repaintEverything) {
318        dirty.set(getBounds());
319    } else {
320        const Transform& planeTransform(mGlobalTransform);
321        dirty = planeTransform.transform(this->dirtyRegion);
322        dirty.andSelf(getBounds());
323    }
324    return dirty;
325}
326
327// ----------------------------------------------------------------------------
328void DisplayDevice::setPowerMode(int mode) {
329    mPowerMode = mode;
330}
331
332int DisplayDevice::getPowerMode()  const {
333    return mPowerMode;
334}
335
336bool DisplayDevice::isDisplayOn() const {
337    return (mPowerMode != HWC_POWER_MODE_OFF);
338}
339
340// ----------------------------------------------------------------------------
341void DisplayDevice::setActiveConfig(int mode) {
342    mActiveConfig = mode;
343}
344
345int DisplayDevice::getActiveConfig()  const {
346    return mActiveConfig;
347}
348
349// ----------------------------------------------------------------------------
350
351void DisplayDevice::setLayerStack(uint32_t stack) {
352    mLayerStack = stack;
353    dirtyRegion.set(bounds());
354}
355
356// ----------------------------------------------------------------------------
357
358uint32_t DisplayDevice::getOrientationTransform() const {
359    uint32_t transform = 0;
360    switch (mOrientation) {
361        case DisplayState::eOrientationDefault:
362            transform = Transform::ROT_0;
363            break;
364        case DisplayState::eOrientation90:
365            transform = Transform::ROT_90;
366            break;
367        case DisplayState::eOrientation180:
368            transform = Transform::ROT_180;
369            break;
370        case DisplayState::eOrientation270:
371            transform = Transform::ROT_270;
372            break;
373    }
374    return transform;
375}
376
377status_t DisplayDevice::orientationToTransfrom(
378        int orientation, int w, int h, Transform* tr)
379{
380    uint32_t flags = 0;
381    switch (orientation) {
382    case DisplayState::eOrientationDefault:
383        flags = Transform::ROT_0;
384        break;
385    case DisplayState::eOrientation90:
386        flags = Transform::ROT_90;
387        break;
388    case DisplayState::eOrientation180:
389        flags = Transform::ROT_180;
390        break;
391    case DisplayState::eOrientation270:
392        flags = Transform::ROT_270;
393        break;
394    default:
395        return BAD_VALUE;
396    }
397    tr->set(flags, w, h);
398    return NO_ERROR;
399}
400
401void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
402    dirtyRegion.set(getBounds());
403
404    mDisplaySurface->resizeBuffers(newWidth, newHeight);
405
406    ANativeWindow* const window = mNativeWindow.get();
407    mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL);
408    eglQuerySurface(mDisplay, mSurface, EGL_WIDTH,  &mDisplayWidth);
409    eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight);
410
411    LOG_FATAL_IF(mDisplayWidth != newWidth,
412                "Unable to set new width to %d", newWidth);
413    LOG_FATAL_IF(mDisplayHeight != newHeight,
414                "Unable to set new height to %d", newHeight);
415}
416
417void DisplayDevice::setProjection(int orientation,
418        const Rect& newViewport, const Rect& newFrame) {
419    Rect viewport(newViewport);
420    Rect frame(newFrame);
421
422    const int w = mDisplayWidth;
423    const int h = mDisplayHeight;
424
425    Transform R;
426    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
427
428    if (!frame.isValid()) {
429        // the destination frame can be invalid if it has never been set,
430        // in that case we assume the whole display frame.
431        frame = Rect(w, h);
432    }
433
434    if (viewport.isEmpty()) {
435        // viewport can be invalid if it has never been set, in that case
436        // we assume the whole display size.
437        // it's also invalid to have an empty viewport, so we handle that
438        // case in the same way.
439        viewport = Rect(w, h);
440        if (R.getOrientation() & Transform::ROT_90) {
441            // viewport is always specified in the logical orientation
442            // of the display (ie: post-rotation).
443            swap(viewport.right, viewport.bottom);
444        }
445    }
446
447    dirtyRegion.set(getBounds());
448
449    Transform TL, TP, S;
450    float src_width  = viewport.width();
451    float src_height = viewport.height();
452    float dst_width  = frame.width();
453    float dst_height = frame.height();
454    if (src_width != dst_width || src_height != dst_height) {
455        float sx = dst_width  / src_width;
456        float sy = dst_height / src_height;
457        S.set(sx, 0, 0, sy);
458    }
459
460    float src_x = viewport.left;
461    float src_y = viewport.top;
462    float dst_x = frame.left;
463    float dst_y = frame.top;
464    TL.set(-src_x, -src_y);
465    TP.set(dst_x, dst_y);
466
467    // The viewport and frame are both in the logical orientation.
468    // Apply the logical translation, scale to physical size, apply the
469    // physical translation and finally rotate to the physical orientation.
470    mGlobalTransform = R * TP * S * TL;
471
472    const uint8_t type = mGlobalTransform.getType();
473    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
474            (type >= Transform::SCALE));
475
476    mScissor = mGlobalTransform.transform(viewport);
477    if (mScissor.isEmpty()) {
478        mScissor = getBounds();
479    }
480
481    mOrientation = orientation;
482    mViewport = viewport;
483    mFrame = frame;
484}
485
486void DisplayDevice::dump(String8& result) const {
487    const Transform& tr(mGlobalTransform);
488    result.appendFormat(
489        "+ DisplayDevice: %s\n"
490        "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
491        "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
492        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
493        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
494        mDisplayName.string(), mType, mHwcDisplayId,
495        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
496        mOrientation, tr.getType(), getPageFlipCount(),
497        mIsSecure, mSecureLayerVisible, mPowerMode, mActiveConfig,
498        mVisibleLayersSortedByZ.size(),
499        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
500        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
501        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
502        tr[0][0], tr[1][0], tr[2][0],
503        tr[0][1], tr[1][1], tr[2][1],
504        tr[0][2], tr[1][2], tr[2][2]);
505
506    String8 surfaceDump;
507    mDisplaySurface->dump(surfaceDump);
508    result.append(surfaceDump);
509}
510