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>
34 #include <EGL/eglext.h>
36 #include <hardware/gralloc.h>
38 #include "DisplayHardware/DisplaySurface.h"
39 #include "DisplayHardware/HWComposer.h"
42 #include "DisplayDevice.h"
43 #include "GLExtensions.h"
44 #include "SurfaceFlinger.h"
47 // ----------------------------------------------------------------------------
48 using namespace android;
49 // ----------------------------------------------------------------------------
51 static __attribute__((noinline))
55 // there could be more than one error flag
56 GLenum error = glGetError();
57 if (error == GL_NO_ERROR)
59 ALOGE("GL error 0x%04x", int(error));
63 // ----------------------------------------------------------------------------
66 * Initialize the display to the specified values.
70 DisplayDevice::DisplayDevice(
71 const sp<SurfaceFlinger>& flinger,
75 const wp<IBinder>& displayToken,
76 const sp<DisplaySurface>& displaySurface,
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(),
89 mSecureLayerVisible(false),
90 mScreenAcquired(false),
91 mLayerStack(NO_LAYER_STACK),
94 mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
95 ANativeWindow* const window = mNativeWindow.get();
98 window->query(window, NATIVE_WINDOW_FORMAT, &format);
101 * Create our display's surface
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);
115 mViewport.makeInvalid();
116 mFrame.makeInvalid();
118 // virtual displays are always considered enabled
119 mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
121 // Name the display. The name will be replaced shortly if the display
122 // was created with createDisplay().
124 case DISPLAY_PRIMARY:
125 mDisplayName = "Built-in Screen";
127 case DISPLAY_EXTERNAL:
128 mDisplayName = "HDMI Screen";
131 mDisplayName = "Virtual Screen"; // e.g. Overlay #n
135 // initialize the display orientation transform.
136 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
139 DisplayDevice::~DisplayDevice() {
140 if (mSurface != EGL_NO_SURFACE) {
141 eglDestroySurface(mDisplay, mSurface);
142 mSurface = EGL_NO_SURFACE;
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
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 void 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);
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);
216 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
217 mDisplay, mSurface, error);
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);
229 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
230 if (hwc.initCheck() == NO_ERROR) {
231 mDisplaySurface->onFrameCommitted();
235 uint32_t DisplayDevice::getFlags() const
240 EGLBoolean 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);
253 void 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);
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);
264 // ----------------------------------------------------------------------------
266 void 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;
278 const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
279 return mVisibleLayersSortedByZ;
282 bool DisplayDevice::getSecureLayerVisible() const {
283 return mSecureLayerVisible;
286 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
288 if (repaintEverything) {
289 dirty.set(getBounds());
291 const Transform& planeTransform(mGlobalTransform);
292 dirty = planeTransform.transform(this->dirtyRegion);
293 dirty.andSelf(getBounds());
298 // ----------------------------------------------------------------------------
300 bool DisplayDevice::canDraw() const {
301 return mScreenAcquired;
304 void DisplayDevice::releaseScreen() const {
305 mScreenAcquired = false;
308 void DisplayDevice::acquireScreen() const {
309 mScreenAcquired = true;
312 bool DisplayDevice::isScreenAcquired() const {
313 return mScreenAcquired;
316 // ----------------------------------------------------------------------------
318 void DisplayDevice::setLayerStack(uint32_t stack) {
320 dirtyRegion.set(bounds());
323 // ----------------------------------------------------------------------------
325 status_t DisplayDevice::orientationToTransfrom(
326 int orientation, int w, int h, Transform* tr)
329 switch (orientation) {
330 case DisplayState::eOrientationDefault:
331 flags = Transform::ROT_0;
333 case DisplayState::eOrientation90:
334 flags = Transform::ROT_90;
336 case DisplayState::eOrientation180:
337 flags = Transform::ROT_180;
339 case DisplayState::eOrientation270:
340 flags = Transform::ROT_270;
345 tr->set(flags, w, h);
349 void DisplayDevice::setProjection(int orientation,
350 const Rect& newViewport, const Rect& newFrame) {
351 Rect viewport(newViewport);
352 Rect frame(newFrame);
354 const int w = mDisplayWidth;
355 const int h = mDisplayHeight;
358 DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
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.
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);
379 dirtyRegion.set(getBounds());
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;
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);
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;
404 const uint8_t type = mGlobalTransform.getType();
405 mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
406 (type >= Transform::SCALE));
408 mScissor = mGlobalTransform.transform(viewport);
409 if (mScissor.isEmpty()) {
410 mScissor.set(getBounds());
413 mOrientation = orientation;
414 mViewport = viewport;
418 void 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]);
437 result.append(buffer);
440 mDisplaySurface->dump(surfaceDump);
441 result.append(surfaceDump);