DisplayDevice.cpp revision 13f01cbdbd34779a234bc674df79e23672fd5c0b
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        bool isSecure,
74        const wp<IBinder>& displayToken,
75        const sp<DisplaySurface>& displaySurface,
76        EGLConfig config)
77    : mFlinger(flinger),
78      mType(type), mHwcDisplayId(-1),
79      mDisplayToken(displayToken),
80      mDisplaySurface(displaySurface),
81      mDisplay(EGL_NO_DISPLAY),
82      mSurface(EGL_NO_SURFACE),
83      mContext(EGL_NO_CONTEXT),
84      mDisplayWidth(), mDisplayHeight(), mFormat(),
85      mFlags(),
86      mPageFlipCount(),
87      mIsSecure(isSecure),
88      mSecureLayerVisible(false),
89      mScreenAcquired(false),
90      mLayerStack(NO_LAYER_STACK),
91      mOrientation()
92{
93    mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
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    return mDisplaySurface->compositionComplete();
186}
187
188void DisplayDevice::flip(const Region& dirty) const
189{
190    checkGLErrors();
191
192    EGLDisplay dpy = mDisplay;
193    EGLSurface surface = mSurface;
194
195#ifdef EGL_ANDROID_swap_rectangle
196    if (mFlags & SWAP_RECTANGLE) {
197        const Region newDirty(dirty.intersect(bounds()));
198        const Rect b(newDirty.getBounds());
199        eglSetSwapRectangleANDROID(dpy, surface,
200                b.left, b.top, b.width(), b.height());
201    }
202#endif
203
204    mPageFlipCount++;
205}
206
207void DisplayDevice::swapBuffers(HWComposer& hwc) const {
208    // We need to call eglSwapBuffers() unless:
209    // (a) there was no GLES composition this frame, or
210    // (b) we're using a legacy HWC with no framebuffer target support (in
211    //     which case HWComposer::commit() handles things).
212    if (hwc.initCheck() != NO_ERROR ||
213            (hwc.hasGlesComposition(mHwcDisplayId) &&
214             hwc.supportsFramebufferTarget())) {
215        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
216        if (!success) {
217            EGLint error = eglGetError();
218            if (error == EGL_CONTEXT_LOST ||
219                    mType == DisplayDevice::DISPLAY_PRIMARY) {
220                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
221                        mDisplay, mSurface, error);
222            } else {
223                ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
224                        mDisplay, mSurface, error);
225            }
226        }
227    }
228
229    status_t result = mDisplaySurface->advanceFrame();
230    if (result != NO_ERROR) {
231        ALOGE("[%s] failed pushing new frame to HWC: %d",
232                mDisplayName.string(), result);
233    }
234}
235
236void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
237    if (hwc.initCheck() == NO_ERROR) {
238        sp<Fence> fence = hwc.getAndResetReleaseFence(mType);
239        mDisplaySurface->onFrameCommitted(fence);
240    }
241}
242
243uint32_t DisplayDevice::getFlags() const
244{
245    return mFlags;
246}
247
248EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
249        const sp<const DisplayDevice>& hw, EGLContext ctx) {
250    EGLBoolean result = EGL_TRUE;
251    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
252    if (sur != hw->mSurface) {
253        result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
254        if (result == EGL_TRUE) {
255            setViewportAndProjection(hw);
256        }
257    }
258    return result;
259}
260
261void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw) {
262    GLsizei w = hw->mDisplayWidth;
263    GLsizei h = hw->mDisplayHeight;
264    glViewport(0, 0, w, h);
265    glMatrixMode(GL_PROJECTION);
266    glLoadIdentity();
267    // put the origin in the left-bottom corner
268    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
269    glMatrixMode(GL_MODELVIEW);
270}
271
272// ----------------------------------------------------------------------------
273
274void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
275    mVisibleLayersSortedByZ = layers;
276    mSecureLayerVisible = false;
277    size_t count = layers.size();
278    for (size_t i=0 ; i<count ; i++) {
279        const sp<Layer>& layer(layers[i]);
280        if (layer->isSecure()) {
281            mSecureLayerVisible = true;
282        }
283    }
284}
285
286const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
287    return mVisibleLayersSortedByZ;
288}
289
290bool DisplayDevice::getSecureLayerVisible() const {
291    return mSecureLayerVisible;
292}
293
294Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
295    Region dirty;
296    if (repaintEverything) {
297        dirty.set(getBounds());
298    } else {
299        const Transform& planeTransform(mGlobalTransform);
300        dirty = planeTransform.transform(this->dirtyRegion);
301        dirty.andSelf(getBounds());
302    }
303    return dirty;
304}
305
306// ----------------------------------------------------------------------------
307
308bool DisplayDevice::canDraw() const {
309    return mScreenAcquired;
310}
311
312void DisplayDevice::releaseScreen() const {
313    mScreenAcquired = false;
314}
315
316void DisplayDevice::acquireScreen() const {
317    mScreenAcquired = true;
318}
319
320bool DisplayDevice::isScreenAcquired() const {
321    return mScreenAcquired;
322}
323
324// ----------------------------------------------------------------------------
325
326void DisplayDevice::setLayerStack(uint32_t stack) {
327    mLayerStack = stack;
328    dirtyRegion.set(bounds());
329}
330
331// ----------------------------------------------------------------------------
332
333status_t DisplayDevice::orientationToTransfrom(
334        int orientation, int w, int h, Transform* tr)
335{
336    uint32_t flags = 0;
337    switch (orientation) {
338    case DisplayState::eOrientationDefault:
339        flags = Transform::ROT_0;
340        break;
341    case DisplayState::eOrientation90:
342        flags = Transform::ROT_90;
343        break;
344    case DisplayState::eOrientation180:
345        flags = Transform::ROT_180;
346        break;
347    case DisplayState::eOrientation270:
348        flags = Transform::ROT_270;
349        break;
350    default:
351        return BAD_VALUE;
352    }
353    tr->set(flags, w, h);
354    return NO_ERROR;
355}
356
357void DisplayDevice::setProjection(int orientation,
358        const Rect& newViewport, const Rect& newFrame) {
359    Rect viewport(newViewport);
360    Rect frame(newFrame);
361
362    const int w = mDisplayWidth;
363    const int h = mDisplayHeight;
364
365    Transform R;
366    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
367
368    if (!frame.isValid()) {
369        // the destination frame can be invalid if it has never been set,
370        // in that case we assume the whole display frame.
371        frame = Rect(w, h);
372    }
373
374    if (viewport.isEmpty()) {
375        // viewport can be invalid if it has never been set, in that case
376        // we assume the whole display size.
377        // it's also invalid to have an empty viewport, so we handle that
378        // case in the same way.
379        viewport = Rect(w, h);
380        if (R.getOrientation() & Transform::ROT_90) {
381            // viewport is always specified in the logical orientation
382            // of the display (ie: post-rotation).
383            swap(viewport.right, viewport.bottom);
384        }
385    }
386
387    dirtyRegion.set(getBounds());
388
389    Transform TL, TP, S;
390    float src_width  = viewport.width();
391    float src_height = viewport.height();
392    float dst_width  = frame.width();
393    float dst_height = frame.height();
394    if (src_width != dst_width || src_height != dst_height) {
395        float sx = dst_width  / src_width;
396        float sy = dst_height / src_height;
397        S.set(sx, 0, 0, sy);
398    }
399
400    float src_x = viewport.left;
401    float src_y = viewport.top;
402    float dst_x = frame.left;
403    float dst_y = frame.top;
404    TL.set(-src_x, -src_y);
405    TP.set(dst_x, dst_y);
406
407    // The viewport and frame are both in the logical orientation.
408    // Apply the logical translation, scale to physical size, apply the
409    // physical translation and finally rotate to the physical orientation.
410    mGlobalTransform = R * TP * S * TL;
411
412    const uint8_t type = mGlobalTransform.getType();
413    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
414            (type >= Transform::SCALE));
415
416    mScissor = mGlobalTransform.transform(viewport);
417    if (mScissor.isEmpty()) {
418        mScissor.set(getBounds());
419    }
420
421    mOrientation = orientation;
422    mViewport = viewport;
423    mFrame = frame;
424}
425
426void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
427    const Transform& tr(mGlobalTransform);
428    snprintf(buffer, SIZE,
429        "+ DisplayDevice: %s\n"
430        "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
431        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
432        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
433        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
434        mDisplayName.string(), mType,
435        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
436        mOrientation, tr.getType(), getPageFlipCount(),
437        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
438        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
439        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
440        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
441        tr[0][0], tr[1][0], tr[2][0],
442        tr[0][1], tr[1][1], tr[2][1],
443        tr[0][2], tr[1][2], tr[2][2]);
444
445    result.append(buffer);
446
447    String8 surfaceDump;
448    mDisplaySurface->dump(surfaceDump);
449    result.append(surfaceDump);
450}
451