2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <cutils/properties.h>
24 #include <utils/RefBase.h>
25 #include <utils/Log.h>
27 #include <ui/DisplayInfo.h>
28 #include <ui/PixelFormat.h>
30 #include <gui/Surface.h>
32 #include <hardware/gralloc.h>
34 #include "DisplayHardware/DisplaySurface.h"
35 #include "DisplayHardware/HWComposer.h"
36 #include "RenderEngine/RenderEngine.h"
39 #include "DisplayDevice.h"
40 #include "SurfaceFlinger.h"
43 // ----------------------------------------------------------------------------
44 using namespace android;
45 // ----------------------------------------------------------------------------
48 * Initialize the display to the specified values.
52 DisplayDevice::DisplayDevice(
53 const sp<SurfaceFlinger>& flinger,
57 const wp<IBinder>& displayToken,
58 const sp<DisplaySurface>& displaySurface,
61 mType(type), mHwcDisplayId(hwcId),
62 mDisplayToken(displayToken),
63 mDisplaySurface(displaySurface),
64 mDisplay(EGL_NO_DISPLAY),
65 mSurface(EGL_NO_SURFACE),
66 mDisplayWidth(), mDisplayHeight(), mFormat(),
70 mSecureLayerVisible(false),
71 mScreenAcquired(false),
72 mLayerStack(NO_LAYER_STACK),
75 mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
76 ANativeWindow* const window = mNativeWindow.get();
79 window->query(window, NATIVE_WINDOW_FORMAT, &format);
81 // Make sure that composition can never be stalled by a virtual display
82 // consumer that isn't processing buffers fast enough. We have to do this
84 // * Here, in case the display is composed entirely by HWC.
85 // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
86 // window's swap interval in eglMakeCurrent, so they'll override the
87 // interval we set here.
88 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
89 window->setSwapInterval(window, 0);
92 * Create our display's surface
97 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
98 surface = eglCreateWindowSurface(display, config, window, NULL);
99 eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
100 eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
106 mViewport.makeInvalid();
107 mFrame.makeInvalid();
109 // virtual displays are always considered enabled
110 mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
112 // Name the display. The name will be replaced shortly if the display
113 // was created with createDisplay().
115 case DISPLAY_PRIMARY:
116 mDisplayName = "Built-in Screen";
118 case DISPLAY_EXTERNAL:
119 mDisplayName = "HDMI Screen";
122 mDisplayName = "Virtual Screen"; // e.g. Overlay #n
126 // initialize the display orientation transform.
127 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
130 DisplayDevice::~DisplayDevice() {
131 if (mSurface != EGL_NO_SURFACE) {
132 eglDestroySurface(mDisplay, mSurface);
133 mSurface = EGL_NO_SURFACE;
137 void DisplayDevice::disconnect(HWComposer& hwc) {
138 if (mHwcDisplayId >= 0) {
139 hwc.disconnectDisplay(mHwcDisplayId);
140 if (mHwcDisplayId >= DISPLAY_VIRTUAL)
141 hwc.freeDisplayId(mHwcDisplayId);
146 bool DisplayDevice::isValid() const {
147 return mFlinger != NULL;
150 int DisplayDevice::getWidth() const {
151 return mDisplayWidth;
154 int DisplayDevice::getHeight() const {
155 return mDisplayHeight;
158 PixelFormat DisplayDevice::getFormat() const {
162 EGLSurface DisplayDevice::getEGLSurface() const {
166 void DisplayDevice::setDisplayName(const String8& displayName) {
167 if (!displayName.isEmpty()) {
168 // never override the name with an empty name
169 mDisplayName = displayName;
173 uint32_t DisplayDevice::getPageFlipCount() const {
174 return mPageFlipCount;
177 status_t DisplayDevice::compositionComplete() const {
178 return mDisplaySurface->compositionComplete();
181 void DisplayDevice::flip(const Region& dirty) const
183 mFlinger->getRenderEngine().checkErrors();
185 EGLDisplay dpy = mDisplay;
186 EGLSurface surface = mSurface;
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());
200 status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
201 DisplaySurface::CompositionType compositionType;
202 bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
203 bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
204 if (haveGles && haveHwc) {
205 compositionType = DisplaySurface::COMPOSITION_MIXED;
206 } else if (haveGles) {
207 compositionType = DisplaySurface::COMPOSITION_GLES;
208 } else if (haveHwc) {
209 compositionType = DisplaySurface::COMPOSITION_HWC;
211 // Nothing to do -- when turning the screen off we get a frame like
212 // this. Call it a HWC frame since we won't be doing any GLES work but
213 // will do a prepare/set cycle.
214 compositionType = DisplaySurface::COMPOSITION_HWC;
216 return mDisplaySurface->prepareFrame(compositionType);
219 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
220 // We need to call eglSwapBuffers() unless:
221 // (a) there was no GLES composition this frame, or
222 // (b) we're using a legacy HWC with no framebuffer target support (in
223 // which case HWComposer::commit() handles things).
224 if (hwc.initCheck() != NO_ERROR ||
225 (hwc.hasGlesComposition(mHwcDisplayId) &&
226 hwc.supportsFramebufferTarget())) {
227 EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
229 EGLint error = eglGetError();
230 if (error == EGL_CONTEXT_LOST ||
231 mType == DisplayDevice::DISPLAY_PRIMARY) {
232 LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
233 mDisplay, mSurface, error);
235 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
236 mDisplay, mSurface, error);
241 status_t result = mDisplaySurface->advanceFrame();
242 if (result != NO_ERROR) {
243 ALOGE("[%s] failed pushing new frame to HWC: %d",
244 mDisplayName.string(), result);
248 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
249 if (hwc.initCheck() == NO_ERROR) {
250 mDisplaySurface->onFrameCommitted();
254 uint32_t DisplayDevice::getFlags() const
259 EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
260 EGLBoolean result = EGL_TRUE;
261 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
262 if (sur != mSurface) {
263 result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
264 if (result == EGL_TRUE) {
265 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
266 eglSwapInterval(dpy, 0);
267 setViewportAndProjection();
273 void DisplayDevice::setViewportAndProjection() const {
274 size_t w = mDisplayWidth;
275 size_t h = mDisplayHeight;
276 mFlinger->getRenderEngine().setViewportAndProjection(w, h);
279 // ----------------------------------------------------------------------------
281 void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
282 mVisibleLayersSortedByZ = layers;
283 mSecureLayerVisible = false;
284 size_t count = layers.size();
285 for (size_t i=0 ; i<count ; i++) {
286 const sp<Layer>& layer(layers[i]);
287 if (layer->isSecure()) {
288 mSecureLayerVisible = true;
293 const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
294 return mVisibleLayersSortedByZ;
297 bool DisplayDevice::getSecureLayerVisible() const {
298 return mSecureLayerVisible;
301 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
303 if (repaintEverything) {
304 dirty.set(getBounds());
306 const Transform& planeTransform(mGlobalTransform);
307 dirty = planeTransform.transform(this->dirtyRegion);
308 dirty.andSelf(getBounds());
313 // ----------------------------------------------------------------------------
315 bool DisplayDevice::canDraw() const {
316 return mScreenAcquired;
319 void DisplayDevice::releaseScreen() const {
320 mScreenAcquired = false;
323 void DisplayDevice::acquireScreen() const {
324 mScreenAcquired = true;
327 bool DisplayDevice::isScreenAcquired() const {
328 return mScreenAcquired;
331 // ----------------------------------------------------------------------------
333 void DisplayDevice::setLayerStack(uint32_t stack) {
335 dirtyRegion.set(bounds());
338 // ----------------------------------------------------------------------------
340 status_t DisplayDevice::orientationToTransfrom(
341 int orientation, int w, int h, Transform* tr)
344 switch (orientation) {
345 case DisplayState::eOrientationDefault:
346 flags = Transform::ROT_0;
348 case DisplayState::eOrientation90:
349 flags = Transform::ROT_90;
351 case DisplayState::eOrientation180:
352 flags = Transform::ROT_180;
354 case DisplayState::eOrientation270:
355 flags = Transform::ROT_270;
360 tr->set(flags, w, h);
364 void DisplayDevice::setProjection(int orientation,
365 const Rect& newViewport, const Rect& newFrame) {
366 Rect viewport(newViewport);
367 Rect frame(newFrame);
369 const int w = mDisplayWidth;
370 const int h = mDisplayHeight;
373 DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
375 if (!frame.isValid()) {
376 // the destination frame can be invalid if it has never been set,
377 // in that case we assume the whole display frame.
381 if (viewport.isEmpty()) {
382 // viewport can be invalid if it has never been set, in that case
383 // we assume the whole display size.
384 // it's also invalid to have an empty viewport, so we handle that
385 // case in the same way.
386 viewport = Rect(w, h);
387 if (R.getOrientation() & Transform::ROT_90) {
388 // viewport is always specified in the logical orientation
389 // of the display (ie: post-rotation).
390 swap(viewport.right, viewport.bottom);
394 dirtyRegion.set(getBounds());
397 float src_width = viewport.width();
398 float src_height = viewport.height();
399 float dst_width = frame.width();
400 float dst_height = frame.height();
401 if (src_width != dst_width || src_height != dst_height) {
402 float sx = dst_width / src_width;
403 float sy = dst_height / src_height;
407 float src_x = viewport.left;
408 float src_y = viewport.top;
409 float dst_x = frame.left;
410 float dst_y = frame.top;
411 TL.set(-src_x, -src_y);
412 TP.set(dst_x, dst_y);
414 // The viewport and frame are both in the logical orientation.
415 // Apply the logical translation, scale to physical size, apply the
416 // physical translation and finally rotate to the physical orientation.
417 mGlobalTransform = R * TP * S * TL;
419 const uint8_t type = mGlobalTransform.getType();
420 mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
421 (type >= Transform::SCALE));
423 mScissor = mGlobalTransform.transform(viewport);
424 if (mScissor.isEmpty()) {
425 mScissor = getBounds();
428 mOrientation = orientation;
429 mViewport = viewport;
433 void DisplayDevice::dump(String8& result) const {
434 const Transform& tr(mGlobalTransform);
436 "+ DisplayDevice: %s\n"
437 " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
438 "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
439 " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
440 "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
441 mDisplayName.string(), mType, mHwcDisplayId,
442 mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
443 mOrientation, tr.getType(), getPageFlipCount(),
444 mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
445 mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
446 mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
447 mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
448 tr[0][0], tr[1][0], tr[2][0],
449 tr[0][1], tr[1][1], tr[2][1],
450 tr[0][2], tr[1][2], tr[2][2]);
453 mDisplaySurface->dump(surfaceDump);
454 result.append(surfaceDump);