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