DisplayDevice.cpp revision 875d8e1323536e16dcfc90c9674d7ad32116a69a
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
17edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdlib.h>
18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdio.h>
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <string.h>
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <math.h>
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <cutils/properties.h>
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
24076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian#include <utils/RefBase.h>
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h>
26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
27c666cae2d5995097ec49a87e375e2afdd92802b7Mathias Agopian#include <ui/DisplayInfo.h>
28076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian#include <ui/PixelFormat.h>
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
30e3c697fb929c856b59fa56a8e05a2a7eba187c3dMathias Agopian#include <gui/Surface.h>
311a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis
32076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian#include <hardware/gralloc.h>
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
3499c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall#include "DisplayHardware/DisplaySurface.h"
351b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian#include "DisplayHardware/HWComposer.h"
36875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian#include "RenderEngine/RenderEngine.h"
371b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
38da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian#include "clz.h"
390f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopian#include "DisplayDevice.h"
40c7d14e247117392fbd44aa454622778a25c076aeMathias Agopian#include "SurfaceFlinger.h"
4113127d8921356dff794250e04208c3ed60b3a3dfMathias Agopian#include "Layer.h"
421f7bec634f19c123410a5155c8d282e177c01930Mathias Agopian
43a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian// ----------------------------------------------------------------------------
44edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectusing namespace android;
45a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian// ----------------------------------------------------------------------------
46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
47edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
48edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Initialize the display to the specified values.
49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
520f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias AgopianDisplayDevice::DisplayDevice(
53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const sp<SurfaceFlinger>& flinger,
54dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis        DisplayType type,
55ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall        int32_t hwcId,
56dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis        bool isSecure,
57dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis        const wp<IBinder>& displayToken,
5899c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall        const sp<DisplaySurface>& displaySurface,
59a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        EGLConfig config)
6092a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian    : mFlinger(flinger),
61ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall      mType(type), mHwcDisplayId(hwcId),
6227e2562868dcd3ad26f9b4677b64ae272941704eChih-Wei Huang      mDisplayToken(displayToken),
6399c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall      mDisplaySurface(displaySurface),
6492a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mDisplay(EGL_NO_DISPLAY),
6592a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mSurface(EGL_NO_SURFACE),
6692a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mContext(EGL_NO_CONTEXT),
6792a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mDisplayWidth(), mDisplayHeight(), mFormat(),
6892a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mFlags(),
6992a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mPageFlipCount(),
70dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis      mIsSecure(isSecure),
7192a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mSecureLayerVisible(false),
7292a979a92c34b7de609ce2b1662c73bb8a2728b9Mathias Agopian      mScreenAcquired(false),
7301e29054e672301e4adbbca15b3562a59a20f267Jesse Hall      mLayerStack(NO_LAYER_STACK),
74da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian      mOrientation()
75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
7699c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
77a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    ANativeWindow* const window = mNativeWindow.get();
78a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian
796163091a2c366f8311fc3ee627dc7deb9681236eMathias Agopian    int format;
806163091a2c366f8311fc3ee627dc7deb9681236eMathias Agopian    window->query(window, NATIVE_WINDOW_FORMAT, &format);
81b5dd9c0fee3b3d6d35035dfb992951ebea3e0e4eMathias Agopian
82a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    /*
83a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian     * Create our display's surface
84b5dd9c0fee3b3d6d35035dfb992951ebea3e0e4eMathias Agopian     */
85385977f6d6c4e76379df384d50695a10cb3757f2Mathias Agopian
861f7bec634f19c123410a5155c8d282e177c01930Mathias Agopian    EGLSurface surface;
87a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    EGLint w, h;
88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
89a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    surface = eglCreateWindowSurface(display, config, window, NULL);
901b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
911b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
92edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
931f7bec634f19c123410a5155c8d282e177c01930Mathias Agopian    mDisplay = display;
941f7bec634f19c123410a5155c8d282e177c01930Mathias Agopian    mSurface = surface;
95a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    mFormat  = format;
961f7bec634f19c123410a5155c8d282e177c01930Mathias Agopian    mPageFlipCount = 0;
97da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian    mViewport.makeInvalid();
98da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian    mFrame.makeInvalid();
991f7bec634f19c123410a5155c8d282e177c01930Mathias Agopian
100ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    // virtual displays are always considered enabled
101ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
1025f20e2d4462da3471f59152b32cd8640fa4a21daMathias Agopian
1038dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden    // Name the display.  The name will be replaced shortly if the display
1048dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden    // was created with createDisplay().
1058dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden    switch (mType) {
1068dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden        case DISPLAY_PRIMARY:
1078dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden            mDisplayName = "Built-in Screen";
1088dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden            break;
1098dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden        case DISPLAY_EXTERNAL:
1108dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden            mDisplayName = "HDMI Screen";
1118dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden            break;
1128dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden        default:
1138dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
1148dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden            break;
1158dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden    }
1168dfa92fef9759a881e96ee58d59875d35023aab9Andy McFadden
11798a121aa916eb7acbf11df0e3e31a6fede6fc9ddMathias Agopian    // initialize the display orientation transform.
11800e8c7a88a5b9c4104a71013a713acd3e4d3b77bMathias Agopian    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
119a350ff98692b3a50cad5cc93f9f83221242ca86aMathias Agopian}
120a350ff98692b3a50cad5cc93f9f83221242ca86aMathias Agopian
121ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse HallDisplayDevice::~DisplayDevice() {
122ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    if (mSurface != EGL_NO_SURFACE) {
123ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall        eglDestroySurface(mDisplay, mSurface);
124ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall        mSurface = EGL_NO_SURFACE;
125ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    }
126ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall}
127ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall
12802d86567d95b99e1142941ed7ec23a4465822813Jesse Hallvoid DisplayDevice::disconnect(HWComposer& hwc) {
12902d86567d95b99e1142941ed7ec23a4465822813Jesse Hall    if (mHwcDisplayId >= 0) {
13002d86567d95b99e1142941ed7ec23a4465822813Jesse Hall        hwc.disconnectDisplay(mHwcDisplayId);
13102d86567d95b99e1142941ed7ec23a4465822813Jesse Hall        if (mHwcDisplayId >= DISPLAY_VIRTUAL)
13202d86567d95b99e1142941ed7ec23a4465822813Jesse Hall            hwc.freeDisplayId(mHwcDisplayId);
13302d86567d95b99e1142941ed7ec23a4465822813Jesse Hall        mHwcDisplayId = -1;
13402d86567d95b99e1142941ed7ec23a4465822813Jesse Hall    }
13502d86567d95b99e1142941ed7ec23a4465822813Jesse Hall}
13602d86567d95b99e1142941ed7ec23a4465822813Jesse Hall
137ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hallbool DisplayDevice::isValid() const {
138ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    return mFlinger != NULL;
139ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall}
140ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall
141ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hallint DisplayDevice::getWidth() const {
142ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    return mDisplayWidth;
143ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall}
144ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall
145ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hallint DisplayDevice::getHeight() const {
146ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    return mDisplayHeight;
147ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall}
148ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall
149ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse HallPixelFormat DisplayDevice::getFormat() const {
150ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    return mFormat;
151ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall}
152ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall
153ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse HallEGLSurface DisplayDevice::getEGLSurface() const {
154ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall    return mSurface;
155ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall}
156ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0aJesse Hall
1579e2463e71796964cfaa06bf09a880875ac3537bcMathias Agopianvoid DisplayDevice::setDisplayName(const String8& displayName) {
1589e2463e71796964cfaa06bf09a880875ac3537bcMathias Agopian    if (!displayName.isEmpty()) {
1599e2463e71796964cfaa06bf09a880875ac3537bcMathias Agopian        // never override the name with an empty name
1609e2463e71796964cfaa06bf09a880875ac3537bcMathias Agopian        mDisplayName = displayName;
1619e2463e71796964cfaa06bf09a880875ac3537bcMathias Agopian    }
1629e2463e71796964cfaa06bf09a880875ac3537bcMathias Agopian}
1639e2463e71796964cfaa06bf09a880875ac3537bcMathias Agopian
1640f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopianuint32_t DisplayDevice::getPageFlipCount() const {
165076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian    return mPageFlipCount;
166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1680f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopianstatus_t DisplayDevice::compositionComplete() const {
16999c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    return mDisplaySurface->compositionComplete();
17074faca212e2675aa55a30235c77cb6403471a4b9Mathias Agopian}
171edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1720f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopianvoid DisplayDevice::flip(const Region& dirty) const
173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
174875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian    mFlinger->getRenderEngine().checkErrors();
175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    EGLDisplay dpy = mDisplay;
177edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    EGLSurface surface = mSurface;
178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
17901e29054e672301e4adbbca15b3562a59a20f267Jesse Hall#ifdef EGL_ANDROID_swap_rectangle
180df3ca30bf663cb8eed88ee3f16fb5e9a65dc00fcMathias Agopian    if (mFlags & SWAP_RECTANGLE) {
181b8a5560e1303cb10f5cd482af466fc04d2bdfcabMathias Agopian        const Region newDirty(dirty.intersect(bounds()));
182b8a5560e1303cb10f5cd482af466fc04d2bdfcabMathias Agopian        const Rect b(newDirty.getBounds());
183df3ca30bf663cb8eed88ee3f16fb5e9a65dc00fcMathias Agopian        eglSetSwapRectangleANDROID(dpy, surface,
184df3ca30bf663cb8eed88ee3f16fb5e9a65dc00fcMathias Agopian                b.left, b.top, b.width(), b.height());
18501e29054e672301e4adbbca15b3562a59a20f267Jesse Hall    }
1865e78e0965169790111f01354e78b0f8d34c94840Mathias Agopian#endif
187d870703d5566490cfdfb389d9336b2b8d3c6cc7aMathias Agopian
188076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian    mPageFlipCount++;
189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
191da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopianvoid DisplayDevice::swapBuffers(HWComposer& hwc) const {
19299c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    // We need to call eglSwapBuffers() unless:
19399c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    // (a) there was no GLES composition this frame, or
19499c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    // (b) we're using a legacy HWC with no framebuffer target support (in
19599c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    //     which case HWComposer::commit() handles things).
19699c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    if (hwc.initCheck() != NO_ERROR ||
19799c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall            (hwc.hasGlesComposition(mHwcDisplayId) &&
19899c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall             hwc.supportsFramebufferTarget())) {
19999c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
20099c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall        if (!success) {
20199c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall            EGLint error = eglGetError();
20299c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall            if (error == EGL_CONTEXT_LOST ||
20399c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall                    mType == DisplayDevice::DISPLAY_PRIMARY) {
20499c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
20599c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall                        mDisplay, mSurface, error);
20699c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall            } else {
20799c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall                ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
20899c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall                        mDisplay, mSurface, error);
209da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian            }
210da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian        }
211da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian    }
21252e21483fa48baeb4a88372d75e083bca2e92923Mathias Agopian
21399c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    status_t result = mDisplaySurface->advanceFrame();
21499c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    if (result != NO_ERROR) {
21599c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall        ALOGE("[%s] failed pushing new frame to HWC: %d",
21699c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall                mDisplayName.string(), result);
21732341381c9493d7953e40f7f79653cfc52868863Mathias Agopian    }
218da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian}
219da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian
220da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopianvoid DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
221da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian    if (hwc.initCheck() == NO_ERROR) {
222851cfe834295224cd64bdd499872b95b19c4de8cJesse Hall        mDisplaySurface->onFrameCommitted();
223da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian    }
224da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian}
225da27af9832a0170f1fc40ef3f21371c4d30d21b3Mathias Agopian
2260f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopianuint32_t DisplayDevice::getFlags() const
227edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
228edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mFlags;
229edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
230edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
231875d8e1323536e16dcfc90c9674d7ad32116a69aMathias AgopianEGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
232da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian    EGLBoolean result = EGL_TRUE;
23352bbb1ae239c8a4d05543a23fa8c08467d09c3b2Mathias Agopian    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
234875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian    if (sur != mSurface) {
235875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian        result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
236da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian        if (result == EGL_TRUE) {
237875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian            setViewportAndProjection();
238da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian        }
23952bbb1ae239c8a4d05543a23fa8c08467d09c3b2Mathias Agopian    }
240da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian    return result;
24152bbb1ae239c8a4d05543a23fa8c08467d09c3b2Mathias Agopian}
24252bbb1ae239c8a4d05543a23fa8c08467d09c3b2Mathias Agopian
243875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopianvoid DisplayDevice::setViewportAndProjection() const {
244875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian    size_t w = mDisplayWidth;
245875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian    size_t h = mDisplayHeight;
246875d8e1323536e16dcfc90c9674d7ad32116a69aMathias Agopian    mFlinger->getRenderEngine().setViewportAndProjection(w, h);
247bae92d0d605e99a14731add4f11b72413b2835e5Mathias Agopian}
248bae92d0d605e99a14731add4f11b72413b2835e5Mathias Agopian
2491b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian// ----------------------------------------------------------------------------
2501b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
25113127d8921356dff794250e04208c3ed60b3a3dfMathias Agopianvoid DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
2523b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    mVisibleLayersSortedByZ = layers;
253ef7b9c7eac036cc1230c64821039d18f8cbd2c1cMathias Agopian    mSecureLayerVisible = false;
2543b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    size_t count = layers.size();
2553b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    for (size_t i=0 ; i<count ; i++) {
25613127d8921356dff794250e04208c3ed60b3a3dfMathias Agopian        const sp<Layer>& layer(layers[i]);
257f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        if (layer->isSecure()) {
2583b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian            mSecureLayerVisible = true;
2593b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian        }
2603b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    }
2613b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian}
2623b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian
26313127d8921356dff794250e04208c3ed60b3a3dfMathias Agopianconst Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
2643b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    return mVisibleLayersSortedByZ;
2653b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian}
2663b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian
2670f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopianbool DisplayDevice::getSecureLayerVisible() const {
2683b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    return mSecureLayerVisible;
2693b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian}
2703b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian
271cd60f99aba9e750700a967db30b74a29145739cfMathias AgopianRegion DisplayDevice::getDirtyRegion(bool repaintEverything) const {
272cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian    Region dirty;
273cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian    if (repaintEverything) {
274cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian        dirty.set(getBounds());
275cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian    } else {
276da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian        const Transform& planeTransform(mGlobalTransform);
277cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian        dirty = planeTransform.transform(this->dirtyRegion);
278cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian        dirty.andSelf(getBounds());
279cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian    }
280cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian    return dirty;
281cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian}
282cd60f99aba9e750700a967db30b74a29145739cfMathias Agopian
2833b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian// ----------------------------------------------------------------------------
284d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
285d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopianbool DisplayDevice::canDraw() const {
286d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    return mScreenAcquired;
287d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian}
288d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
289d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopianvoid DisplayDevice::releaseScreen() const {
290d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    mScreenAcquired = false;
291d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian}
292d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
293d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopianvoid DisplayDevice::acquireScreen() const {
294d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    mScreenAcquired = true;
295d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian}
296d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
297d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopianbool DisplayDevice::isScreenAcquired() const {
298d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    return mScreenAcquired;
299d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian}
300d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
301d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian// ----------------------------------------------------------------------------
3023b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian
30328947d7fbf9f486539322e8e12dd057568e180c2Mathias Agopianvoid DisplayDevice::setLayerStack(uint32_t stack) {
30428947d7fbf9f486539322e8e12dd057568e180c2Mathias Agopian    mLayerStack = stack;
30528947d7fbf9f486539322e8e12dd057568e180c2Mathias Agopian    dirtyRegion.set(bounds());
30628947d7fbf9f486539322e8e12dd057568e180c2Mathias Agopian}
30728947d7fbf9f486539322e8e12dd057568e180c2Mathias Agopian
30828947d7fbf9f486539322e8e12dd057568e180c2Mathias Agopian// ----------------------------------------------------------------------------
30928947d7fbf9f486539322e8e12dd057568e180c2Mathias Agopian
3100f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopianstatus_t DisplayDevice::orientationToTransfrom(
3111b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        int orientation, int w, int h, Transform* tr)
3121b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian{
3131b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    uint32_t flags = 0;
3141b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    switch (orientation) {
3153165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian    case DisplayState::eOrientationDefault:
3161b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        flags = Transform::ROT_0;
3171b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        break;
3183165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian    case DisplayState::eOrientation90:
3191b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        flags = Transform::ROT_90;
3201b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        break;
3213165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian    case DisplayState::eOrientation180:
3221b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        flags = Transform::ROT_180;
3231b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        break;
3243165cc21cfea781988407b19bd83292b19f05f55Mathias Agopian    case DisplayState::eOrientation270:
3251b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        flags = Transform::ROT_270;
3261b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        break;
3271b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    default:
3281b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian        return BAD_VALUE;
3291b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    }
3301b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    tr->set(flags, w, h);
3311b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    return NO_ERROR;
3321b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian}
3331b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
33400e8c7a88a5b9c4104a71013a713acd3e4d3b77bMathias Agopianvoid DisplayDevice::setProjection(int orientation,
335f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        const Rect& newViewport, const Rect& newFrame) {
336f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    Rect viewport(newViewport);
337f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    Rect frame(newFrame);
338da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian
339f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    const int w = mDisplayWidth;
340f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    const int h = mDisplayHeight;
341da8d0a5c0cf9d41915d3b106cad4aaec3e767c11Mathias Agopian
342f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    Transform R;
343f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
3441b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
345f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    if (!frame.isValid()) {
346f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        // the destination frame can be invalid if it has never been set,
347f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        // in that case we assume the whole display frame.
348f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        frame = Rect(w, h);
349f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    }
3506360ec42d414b1351ecb6c5fc4b8afa30d8f4ebfJesse Hall
351f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    if (viewport.isEmpty()) {
352f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        // viewport can be invalid if it has never been set, in that case
353f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        // we assume the whole display size.
354f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        // it's also invalid to have an empty viewport, so we handle that
355f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        // case in the same way.
356f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        viewport = Rect(w, h);
357f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        if (R.getOrientation() & Transform::ROT_90) {
358f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian            // viewport is always specified in the logical orientation
359f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian            // of the display (ie: post-rotation).
360f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian            swap(viewport.right, viewport.bottom);
361766dc49c17dda977bf7b93a5fd8da41c0b737611Mathias Agopian        }
3621b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    }
363f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian
364f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    dirtyRegion.set(getBounds());
365f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian
366f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    Transform TL, TP, S;
367f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float src_width  = viewport.width();
368f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float src_height = viewport.height();
369f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float dst_width  = frame.width();
370f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float dst_height = frame.height();
371f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    if (src_width != dst_width || src_height != dst_height) {
372f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        float sx = dst_width  / src_width;
373f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        float sy = dst_height / src_height;
374f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian        S.set(sx, 0, 0, sy);
375f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    }
376f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian
377f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float src_x = viewport.left;
378f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float src_y = viewport.top;
379f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float dst_x = frame.left;
380f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    float dst_y = frame.top;
381f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    TL.set(-src_x, -src_y);
382f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    TP.set(dst_x, dst_y);
383f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian
384f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    // The viewport and frame are both in the logical orientation.
385f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    // Apply the logical translation, scale to physical size, apply the
386f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    // physical translation and finally rotate to the physical orientation.
387f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    mGlobalTransform = R * TP * S * TL;
388f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian
389f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    const uint8_t type = mGlobalTransform.getType();
390f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
391f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian            (type >= Transform::SCALE));
392f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian
393f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    mScissor = mGlobalTransform.transform(viewport);
394f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    if (mScissor.isEmpty()) {
3956c7f25afb75ac155bad0b3bc17c0089d0337d060Mathias Agopian        mScissor = getBounds();
396f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    }
397f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian
398f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    mOrientation = orientation;
399f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    mViewport = viewport;
400f5f714aa188884098aaecbe39d0bc61b40311c0dMathias Agopian    mFrame = frame;
4011b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian}
4021d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian
40374d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopianvoid DisplayDevice::dump(String8& result) const {
4041d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian    const Transform& tr(mGlobalTransform);
40574d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    result.appendFormat(
4061d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        "+ DisplayDevice: %s\n"
40702d86567d95b99e1142941ed7ec23a4465822813Jesse Hall        "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
408dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
409766dc49c17dda977bf7b93a5fd8da41c0b737611Mathias Agopian        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
4101d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
41102d86567d95b99e1142941ed7ec23a4465822813Jesse Hall        mDisplayName.string(), mType, mHwcDisplayId,
4121d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
4131d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        mOrientation, tr.getType(), getPageFlipCount(),
414dd3cb84cfbe8068790c6233b5829fae9c4a0ee93Jamie Gennis        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
4151d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
4161d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
417766dc49c17dda977bf7b93a5fd8da41c0b737611Mathias Agopian        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
4181d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        tr[0][0], tr[1][0], tr[2][0],
4191d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        tr[0][1], tr[1][1], tr[2][1],
4201d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian        tr[0][2], tr[1][2], tr[2][2]);
4211d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian
42299c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    String8 surfaceDump;
42399c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    mDisplaySurface->dump(surfaceDump);
42499c7dbb24994df2f3e175f7b25dd2c9dd92a72f0Jesse Hall    result.append(surfaceDump);
4251d12d8a8e61163b35cf42c51c558a67138014e82Mathias Agopian}
426