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 // #define LOG_NDEBUG 0
18 #undef LOG_TAG
19 #define LOG_TAG "DisplayDevice"
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25
26 #include <cutils/properties.h>
27
28 #include <utils/RefBase.h>
29 #include <utils/Log.h>
30
31 #include <ui/DisplayInfo.h>
32 #include <ui/PixelFormat.h>
33
34 #include <gui/Surface.h>
35
36 #include <hardware/gralloc.h>
37
38 #include "DisplayHardware/DisplaySurface.h"
39 #include "DisplayHardware/HWComposer.h"
40 #ifdef USE_HWC2
41 #include "DisplayHardware/HWC2.h"
42 #endif
43 #include "RenderEngine/RenderEngine.h"
44
45 #include "clz.h"
46 #include "DisplayDevice.h"
47 #include "SurfaceFlinger.h"
48 #include "Layer.h"
49
50 // ----------------------------------------------------------------------------
51 using namespace android;
52 // ----------------------------------------------------------------------------
53
54 #ifdef EGL_ANDROID_swap_rectangle
55 static constexpr bool kEGLAndroidSwapRectangle = true;
56 #else
57 static constexpr bool kEGLAndroidSwapRectangle = false;
58 #endif
59
60 #if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
61 // Dummy implementation in case it is missing.
eglSetSwapRectangleANDROID(EGLDisplay,EGLSurface,EGLint,EGLint,EGLint,EGLint)62 inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
63 }
64 #endif
65
66 /*
67 * Initialize the display to the specified values.
68 *
69 */
70
71 uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
72
DisplayDevice(const sp<SurfaceFlinger> & flinger,DisplayType type,int32_t hwcId,int format,bool isSecure,const wp<IBinder> & displayToken,const sp<DisplaySurface> & displaySurface,const sp<IGraphicBufferProducer> & producer,EGLConfig config)73 DisplayDevice::DisplayDevice(
74 const sp<SurfaceFlinger>& flinger,
75 DisplayType type,
76 int32_t hwcId,
77 #ifndef USE_HWC2
78 int format,
79 #endif
80 bool isSecure,
81 const wp<IBinder>& displayToken,
82 const sp<DisplaySurface>& displaySurface,
83 const sp<IGraphicBufferProducer>& producer,
84 EGLConfig config)
85 : lastCompositionHadVisibleLayers(false),
86 mFlinger(flinger),
87 mType(type),
88 mHwcDisplayId(hwcId),
89 mDisplayToken(displayToken),
90 mDisplaySurface(displaySurface),
91 mDisplay(EGL_NO_DISPLAY),
92 mSurface(EGL_NO_SURFACE),
93 mDisplayWidth(),
94 mDisplayHeight(),
95 #ifndef USE_HWC2
96 mFormat(),
97 #endif
98 mFlags(),
99 mPageFlipCount(),
100 mIsSecure(isSecure),
101 mLayerStack(NO_LAYER_STACK),
102 mOrientation(),
103 mPowerMode(HWC_POWER_MODE_OFF),
104 mActiveConfig(0)
105 {
106 Surface* surface;
107 mNativeWindow = surface = new Surface(producer, false);
108 ANativeWindow* const window = mNativeWindow.get();
109
110 /*
111 * Create our display's surface
112 */
113
114 EGLSurface eglSurface;
115 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
116 if (config == EGL_NO_CONFIG) {
117 #ifdef USE_HWC2
118 config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
119 #else
120 config = RenderEngine::chooseEglConfig(display, format);
121 #endif
122 }
123 eglSurface = eglCreateWindowSurface(display, config, window, NULL);
124 eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth);
125 eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
126
127 // Make sure that composition can never be stalled by a virtual display
128 // consumer that isn't processing buffers fast enough. We have to do this
129 // in two places:
130 // * Here, in case the display is composed entirely by HWC.
131 // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
132 // window's swap interval in eglMakeCurrent, so they'll override the
133 // interval we set here.
134 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
135 window->setSwapInterval(window, 0);
136
137 mConfig = config;
138 mDisplay = display;
139 mSurface = eglSurface;
140 #ifndef USE_HWC2
141 mFormat = format;
142 #endif
143 mPageFlipCount = 0;
144 mViewport.makeInvalid();
145 mFrame.makeInvalid();
146
147 // virtual displays are always considered enabled
148 mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
149 HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
150
151 // Name the display. The name will be replaced shortly if the display
152 // was created with createDisplay().
153 switch (mType) {
154 case DISPLAY_PRIMARY:
155 mDisplayName = "Built-in Screen";
156 break;
157 case DISPLAY_EXTERNAL:
158 mDisplayName = "HDMI Screen";
159 break;
160 default:
161 mDisplayName = "Virtual Screen"; // e.g. Overlay #n
162 break;
163 }
164
165 // initialize the display orientation transform.
166 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
167
168 #ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
169 surface->allocateBuffers();
170 #endif
171 }
172
~DisplayDevice()173 DisplayDevice::~DisplayDevice() {
174 if (mSurface != EGL_NO_SURFACE) {
175 eglDestroySurface(mDisplay, mSurface);
176 mSurface = EGL_NO_SURFACE;
177 }
178 }
179
disconnect(HWComposer & hwc)180 void DisplayDevice::disconnect(HWComposer& hwc) {
181 if (mHwcDisplayId >= 0) {
182 hwc.disconnectDisplay(mHwcDisplayId);
183 #ifndef USE_HWC2
184 if (mHwcDisplayId >= DISPLAY_VIRTUAL)
185 hwc.freeDisplayId(mHwcDisplayId);
186 #endif
187 mHwcDisplayId = -1;
188 }
189 }
190
isValid() const191 bool DisplayDevice::isValid() const {
192 return mFlinger != NULL;
193 }
194
getWidth() const195 int DisplayDevice::getWidth() const {
196 return mDisplayWidth;
197 }
198
getHeight() const199 int DisplayDevice::getHeight() const {
200 return mDisplayHeight;
201 }
202
203 #ifndef USE_HWC2
getFormat() const204 PixelFormat DisplayDevice::getFormat() const {
205 return mFormat;
206 }
207 #endif
208
getEGLSurface() const209 EGLSurface DisplayDevice::getEGLSurface() const {
210 return mSurface;
211 }
212
setDisplayName(const String8 & displayName)213 void DisplayDevice::setDisplayName(const String8& displayName) {
214 if (!displayName.isEmpty()) {
215 // never override the name with an empty name
216 mDisplayName = displayName;
217 }
218 }
219
getPageFlipCount() const220 uint32_t DisplayDevice::getPageFlipCount() const {
221 return mPageFlipCount;
222 }
223
224 #ifndef USE_HWC2
compositionComplete() const225 status_t DisplayDevice::compositionComplete() const {
226 return mDisplaySurface->compositionComplete();
227 }
228 #endif
229
flip(const Region & dirty) const230 void DisplayDevice::flip(const Region& dirty) const
231 {
232 mFlinger->getRenderEngine().checkErrors();
233
234 if (kEGLAndroidSwapRectangle) {
235 if (mFlags & SWAP_RECTANGLE) {
236 const Region newDirty(dirty.intersect(bounds()));
237 const Rect b(newDirty.getBounds());
238 eglSetSwapRectangleANDROID(mDisplay, mSurface,
239 b.left, b.top, b.width(), b.height());
240 }
241 }
242
243 mPageFlipCount++;
244 }
245
beginFrame(bool mustRecompose) const246 status_t DisplayDevice::beginFrame(bool mustRecompose) const {
247 return mDisplaySurface->beginFrame(mustRecompose);
248 }
249
250 #ifdef USE_HWC2
prepareFrame(HWComposer & hwc)251 status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
252 status_t error = hwc.prepare(*this);
253 if (error != NO_ERROR) {
254 return error;
255 }
256
257 DisplaySurface::CompositionType compositionType;
258 bool hasClient = hwc.hasClientComposition(mHwcDisplayId);
259 bool hasDevice = hwc.hasDeviceComposition(mHwcDisplayId);
260 if (hasClient && hasDevice) {
261 compositionType = DisplaySurface::COMPOSITION_MIXED;
262 } else if (hasClient) {
263 compositionType = DisplaySurface::COMPOSITION_GLES;
264 } else if (hasDevice) {
265 compositionType = DisplaySurface::COMPOSITION_HWC;
266 } else {
267 // Nothing to do -- when turning the screen off we get a frame like
268 // this. Call it a HWC frame since we won't be doing any GLES work but
269 // will do a prepare/set cycle.
270 compositionType = DisplaySurface::COMPOSITION_HWC;
271 }
272 return mDisplaySurface->prepareFrame(compositionType);
273 }
274 #else
prepareFrame(const HWComposer & hwc) const275 status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
276 DisplaySurface::CompositionType compositionType;
277 bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
278 bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
279 if (haveGles && haveHwc) {
280 compositionType = DisplaySurface::COMPOSITION_MIXED;
281 } else if (haveGles) {
282 compositionType = DisplaySurface::COMPOSITION_GLES;
283 } else if (haveHwc) {
284 compositionType = DisplaySurface::COMPOSITION_HWC;
285 } else {
286 // Nothing to do -- when turning the screen off we get a frame like
287 // this. Call it a HWC frame since we won't be doing any GLES work but
288 // will do a prepare/set cycle.
289 compositionType = DisplaySurface::COMPOSITION_HWC;
290 }
291 return mDisplaySurface->prepareFrame(compositionType);
292 }
293 #endif
294
swapBuffers(HWComposer & hwc) const295 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
296 #ifdef USE_HWC2
297 if (hwc.hasClientComposition(mHwcDisplayId)) {
298 #else
299 // We need to call eglSwapBuffers() if:
300 // (1) we don't have a hardware composer, or
301 // (2) we did GLES composition this frame, and either
302 // (a) we have framebuffer target support (not present on legacy
303 // devices, where HWComposer::commit() handles things); or
304 // (b) this is a virtual display
305 if (hwc.initCheck() != NO_ERROR ||
306 (hwc.hasGlesComposition(mHwcDisplayId) &&
307 (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
308 #endif
309 EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
310 if (!success) {
311 EGLint error = eglGetError();
312 if (error == EGL_CONTEXT_LOST ||
313 mType == DisplayDevice::DISPLAY_PRIMARY) {
314 LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
315 mDisplay, mSurface, error);
316 } else {
317 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
318 mDisplay, mSurface, error);
319 }
320 }
321 }
322
323 status_t result = mDisplaySurface->advanceFrame();
324 if (result != NO_ERROR) {
325 ALOGE("[%s] failed pushing new frame to HWC: %d",
326 mDisplayName.string(), result);
327 }
328 }
329
330 #ifdef USE_HWC2
331 void DisplayDevice::onSwapBuffersCompleted() const {
332 mDisplaySurface->onFrameCommitted();
333 }
334 #else
335 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
336 if (hwc.initCheck() == NO_ERROR) {
337 mDisplaySurface->onFrameCommitted();
338 }
339 }
340 #endif
341
342 uint32_t DisplayDevice::getFlags() const
343 {
344 return mFlags;
345 }
346
347 EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
348 EGLBoolean result = EGL_TRUE;
349 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
350 if (sur != mSurface) {
351 result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
352 if (result == EGL_TRUE) {
353 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
354 eglSwapInterval(dpy, 0);
355 }
356 }
357 setViewportAndProjection();
358 return result;
359 }
360
361 void DisplayDevice::setViewportAndProjection() const {
362 size_t w = mDisplayWidth;
363 size_t h = mDisplayHeight;
364 Rect sourceCrop(0, 0, w, h);
365 mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h,
366 false, Transform::ROT_0);
367 }
368
369 const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
370 return mDisplaySurface->getClientTargetAcquireFence();
371 }
372
373 // ----------------------------------------------------------------------------
374
375 void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
376 mVisibleLayersSortedByZ = layers;
377 }
378
379 const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
380 return mVisibleLayersSortedByZ;
381 }
382
383 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
384 Region dirty;
385 if (repaintEverything) {
386 dirty.set(getBounds());
387 } else {
388 const Transform& planeTransform(mGlobalTransform);
389 dirty = planeTransform.transform(this->dirtyRegion);
390 dirty.andSelf(getBounds());
391 }
392 return dirty;
393 }
394
395 // ----------------------------------------------------------------------------
396 void DisplayDevice::setPowerMode(int mode) {
397 mPowerMode = mode;
398 }
399
400 int DisplayDevice::getPowerMode() const {
401 return mPowerMode;
402 }
403
404 bool DisplayDevice::isDisplayOn() const {
405 return (mPowerMode != HWC_POWER_MODE_OFF);
406 }
407
408 // ----------------------------------------------------------------------------
409 void DisplayDevice::setActiveConfig(int mode) {
410 mActiveConfig = mode;
411 }
412
413 int DisplayDevice::getActiveConfig() const {
414 return mActiveConfig;
415 }
416
417 // ----------------------------------------------------------------------------
418
419 void DisplayDevice::setLayerStack(uint32_t stack) {
420 mLayerStack = stack;
421 dirtyRegion.set(bounds());
422 }
423
424 // ----------------------------------------------------------------------------
425
426 uint32_t DisplayDevice::getOrientationTransform() const {
427 uint32_t transform = 0;
428 switch (mOrientation) {
429 case DisplayState::eOrientationDefault:
430 transform = Transform::ROT_0;
431 break;
432 case DisplayState::eOrientation90:
433 transform = Transform::ROT_90;
434 break;
435 case DisplayState::eOrientation180:
436 transform = Transform::ROT_180;
437 break;
438 case DisplayState::eOrientation270:
439 transform = Transform::ROT_270;
440 break;
441 }
442 return transform;
443 }
444
445 status_t DisplayDevice::orientationToTransfrom(
446 int orientation, int w, int h, Transform* tr)
447 {
448 uint32_t flags = 0;
449 switch (orientation) {
450 case DisplayState::eOrientationDefault:
451 flags = Transform::ROT_0;
452 break;
453 case DisplayState::eOrientation90:
454 flags = Transform::ROT_90;
455 break;
456 case DisplayState::eOrientation180:
457 flags = Transform::ROT_180;
458 break;
459 case DisplayState::eOrientation270:
460 flags = Transform::ROT_270;
461 break;
462 default:
463 return BAD_VALUE;
464 }
465 tr->set(flags, w, h);
466 return NO_ERROR;
467 }
468
469 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
470 dirtyRegion.set(getBounds());
471
472 if (mSurface != EGL_NO_SURFACE) {
473 eglDestroySurface(mDisplay, mSurface);
474 mSurface = EGL_NO_SURFACE;
475 }
476
477 mDisplaySurface->resizeBuffers(newWidth, newHeight);
478
479 ANativeWindow* const window = mNativeWindow.get();
480 mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL);
481 eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mDisplayWidth);
482 eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight);
483
484 LOG_FATAL_IF(mDisplayWidth != newWidth,
485 "Unable to set new width to %d", newWidth);
486 LOG_FATAL_IF(mDisplayHeight != newHeight,
487 "Unable to set new height to %d", newHeight);
488 }
489
490 void DisplayDevice::setProjection(int orientation,
491 const Rect& newViewport, const Rect& newFrame) {
492 Rect viewport(newViewport);
493 Rect frame(newFrame);
494
495 const int w = mDisplayWidth;
496 const int h = mDisplayHeight;
497
498 Transform R;
499 DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
500
501 if (!frame.isValid()) {
502 // the destination frame can be invalid if it has never been set,
503 // in that case we assume the whole display frame.
504 frame = Rect(w, h);
505 }
506
507 if (viewport.isEmpty()) {
508 // viewport can be invalid if it has never been set, in that case
509 // we assume the whole display size.
510 // it's also invalid to have an empty viewport, so we handle that
511 // case in the same way.
512 viewport = Rect(w, h);
513 if (R.getOrientation() & Transform::ROT_90) {
514 // viewport is always specified in the logical orientation
515 // of the display (ie: post-rotation).
516 swap(viewport.right, viewport.bottom);
517 }
518 }
519
520 dirtyRegion.set(getBounds());
521
522 Transform TL, TP, S;
523 float src_width = viewport.width();
524 float src_height = viewport.height();
525 float dst_width = frame.width();
526 float dst_height = frame.height();
527 if (src_width != dst_width || src_height != dst_height) {
528 float sx = dst_width / src_width;
529 float sy = dst_height / src_height;
530 S.set(sx, 0, 0, sy);
531 }
532
533 float src_x = viewport.left;
534 float src_y = viewport.top;
535 float dst_x = frame.left;
536 float dst_y = frame.top;
537 TL.set(-src_x, -src_y);
538 TP.set(dst_x, dst_y);
539
540 // The viewport and frame are both in the logical orientation.
541 // Apply the logical translation, scale to physical size, apply the
542 // physical translation and finally rotate to the physical orientation.
543 mGlobalTransform = R * TP * S * TL;
544
545 const uint8_t type = mGlobalTransform.getType();
546 mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
547 (type >= Transform::SCALE));
548
549 mScissor = mGlobalTransform.transform(viewport);
550 if (mScissor.isEmpty()) {
551 mScissor = getBounds();
552 }
553
554 mOrientation = orientation;
555 if (mType == DisplayType::DISPLAY_PRIMARY) {
556 uint32_t transform = 0;
557 switch (mOrientation) {
558 case DisplayState::eOrientationDefault:
559 transform = Transform::ROT_0;
560 break;
561 case DisplayState::eOrientation90:
562 transform = Transform::ROT_90;
563 break;
564 case DisplayState::eOrientation180:
565 transform = Transform::ROT_180;
566 break;
567 case DisplayState::eOrientation270:
568 transform = Transform::ROT_270;
569 break;
570 }
571 sPrimaryDisplayOrientation = transform;
572 }
573 mViewport = viewport;
574 mFrame = frame;
575 }
576
577 uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() {
578 return sPrimaryDisplayOrientation;
579 }
580
581 void DisplayDevice::dump(String8& result) const {
582 const Transform& tr(mGlobalTransform);
583 result.appendFormat(
584 "+ DisplayDevice: %s\n"
585 " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
586 "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
587 " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
588 "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
589 mDisplayName.string(), mType, mHwcDisplayId,
590 mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
591 mOrientation, tr.getType(), getPageFlipCount(),
592 mIsSecure, mPowerMode, mActiveConfig,
593 mVisibleLayersSortedByZ.size(),
594 mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
595 mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
596 mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
597 tr[0][0], tr[1][0], tr[2][0],
598 tr[0][1], tr[1][1], tr[2][1],
599 tr[0][2], tr[1][2], tr[2][2]);
600
601 String8 surfaceDump;
602 mDisplaySurface->dumpAsString(surfaceDump);
603 result.append(surfaceDump);
604 }
605