OSDN Git Service

display projection API now has a single function instead of 3
[android-x86/frameworks-native.git] / services / surfaceflinger / DisplayDevice.cpp
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 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <math.h>
21
22 #include <cutils/properties.h>
23
24 #include <utils/RefBase.h>
25 #include <utils/Log.h>
26
27 #include <ui/DisplayInfo.h>
28 #include <ui/PixelFormat.h>
29
30 #include <gui/SurfaceTextureClient.h>
31
32 #include <GLES/gl.h>
33 #include <EGL/egl.h>
34 #include <EGL/eglext.h>
35
36 #include <hardware/gralloc.h>
37
38 #include "DisplayHardware/FramebufferSurface.h"
39 #include "DisplayHardware/HWComposer.h"
40
41 #include "clz.h"
42 #include "DisplayDevice.h"
43 #include "GLExtensions.h"
44 #include "SurfaceFlinger.h"
45 #include "LayerBase.h"
46
47 // ----------------------------------------------------------------------------
48 using namespace android;
49 // ----------------------------------------------------------------------------
50
51 static __attribute__((noinline))
52 void checkGLErrors()
53 {
54     do {
55         // there could be more than one error flag
56         GLenum error = glGetError();
57         if (error == GL_NO_ERROR)
58             break;
59         ALOGE("GL error 0x%04x", int(error));
60     } while(true);
61 }
62
63 // ----------------------------------------------------------------------------
64
65 /*
66  * Initialize the display to the specified values.
67  *
68  */
69
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,
75         EGLConfig config)
76     : mFlinger(flinger),
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(),
84       mFlags(),
85       mPageFlipCount(),
86       mSecureLayerVisible(false),
87       mScreenAcquired(false),
88       mLayerStack(0),
89       mOrientation()
90 {
91     init(config);
92 }
93
94 DisplayDevice::~DisplayDevice() {
95     if (mSurface != EGL_NO_SURFACE) {
96         eglDestroySurface(mDisplay, mSurface);
97         mSurface = EGL_NO_SURFACE;
98     }
99 }
100
101 bool DisplayDevice::isValid() const {
102     return mFlinger != NULL;
103 }
104
105 int DisplayDevice::getWidth() const {
106     return mDisplayWidth;
107 }
108
109 int DisplayDevice::getHeight() const {
110     return mDisplayHeight;
111 }
112
113 PixelFormat DisplayDevice::getFormat() const {
114     return mFormat;
115 }
116
117 EGLSurface DisplayDevice::getEGLSurface() const {
118     return mSurface;
119 }
120
121 void DisplayDevice::init(EGLConfig config)
122 {
123     ANativeWindow* const window = mNativeWindow.get();
124
125     int format;
126     window->query(window, NATIVE_WINDOW_FORMAT, &format);
127
128     /*
129      * Create our display's surface
130      */
131
132     EGLSurface surface;
133     EGLint w, h;
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);
138
139     mDisplay = display;
140     mSurface = surface;
141     mFormat  = format;
142     mPageFlipCount = 0;
143     mViewport.makeInvalid();
144     mFrame.makeInvalid();
145
146     // external displays are always considered enabled
147     mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
148
149     // get an h/w composer ID
150     mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
151
152     // initialize the display orientation transform.
153     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
154 }
155
156 uint32_t DisplayDevice::getPageFlipCount() const {
157     return mPageFlipCount;
158 }
159
160 status_t DisplayDevice::compositionComplete() const {
161     if (mFramebufferSurface == NULL) {
162         return NO_ERROR;
163     }
164     return mFramebufferSurface->compositionComplete();
165 }
166
167 void DisplayDevice::flip(const Region& dirty) const
168 {
169     checkGLErrors();
170
171     EGLDisplay dpy = mDisplay;
172     EGLSurface surface = mSurface;
173
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());
180     } 
181 #endif
182     
183     mPageFlipCount++;
184 }
185
186 uint32_t DisplayDevice::getFlags() const
187 {
188     return mFlags;
189 }
190
191 void DisplayDevice::dump(String8& res) const
192 {
193     if (mFramebufferSurface != NULL) {
194         mFramebufferSurface->dump(res);
195     }
196 }
197
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);
209             glLoadIdentity();
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
212         }
213     }
214     return result;
215 }
216
217 // ----------------------------------------------------------------------------
218
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;
226         }
227     }
228 }
229
230 const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const {
231     return mVisibleLayersSortedByZ;
232 }
233
234 bool DisplayDevice::getSecureLayerVisible() const {
235     return mSecureLayerVisible;
236 }
237
238 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
239     Region dirty;
240     if (repaintEverything) {
241         dirty.set(getBounds());
242     } else {
243         const Transform& planeTransform(mGlobalTransform);
244         dirty = planeTransform.transform(this->dirtyRegion);
245         dirty.andSelf(getBounds());
246     }
247     return dirty;
248 }
249
250 // ----------------------------------------------------------------------------
251
252 bool DisplayDevice::canDraw() const {
253     return mScreenAcquired;
254 }
255
256 void DisplayDevice::releaseScreen() const {
257     mScreenAcquired = false;
258 }
259
260 void DisplayDevice::acquireScreen() const {
261     mScreenAcquired = true;
262 }
263
264 bool DisplayDevice::isScreenAcquired() const {
265     return mScreenAcquired;
266 }
267
268 // ----------------------------------------------------------------------------
269
270 void DisplayDevice::setLayerStack(uint32_t stack) {
271     mLayerStack = stack;
272     dirtyRegion.set(bounds());
273 }
274
275 // ----------------------------------------------------------------------------
276
277 status_t DisplayDevice::orientationToTransfrom(
278         int orientation, int w, int h, Transform* tr)
279 {
280     uint32_t flags = 0;
281     switch (orientation) {
282     case DisplayState::eOrientationDefault:
283         flags = Transform::ROT_0;
284         break;
285     case DisplayState::eOrientation90:
286         flags = Transform::ROT_90;
287         break;
288     case DisplayState::eOrientation180:
289         flags = Transform::ROT_180;
290         break;
291     case DisplayState::eOrientation270:
292         flags = Transform::ROT_270;
293         break;
294     default:
295         return BAD_VALUE;
296     }
297     tr->set(flags, w, h);
298     return NO_ERROR;
299 }
300
301 void DisplayDevice::setProjection(int orientation,
302         const Rect& viewport, const Rect& frame) {
303     mOrientation = orientation;
304     mViewport = viewport;
305     mFrame = frame;
306     updateGeometryTransform();
307 }
308
309 void DisplayDevice::updateGeometryTransform() {
310     int w = mDisplayWidth;
311     int h = mDisplayHeight;
312     Transform R, S;
313     if (DisplayDevice::orientationToTransfrom(
314             mOrientation, w, h, &R) == NO_ERROR) {
315         dirtyRegion.set(bounds());
316
317         Rect viewport(mViewport);
318         Rect frame(mFrame);
319
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.
323             frame = Rect(w, h);
324         }
325
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);
336             }
337         }
338
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;
346             S.set(sx, 0, 0, sy);
347         }
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;
354         S.set(tx, ty);
355
356         // rotate first, followed by scaling
357         mGlobalTransform = S * R;
358     }
359 }