DisplayDevice.cpp revision 851cfe834295224cd64bdd499872b95b19c4de8c
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        mDisplaySurface->onFrameCommitted();
239    }
240}
241
242uint32_t DisplayDevice::getFlags() const
243{
244    return mFlags;
245}
246
247EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
248        const sp<const DisplayDevice>& hw, EGLContext ctx) {
249    EGLBoolean result = EGL_TRUE;
250    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
251    if (sur != hw->mSurface) {
252        result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
253        if (result == EGL_TRUE) {
254            setViewportAndProjection(hw);
255        }
256    }
257    return result;
258}
259
260void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw) {
261    GLsizei w = hw->mDisplayWidth;
262    GLsizei h = hw->mDisplayHeight;
263    glViewport(0, 0, w, h);
264    glMatrixMode(GL_PROJECTION);
265    glLoadIdentity();
266    // put the origin in the left-bottom corner
267    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
268    glMatrixMode(GL_MODELVIEW);
269}
270
271// ----------------------------------------------------------------------------
272
273void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
274    mVisibleLayersSortedByZ = layers;
275    mSecureLayerVisible = false;
276    size_t count = layers.size();
277    for (size_t i=0 ; i<count ; i++) {
278        const sp<Layer>& layer(layers[i]);
279        if (layer->isSecure()) {
280            mSecureLayerVisible = true;
281        }
282    }
283}
284
285const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
286    return mVisibleLayersSortedByZ;
287}
288
289bool DisplayDevice::getSecureLayerVisible() const {
290    return mSecureLayerVisible;
291}
292
293Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
294    Region dirty;
295    if (repaintEverything) {
296        dirty.set(getBounds());
297    } else {
298        const Transform& planeTransform(mGlobalTransform);
299        dirty = planeTransform.transform(this->dirtyRegion);
300        dirty.andSelf(getBounds());
301    }
302    return dirty;
303}
304
305// ----------------------------------------------------------------------------
306
307bool DisplayDevice::canDraw() const {
308    return mScreenAcquired;
309}
310
311void DisplayDevice::releaseScreen() const {
312    mScreenAcquired = false;
313}
314
315void DisplayDevice::acquireScreen() const {
316    mScreenAcquired = true;
317}
318
319bool DisplayDevice::isScreenAcquired() const {
320    return mScreenAcquired;
321}
322
323// ----------------------------------------------------------------------------
324
325void DisplayDevice::setLayerStack(uint32_t stack) {
326    mLayerStack = stack;
327    dirtyRegion.set(bounds());
328}
329
330// ----------------------------------------------------------------------------
331
332status_t DisplayDevice::orientationToTransfrom(
333        int orientation, int w, int h, Transform* tr)
334{
335    uint32_t flags = 0;
336    switch (orientation) {
337    case DisplayState::eOrientationDefault:
338        flags = Transform::ROT_0;
339        break;
340    case DisplayState::eOrientation90:
341        flags = Transform::ROT_90;
342        break;
343    case DisplayState::eOrientation180:
344        flags = Transform::ROT_180;
345        break;
346    case DisplayState::eOrientation270:
347        flags = Transform::ROT_270;
348        break;
349    default:
350        return BAD_VALUE;
351    }
352    tr->set(flags, w, h);
353    return NO_ERROR;
354}
355
356void DisplayDevice::setProjection(int orientation,
357        const Rect& newViewport, const Rect& newFrame) {
358    Rect viewport(newViewport);
359    Rect frame(newFrame);
360
361    const int w = mDisplayWidth;
362    const int h = mDisplayHeight;
363
364    Transform R;
365    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
366
367    if (!frame.isValid()) {
368        // the destination frame can be invalid if it has never been set,
369        // in that case we assume the whole display frame.
370        frame = Rect(w, h);
371    }
372
373    if (viewport.isEmpty()) {
374        // viewport can be invalid if it has never been set, in that case
375        // we assume the whole display size.
376        // it's also invalid to have an empty viewport, so we handle that
377        // case in the same way.
378        viewport = Rect(w, h);
379        if (R.getOrientation() & Transform::ROT_90) {
380            // viewport is always specified in the logical orientation
381            // of the display (ie: post-rotation).
382            swap(viewport.right, viewport.bottom);
383        }
384    }
385
386    dirtyRegion.set(getBounds());
387
388    Transform TL, TP, S;
389    float src_width  = viewport.width();
390    float src_height = viewport.height();
391    float dst_width  = frame.width();
392    float dst_height = frame.height();
393    if (src_width != dst_width || src_height != dst_height) {
394        float sx = dst_width  / src_width;
395        float sy = dst_height / src_height;
396        S.set(sx, 0, 0, sy);
397    }
398
399    float src_x = viewport.left;
400    float src_y = viewport.top;
401    float dst_x = frame.left;
402    float dst_y = frame.top;
403    TL.set(-src_x, -src_y);
404    TP.set(dst_x, dst_y);
405
406    // The viewport and frame are both in the logical orientation.
407    // Apply the logical translation, scale to physical size, apply the
408    // physical translation and finally rotate to the physical orientation.
409    mGlobalTransform = R * TP * S * TL;
410
411    const uint8_t type = mGlobalTransform.getType();
412    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
413            (type >= Transform::SCALE));
414
415    mScissor = mGlobalTransform.transform(viewport);
416    if (mScissor.isEmpty()) {
417        mScissor.set(getBounds());
418    }
419
420    mOrientation = orientation;
421    mViewport = viewport;
422    mFrame = frame;
423}
424
425void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
426    const Transform& tr(mGlobalTransform);
427    snprintf(buffer, SIZE,
428        "+ DisplayDevice: %s\n"
429        "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
430        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
431        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
432        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
433        mDisplayName.string(), mType,
434        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
435        mOrientation, tr.getType(), getPageFlipCount(),
436        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
437        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
438        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
439        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
440        tr[0][0], tr[1][0], tr[2][0],
441        tr[0][1], tr[1][1], tr[2][1],
442        tr[0][2], tr[1][2], tr[2][2]);
443
444    result.append(buffer);
445
446    String8 surfaceDump;
447    mDisplaySurface->dump(surfaceDump);
448    result.append(surfaceDump);
449}
450