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