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/SurfaceTextureClient.h>
34 #include <EGL/eglext.h>
36 #include <hardware/gralloc.h>
38 #include "DisplayHardware/FramebufferSurface.h"
39 #include "DisplayHardware/HWComposer.h"
42 #include "DisplayDevice.h"
43 #include "GLExtensions.h"
44 #include "SurfaceFlinger.h"
45 #include "LayerBase.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,
72 DisplayType type, const wp<IBinder>& displayToken,
73 const sp<ANativeWindow>& nativeWindow,
74 const sp<FramebufferSurface>& framebufferSurface,
77 mType(type), mHwcDisplayId(-1),
78 mNativeWindow(nativeWindow),
79 mFramebufferSurface(framebufferSurface),
80 mDisplay(EGL_NO_DISPLAY),
81 mSurface(EGL_NO_SURFACE),
82 mContext(EGL_NO_CONTEXT),
83 mDisplayWidth(), mDisplayHeight(), mFormat(),
86 mSecureLayerVisible(false),
87 mScreenAcquired(false),
94 DisplayDevice::~DisplayDevice() {
95 if (mSurface != EGL_NO_SURFACE) {
96 eglDestroySurface(mDisplay, mSurface);
97 mSurface = EGL_NO_SURFACE;
101 bool DisplayDevice::isValid() const {
102 return mFlinger != NULL;
105 int DisplayDevice::getWidth() const {
106 return mDisplayWidth;
109 int DisplayDevice::getHeight() const {
110 return mDisplayHeight;
113 PixelFormat DisplayDevice::getFormat() const {
117 EGLSurface DisplayDevice::getEGLSurface() const {
121 void DisplayDevice::init(EGLConfig config)
123 ANativeWindow* const window = mNativeWindow.get();
126 window->query(window, NATIVE_WINDOW_FORMAT, &format);
129 * Create our display's surface
134 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
135 surface = eglCreateWindowSurface(display, config, window, NULL);
136 eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
137 eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
143 mViewport.makeInvalid();
144 mFrame.makeInvalid();
146 // external displays are always considered enabled
147 mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
149 // get an h/w composer ID
150 mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
152 // initialize the display orientation transform.
153 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
156 uint32_t DisplayDevice::getPageFlipCount() const {
157 return mPageFlipCount;
160 status_t DisplayDevice::compositionComplete() const {
161 if (mFramebufferSurface == NULL) {
164 return mFramebufferSurface->compositionComplete();
167 void DisplayDevice::flip(const Region& dirty) const
171 EGLDisplay dpy = mDisplay;
172 EGLSurface surface = mSurface;
174 #ifdef EGL_ANDROID_swap_rectangle
175 if (mFlags & SWAP_RECTANGLE) {
176 const Region newDirty(dirty.intersect(bounds()));
177 const Rect b(newDirty.getBounds());
178 eglSetSwapRectangleANDROID(dpy, surface,
179 b.left, b.top, b.width(), b.height());
186 uint32_t DisplayDevice::getFlags() const
191 void DisplayDevice::dump(String8& res) const
193 if (mFramebufferSurface != NULL) {
194 mFramebufferSurface->dump(res);
198 EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
199 const sp<const DisplayDevice>& hw, EGLContext ctx) {
200 EGLBoolean result = EGL_TRUE;
201 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
202 if (sur != hw->mSurface) {
203 result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
204 if (result == EGL_TRUE) {
205 GLsizei w = hw->mDisplayWidth;
206 GLsizei h = hw->mDisplayHeight;
207 glViewport(0, 0, w, h);
208 glMatrixMode(GL_PROJECTION);
210 // put the origin in the left-bottom corner
211 glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
217 // ----------------------------------------------------------------------------
219 void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
220 mVisibleLayersSortedByZ = layers;
221 mSecureLayerVisible = false;
222 size_t count = layers.size();
223 for (size_t i=0 ; i<count ; i++) {
224 if (layers[i]->isSecure()) {
225 mSecureLayerVisible = true;
230 const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const {
231 return mVisibleLayersSortedByZ;
234 bool DisplayDevice::getSecureLayerVisible() const {
235 return mSecureLayerVisible;
238 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
240 if (repaintEverything) {
241 dirty.set(getBounds());
243 const Transform& planeTransform(mGlobalTransform);
244 dirty = planeTransform.transform(this->dirtyRegion);
245 dirty.andSelf(getBounds());
250 // ----------------------------------------------------------------------------
252 bool DisplayDevice::canDraw() const {
253 return mScreenAcquired;
256 void DisplayDevice::releaseScreen() const {
257 mScreenAcquired = false;
260 void DisplayDevice::acquireScreen() const {
261 mScreenAcquired = true;
264 bool DisplayDevice::isScreenAcquired() const {
265 return mScreenAcquired;
268 // ----------------------------------------------------------------------------
270 void DisplayDevice::setLayerStack(uint32_t stack) {
272 dirtyRegion.set(bounds());
275 // ----------------------------------------------------------------------------
277 status_t DisplayDevice::orientationToTransfrom(
278 int orientation, int w, int h, Transform* tr)
281 switch (orientation) {
282 case DisplayState::eOrientationDefault:
283 flags = Transform::ROT_0;
285 case DisplayState::eOrientation90:
286 flags = Transform::ROT_90;
288 case DisplayState::eOrientation180:
289 flags = Transform::ROT_180;
291 case DisplayState::eOrientation270:
292 flags = Transform::ROT_270;
297 tr->set(flags, w, h);
301 void DisplayDevice::setProjection(int orientation,
302 const Rect& viewport, const Rect& frame) {
303 mOrientation = orientation;
304 mViewport = viewport;
306 updateGeometryTransform();
309 void DisplayDevice::updateGeometryTransform() {
310 int w = mDisplayWidth;
311 int h = mDisplayHeight;
313 if (DisplayDevice::orientationToTransfrom(
314 mOrientation, w, h, &R) == NO_ERROR) {
315 dirtyRegion.set(bounds());
317 Rect viewport(mViewport);
320 if (!frame.isValid()) {
321 // the destination frame can be invalid if it has never been set,
322 // in that case we assume the whole display frame.
326 if (viewport.isEmpty()) {
327 // viewport can be invalid if it has never been set, in that case
328 // we assume the whole display size.
329 // it's also invalid to have an empty viewport, so we handle that
330 // case in the same way.
331 viewport = Rect(w, h);
332 if (R.getOrientation() & Transform::ROT_90) {
333 // viewport is always specified in the logical orientation
334 // of the display (ie: post-rotation).
335 swap(viewport.right, viewport.bottom);
339 float src_width = viewport.width();
340 float src_height = viewport.height();
341 float dst_width = frame.width();
342 float dst_height = frame.height();
343 if (src_width != src_height || dst_width != dst_height) {
344 float sx = dst_width / src_width;
345 float sy = dst_height / src_height;
348 float src_x = viewport.left;
349 float src_y = viewport.top;
350 float dst_x = frame.left;
351 float dst_y = frame.top;
352 float tx = dst_x - src_x;
353 float ty = dst_y - src_y;
356 // rotate first, followed by scaling
357 mGlobalTransform = S * R;