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,
59 const sp<IGraphicBufferProducer>& producer,
62 mType(type), mHwcDisplayId(hwcId),
63 mDisplayToken(displayToken),
64 mDisplaySurface(displaySurface),
65 mDisplay(EGL_NO_DISPLAY),
66 mSurface(EGL_NO_SURFACE),
67 mDisplayWidth(), mDisplayHeight(), mFormat(),
71 mSecureLayerVisible(false),
72 mScreenAcquired(false),
73 mLayerStack(NO_LAYER_STACK),
76 mNativeWindow = new Surface(producer, false);
77 ANativeWindow* const window = mNativeWindow.get();
80 window->query(window, NATIVE_WINDOW_FORMAT, &format);
82 // Make sure that composition can never be stalled by a virtual display
83 // consumer that isn't processing buffers fast enough. We have to do this
85 // * Here, in case the display is composed entirely by HWC.
86 // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
87 // window's swap interval in eglMakeCurrent, so they'll override the
88 // interval we set here.
89 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
90 window->setSwapInterval(window, 0);
93 * Create our display's surface
98 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
99 surface = eglCreateWindowSurface(display, config, window, NULL);
100 eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
101 eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
107 mViewport.makeInvalid();
108 mFrame.makeInvalid();
110 // virtual displays are always considered enabled
111 mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
113 // Name the display. The name will be replaced shortly if the display
114 // was created with createDisplay().
116 case DISPLAY_PRIMARY:
117 mDisplayName = "Built-in Screen";
119 case DISPLAY_EXTERNAL:
120 mDisplayName = "HDMI Screen";
123 mDisplayName = "Virtual Screen"; // e.g. Overlay #n
127 // initialize the display orientation transform.
128 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
131 DisplayDevice::~DisplayDevice() {
132 if (mSurface != EGL_NO_SURFACE) {
133 eglDestroySurface(mDisplay, mSurface);
134 mSurface = EGL_NO_SURFACE;
138 void DisplayDevice::disconnect(HWComposer& hwc) {
139 if (mHwcDisplayId >= 0) {
140 hwc.disconnectDisplay(mHwcDisplayId);
141 if (mHwcDisplayId >= DISPLAY_VIRTUAL)
142 hwc.freeDisplayId(mHwcDisplayId);
147 bool DisplayDevice::isValid() const {
148 return mFlinger != NULL;
151 int DisplayDevice::getWidth() const {
152 return mDisplayWidth;
155 int DisplayDevice::getHeight() const {
156 return mDisplayHeight;
159 PixelFormat DisplayDevice::getFormat() const {
163 EGLSurface DisplayDevice::getEGLSurface() const {
167 void DisplayDevice::setDisplayName(const String8& displayName) {
168 if (!displayName.isEmpty()) {
169 // never override the name with an empty name
170 mDisplayName = displayName;
174 uint32_t DisplayDevice::getPageFlipCount() const {
175 return mPageFlipCount;
178 status_t DisplayDevice::compositionComplete() const {
179 return mDisplaySurface->compositionComplete();
182 void DisplayDevice::flip(const Region& dirty) const
184 mFlinger->getRenderEngine().checkErrors();
186 EGLDisplay dpy = mDisplay;
187 EGLSurface surface = mSurface;
189 #ifdef EGL_ANDROID_swap_rectangle
190 if (mFlags & SWAP_RECTANGLE) {
191 const Region newDirty(dirty.intersect(bounds()));
192 const Rect b(newDirty.getBounds());
193 eglSetSwapRectangleANDROID(dpy, surface,
194 b.left, b.top, b.width(), b.height());
201 status_t DisplayDevice::beginFrame() const {
202 return mDisplaySurface->beginFrame();
205 status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
206 DisplaySurface::CompositionType compositionType;
207 bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
208 bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
209 if (haveGles && haveHwc) {
210 compositionType = DisplaySurface::COMPOSITION_MIXED;
211 } else if (haveGles) {
212 compositionType = DisplaySurface::COMPOSITION_GLES;
213 } else if (haveHwc) {
214 compositionType = DisplaySurface::COMPOSITION_HWC;
216 // Nothing to do -- when turning the screen off we get a frame like
217 // this. Call it a HWC frame since we won't be doing any GLES work but
218 // will do a prepare/set cycle.
219 compositionType = DisplaySurface::COMPOSITION_HWC;
221 return mDisplaySurface->prepareFrame(compositionType);
224 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
225 // We need to call eglSwapBuffers() if:
226 // (1) we don't have a hardware composer, or
227 // (2) we did GLES composition this frame, and either
228 // (a) we have framebuffer target support (not present on legacy
229 // devices, where HWComposer::commit() handles things); or
230 // (b) this is a virtual display
231 if (hwc.initCheck() != NO_ERROR ||
232 (hwc.hasGlesComposition(mHwcDisplayId) &&
233 (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
234 EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
236 EGLint error = eglGetError();
237 if (error == EGL_CONTEXT_LOST ||
238 mType == DisplayDevice::DISPLAY_PRIMARY) {
239 LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
240 mDisplay, mSurface, error);
242 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
243 mDisplay, mSurface, error);
248 status_t result = mDisplaySurface->advanceFrame();
249 if (result != NO_ERROR) {
250 ALOGE("[%s] failed pushing new frame to HWC: %d",
251 mDisplayName.string(), result);
255 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
256 if (hwc.initCheck() == NO_ERROR) {
257 mDisplaySurface->onFrameCommitted();
261 uint32_t DisplayDevice::getFlags() const
266 EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
267 EGLBoolean result = EGL_TRUE;
268 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
269 if (sur != mSurface) {
270 result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
271 if (result == EGL_TRUE) {
272 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
273 eglSwapInterval(dpy, 0);
276 setViewportAndProjection();
280 void DisplayDevice::setViewportAndProjection() const {
281 size_t w = mDisplayWidth;
282 size_t h = mDisplayHeight;
283 mFlinger->getRenderEngine().setViewportAndProjection(w, h, w, h, false);
286 // ----------------------------------------------------------------------------
288 void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
289 mVisibleLayersSortedByZ = layers;
290 mSecureLayerVisible = false;
291 size_t count = layers.size();
292 for (size_t i=0 ; i<count ; i++) {
293 const sp<Layer>& layer(layers[i]);
294 if (layer->isSecure()) {
295 mSecureLayerVisible = true;
300 const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
301 return mVisibleLayersSortedByZ;
304 bool DisplayDevice::getSecureLayerVisible() const {
305 return mSecureLayerVisible;
308 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
310 if (repaintEverything) {
311 dirty.set(getBounds());
313 const Transform& planeTransform(mGlobalTransform);
314 dirty = planeTransform.transform(this->dirtyRegion);
315 dirty.andSelf(getBounds());
320 // ----------------------------------------------------------------------------
322 bool DisplayDevice::canDraw() const {
323 return mScreenAcquired;
326 void DisplayDevice::releaseScreen() const {
327 mScreenAcquired = false;
330 void DisplayDevice::acquireScreen() const {
331 mScreenAcquired = true;
334 bool DisplayDevice::isScreenAcquired() const {
335 return mScreenAcquired;
338 // ----------------------------------------------------------------------------
340 void DisplayDevice::setLayerStack(uint32_t stack) {
342 dirtyRegion.set(bounds());
345 // ----------------------------------------------------------------------------
347 uint32_t DisplayDevice::getOrientationTransform() const {
348 uint32_t transform = 0;
349 switch (mOrientation) {
350 case DisplayState::eOrientationDefault:
351 transform = Transform::ROT_0;
353 case DisplayState::eOrientation90:
354 transform = Transform::ROT_90;
356 case DisplayState::eOrientation180:
357 transform = Transform::ROT_180;
359 case DisplayState::eOrientation270:
360 transform = Transform::ROT_270;
366 status_t DisplayDevice::orientationToTransfrom(
367 int orientation, int w, int h, Transform* tr)
370 switch (orientation) {
371 case DisplayState::eOrientationDefault:
372 flags = Transform::ROT_0;
374 case DisplayState::eOrientation90:
375 flags = Transform::ROT_90;
377 case DisplayState::eOrientation180:
378 flags = Transform::ROT_180;
380 case DisplayState::eOrientation270:
381 flags = Transform::ROT_270;
386 tr->set(flags, w, h);
390 void DisplayDevice::setProjection(int orientation,
391 const Rect& newViewport, const Rect& newFrame) {
392 Rect viewport(newViewport);
393 Rect frame(newFrame);
395 const int w = mDisplayWidth;
396 const int h = mDisplayHeight;
399 DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
401 if (!frame.isValid()) {
402 // the destination frame can be invalid if it has never been set,
403 // in that case we assume the whole display frame.
407 if (viewport.isEmpty()) {
408 // viewport can be invalid if it has never been set, in that case
409 // we assume the whole display size.
410 // it's also invalid to have an empty viewport, so we handle that
411 // case in the same way.
412 viewport = Rect(w, h);
413 if (R.getOrientation() & Transform::ROT_90) {
414 // viewport is always specified in the logical orientation
415 // of the display (ie: post-rotation).
416 swap(viewport.right, viewport.bottom);
420 dirtyRegion.set(getBounds());
423 float src_width = viewport.width();
424 float src_height = viewport.height();
425 float dst_width = frame.width();
426 float dst_height = frame.height();
427 if (src_width != dst_width || src_height != dst_height) {
428 float sx = dst_width / src_width;
429 float sy = dst_height / src_height;
433 float src_x = viewport.left;
434 float src_y = viewport.top;
435 float dst_x = frame.left;
436 float dst_y = frame.top;
437 TL.set(-src_x, -src_y);
438 TP.set(dst_x, dst_y);
440 // The viewport and frame are both in the logical orientation.
441 // Apply the logical translation, scale to physical size, apply the
442 // physical translation and finally rotate to the physical orientation.
443 mGlobalTransform = R * TP * S * TL;
445 const uint8_t type = mGlobalTransform.getType();
446 mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
447 (type >= Transform::SCALE));
449 mScissor = mGlobalTransform.transform(viewport);
450 if (mScissor.isEmpty()) {
451 mScissor = getBounds();
454 mOrientation = orientation;
455 mViewport = viewport;
459 void DisplayDevice::dump(String8& result) const {
460 const Transform& tr(mGlobalTransform);
462 "+ DisplayDevice: %s\n"
463 " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
464 "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
465 " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
466 "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
467 mDisplayName.string(), mType, mHwcDisplayId,
468 mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
469 mOrientation, tr.getType(), getPageFlipCount(),
470 mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
471 mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
472 mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
473 mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
474 tr[0][0], tr[1][0], tr[2][0],
475 tr[0][1], tr[1][1], tr[2][1],
476 tr[0][2], tr[1][2], tr[2][2]);
479 mDisplaySurface->dump(surfaceDump);
480 result.append(surfaceDump);