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