DisplayDevice.cpp revision e3c697fb929c856b59fa56a8e05a2a7eba187c3d
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(0),
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        if (layers[i]->isSecure()) {
291            mSecureLayerVisible = true;
292        }
293    }
294}
295
296const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const {
297    return mVisibleLayersSortedByZ;
298}
299
300bool DisplayDevice::getSecureLayerVisible() const {
301    return mSecureLayerVisible;
302}
303
304Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
305    Region dirty;
306    if (repaintEverything) {
307        dirty.set(getBounds());
308    } else {
309        const Transform& planeTransform(mGlobalTransform);
310        dirty = planeTransform.transform(this->dirtyRegion);
311        dirty.andSelf(getBounds());
312    }
313    return dirty;
314}
315
316// ----------------------------------------------------------------------------
317
318bool DisplayDevice::canDraw() const {
319    return mScreenAcquired;
320}
321
322void DisplayDevice::releaseScreen() const {
323    mScreenAcquired = false;
324}
325
326void DisplayDevice::acquireScreen() const {
327    mScreenAcquired = true;
328}
329
330bool DisplayDevice::isScreenAcquired() const {
331    return mScreenAcquired;
332}
333
334// ----------------------------------------------------------------------------
335
336void DisplayDevice::setLayerStack(uint32_t stack) {
337    mLayerStack = stack;
338    dirtyRegion.set(bounds());
339}
340
341// ----------------------------------------------------------------------------
342
343status_t DisplayDevice::orientationToTransfrom(
344        int orientation, int w, int h, Transform* tr)
345{
346    uint32_t flags = 0;
347    switch (orientation) {
348    case DisplayState::eOrientationDefault:
349        flags = Transform::ROT_0;
350        break;
351    case DisplayState::eOrientation90:
352        flags = Transform::ROT_90;
353        break;
354    case DisplayState::eOrientation180:
355        flags = Transform::ROT_180;
356        break;
357    case DisplayState::eOrientation270:
358        flags = Transform::ROT_270;
359        break;
360    default:
361        return BAD_VALUE;
362    }
363    tr->set(flags, w, h);
364    return NO_ERROR;
365}
366
367void DisplayDevice::setProjection(int orientation,
368        const Rect& viewport, const Rect& frame) {
369    mOrientation = orientation;
370    mViewport = viewport;
371    mFrame = frame;
372    updateGeometryTransform();
373}
374
375void DisplayDevice::updateGeometryTransform() {
376    int w = mDisplayWidth;
377    int h = mDisplayHeight;
378    Transform TL, TP, R, S;
379    if (DisplayDevice::orientationToTransfrom(
380            mOrientation, w, h, &R) == NO_ERROR) {
381        dirtyRegion.set(bounds());
382
383        Rect viewport(mViewport);
384        Rect frame(mFrame);
385
386        if (!frame.isValid()) {
387            // the destination frame can be invalid if it has never been set,
388            // in that case we assume the whole display frame.
389            frame = Rect(w, h);
390        }
391
392        if (viewport.isEmpty()) {
393            // viewport can be invalid if it has never been set, in that case
394            // we assume the whole display size.
395            // it's also invalid to have an empty viewport, so we handle that
396            // case in the same way.
397            viewport = Rect(w, h);
398            if (R.getOrientation() & Transform::ROT_90) {
399                // viewport is always specified in the logical orientation
400                // of the display (ie: post-rotation).
401                swap(viewport.right, viewport.bottom);
402            }
403        }
404
405        float src_width  = viewport.width();
406        float src_height = viewport.height();
407        float dst_width  = frame.width();
408        float dst_height = frame.height();
409        if (src_width != dst_width || src_height != dst_height) {
410            float sx = dst_width  / src_width;
411            float sy = dst_height / src_height;
412            S.set(sx, 0, 0, sy);
413        }
414
415        float src_x = viewport.left;
416        float src_y = viewport.top;
417        float dst_x = frame.left;
418        float dst_y = frame.top;
419        TL.set(-src_x, -src_y);
420        TP.set(dst_x, dst_y);
421
422        // The viewport and frame are both in the logical orientation.
423        // Apply the logical translation, scale to physical size, apply the
424        // physical translation and finally rotate to the physical orientation.
425        mGlobalTransform = R * TP * S * TL;
426
427        const uint8_t type = mGlobalTransform.getType();
428        mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
429                (type >= Transform::SCALE));
430
431        mScissor = mGlobalTransform.transform(mViewport);
432        if (mScissor.isEmpty()) {
433            mScissor.set(getBounds());
434        }
435    }
436}
437
438void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
439    const Transform& tr(mGlobalTransform);
440    snprintf(buffer, SIZE,
441        "+ DisplayDevice: %s\n"
442        "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
443        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
444        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
445        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
446        mDisplayName.string(), mType,
447        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
448        mOrientation, tr.getType(), getPageFlipCount(),
449        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
450        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
451        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
452        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
453        tr[0][0], tr[1][0], tr[2][0],
454        tr[0][1], tr[1][1], tr[2][1],
455        tr[0][2], tr[1][2], tr[2][2]);
456
457    result.append(buffer);
458
459    String8 fbtargetDump;
460    if (mFramebufferSurface != NULL) {
461        mFramebufferSurface->dump(fbtargetDump);
462        result.append(fbtargetDump);
463    }
464}
465