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