blob: 082effe699f749f8d3a0e708c503fb4ac2391af6 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <stdlib.h>
18#include <stdio.h>
19#include <stdint.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <math.h>
Jean-Baptiste Querua837ba72009-01-26 11:51:12 -080024#include <limits.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/ioctl.h>
28
29#include <cutils/log.h>
30#include <cutils/properties.h>
31
Mathias Agopianc5b2c0b2009-05-19 19:08:10 -070032#include <binder/IPCThreadState.h>
33#include <binder/IServiceManager.h>
Mathias Agopian7303c6b2009-07-02 18:11:53 -070034#include <binder/MemoryHeapBase.h>
Mathias Agopian99b49842011-06-27 16:05:52 -070035#include <binder/PermissionCache.h>
Mathias Agopian7303c6b2009-07-02 18:11:53 -070036
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037#include <utils/String8.h>
38#include <utils/String16.h>
39#include <utils/StopWatch.h>
40
Mathias Agopian3330b202009-10-05 17:07:12 -070041#include <ui/GraphicBufferAllocator.h>
Mathias Agopian35b48d12010-09-13 22:57:58 -070042#include <ui/GraphicLog.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080043#include <ui/PixelFormat.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044
45#include <pixelflinger/pixelflinger.h>
46#include <GLES/gl.h>
47
48#include "clz.h"
Mathias Agopian1f7bec62010-06-25 18:02:21 -070049#include "GLExtensions.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080051#include "LayerDim.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080052#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080053
54#include "DisplayHardware/DisplayHardware.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070055#include "DisplayHardware/HWComposer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080056
Mathias Agopiana67932f2011-04-20 14:20:59 -070057#include <private/surfaceflinger/SharedBufferStack.h>
58
Mathias Agopiana1ecca92009-05-21 19:21:59 -070059/* ideally AID_GRAPHICS would be in a semi-public header
60 * or there would be a way to map a user/group name to its id
61 */
62#ifndef AID_GRAPHICS
63#define AID_GRAPHICS 1003
64#endif
65
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080066#define DISPLAY_COUNT 1
67
68namespace android {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080069// ---------------------------------------------------------------------------
70
Mathias Agopian99b49842011-06-27 16:05:52 -070071const String16 sHardwareTest("android.permission.HARDWARE_TEST");
72const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
73const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
74const String16 sDump("android.permission.DUMP");
75
76// ---------------------------------------------------------------------------
77
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080078SurfaceFlinger::SurfaceFlinger()
79 : BnSurfaceComposer(), Thread(false),
80 mTransactionFlags(0),
Mathias Agopiancbb288b2009-09-07 16:32:45 -070081 mResizeTransationPending(false),
Mathias Agopian076b1cc2009-04-10 14:24:30 -070082 mLayersRemoved(false),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080083 mBootTime(systemTime()),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080084 mVisibleRegionsDirty(false),
Mathias Agopiana350ff92010-08-10 17:14:02 -070085 mHwWorkListDirty(false),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080086 mDeferReleaseConsole(false),
87 mFreezeDisplay(false),
Mathias Agopianabd671a2010-10-14 14:54:06 -070088 mElectronBeamAnimationMode(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080089 mFreezeCount(0),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -070090 mFreezeDisplayTime(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080091 mDebugRegion(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080092 mDebugBackground(0),
Mathias Agopian73d3ba92010-09-22 18:58:01 -070093 mDebugDisableHWC(0),
Mathias Agopian9795c422009-08-26 16:36:26 -070094 mDebugInSwapBuffers(0),
95 mLastSwapBufferTime(0),
96 mDebugInTransaction(0),
97 mLastTransactionTime(0),
Mathias Agopian3330b202009-10-05 17:07:12 -070098 mBootFinished(false),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080099 mConsoleSignals(0),
100 mSecureFrameBuffer(0)
101{
102 init();
103}
104
105void SurfaceFlinger::init()
106{
107 LOGI("SurfaceFlinger is starting");
108
109 // debugging stuff...
110 char value[PROPERTY_VALUE_MAX];
111 property_get("debug.sf.showupdates", value, "0");
112 mDebugRegion = atoi(value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800113 property_get("debug.sf.showbackground", value, "0");
114 mDebugBackground = atoi(value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800115
Mathias Agopian78fd5012010-04-20 14:51:04 -0700116 LOGI_IF(mDebugRegion, "showupdates enabled");
117 LOGI_IF(mDebugBackground, "showbackground enabled");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800118}
119
120SurfaceFlinger::~SurfaceFlinger()
121{
122 glDeleteTextures(1, &mWormholeTexName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800123}
124
Mathias Agopian7303c6b2009-07-02 18:11:53 -0700125sp<IMemoryHeap> SurfaceFlinger::getCblk() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800126{
Mathias Agopian7303c6b2009-07-02 18:11:53 -0700127 return mServerHeap;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800128}
129
Mathias Agopian7e27f052010-05-28 14:22:23 -0700130sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800131{
Mathias Agopian96f08192010-06-02 23:28:45 -0700132 sp<ISurfaceComposerClient> bclient;
133 sp<Client> client(new Client(this));
134 status_t err = client->initCheck();
135 if (err == NO_ERROR) {
136 bclient = client;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800138 return bclient;
139}
140
Jamie Gennis9a78c902011-01-12 18:30:40 -0800141sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
142{
143 sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
144 return gba;
145}
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700146
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800147const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
148{
149 LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
150 const GraphicPlane& plane(mGraphicPlanes[dpy]);
151 return plane;
152}
153
154GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
155{
156 return const_cast<GraphicPlane&>(
157 const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
158}
159
160void SurfaceFlinger::bootFinished()
161{
162 const nsecs_t now = systemTime();
163 const nsecs_t duration = now - mBootTime;
Andreas Huber8b42e8a2010-08-16 08:49:37 -0700164 LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
Mathias Agopian3330b202009-10-05 17:07:12 -0700165 mBootFinished = true;
Mathias Agopian1f339ff2011-07-01 17:08:43 -0700166
167 // wait patiently for the window manager death
168 const String16 name("window");
169 sp<IBinder> window(defaultServiceManager()->getService(name));
170 if (window != 0) {
171 window->linkToDeath(this);
172 }
173
174 // stop boot animation
Mathias Agopiana1ecca92009-05-21 19:21:59 -0700175 property_set("ctl.stop", "bootanim");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176}
177
Mathias Agopian1f339ff2011-07-01 17:08:43 -0700178void SurfaceFlinger::binderDied(const wp<IBinder>& who)
179{
180 // the window manager died on us. prepare its eulogy.
181
182 // unfreeze the screen in case it was... frozen
183 mFreezeDisplayTime = 0;
184 mFreezeCount = 0;
185 mFreezeDisplay = false;
186
187 // reset screen orientation
188 setOrientation(0, eOrientationDefault, 0);
189
190 // restart the boot-animation
191 property_set("ctl.start", "bootanim");
192}
193
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194void SurfaceFlinger::onFirstRef()
195{
196 run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
197
198 // Wait for the main thread to be done with its initialization
199 mReadyToRunBarrier.wait();
200}
201
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800202static inline uint16_t pack565(int r, int g, int b) {
203 return (r<<11)|(g<<5)|b;
204}
205
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800206status_t SurfaceFlinger::readyToRun()
207{
208 LOGI( "SurfaceFlinger's main thread ready to run. "
209 "Initializing graphics H/W...");
210
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800211 // we only support one display currently
212 int dpy = 0;
213
214 {
215 // initialize the main display
216 GraphicPlane& plane(graphicPlane(dpy));
217 DisplayHardware* const hw = new DisplayHardware(this, dpy);
218 plane.setDisplayHardware(hw);
219 }
220
Mathias Agopian7303c6b2009-07-02 18:11:53 -0700221 // create the shared control-block
222 mServerHeap = new MemoryHeapBase(4096,
223 MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
224 LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
Andreas Huber8b42e8a2010-08-16 08:49:37 -0700225
Mathias Agopian7303c6b2009-07-02 18:11:53 -0700226 mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
227 LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
Andreas Huber8b42e8a2010-08-16 08:49:37 -0700228
Mathias Agopian7303c6b2009-07-02 18:11:53 -0700229 new(mServerCblk) surface_flinger_cblk_t;
230
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800231 // initialize primary screen
232 // (other display should be initialized in the same manner, but
233 // asynchronously, as they could come and go. None of this is supported
234 // yet).
235 const GraphicPlane& plane(graphicPlane(dpy));
236 const DisplayHardware& hw = plane.displayHardware();
237 const uint32_t w = hw.getWidth();
238 const uint32_t h = hw.getHeight();
239 const uint32_t f = hw.getFormat();
240 hw.makeCurrent();
241
242 // initialize the shared control block
243 mServerCblk->connected |= 1<<dpy;
244 display_cblk_t* dcblk = mServerCblk->displays + dpy;
245 memset(dcblk, 0, sizeof(display_cblk_t));
Mathias Agopian2b92d892010-02-08 15:49:35 -0800246 dcblk->w = plane.getWidth();
247 dcblk->h = plane.getHeight();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800248 dcblk->format = f;
249 dcblk->orientation = ISurfaceComposer::eOrientationDefault;
250 dcblk->xdpi = hw.getDpiX();
251 dcblk->ydpi = hw.getDpiY();
252 dcblk->fps = hw.getRefreshRate();
253 dcblk->density = hw.getDensity();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800254
255 // Initialize OpenGL|ES
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800256 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
Andreas Huber8b42e8a2010-08-16 08:49:37 -0700257 glPixelStorei(GL_PACK_ALIGNMENT, 4);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800258 glEnableClientState(GL_VERTEX_ARRAY);
259 glEnable(GL_SCISSOR_TEST);
260 glShadeModel(GL_FLAT);
261 glDisable(GL_DITHER);
262 glDisable(GL_CULL_FACE);
263
264 const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
265 const uint16_t g1 = pack565(0x17,0x2f,0x17);
266 const uint16_t textureData[4] = { g0, g1, g1, g0 };
267 glGenTextures(1, &mWormholeTexName);
268 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
269 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
270 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
271 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
272 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
273 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
274 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);
275
276 glViewport(0, 0, w, h);
277 glMatrixMode(GL_PROJECTION);
278 glLoadIdentity();
Mathias Agopianffcf4652011-07-07 17:30:31 -0700279 // put the origin in the left-bottom corner
280 glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800281
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800282 mReadyToRunBarrier.open();
283
284 /*
285 * We're now ready to accept clients...
286 */
287
Mathias Agopiana1ecca92009-05-21 19:21:59 -0700288 // start boot animation
289 property_set("ctl.start", "bootanim");
Andreas Huber8b42e8a2010-08-16 08:49:37 -0700290
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800291 return NO_ERROR;
292}
293
294// ----------------------------------------------------------------------------
295#if 0
296#pragma mark -
297#pragma mark Events Handler
298#endif
299
300void SurfaceFlinger::waitForEvent()
301{
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700302 while (true) {
303 nsecs_t timeout = -1;
Mathias Agopian04087722009-12-01 17:23:28 -0800304 const nsecs_t freezeDisplayTimeout = ms2ns(5000);
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700305 if (UNLIKELY(isFrozen())) {
306 // wait 5 seconds
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700307 const nsecs_t now = systemTime();
308 if (mFreezeDisplayTime == 0) {
309 mFreezeDisplayTime = now;
310 }
311 nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
312 timeout = waitTime>0 ? waitTime : 0;
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700313 }
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700314
Mathias Agopianbb641242010-05-18 17:06:55 -0700315 sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
Mathias Agopian04087722009-12-01 17:23:28 -0800316
317 // see if we timed out
318 if (isFrozen()) {
319 const nsecs_t now = systemTime();
320 nsecs_t frozenTime = (now - mFreezeDisplayTime);
321 if (frozenTime >= freezeDisplayTimeout) {
322 // we timed out and are still frozen
323 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
324 mFreezeDisplay, mFreezeCount);
325 mFreezeDisplayTime = 0;
326 mFreezeCount = 0;
327 mFreezeDisplay = false;
328 }
329 }
330
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700331 if (msg != 0) {
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700332 switch (msg->what) {
333 case MessageQueue::INVALIDATE:
334 // invalidate message, just return to the main loop
335 return;
336 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800337 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800338 }
339}
340
341void SurfaceFlinger::signalEvent() {
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700342 mEventQueue.invalidate();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800343}
344
Jamie Gennis134f0422011-03-08 12:18:54 -0800345bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const {
346 Mutex::Autolock _l(mStateLock);
347 sp<IBinder> surfBinder(surface->asBinder());
348
349 // Check the visible layer list for the ISurface
350 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
351 size_t count = currentLayers.size();
352 for (size_t i=0 ; i<count ; i++) {
353 const sp<LayerBase>& layer(currentLayers[i]);
354 sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
355 if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) {
356 return true;
357 }
358 }
359
360 // Check the layers in the purgatory. This check is here so that if a
361 // Surface gets destroyed before all the clients are done using it, the
362 // error will not be reported as "surface XYZ is not authenticated", but
363 // will instead fail later on when the client tries to use the surface,
364 // which should be reported as "surface XYZ returned an -ENODEV". The
365 // purgatorized layers are no less authentic than the visible ones, so this
366 // should not cause any harm.
367 size_t purgatorySize = mLayerPurgatory.size();
368 for (size_t i=0 ; i<purgatorySize ; i++) {
369 const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
370 sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
371 if (lbc != NULL && lbc->getSurfaceBinder() == surfBinder) {
372 return true;
373 }
374 }
375
376 return false;
377}
378
Mathias Agopianbb641242010-05-18 17:06:55 -0700379status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
380 nsecs_t reltime, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800381{
Mathias Agopianbb641242010-05-18 17:06:55 -0700382 return mEventQueue.postMessage(msg, reltime, flags);
383}
384
385status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
386 nsecs_t reltime, uint32_t flags)
387{
388 status_t res = mEventQueue.postMessage(msg, reltime, flags);
389 if (res == NO_ERROR) {
390 msg->wait();
391 }
392 return res;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800393}
394
395// ----------------------------------------------------------------------------
396#if 0
397#pragma mark -
398#pragma mark Main loop
399#endif
400
401bool SurfaceFlinger::threadLoop()
402{
403 waitForEvent();
404
405 // check for transactions
406 if (UNLIKELY(mConsoleSignals)) {
407 handleConsoleEvents();
408 }
409
Mathias Agopian698c0872011-06-28 19:09:31 -0700410 // if we're in a global transaction, don't do anything.
411 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
412 uint32_t transactionFlags = peekTransactionFlags(mask);
413 if (UNLIKELY(transactionFlags)) {
414 handleTransaction(transactionFlags);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800415 }
416
417 // post surfaces (if needed)
418 handlePageFlip();
419
Mathias Agopiana350ff92010-08-10 17:14:02 -0700420 if (UNLIKELY(mHwWorkListDirty)) {
421 // build the h/w work list
422 handleWorkList();
423 }
424
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800425 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopian8a77baa2009-09-27 22:47:27 -0700426 if (LIKELY(hw.canDraw() && !isFrozen())) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800427 // repaint the framebuffer (if needed)
Mathias Agopian35b48d12010-09-13 22:57:58 -0700428
429 const int index = hw.getCurrentBufferIndex();
430 GraphicLog& logger(GraphicLog::getInstance());
431
432 logger.log(GraphicLog::SF_REPAINT, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800433 handleRepaint();
434
Mathias Agopian74faca22009-09-17 16:18:16 -0700435 // inform the h/w that we're done compositing
Mathias Agopian35b48d12010-09-13 22:57:58 -0700436 logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index);
Mathias Agopian74faca22009-09-17 16:18:16 -0700437 hw.compositionComplete();
438
Mathias Agopian35b48d12010-09-13 22:57:58 -0700439 logger.log(GraphicLog::SF_SWAP_BUFFERS, index);
Antti Hatala8392b502010-09-08 06:37:14 -0700440 postFramebuffer();
441
Mathias Agopian35b48d12010-09-13 22:57:58 -0700442 logger.log(GraphicLog::SF_REPAINT_DONE, index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800443 } else {
444 // pretend we did the post
Mathias Agopiane6f09842010-12-15 14:41:59 -0800445 hw.compositionComplete();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800446 usleep(16667); // 60 fps period
447 }
448 return true;
449}
450
451void SurfaceFlinger::postFramebuffer()
452{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800453 if (!mInvalidRegion.isEmpty()) {
454 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopian9795c422009-08-26 16:36:26 -0700455 const nsecs_t now = systemTime();
456 mDebugInSwapBuffers = now;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800457 hw.flip(mInvalidRegion);
Mathias Agopian9795c422009-08-26 16:36:26 -0700458 mLastSwapBufferTime = systemTime() - now;
459 mDebugInSwapBuffers = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800460 mInvalidRegion.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461 }
462}
463
464void SurfaceFlinger::handleConsoleEvents()
465{
466 // something to do with the console
467 const DisplayHardware& hw = graphicPlane(0).displayHardware();
468
469 int what = android_atomic_and(0, &mConsoleSignals);
470 if (what & eConsoleAcquired) {
471 hw.acquireScreen();
Mathias Agopian9daa5c92010-10-12 16:05:48 -0700472 // this is a temporary work-around, eventually this should be called
473 // by the power-manager
Mathias Agopianabd671a2010-10-14 14:54:06 -0700474 SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800475 }
476
Mathias Agopian59119e62010-10-11 12:37:43 -0700477 if (mDeferReleaseConsole && hw.isScreenAcquired()) {
Mathias Agopian62b74442009-04-14 23:02:51 -0700478 // We got the release signal before the acquire signal
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800479 mDeferReleaseConsole = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800480 hw.releaseScreen();
481 }
482
483 if (what & eConsoleReleased) {
Mathias Agopian59119e62010-10-11 12:37:43 -0700484 if (hw.isScreenAcquired()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800485 hw.releaseScreen();
486 } else {
487 mDeferReleaseConsole = true;
488 }
489 }
490
491 mDirtyRegion.set(hw.bounds());
492}
493
494void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
495{
Mathias Agopianca4d3602011-05-19 15:38:14 -0700496 Mutex::Autolock _l(mStateLock);
497 const nsecs_t now = systemTime();
498 mDebugInTransaction = now;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800499
Mathias Agopianca4d3602011-05-19 15:38:14 -0700500 // Here we're guaranteed that some transaction flags are set
501 // so we can call handleTransactionLocked() unconditionally.
502 // We call getTransactionFlags(), which will also clear the flags,
503 // with mStateLock held to guarantee that mCurrentState won't change
504 // until the transaction is committed.
Mathias Agopian4da75192010-08-10 17:19:56 -0700505
Mathias Agopianca4d3602011-05-19 15:38:14 -0700506 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
507 transactionFlags = getTransactionFlags(mask);
508 handleTransactionLocked(transactionFlags);
Mathias Agopiandea20b12011-05-03 17:04:02 -0700509
Mathias Agopianca4d3602011-05-19 15:38:14 -0700510 mLastTransactionTime = systemTime() - now;
511 mDebugInTransaction = 0;
512 invalidateHwcGeometry();
513 // here the transaction has been committed
Mathias Agopian3d579642009-06-04 18:46:21 -0700514}
515
Mathias Agopianca4d3602011-05-19 15:38:14 -0700516void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
Mathias Agopian3d579642009-06-04 18:46:21 -0700517{
518 const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800519 const size_t count = currentLayers.size();
520
521 /*
522 * Traversal of the children
523 * (perform the transaction for each of them if needed)
524 */
525
526 const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
527 if (layersNeedTransaction) {
528 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700529 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800530 uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
531 if (!trFlags) continue;
532
533 const uint32_t flags = layer->doTransaction(0);
534 if (flags & Layer::eVisibleRegion)
535 mVisibleRegionsDirty = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800536 }
537 }
538
539 /*
540 * Perform our own transaction if needed
541 */
542
543 if (transactionFlags & eTransactionNeeded) {
544 if (mCurrentState.orientation != mDrawingState.orientation) {
545 // the orientation has changed, recompute all visible regions
546 // and invalidate everything.
547
548 const int dpy = 0;
549 const int orientation = mCurrentState.orientation;
Mathias Agopianc08731e2009-03-27 18:11:38 -0700550 const uint32_t type = mCurrentState.orientationType;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800551 GraphicPlane& plane(graphicPlane(dpy));
552 plane.setOrientation(orientation);
553
554 // update the shared control block
555 const DisplayHardware& hw(plane.displayHardware());
556 volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
557 dcblk->orientation = orientation;
Mathias Agopian2b92d892010-02-08 15:49:35 -0800558 dcblk->w = plane.getWidth();
559 dcblk->h = plane.getHeight();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800560
561 mVisibleRegionsDirty = true;
562 mDirtyRegion.set(hw.bounds());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800563 }
564
565 if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
566 // freezing or unfreezing the display -> trigger animation if needed
567 mFreezeDisplay = mCurrentState.freezeDisplay;
Mathias Agopian064e1e62010-03-01 17:51:17 -0800568 if (mFreezeDisplay)
569 mFreezeDisplayTime = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800570 }
571
Mathias Agopian0aa758d2009-04-22 15:23:34 -0700572 if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
573 // layers have been added
574 mVisibleRegionsDirty = true;
575 }
576
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800577 // some layers might have been removed, so
578 // we need to update the regions they're exposing.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700579 if (mLayersRemoved) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700580 mLayersRemoved = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800581 mVisibleRegionsDirty = true;
Mathias Agopian0aa758d2009-04-22 15:23:34 -0700582 const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
Mathias Agopian3d579642009-06-04 18:46:21 -0700583 const size_t count = previousLayers.size();
584 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian0aa758d2009-04-22 15:23:34 -0700585 const sp<LayerBase>& layer(previousLayers[i]);
586 if (currentLayers.indexOf( layer ) < 0) {
587 // this layer is not visible anymore
Mathias Agopian5d7126b2009-07-28 14:20:21 -0700588 mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
Mathias Agopian0aa758d2009-04-22 15:23:34 -0700589 }
590 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800591 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800592 }
593
594 commitTransaction();
595}
596
597sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
598{
599 return new FreezeLock(const_cast<SurfaceFlinger *>(this));
600}
601
602void SurfaceFlinger::computeVisibleRegions(
Mathias Agopian1bbafb92011-03-11 16:54:47 -0800603 const LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800604{
605 const GraphicPlane& plane(graphicPlane(0));
606 const Transform& planeTransform(plane.transform());
Mathias Agopianab028732010-03-16 16:41:46 -0700607 const DisplayHardware& hw(plane.displayHardware());
608 const Region screenRegion(hw.bounds());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800609
610 Region aboveOpaqueLayers;
611 Region aboveCoveredLayers;
612 Region dirty;
613
614 bool secureFrameBuffer = false;
615
616 size_t i = currentLayers.size();
617 while (i--) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700618 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800619 layer->validateVisibility(planeTransform);
620
621 // start with the whole surface at its current location
Mathias Agopian97011222009-07-28 10:57:27 -0700622 const Layer::State& s(layer->drawingState());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800623
Mathias Agopianab028732010-03-16 16:41:46 -0700624 /*
625 * opaqueRegion: area of a surface that is fully opaque.
626 */
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800627 Region opaqueRegion;
Mathias Agopianab028732010-03-16 16:41:46 -0700628
629 /*
630 * visibleRegion: area of a surface that is visible on screen
631 * and not fully transparent. This is essentially the layer's
632 * footprint minus the opaque regions above it.
633 * Areas covered by a translucent surface are considered visible.
634 */
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800635 Region visibleRegion;
Mathias Agopianab028732010-03-16 16:41:46 -0700636
637 /*
638 * coveredRegion: area of a surface that is covered by all
639 * visible regions above it (which includes the translucent areas).
640 */
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800641 Region coveredRegion;
Mathias Agopianab028732010-03-16 16:41:46 -0700642
643
644 // handle hidden surfaces by setting the visible region to empty
Mathias Agopian97011222009-07-28 10:57:27 -0700645 if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700646 const bool translucent = !layer->isOpaque();
Mathias Agopian97011222009-07-28 10:57:27 -0700647 const Rect bounds(layer->visibleBounds());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800648 visibleRegion.set(bounds);
Mathias Agopianab028732010-03-16 16:41:46 -0700649 visibleRegion.andSelf(screenRegion);
650 if (!visibleRegion.isEmpty()) {
651 // Remove the transparent area from the visible region
652 if (translucent) {
653 visibleRegion.subtractSelf(layer->transparentRegionScreen);
654 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800655
Mathias Agopianab028732010-03-16 16:41:46 -0700656 // compute the opaque region
657 const int32_t layerOrientation = layer->getOrientation();
658 if (s.alpha==255 && !translucent &&
659 ((layerOrientation & Transform::ROT_INVALID) == false)) {
660 // the opaque region is the layer's footprint
661 opaqueRegion = visibleRegion;
662 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800663 }
664 }
665
Mathias Agopianab028732010-03-16 16:41:46 -0700666 // Clip the covered region to the visible region
667 coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
668
669 // Update aboveCoveredLayers for next (lower) layer
670 aboveCoveredLayers.orSelf(visibleRegion);
671
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800672 // subtract the opaque region covered by the layers above us
673 visibleRegion.subtractSelf(aboveOpaqueLayers);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800674
675 // compute this layer's dirty region
676 if (layer->contentDirty) {
677 // we need to invalidate the whole region
678 dirty = visibleRegion;
679 // as well, as the old visible region
680 dirty.orSelf(layer->visibleRegionScreen);
681 layer->contentDirty = false;
682 } else {
Mathias Agopiana8d44f72009-06-28 02:54:16 -0700683 /* compute the exposed region:
Mathias Agopianab028732010-03-16 16:41:46 -0700684 * the exposed region consists of two components:
685 * 1) what's VISIBLE now and was COVERED before
686 * 2) what's EXPOSED now less what was EXPOSED before
687 *
688 * note that (1) is conservative, we start with the whole
689 * visible region but only keep what used to be covered by
690 * something -- which mean it may have been exposed.
691 *
692 * (2) handles areas that were not covered by anything but got
693 * exposed because of a resize.
Mathias Agopiana8d44f72009-06-28 02:54:16 -0700694 */
Mathias Agopianab028732010-03-16 16:41:46 -0700695 const Region newExposed = visibleRegion - coveredRegion;
696 const Region oldVisibleRegion = layer->visibleRegionScreen;
697 const Region oldCoveredRegion = layer->coveredRegionScreen;
698 const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
699 dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800700 }
701 dirty.subtractSelf(aboveOpaqueLayers);
702
703 // accumulate to the screen dirty region
704 dirtyRegion.orSelf(dirty);
705
Mathias Agopianab028732010-03-16 16:41:46 -0700706 // Update aboveOpaqueLayers for next (lower) layer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800707 aboveOpaqueLayers.orSelf(opaqueRegion);
Andreas Huber8b42e8a2010-08-16 08:49:37 -0700708
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800709 // Store the visible region is screen space
710 layer->setVisibleRegion(visibleRegion);
711 layer->setCoveredRegion(coveredRegion);
712
Mathias Agopian97011222009-07-28 10:57:27 -0700713 // If a secure layer is partially visible, lock-down the screen!
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800714 if (layer->isSecure() && !visibleRegion.isEmpty()) {
715 secureFrameBuffer = true;
716 }
717 }
718
Mathias Agopian97011222009-07-28 10:57:27 -0700719 // invalidate the areas where a layer was removed
720 dirtyRegion.orSelf(mDirtyRegionRemovedLayer);
721 mDirtyRegionRemovedLayer.clear();
722
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800723 mSecureFrameBuffer = secureFrameBuffer;
724 opaqueRegion = aboveOpaqueLayers;
725}
726
727
728void SurfaceFlinger::commitTransaction()
729{
730 mDrawingState = mCurrentState;
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700731 mResizeTransationPending = false;
732 mTransactionCV.broadcast();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800733}
734
735void SurfaceFlinger::handlePageFlip()
736{
737 bool visibleRegions = mVisibleRegionsDirty;
Mathias Agopian1bbafb92011-03-11 16:54:47 -0800738 const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800739 visibleRegions |= lockPageFlip(currentLayers);
740
741 const DisplayHardware& hw = graphicPlane(0).displayHardware();
742 const Region screenRegion(hw.bounds());
743 if (visibleRegions) {
744 Region opaqueRegion;
745 computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
Mathias Agopian4da75192010-08-10 17:19:56 -0700746
747 /*
748 * rebuild the visible layer list
749 */
Mathias Agopian1bbafb92011-03-11 16:54:47 -0800750 const size_t count = currentLayers.size();
Mathias Agopian4da75192010-08-10 17:19:56 -0700751 mVisibleLayersSortedByZ.clear();
Mathias Agopian4da75192010-08-10 17:19:56 -0700752 mVisibleLayersSortedByZ.setCapacity(count);
753 for (size_t i=0 ; i<count ; i++) {
754 if (!currentLayers[i]->visibleRegionScreen.isEmpty())
755 mVisibleLayersSortedByZ.add(currentLayers[i]);
756 }
757
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800758 mWormholeRegion = screenRegion.subtract(opaqueRegion);
759 mVisibleRegionsDirty = false;
Mathias Agopianad456f92011-01-13 17:53:01 -0800760 invalidateHwcGeometry();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800761 }
762
763 unlockPageFlip(currentLayers);
764 mDirtyRegion.andSelf(screenRegion);
765}
766
Mathias Agopianad456f92011-01-13 17:53:01 -0800767void SurfaceFlinger::invalidateHwcGeometry()
768{
769 mHwWorkListDirty = true;
770}
771
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800772bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
773{
774 bool recomputeVisibleRegions = false;
775 size_t count = currentLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700776 sp<LayerBase> const* layers = currentLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800777 for (size_t i=0 ; i<count ; i++) {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700778 const sp<LayerBase>& layer(layers[i]);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800779 layer->lockPageFlip(recomputeVisibleRegions);
780 }
781 return recomputeVisibleRegions;
782}
783
784void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
785{
786 const GraphicPlane& plane(graphicPlane(0));
787 const Transform& planeTransform(plane.transform());
788 size_t count = currentLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700789 sp<LayerBase> const* layers = currentLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800790 for (size_t i=0 ; i<count ; i++) {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700791 const sp<LayerBase>& layer(layers[i]);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800792 layer->unlockPageFlip(planeTransform, mDirtyRegion);
793 }
794}
795
Mathias Agopiana350ff92010-08-10 17:14:02 -0700796void SurfaceFlinger::handleWorkList()
797{
798 mHwWorkListDirty = false;
799 HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
800 if (hwc.initCheck() == NO_ERROR) {
801 const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
802 const size_t count = currentLayers.size();
803 hwc.createWorkList(count);
Mathias Agopian45721772010-08-12 15:03:26 -0700804 hwc_layer_t* const cur(hwc.getLayers());
805 for (size_t i=0 ; cur && i<count ; i++) {
806 currentLayers[i]->setGeometry(&cur[i]);
Mathias Agopian73d3ba92010-09-22 18:58:01 -0700807 if (mDebugDisableHWC) {
808 cur[i].compositionType = HWC_FRAMEBUFFER;
809 cur[i].flags |= HWC_SKIP_LAYER;
810 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700811 }
812 }
813}
Mathias Agopianb8a55602009-06-26 19:06:36 -0700814
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800815void SurfaceFlinger::handleRepaint()
816{
Mathias Agopianb8a55602009-06-26 19:06:36 -0700817 // compute the invalid region
818 mInvalidRegion.orSelf(mDirtyRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800819
820 if (UNLIKELY(mDebugRegion)) {
821 debugFlashRegions();
822 }
823
Mathias Agopianb8a55602009-06-26 19:06:36 -0700824 // set the frame buffer
825 const DisplayHardware& hw(graphicPlane(0).displayHardware());
826 glMatrixMode(GL_MODELVIEW);
827 glLoadIdentity();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800828
829 uint32_t flags = hw.getFlags();
Andreas Huber8b42e8a2010-08-16 08:49:37 -0700830 if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
831 (flags & DisplayHardware::BUFFER_PRESERVED))
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700832 {
Mathias Agopian29d06ac2009-06-29 18:49:56 -0700833 // we can redraw only what's dirty, but since SWAP_RECTANGLE only
834 // takes a rectangle, we must make sure to update that whole
835 // rectangle in that case
836 if (flags & DisplayHardware::SWAP_RECTANGLE) {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700837 // TODO: we really should be able to pass a region to
Mathias Agopian29d06ac2009-06-29 18:49:56 -0700838 // SWAP_RECTANGLE so that we don't have to redraw all this.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800839 mDirtyRegion.set(mInvalidRegion.bounds());
840 } else {
Mathias Agopian29d06ac2009-06-29 18:49:56 -0700841 // in the BUFFER_PRESERVED case, obviously, we can update only
842 // what's needed and nothing more.
843 // NOTE: this is NOT a common case, as preserving the backbuffer
844 // is costly and usually involves copying the whole update back.
845 }
846 } else {
Mathias Agopian95a666b2009-09-24 14:57:26 -0700847 if (flags & DisplayHardware::PARTIAL_UPDATES) {
Mathias Agopian29d06ac2009-06-29 18:49:56 -0700848 // We need to redraw the rectangle that will be updated
849 // (pushed to the framebuffer).
Mathias Agopian95a666b2009-09-24 14:57:26 -0700850 // This is needed because PARTIAL_UPDATES only takes one
Mathias Agopian29d06ac2009-06-29 18:49:56 -0700851 // rectangle instead of a region (see DisplayHardware::flip())
852 mDirtyRegion.set(mInvalidRegion.bounds());
853 } else {
854 // we need to redraw everything (the whole screen)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800855 mDirtyRegion.set(hw.bounds());
856 mInvalidRegion = mDirtyRegion;
857 }
858 }
859
860 // compose all surfaces
861 composeSurfaces(mDirtyRegion);
862
863 // clear the dirty regions
864 mDirtyRegion.clear();
865}
866
867void SurfaceFlinger::composeSurfaces(const Region& dirty)
868{
869 if (UNLIKELY(!mWormholeRegion.isEmpty())) {
870 // should never happen unless the window manager has a bug
871 // draw something...
872 drawWormhole();
873 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700874
875 status_t err = NO_ERROR;
Mathias Agopian4da75192010-08-10 17:19:56 -0700876 const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
Mathias Agopian45721772010-08-12 15:03:26 -0700877 size_t count = layers.size();
Mathias Agopiana350ff92010-08-10 17:14:02 -0700878
879 const DisplayHardware& hw(graphicPlane(0).displayHardware());
880 HWComposer& hwc(hw.getHwComposer());
Mathias Agopian45721772010-08-12 15:03:26 -0700881 hwc_layer_t* const cur(hwc.getLayers());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700882
Mathias Agopian45721772010-08-12 15:03:26 -0700883 LOGE_IF(cur && hwc.getNumLayers() != count,
884 "HAL number of layers (%d) doesn't match surfaceflinger (%d)",
885 hwc.getNumLayers(), count);
886
887 // just to be extra-safe, use the smallest count
Erik Gilling24925bf2010-08-12 23:21:40 -0700888 if (hwc.initCheck() == NO_ERROR) {
889 count = count < hwc.getNumLayers() ? count : hwc.getNumLayers();
890 }
Mathias Agopian45721772010-08-12 15:03:26 -0700891
892 /*
893 * update the per-frame h/w composer data for each layer
894 * and build the transparent region of the FB
895 */
896 Region transparent;
897 if (cur) {
898 for (size_t i=0 ; i<count ; i++) {
899 const sp<LayerBase>& layer(layers[i]);
900 layer->setPerFrameData(&cur[i]);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700901 }
902 err = hwc.prepare();
903 LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
Mathias Agopiana350ff92010-08-10 17:14:02 -0700904
Mathias Agopianf20a3242011-01-19 15:24:23 -0800905 if (err == NO_ERROR) {
906 for (size_t i=0 ; i<count ; i++) {
907 if (cur[i].hints & HWC_HINT_CLEAR_FB) {
908 const sp<LayerBase>& layer(layers[i]);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700909 if (layer->isOpaque()) {
Mathias Agopianf20a3242011-01-19 15:24:23 -0800910 transparent.orSelf(layer->visibleRegionScreen);
911 }
912 }
913 }
914
915 /*
916 * clear the area of the FB that need to be transparent
917 */
918 transparent.andSelf(dirty);
919 if (!transparent.isEmpty()) {
920 glClearColor(0,0,0,0);
921 Region::const_iterator it = transparent.begin();
922 Region::const_iterator const end = transparent.end();
923 const int32_t height = hw.getHeight();
924 while (it != end) {
925 const Rect& r(*it++);
926 const GLint sy = height - (r.top + r.height());
927 glScissor(r.left, sy, r.width(), r.height());
928 glClear(GL_COLOR_BUFFER_BIT);
929 }
930 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700931 }
932 }
Mathias Agopian45721772010-08-12 15:03:26 -0700933
934
935 /*
936 * and then, render the layers targeted at the framebuffer
937 */
938 for (size_t i=0 ; i<count ; i++) {
939 if (cur) {
Antti Hatala586a0de2010-09-09 02:32:30 -0700940 if ((cur[i].compositionType != HWC_FRAMEBUFFER) &&
941 !(cur[i].flags & HWC_SKIP_LAYER)) {
Mathias Agopian45721772010-08-12 15:03:26 -0700942 // skip layers handled by the HAL
943 continue;
944 }
945 }
Mathias Agopian73d3ba92010-09-22 18:58:01 -0700946
Mathias Agopian45721772010-08-12 15:03:26 -0700947 const sp<LayerBase>& layer(layers[i]);
948 const Region clip(dirty.intersect(layer->visibleRegionScreen));
949 if (!clip.isEmpty()) {
950 layer->draw(clip);
951 }
952 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800953}
954
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800955void SurfaceFlinger::debugFlashRegions()
956{
Mathias Agopian0a917752010-06-14 21:20:00 -0700957 const DisplayHardware& hw(graphicPlane(0).displayHardware());
958 const uint32_t flags = hw.getFlags();
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700959
Mathias Agopian0a917752010-06-14 21:20:00 -0700960 if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
961 (flags & DisplayHardware::BUFFER_PRESERVED))) {
962 const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
963 mDirtyRegion.bounds() : hw.bounds());
964 composeSurfaces(repaint);
965 }
966
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800967 glDisable(GL_BLEND);
968 glDisable(GL_DITHER);
969 glDisable(GL_SCISSOR_TEST);
970
Mathias Agopian0926f502009-05-04 14:17:04 -0700971 static int toggle = 0;
972 toggle = 1 - toggle;
973 if (toggle) {
Mathias Agopian0a917752010-06-14 21:20:00 -0700974 glColor4f(1, 0, 1, 1);
Mathias Agopian0926f502009-05-04 14:17:04 -0700975 } else {
Mathias Agopian0a917752010-06-14 21:20:00 -0700976 glColor4f(1, 1, 0, 1);
Mathias Agopian0926f502009-05-04 14:17:04 -0700977 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800978
Mathias Agopian20f68782009-05-11 00:03:41 -0700979 Region::const_iterator it = mDirtyRegion.begin();
980 Region::const_iterator const end = mDirtyRegion.end();
981 while (it != end) {
982 const Rect& r = *it++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800983 GLfloat vertices[][2] = {
984 { r.left, r.top },
985 { r.left, r.bottom },
986 { r.right, r.bottom },
987 { r.right, r.top }
988 };
989 glVertexPointer(2, GL_FLOAT, 0, vertices);
990 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
991 }
Mathias Agopian0a917752010-06-14 21:20:00 -0700992
Mathias Agopianb8a55602009-06-26 19:06:36 -0700993 if (mInvalidRegion.isEmpty()) {
994 mDirtyRegion.dump("mDirtyRegion");
995 mInvalidRegion.dump("mInvalidRegion");
996 }
997 hw.flip(mInvalidRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800998
999 if (mDebugRegion > 1)
Mathias Agopian0a917752010-06-14 21:20:00 -07001000 usleep(mDebugRegion * 1000);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001001
1002 glEnable(GL_SCISSOR_TEST);
1003 //mDirtyRegion.dump("mDirtyRegion");
1004}
1005
1006void SurfaceFlinger::drawWormhole() const
1007{
1008 const Region region(mWormholeRegion.intersect(mDirtyRegion));
1009 if (region.isEmpty())
1010 return;
1011
1012 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1013 const int32_t width = hw.getWidth();
1014 const int32_t height = hw.getHeight();
1015
1016 glDisable(GL_BLEND);
1017 glDisable(GL_DITHER);
1018
1019 if (LIKELY(!mDebugBackground)) {
Mathias Agopian0a917752010-06-14 21:20:00 -07001020 glClearColor(0,0,0,0);
Mathias Agopian20f68782009-05-11 00:03:41 -07001021 Region::const_iterator it = region.begin();
1022 Region::const_iterator const end = region.end();
1023 while (it != end) {
1024 const Rect& r = *it++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001025 const GLint sy = height - (r.top + r.height());
1026 glScissor(r.left, sy, r.width(), r.height());
1027 glClear(GL_COLOR_BUFFER_BIT);
1028 }
1029 } else {
1030 const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
1031 { width, height }, { 0, height } };
1032 const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
1033 glVertexPointer(2, GL_SHORT, 0, vertices);
1034 glTexCoordPointer(2, GL_SHORT, 0, tcoords);
1035 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
Michael I. Gold7f198b62010-09-15 15:46:24 -07001036#if defined(GL_OES_EGL_image_external)
Mathias Agopian1f7bec62010-06-25 18:02:21 -07001037 if (GLExtensions::getInstance().haveTextureExternal()) {
1038 glDisable(GL_TEXTURE_EXTERNAL_OES);
1039 }
Mathias Agopian0a917752010-06-14 21:20:00 -07001040#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001041 glEnable(GL_TEXTURE_2D);
1042 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
1043 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1044 glMatrixMode(GL_TEXTURE);
1045 glLoadIdentity();
1046 glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
Mathias Agopian20f68782009-05-11 00:03:41 -07001047 Region::const_iterator it = region.begin();
1048 Region::const_iterator const end = region.end();
1049 while (it != end) {
1050 const Rect& r = *it++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001051 const GLint sy = height - (r.top + r.height());
1052 glScissor(r.left, sy, r.width(), r.height());
1053 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1054 }
1055 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Mathias Agopiana67932f2011-04-20 14:20:59 -07001056 glDisable(GL_TEXTURE_2D);
Mathias Agopianebeb7092010-12-14 18:38:36 -08001057 glLoadIdentity();
1058 glMatrixMode(GL_MODELVIEW);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001059 }
1060}
1061
1062void SurfaceFlinger::debugShowFPS() const
1063{
1064 static int mFrameCount;
1065 static int mLastFrameCount = 0;
1066 static nsecs_t mLastFpsTime = 0;
1067 static float mFps = 0;
1068 mFrameCount++;
1069 nsecs_t now = systemTime();
1070 nsecs_t diff = now - mLastFpsTime;
1071 if (diff > ms2ns(250)) {
1072 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
1073 mLastFpsTime = now;
1074 mLastFrameCount = mFrameCount;
1075 }
1076 // XXX: mFPS has the value we want
1077 }
1078
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001079status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001080{
1081 Mutex::Autolock _l(mStateLock);
1082 addLayer_l(layer);
1083 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1084 return NO_ERROR;
1085}
1086
Mathias Agopian96f08192010-06-02 23:28:45 -07001087status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
1088{
Mathias Agopianf6679fc2010-08-10 18:09:09 -07001089 ssize_t i = mCurrentState.layersSortedByZ.add(layer);
Mathias Agopian96f08192010-06-02 23:28:45 -07001090 return (i < 0) ? status_t(i) : status_t(NO_ERROR);
1091}
1092
1093ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
1094 const sp<LayerBaseClient>& lbc)
1095{
Mathias Agopian96f08192010-06-02 23:28:45 -07001096 // attach this layer to the client
Mathias Agopian4f113742011-05-03 16:21:41 -07001097 size_t name = client->attachLayer(lbc);
1098
1099 Mutex::Autolock _l(mStateLock);
Mathias Agopian96f08192010-06-02 23:28:45 -07001100
1101 // add this layer to the current state list
1102 addLayer_l(lbc);
1103
Mathias Agopian4f113742011-05-03 16:21:41 -07001104 return ssize_t(name);
Mathias Agopian96f08192010-06-02 23:28:45 -07001105}
1106
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001107status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001108{
1109 Mutex::Autolock _l(mStateLock);
Mathias Agopian3d579642009-06-04 18:46:21 -07001110 status_t err = purgatorizeLayer_l(layer);
1111 if (err == NO_ERROR)
1112 setTransactionFlags(eTransactionNeeded);
1113 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001114}
1115
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001116status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001117{
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001118 sp<LayerBaseClient> lbc(layerBase->getLayerBaseClient());
1119 if (lbc != 0) {
Mathias Agopian0d156122011-01-25 20:17:45 -08001120 mLayerMap.removeItem( lbc->getSurfaceBinder() );
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001121 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001122 ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
1123 if (index >= 0) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001124 mLayersRemoved = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001125 return NO_ERROR;
1126 }
Mathias Agopian3d579642009-06-04 18:46:21 -07001127 return status_t(index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128}
1129
Mathias Agopian9a112062009-04-17 19:36:26 -07001130status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
1131{
Mathias Agopian76cd4dd2011-01-14 17:37:42 -08001132 // First add the layer to the purgatory list, which makes sure it won't
1133 // go away, then remove it from the main list (through a transaction).
Mathias Agopian9a112062009-04-17 19:36:26 -07001134 ssize_t err = removeLayer_l(layerBase);
Mathias Agopian76cd4dd2011-01-14 17:37:42 -08001135 if (err >= 0) {
1136 mLayerPurgatory.add(layerBase);
1137 }
Mathias Agopian8c0a3d72009-09-23 16:44:00 -07001138
Mathias Agopian0b3ad462009-10-02 18:12:30 -07001139 layerBase->onRemoved();
1140
Mathias Agopian3d579642009-06-04 18:46:21 -07001141 // it's possible that we don't find a layer, because it might
1142 // have been destroyed already -- this is not technically an error
Mathias Agopian96f08192010-06-02 23:28:45 -07001143 // from the user because there is a race between Client::destroySurface(),
1144 // ~Client() and ~ISurface().
Mathias Agopian9a112062009-04-17 19:36:26 -07001145 return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
1146}
1147
Mathias Agopian96f08192010-06-02 23:28:45 -07001148status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001149{
Mathias Agopian96f08192010-06-02 23:28:45 -07001150 layer->forceVisibilityTransaction();
1151 setTransactionFlags(eTraversalNeeded);
1152 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001153}
1154
Mathias Agopiandea20b12011-05-03 17:04:02 -07001155uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
1156{
1157 return android_atomic_release_load(&mTransactionFlags);
1158}
1159
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001160uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
1161{
1162 return android_atomic_and(~flags, &mTransactionFlags) & flags;
1163}
1164
Mathias Agopianbb641242010-05-18 17:06:55 -07001165uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001166{
1167 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
1168 if ((old & flags)==0) { // wake the server up
Mathias Agopianbb641242010-05-18 17:06:55 -07001169 signalEvent();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001170 }
1171 return old;
1172}
1173
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001174
Mathias Agopian698c0872011-06-28 19:09:31 -07001175void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state) {
1176 Mutex::Autolock _l(mStateLock);
Mathias Agopiancbb288b2009-09-07 16:32:45 -07001177
Mathias Agopian698c0872011-06-28 19:09:31 -07001178 uint32_t flags = 0;
1179 const size_t count = state.size();
1180 for (size_t i=0 ; i<count ; i++) {
1181 const ComposerState& s(state[i]);
1182 sp<Client> client( static_cast<Client *>(s.client.get()) );
1183 flags |= setClientStateLocked(client, s.state);
1184 }
1185 if (flags) {
1186 setTransactionFlags(flags);
1187 }
1188
1189 signalEvent();
1190
1191 // if there is a transaction with a resize, wait for it to
1192 // take effect before returning.
1193 while (mResizeTransationPending) {
1194 status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
1195 if (CC_UNLIKELY(err != NO_ERROR)) {
1196 // just in case something goes wrong in SF, return to the
1197 // called after a few seconds.
1198 LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
1199 mResizeTransationPending = false;
1200 break;
Mathias Agopiancbb288b2009-09-07 16:32:45 -07001201 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001202 }
1203}
1204
1205status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
1206{
1207 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1208 return BAD_VALUE;
1209
1210 Mutex::Autolock _l(mStateLock);
1211 mCurrentState.freezeDisplay = 1;
1212 setTransactionFlags(eTransactionNeeded);
1213
1214 // flags is intended to communicate some sort of animation behavior
Mathias Agopian62b74442009-04-14 23:02:51 -07001215 // (for instance fading)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001216 return NO_ERROR;
1217}
1218
1219status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
1220{
1221 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1222 return BAD_VALUE;
1223
1224 Mutex::Autolock _l(mStateLock);
1225 mCurrentState.freezeDisplay = 0;
1226 setTransactionFlags(eTransactionNeeded);
1227
1228 // flags is intended to communicate some sort of animation behavior
Mathias Agopian62b74442009-04-14 23:02:51 -07001229 // (for instance fading)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001230 return NO_ERROR;
1231}
1232
Andreas Huber8b42e8a2010-08-16 08:49:37 -07001233int SurfaceFlinger::setOrientation(DisplayID dpy,
Mathias Agopianc08731e2009-03-27 18:11:38 -07001234 int orientation, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001235{
1236 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1237 return BAD_VALUE;
1238
1239 Mutex::Autolock _l(mStateLock);
1240 if (mCurrentState.orientation != orientation) {
1241 if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
Mathias Agopianc08731e2009-03-27 18:11:38 -07001242 mCurrentState.orientationType = flags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001243 mCurrentState.orientation = orientation;
1244 setTransactionFlags(eTransactionNeeded);
1245 mTransactionCV.wait(mStateLock);
1246 } else {
1247 orientation = BAD_VALUE;
1248 }
1249 }
1250 return orientation;
1251}
1252
Mathias Agopian0ef4e152011-04-20 14:19:32 -07001253sp<ISurface> SurfaceFlinger::createSurface(
1254 ISurfaceComposerClient::surface_data_t* params,
1255 const String8& name,
1256 const sp<Client>& client,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001257 DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
1258 uint32_t flags)
1259{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001260 sp<LayerBaseClient> layer;
Mathias Agopiana67932f2011-04-20 14:20:59 -07001261 sp<ISurface> surfaceHandle;
Mathias Agopian6e2d6482009-07-09 18:16:43 -07001262
1263 if (int32_t(w|h) < 0) {
1264 LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
1265 int(w), int(h));
1266 return surfaceHandle;
1267 }
Andreas Huber8b42e8a2010-08-16 08:49:37 -07001268
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001269 //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001270 sp<Layer> normalLayer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001271 switch (flags & eFXSurfaceMask) {
1272 case eFXSurfaceNormal:
Mathias Agopiana5529c82010-12-07 19:38:17 -08001273 normalLayer = createNormalSurface(client, d, w, h, flags, format);
1274 layer = normalLayer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001275 break;
1276 case eFXSurfaceBlur:
Mathias Agopian1293a8e2010-12-08 17:13:19 -08001277 // for now we treat Blur as Dim, until we can implement it
1278 // efficiently.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001279 case eFXSurfaceDim:
Mathias Agopian96f08192010-06-02 23:28:45 -07001280 layer = createDimSurface(client, d, w, h, flags);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001281 break;
1282 }
1283
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001284 if (layer != 0) {
Mathias Agopian96f08192010-06-02 23:28:45 -07001285 layer->initStates(w, h, flags);
Mathias Agopian285dbde2010-03-01 16:09:43 -08001286 layer->setName(name);
Mathias Agopian96f08192010-06-02 23:28:45 -07001287 ssize_t token = addClientLayer(client, layer);
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001288
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001289 surfaceHandle = layer->getSurface();
Andreas Huber8b42e8a2010-08-16 08:49:37 -07001290 if (surfaceHandle != 0) {
Mathias Agopian96f08192010-06-02 23:28:45 -07001291 params->token = token;
Mathias Agopiana67932f2011-04-20 14:20:59 -07001292 params->identity = layer->getIdentity();
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001293 if (normalLayer != 0) {
1294 Mutex::Autolock _l(mStateLock);
Mathias Agopiana67932f2011-04-20 14:20:59 -07001295 mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001296 }
Mathias Agopian1c97d2e2009-08-19 17:46:26 -07001297 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001298
Mathias Agopian96f08192010-06-02 23:28:45 -07001299 setTransactionFlags(eTransactionNeeded);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001300 }
1301
1302 return surfaceHandle;
1303}
1304
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001305sp<Layer> SurfaceFlinger::createNormalSurface(
Mathias Agopianf9d93272009-06-19 17:00:27 -07001306 const sp<Client>& client, DisplayID display,
Mathias Agopian96f08192010-06-02 23:28:45 -07001307 uint32_t w, uint32_t h, uint32_t flags,
Mathias Agopian1c97d2e2009-08-19 17:46:26 -07001308 PixelFormat& format)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001309{
1310 // initialize the surfaces
1311 switch (format) { // TODO: take h/w into account
1312 case PIXEL_FORMAT_TRANSPARENT:
1313 case PIXEL_FORMAT_TRANSLUCENT:
1314 format = PIXEL_FORMAT_RGBA_8888;
1315 break;
1316 case PIXEL_FORMAT_OPAQUE:
Mathias Agopiana8f3e4e2010-06-30 15:43:47 -07001317#ifdef NO_RGBX_8888
1318 format = PIXEL_FORMAT_RGB_565;
1319#else
Mathias Agopian8f105402010-04-05 18:01:24 -07001320 format = PIXEL_FORMAT_RGBX_8888;
Mathias Agopiana8f3e4e2010-06-30 15:43:47 -07001321#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001322 break;
1323 }
1324
Mathias Agopiana8f3e4e2010-06-30 15:43:47 -07001325#ifdef NO_RGBX_8888
1326 if (format == PIXEL_FORMAT_RGBX_8888)
1327 format = PIXEL_FORMAT_RGBA_8888;
1328#endif
1329
Mathias Agopian96f08192010-06-02 23:28:45 -07001330 sp<Layer> layer = new Layer(this, display, client);
Mathias Agopianf9d93272009-06-19 17:00:27 -07001331 status_t err = layer->setBuffers(w, h, format, flags);
Mathias Agopian96f08192010-06-02 23:28:45 -07001332 if (LIKELY(err != NO_ERROR)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001333 LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001334 layer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001335 }
1336 return layer;
1337}
1338
Mathias Agopianb7e930d2010-06-01 15:12:58 -07001339sp<LayerDim> SurfaceFlinger::createDimSurface(
Mathias Agopianf9d93272009-06-19 17:00:27 -07001340 const sp<Client>& client, DisplayID display,
Mathias Agopian96f08192010-06-02 23:28:45 -07001341 uint32_t w, uint32_t h, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001342{
Mathias Agopian96f08192010-06-02 23:28:45 -07001343 sp<LayerDim> layer = new LayerDim(this, display, client);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001344 layer->initStates(w, h, flags);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001345 return layer;
1346}
1347
Mathias Agopian96f08192010-06-02 23:28:45 -07001348status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001349{
Mathias Agopian9a112062009-04-17 19:36:26 -07001350 /*
1351 * called by the window manager, when a surface should be marked for
1352 * destruction.
Andreas Huber8b42e8a2010-08-16 08:49:37 -07001353 *
Mathias Agopian0aa758d2009-04-22 15:23:34 -07001354 * The surface is removed from the current and drawing lists, but placed
1355 * in the purgatory queue, so it's not destroyed right-away (we need
1356 * to wait for all client's references to go away first).
Mathias Agopian9a112062009-04-17 19:36:26 -07001357 */
Mathias Agopian9a112062009-04-17 19:36:26 -07001358
Mathias Agopian48d819a2009-09-10 19:41:18 -07001359 status_t err = NAME_NOT_FOUND;
Mathias Agopian0aa758d2009-04-22 15:23:34 -07001360 Mutex::Autolock _l(mStateLock);
Mathias Agopian96f08192010-06-02 23:28:45 -07001361 sp<LayerBaseClient> layer = client->getLayerUser(sid);
Mathias Agopian48d819a2009-09-10 19:41:18 -07001362 if (layer != 0) {
1363 err = purgatorizeLayer_l(layer);
1364 if (err == NO_ERROR) {
Mathias Agopian48d819a2009-09-10 19:41:18 -07001365 setTransactionFlags(eTransactionNeeded);
1366 }
Mathias Agopian9a112062009-04-17 19:36:26 -07001367 }
1368 return err;
1369}
1370
Mathias Agopianca4d3602011-05-19 15:38:14 -07001371status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer)
Mathias Agopian9a112062009-04-17 19:36:26 -07001372{
Mathias Agopian759fdb22009-07-02 17:33:40 -07001373 // called by ~ISurface() when all references are gone
Mathias Agopianca4d3602011-05-19 15:38:14 -07001374 status_t err = NO_ERROR;
1375 sp<LayerBaseClient> l(layer.promote());
1376 if (l != NULL) {
1377 Mutex::Autolock _l(mStateLock);
1378 err = removeLayer_l(l);
1379 if (err == NAME_NOT_FOUND) {
1380 // The surface wasn't in the current list, which means it was
1381 // removed already, which means it is in the purgatory,
1382 // and need to be removed from there.
1383 ssize_t idx = mLayerPurgatory.remove(l);
1384 LOGE_IF(idx < 0,
1385 "layer=%p is not in the purgatory list", l.get());
Mathias Agopianf1d8e872009-04-20 19:39:12 -07001386 }
Mathias Agopianca4d3602011-05-19 15:38:14 -07001387 LOGE_IF(err<0 && err != NAME_NOT_FOUND,
1388 "error removing layer=%p (%s)", l.get(), strerror(-err));
1389 }
1390 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001391}
1392
Mathias Agopian698c0872011-06-28 19:09:31 -07001393uint32_t SurfaceFlinger::setClientStateLocked(
Mathias Agopian96f08192010-06-02 23:28:45 -07001394 const sp<Client>& client,
Mathias Agopian698c0872011-06-28 19:09:31 -07001395 const layer_state_t& s)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001396{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001397 uint32_t flags = 0;
Mathias Agopian698c0872011-06-28 19:09:31 -07001398 sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
1399 if (layer != 0) {
1400 const uint32_t what = s.what;
1401 if (what & ePositionChanged) {
1402 if (layer->setPosition(s.x, s.y))
1403 flags |= eTraversalNeeded;
1404 }
1405 if (what & eLayerChanged) {
1406 ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
1407 if (layer->setLayer(s.z)) {
1408 mCurrentState.layersSortedByZ.removeAt(idx);
1409 mCurrentState.layersSortedByZ.add(layer);
1410 // we need traversal (state changed)
1411 // AND transaction (list changed)
1412 flags |= eTransactionNeeded|eTraversalNeeded;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001413 }
1414 }
Mathias Agopian698c0872011-06-28 19:09:31 -07001415 if (what & eSizeChanged) {
1416 if (layer->setSize(s.w, s.h)) {
1417 flags |= eTraversalNeeded;
1418 mResizeTransationPending = true;
1419 }
1420 }
1421 if (what & eAlphaChanged) {
1422 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
1423 flags |= eTraversalNeeded;
1424 }
1425 if (what & eMatrixChanged) {
1426 if (layer->setMatrix(s.matrix))
1427 flags |= eTraversalNeeded;
1428 }
1429 if (what & eTransparentRegionChanged) {
1430 if (layer->setTransparentRegionHint(s.transparentRegion))
1431 flags |= eTraversalNeeded;
1432 }
1433 if (what & eVisibilityChanged) {
1434 if (layer->setFlags(s.flags, s.mask))
1435 flags |= eTraversalNeeded;
1436 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001437 }
Mathias Agopian698c0872011-06-28 19:09:31 -07001438 return flags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001439}
1440
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001441void SurfaceFlinger::screenReleased(int dpy)
1442{
1443 // this may be called by a signal handler, we can't do too much in here
1444 android_atomic_or(eConsoleReleased, &mConsoleSignals);
1445 signalEvent();
1446}
1447
1448void SurfaceFlinger::screenAcquired(int dpy)
1449{
1450 // this may be called by a signal handler, we can't do too much in here
1451 android_atomic_or(eConsoleAcquired, &mConsoleSignals);
1452 signalEvent();
1453}
1454
1455status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
1456{
Erik Gilling1d21a9c2010-12-01 16:38:01 -08001457 const size_t SIZE = 4096;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001458 char buffer[SIZE];
1459 String8 result;
Mathias Agopian99b49842011-06-27 16:05:52 -07001460
1461 if (!PermissionCache::checkCallingPermission(sDump)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001462 snprintf(buffer, SIZE, "Permission Denial: "
1463 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1464 IPCThreadState::self()->getCallingPid(),
1465 IPCThreadState::self()->getCallingUid());
1466 result.append(buffer);
1467 } else {
Mathias Agopian9795c422009-08-26 16:36:26 -07001468
1469 // figure out if we're stuck somewhere
1470 const nsecs_t now = systemTime();
1471 const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
1472 const nsecs_t inTransaction(mDebugInTransaction);
1473 nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
1474 nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
1475
1476 // Try to get the main lock, but don't insist if we can't
1477 // (this would indicate SF is stuck, but we want to be able to
1478 // print something in dumpsys).
1479 int retry = 3;
1480 while (mStateLock.tryLock()<0 && --retry>=0) {
1481 usleep(1000000);
1482 }
1483 const bool locked(retry >= 0);
1484 if (!locked) {
Andreas Huber8b42e8a2010-08-16 08:49:37 -07001485 snprintf(buffer, SIZE,
Mathias Agopian9795c422009-08-26 16:36:26 -07001486 "SurfaceFlinger appears to be unresponsive, "
1487 "dumping anyways (no locks held)\n");
1488 result.append(buffer);
1489 }
1490
Mathias Agopian48b888a2011-01-19 16:15:53 -08001491 /*
1492 * Dump the visible layer list
1493 */
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001494 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
1495 const size_t count = currentLayers.size();
Mathias Agopian48b888a2011-01-19 16:15:53 -08001496 snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
1497 result.append(buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001498 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian1b5e1022010-04-20 17:55:49 -07001499 const sp<LayerBase>& layer(currentLayers[i]);
1500 layer->dump(result, buffer, SIZE);
1501 const Layer::State& s(layer->drawingState());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001502 s.transparentRegion.dump(result, "transparentRegion");
1503 layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
1504 layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
1505 }
Mathias Agopian1b5e1022010-04-20 17:55:49 -07001506
Mathias Agopian48b888a2011-01-19 16:15:53 -08001507 /*
1508 * Dump the layers in the purgatory
1509 */
1510
1511 const size_t purgatorySize = mLayerPurgatory.size();
1512 snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
1513 result.append(buffer);
1514 for (size_t i=0 ; i<purgatorySize ; i++) {
1515 const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
1516 layer->shortDump(result, buffer, SIZE);
1517 }
1518
1519 /*
1520 * Dump SurfaceFlinger global state
1521 */
1522
Mathias Agopianad701862011-07-14 18:01:49 -07001523 snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
Mathias Agopian48b888a2011-01-19 16:15:53 -08001524 result.append(buffer);
Mathias Agopianad701862011-07-14 18:01:49 -07001525
1526 const GLExtensions& extensions(GLExtensions::getInstance());
1527 snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
1528 extensions.getVendor(),
1529 extensions.getRenderer(),
1530 extensions.getVersion());
1531 result.append(buffer);
1532 snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
1533 result.append(buffer);
1534
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001535 mWormholeRegion.dump(result, "WormholeRegion");
1536 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1537 snprintf(buffer, SIZE,
1538 " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1539 mFreezeDisplay?"yes":"no", mFreezeCount,
1540 mCurrentState.orientation, hw.canDraw());
1541 result.append(buffer);
Mathias Agopian9795c422009-08-26 16:36:26 -07001542 snprintf(buffer, SIZE,
1543 " last eglSwapBuffers() time: %f us\n"
1544 " last transaction time : %f us\n",
1545 mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0);
1546 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -07001547
Mathias Agopian9795c422009-08-26 16:36:26 -07001548 if (inSwapBuffersDuration || !locked) {
1549 snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
1550 inSwapBuffersDuration/1000.0);
1551 result.append(buffer);
1552 }
Mathias Agopian1b5e1022010-04-20 17:55:49 -07001553
Mathias Agopian9795c422009-08-26 16:36:26 -07001554 if (inTransactionDuration || !locked) {
1555 snprintf(buffer, SIZE, " transaction time: %f us\n",
1556 inTransactionDuration/1000.0);
1557 result.append(buffer);
1558 }
Mathias Agopian1b5e1022010-04-20 17:55:49 -07001559
Mathias Agopian48b888a2011-01-19 16:15:53 -08001560 /*
1561 * Dump HWComposer state
1562 */
Mathias Agopian73d3ba92010-09-22 18:58:01 -07001563 HWComposer& hwc(hw.getHwComposer());
1564 snprintf(buffer, SIZE, " h/w composer %s and %s\n",
1565 hwc.initCheck()==NO_ERROR ? "present" : "not present",
1566 mDebugDisableHWC ? "disabled" : "enabled");
1567 result.append(buffer);
Mathias Agopian83727852010-09-23 18:13:21 -07001568 hwc.dump(result, buffer, SIZE);
Mathias Agopian73d3ba92010-09-22 18:58:01 -07001569
Mathias Agopian48b888a2011-01-19 16:15:53 -08001570 /*
1571 * Dump gralloc state
1572 */
Mathias Agopian3330b202009-10-05 17:07:12 -07001573 const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001574 alloc.dump(result);
Erik Gilling1d21a9c2010-12-01 16:38:01 -08001575 hw.dump(result);
Mathias Agopian9795c422009-08-26 16:36:26 -07001576
1577 if (locked) {
1578 mStateLock.unlock();
1579 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001580 }
1581 write(fd, result.string(), result.size());
1582 return NO_ERROR;
1583}
1584
1585status_t SurfaceFlinger::onTransact(
1586 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1587{
1588 switch (code) {
1589 case CREATE_CONNECTION:
Mathias Agopian698c0872011-06-28 19:09:31 -07001590 case SET_TRANSACTION_STATE:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001591 case SET_ORIENTATION:
1592 case FREEZE_DISPLAY:
1593 case UNFREEZE_DISPLAY:
1594 case BOOT_FINISHED:
Mathias Agopian59119e62010-10-11 12:37:43 -07001595 case TURN_ELECTRON_BEAM_OFF:
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001596 case TURN_ELECTRON_BEAM_ON:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001597 {
1598 // codes that require permission check
1599 IPCThreadState* ipc = IPCThreadState::self();
1600 const int pid = ipc->getCallingPid();
Mathias Agopiana1ecca92009-05-21 19:21:59 -07001601 const int uid = ipc->getCallingUid();
Mathias Agopian99b49842011-06-27 16:05:52 -07001602 if ((uid != AID_GRAPHICS) &&
1603 !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
Mathias Agopian375f5632009-06-15 18:24:59 -07001604 LOGE("Permission Denial: "
1605 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
1606 return PERMISSION_DENIED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001607 }
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07001608 break;
1609 }
1610 case CAPTURE_SCREEN:
1611 {
1612 // codes that require permission check
1613 IPCThreadState* ipc = IPCThreadState::self();
1614 const int pid = ipc->getCallingPid();
1615 const int uid = ipc->getCallingUid();
Mathias Agopian99b49842011-06-27 16:05:52 -07001616 if ((uid != AID_GRAPHICS) &&
1617 !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07001618 LOGE("Permission Denial: "
1619 "can't read framebuffer pid=%d, uid=%d", pid, uid);
1620 return PERMISSION_DENIED;
1621 }
1622 break;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001623 }
1624 }
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07001625
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001626 status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
1627 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
Mathias Agopianb8a55602009-06-26 19:06:36 -07001628 CHECK_INTERFACE(ISurfaceComposer, data, reply);
Mathias Agopian99b49842011-06-27 16:05:52 -07001629 if (UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
Mathias Agopian375f5632009-06-15 18:24:59 -07001630 IPCThreadState* ipc = IPCThreadState::self();
1631 const int pid = ipc->getCallingPid();
1632 const int uid = ipc->getCallingUid();
1633 LOGE("Permission Denial: "
1634 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001635 return PERMISSION_DENIED;
1636 }
1637 int n;
1638 switch (code) {
Mathias Agopian01b76682009-04-16 20:04:08 -07001639 case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
Mathias Agopian35b48d12010-09-13 22:57:58 -07001640 case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001641 return NO_ERROR;
1642 case 1002: // SHOW_UPDATES
1643 n = data.readInt32();
1644 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
1645 return NO_ERROR;
1646 case 1003: // SHOW_BACKGROUND
1647 n = data.readInt32();
1648 mDebugBackground = n ? 1 : 0;
1649 return NO_ERROR;
Mathias Agopian73d3ba92010-09-22 18:58:01 -07001650 case 1008: // toggle use of hw composer
1651 n = data.readInt32();
1652 mDebugDisableHWC = n ? 1 : 0;
Mathias Agopianad456f92011-01-13 17:53:01 -08001653 invalidateHwcGeometry();
Mathias Agopian73d3ba92010-09-22 18:58:01 -07001654 // fall-through...
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001655 case 1004:{ // repaint everything
1656 Mutex::Autolock _l(mStateLock);
1657 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1658 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
1659 signalEvent();
Mathias Agopiancbb288b2009-09-07 16:32:45 -07001660 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001661 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -07001662 case 1005:{ // force transaction
1663 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1664 return NO_ERROR;
1665 }
Mathias Agopian35b48d12010-09-13 22:57:58 -07001666 case 1006:{ // enable/disable GraphicLog
1667 int enabled = data.readInt32();
1668 GraphicLog::getInstance().setEnabled(enabled);
1669 return NO_ERROR;
1670 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001671 case 1007: // set mFreezeCount
1672 mFreezeCount = data.readInt32();
Mathias Agopian04087722009-12-01 17:23:28 -08001673 mFreezeDisplayTime = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001674 return NO_ERROR;
1675 case 1010: // interrogate.
Mathias Agopian01b76682009-04-16 20:04:08 -07001676 reply->writeInt32(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001677 reply->writeInt32(0);
1678 reply->writeInt32(mDebugRegion);
1679 reply->writeInt32(mDebugBackground);
1680 return NO_ERROR;
1681 case 1013: {
1682 Mutex::Autolock _l(mStateLock);
1683 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1684 reply->writeInt32(hw.getPageFlipCount());
1685 }
1686 return NO_ERROR;
1687 }
1688 }
1689 return err;
1690}
1691
Mathias Agopian59119e62010-10-11 12:37:43 -07001692// ---------------------------------------------------------------------------
1693
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001694status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
1695 GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
Mathias Agopian59119e62010-10-11 12:37:43 -07001696{
Mathias Agopian59119e62010-10-11 12:37:43 -07001697 if (!GLExtensions::getInstance().haveFramebufferObject())
1698 return INVALID_OPERATION;
1699
1700 // get screen geometry
Mathias Agopian59119e62010-10-11 12:37:43 -07001701 const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
Mathias Agopian59119e62010-10-11 12:37:43 -07001702 const uint32_t hw_w = hw.getWidth();
1703 const uint32_t hw_h = hw.getHeight();
Mathias Agopian59119e62010-10-11 12:37:43 -07001704 GLfloat u = 1;
1705 GLfloat v = 1;
1706
1707 // make sure to clear all GL error flags
1708 while ( glGetError() != GL_NO_ERROR ) ;
1709
1710 // create a FBO
1711 GLuint name, tname;
1712 glGenTextures(1, &tname);
1713 glBindTexture(GL_TEXTURE_2D, tname);
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001714 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1715 hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
Mathias Agopian59119e62010-10-11 12:37:43 -07001716 if (glGetError() != GL_NO_ERROR) {
Mathias Agopian015fb3f2010-10-14 12:19:37 -07001717 while ( glGetError() != GL_NO_ERROR ) ;
Mathias Agopian59119e62010-10-11 12:37:43 -07001718 GLint tw = (2 << (31 - clz(hw_w)));
1719 GLint th = (2 << (31 - clz(hw_h)));
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001720 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1721 tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
Mathias Agopian59119e62010-10-11 12:37:43 -07001722 u = GLfloat(hw_w) / tw;
1723 v = GLfloat(hw_h) / th;
1724 }
1725 glGenFramebuffersOES(1, &name);
1726 glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001727 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
1728 GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
Mathias Agopian59119e62010-10-11 12:37:43 -07001729
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001730 // redraw the screen entirely...
1731 glClearColor(0,0,0,1);
1732 glClear(GL_COLOR_BUFFER_BIT);
1733 const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
1734 const size_t count = layers.size();
1735 for (size_t i=0 ; i<count ; ++i) {
1736 const sp<LayerBase>& layer(layers[i]);
1737 layer->drawForSreenShot();
1738 }
1739
1740 // back to main framebuffer
1741 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
1742 glDisable(GL_SCISSOR_TEST);
1743 glDeleteFramebuffersOES(1, &name);
1744
1745 *textureName = tname;
1746 *uOut = u;
1747 *vOut = v;
1748 return NO_ERROR;
1749}
1750
1751// ---------------------------------------------------------------------------
1752
1753status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
1754{
1755 status_t result = PERMISSION_DENIED;
1756
1757 if (!GLExtensions::getInstance().haveFramebufferObject())
1758 return INVALID_OPERATION;
1759
1760 // get screen geometry
1761 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1762 const uint32_t hw_w = hw.getWidth();
1763 const uint32_t hw_h = hw.getHeight();
1764 const Region screenBounds(hw.bounds());
1765
1766 GLfloat u, v;
1767 GLuint tname;
1768 result = renderScreenToTextureLocked(0, &tname, &u, &v);
1769 if (result != NO_ERROR) {
1770 return result;
1771 }
1772
1773 GLfloat vtx[8];
Mathias Agopianffcf4652011-07-07 17:30:31 -07001774 const GLfloat texCoords[4][2] = { {0,1}, {0,1-v}, {u,1-v}, {u,1} };
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001775 glBindTexture(GL_TEXTURE_2D, tname);
1776 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1777 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1778 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1779 glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1780 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1781 glVertexPointer(2, GL_FLOAT, 0, vtx);
1782
Mathias Agopianffcf4652011-07-07 17:30:31 -07001783 /*
1784 * Texture coordinate mapping
1785 *
1786 * u
1787 * 1 +----------+---+
1788 * | | | | image is inverted
1789 * | V | | w.r.t. the texture
1790 * 1-v +----------+ | coordinates
1791 * | |
1792 * | |
1793 * | |
1794 * 0 +--------------+
1795 * 0 1
1796 *
1797 */
1798
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001799 class s_curve_interpolator {
1800 const float nbFrames, s, v;
1801 public:
1802 s_curve_interpolator(int nbFrames, float s)
1803 : nbFrames(1.0f / (nbFrames-1)), s(s),
1804 v(1.0f + expf(-s + 0.5f*s)) {
1805 }
1806 float operator()(int f) {
1807 const float x = f * nbFrames;
1808 return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
1809 }
1810 };
1811
1812 class v_stretch {
1813 const GLfloat hw_w, hw_h;
1814 public:
1815 v_stretch(uint32_t hw_w, uint32_t hw_h)
1816 : hw_w(hw_w), hw_h(hw_h) {
1817 }
1818 void operator()(GLfloat* vtx, float v) {
1819 const GLfloat w = hw_w + (hw_w * v);
1820 const GLfloat h = hw_h - (hw_h * v);
1821 const GLfloat x = (hw_w - w) * 0.5f;
1822 const GLfloat y = (hw_h - h) * 0.5f;
Mathias Agopianffcf4652011-07-07 17:30:31 -07001823 vtx[0] = x; vtx[1] = y;
1824 vtx[2] = x; vtx[3] = y + h;
1825 vtx[4] = x + w; vtx[5] = y + h;
1826 vtx[6] = x + w; vtx[7] = y;
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001827 }
1828 };
1829
1830 class h_stretch {
1831 const GLfloat hw_w, hw_h;
1832 public:
1833 h_stretch(uint32_t hw_w, uint32_t hw_h)
1834 : hw_w(hw_w), hw_h(hw_h) {
1835 }
1836 void operator()(GLfloat* vtx, float v) {
1837 const GLfloat w = hw_w - (hw_w * v);
1838 const GLfloat h = 1.0f;
1839 const GLfloat x = (hw_w - w) * 0.5f;
1840 const GLfloat y = (hw_h - h) * 0.5f;
Mathias Agopianffcf4652011-07-07 17:30:31 -07001841 vtx[0] = x; vtx[1] = y;
1842 vtx[2] = x; vtx[3] = y + h;
1843 vtx[4] = x + w; vtx[5] = y + h;
1844 vtx[6] = x + w; vtx[7] = y;
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001845 }
1846 };
1847
1848 // the full animation is 24 frames
Mathias Agopianffcf4652011-07-07 17:30:31 -07001849 char value[PROPERTY_VALUE_MAX];
1850 property_get("debug.sf.electron_frames", value, "24");
1851 int nbFrames = (atoi(value) + 1) >> 1;
1852 if (nbFrames <= 0) // just in case
1853 nbFrames = 24;
1854
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001855 s_curve_interpolator itr(nbFrames, 7.5f);
1856 s_curve_interpolator itg(nbFrames, 8.0f);
1857 s_curve_interpolator itb(nbFrames, 8.5f);
1858
1859 v_stretch vverts(hw_w, hw_h);
1860 glEnable(GL_BLEND);
1861 glBlendFunc(GL_ONE, GL_ONE);
1862 for (int i=0 ; i<nbFrames ; i++) {
1863 float x, y, w, h;
1864 const float vr = itr(i);
1865 const float vg = itg(i);
1866 const float vb = itb(i);
1867
1868 // clear screen
1869 glColorMask(1,1,1,1);
Mathias Agopian59119e62010-10-11 12:37:43 -07001870 glClear(GL_COLOR_BUFFER_BIT);
Mathias Agopian59119e62010-10-11 12:37:43 -07001871 glEnable(GL_TEXTURE_2D);
Mathias Agopian59119e62010-10-11 12:37:43 -07001872
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001873 // draw the red plane
1874 vverts(vtx, vr);
1875 glColorMask(1,0,0,1);
1876 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Mathias Agopian59119e62010-10-11 12:37:43 -07001877
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001878 // draw the green plane
1879 vverts(vtx, vg);
1880 glColorMask(0,1,0,1);
1881 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Mathias Agopian59119e62010-10-11 12:37:43 -07001882
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001883 // draw the blue plane
1884 vverts(vtx, vb);
1885 glColorMask(0,0,1,1);
1886 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Mathias Agopian59119e62010-10-11 12:37:43 -07001887
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001888 // draw the white highlight (we use the last vertices)
Mathias Agopian59119e62010-10-11 12:37:43 -07001889 glDisable(GL_TEXTURE_2D);
1890 glColorMask(1,1,1,1);
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001891 glColor4f(vg, vg, vg, 1);
1892 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1893 hw.flip(screenBounds);
Mathias Agopian59119e62010-10-11 12:37:43 -07001894 }
1895
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001896 h_stretch hverts(hw_w, hw_h);
1897 glDisable(GL_BLEND);
1898 glDisable(GL_TEXTURE_2D);
1899 glColorMask(1,1,1,1);
1900 for (int i=0 ; i<nbFrames ; i++) {
1901 const float v = itg(i);
1902 hverts(vtx, v);
1903 glClear(GL_COLOR_BUFFER_BIT);
1904 glColor4f(1-v, 1-v, 1-v, 1);
1905 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1906 hw.flip(screenBounds);
1907 }
1908
1909 glColorMask(1,1,1,1);
1910 glEnable(GL_SCISSOR_TEST);
1911 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1912 glDeleteTextures(1, &tname);
Mathias Agopiana67932f2011-04-20 14:20:59 -07001913 glDisable(GL_TEXTURE_2D);
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001914 return NO_ERROR;
1915}
1916
1917status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
1918{
1919 status_t result = PERMISSION_DENIED;
1920
1921 if (!GLExtensions::getInstance().haveFramebufferObject())
1922 return INVALID_OPERATION;
1923
1924
1925 // get screen geometry
1926 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1927 const uint32_t hw_w = hw.getWidth();
1928 const uint32_t hw_h = hw.getHeight();
1929 const Region screenBounds(hw.bounds());
1930
1931 GLfloat u, v;
1932 GLuint tname;
1933 result = renderScreenToTextureLocked(0, &tname, &u, &v);
1934 if (result != NO_ERROR) {
1935 return result;
1936 }
1937
1938 // back to main framebuffer
1939 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
1940 glDisable(GL_SCISSOR_TEST);
1941
1942 GLfloat vtx[8];
1943 const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
Mathias Agopian9daa5c92010-10-12 16:05:48 -07001944 glBindTexture(GL_TEXTURE_2D, tname);
1945 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1946 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1947 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1948 glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1949 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1950 glVertexPointer(2, GL_FLOAT, 0, vtx);
1951
1952 class s_curve_interpolator {
1953 const float nbFrames, s, v;
1954 public:
1955 s_curve_interpolator(int nbFrames, float s)
1956 : nbFrames(1.0f / (nbFrames-1)), s(s),
1957 v(1.0f + expf(-s + 0.5f*s)) {
1958 }
1959 float operator()(int f) {
1960 const float x = f * nbFrames;
1961 return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
1962 }
1963 };
1964
1965 class v_stretch {
1966 const GLfloat hw_w, hw_h;
1967 public:
1968 v_stretch(uint32_t hw_w, uint32_t hw_h)
1969 : hw_w(hw_w), hw_h(hw_h) {
1970 }
1971 void operator()(GLfloat* vtx, float v) {
1972 const GLfloat w = hw_w + (hw_w * v);
1973 const GLfloat h = hw_h - (hw_h * v);
1974 const GLfloat x = (hw_w - w) * 0.5f;
1975 const GLfloat y = (hw_h - h) * 0.5f;
1976 vtx[0] = x; vtx[1] = y;
1977 vtx[2] = x; vtx[3] = y + h;
1978 vtx[4] = x + w; vtx[5] = y + h;
1979 vtx[6] = x + w; vtx[7] = y;
1980 }
1981 };
1982
1983 class h_stretch {
1984 const GLfloat hw_w, hw_h;
1985 public:
1986 h_stretch(uint32_t hw_w, uint32_t hw_h)
1987 : hw_w(hw_w), hw_h(hw_h) {
1988 }
1989 void operator()(GLfloat* vtx, float v) {
1990 const GLfloat w = hw_w - (hw_w * v);
1991 const GLfloat h = 1.0f;
1992 const GLfloat x = (hw_w - w) * 0.5f;
1993 const GLfloat y = (hw_h - h) * 0.5f;
1994 vtx[0] = x; vtx[1] = y;
1995 vtx[2] = x; vtx[3] = y + h;
1996 vtx[4] = x + w; vtx[5] = y + h;
1997 vtx[6] = x + w; vtx[7] = y;
1998 }
1999 };
2000
Mathias Agopiana6546e52010-10-14 12:33:07 -07002001 // the full animation is 12 frames
2002 int nbFrames = 8;
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002003 s_curve_interpolator itr(nbFrames, 7.5f);
2004 s_curve_interpolator itg(nbFrames, 8.0f);
2005 s_curve_interpolator itb(nbFrames, 8.5f);
2006
2007 h_stretch hverts(hw_w, hw_h);
2008 glDisable(GL_BLEND);
2009 glDisable(GL_TEXTURE_2D);
2010 glColorMask(1,1,1,1);
2011 for (int i=nbFrames-1 ; i>=0 ; i--) {
2012 const float v = itg(i);
2013 hverts(vtx, v);
2014 glClear(GL_COLOR_BUFFER_BIT);
2015 glColor4f(1-v, 1-v, 1-v, 1);
2016 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2017 hw.flip(screenBounds);
2018 }
2019
Mathias Agopiana6546e52010-10-14 12:33:07 -07002020 nbFrames = 4;
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002021 v_stretch vverts(hw_w, hw_h);
2022 glEnable(GL_BLEND);
2023 glBlendFunc(GL_ONE, GL_ONE);
2024 for (int i=nbFrames-1 ; i>=0 ; i--) {
2025 float x, y, w, h;
2026 const float vr = itr(i);
2027 const float vg = itg(i);
2028 const float vb = itb(i);
2029
2030 // clear screen
2031 glColorMask(1,1,1,1);
2032 glClear(GL_COLOR_BUFFER_BIT);
2033 glEnable(GL_TEXTURE_2D);
2034
2035 // draw the red plane
2036 vverts(vtx, vr);
2037 glColorMask(1,0,0,1);
2038 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2039
2040 // draw the green plane
2041 vverts(vtx, vg);
2042 glColorMask(0,1,0,1);
2043 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2044
2045 // draw the blue plane
2046 vverts(vtx, vb);
2047 glColorMask(0,0,1,1);
2048 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2049
2050 hw.flip(screenBounds);
2051 }
2052
2053 glColorMask(1,1,1,1);
2054 glEnable(GL_SCISSOR_TEST);
2055 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Mathias Agopian59119e62010-10-11 12:37:43 -07002056 glDeleteTextures(1, &tname);
Mathias Agopiana67932f2011-04-20 14:20:59 -07002057 glDisable(GL_TEXTURE_2D);
Mathias Agopian59119e62010-10-11 12:37:43 -07002058
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002059 return NO_ERROR;
2060}
2061
2062// ---------------------------------------------------------------------------
2063
Mathias Agopianabd671a2010-10-14 14:54:06 -07002064status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002065{
2066 DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
2067 if (!hw.canDraw()) {
2068 // we're already off
2069 return NO_ERROR;
2070 }
Mathias Agopianabd671a2010-10-14 14:54:06 -07002071 if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {
2072 electronBeamOffAnimationImplLocked();
2073 }
2074
2075 // always clear the whole screen at the end of the animation
2076 glClearColor(0,0,0,1);
2077 glDisable(GL_SCISSOR_TEST);
2078 glClear(GL_COLOR_BUFFER_BIT);
2079 glEnable(GL_SCISSOR_TEST);
2080 hw.flip( Region(hw.bounds()) );
2081
Mathias Agopian015fb3f2010-10-14 12:19:37 -07002082 hw.setCanDraw(false);
2083 return NO_ERROR;
Mathias Agopian59119e62010-10-11 12:37:43 -07002084}
2085
2086status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
2087{
Mathias Agopian59119e62010-10-11 12:37:43 -07002088 class MessageTurnElectronBeamOff : public MessageBase {
2089 SurfaceFlinger* flinger;
Mathias Agopianabd671a2010-10-14 14:54:06 -07002090 int32_t mode;
Mathias Agopian59119e62010-10-11 12:37:43 -07002091 status_t result;
2092 public:
Mathias Agopianabd671a2010-10-14 14:54:06 -07002093 MessageTurnElectronBeamOff(SurfaceFlinger* flinger, int32_t mode)
2094 : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
Mathias Agopian59119e62010-10-11 12:37:43 -07002095 }
2096 status_t getResult() const {
2097 return result;
2098 }
2099 virtual bool handler() {
2100 Mutex::Autolock _l(flinger->mStateLock);
Mathias Agopianabd671a2010-10-14 14:54:06 -07002101 result = flinger->turnElectronBeamOffImplLocked(mode);
Mathias Agopian59119e62010-10-11 12:37:43 -07002102 return true;
2103 }
2104 };
2105
Mathias Agopianabd671a2010-10-14 14:54:06 -07002106 sp<MessageBase> msg = new MessageTurnElectronBeamOff(this, mode);
Mathias Agopian59119e62010-10-11 12:37:43 -07002107 status_t res = postMessageSync(msg);
2108 if (res == NO_ERROR) {
2109 res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002110
2111 // work-around: when the power-manager calls us we activate the
2112 // animation. eventually, the "on" animation will be called
2113 // by the power-manager itself
Mathias Agopianabd671a2010-10-14 14:54:06 -07002114 mElectronBeamAnimationMode = mode;
Mathias Agopian59119e62010-10-11 12:37:43 -07002115 }
2116 return res;
2117}
2118
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002119// ---------------------------------------------------------------------------
Mathias Agopianb7e930d2010-06-01 15:12:58 -07002120
Mathias Agopianabd671a2010-10-14 14:54:06 -07002121status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode)
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002122{
2123 DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
2124 if (hw.canDraw()) {
2125 // we're already on
2126 return NO_ERROR;
2127 }
Mathias Agopianabd671a2010-10-14 14:54:06 -07002128 if (mode & ISurfaceComposer::eElectronBeamAnimationOn) {
2129 electronBeamOnAnimationImplLocked();
2130 }
Mathias Agopian015fb3f2010-10-14 12:19:37 -07002131 hw.setCanDraw(true);
Mathias Agopiana7f03732010-10-14 12:46:24 -07002132
2133 // make sure to redraw the whole screen when the animation is done
2134 mDirtyRegion.set(hw.bounds());
2135 signalEvent();
2136
Mathias Agopian015fb3f2010-10-14 12:19:37 -07002137 return NO_ERROR;
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002138}
2139
2140status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode)
2141{
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002142 class MessageTurnElectronBeamOn : public MessageBase {
2143 SurfaceFlinger* flinger;
Mathias Agopianabd671a2010-10-14 14:54:06 -07002144 int32_t mode;
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002145 status_t result;
2146 public:
Mathias Agopianabd671a2010-10-14 14:54:06 -07002147 MessageTurnElectronBeamOn(SurfaceFlinger* flinger, int32_t mode)
2148 : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002149 }
2150 status_t getResult() const {
2151 return result;
2152 }
2153 virtual bool handler() {
2154 Mutex::Autolock _l(flinger->mStateLock);
Mathias Agopianabd671a2010-10-14 14:54:06 -07002155 result = flinger->turnElectronBeamOnImplLocked(mode);
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002156 return true;
2157 }
2158 };
2159
Mathias Agopianabd671a2010-10-14 14:54:06 -07002160 postMessageAsync( new MessageTurnElectronBeamOn(this, mode) );
Mathias Agopian9daa5c92010-10-12 16:05:48 -07002161 return NO_ERROR;
2162}
2163
2164// ---------------------------------------------------------------------------
2165
Mathias Agopian74c40c02010-09-29 13:02:36 -07002166status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
2167 sp<IMemoryHeap>* heap,
2168 uint32_t* w, uint32_t* h, PixelFormat* f,
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002169 uint32_t sw, uint32_t sh,
2170 uint32_t minLayerZ, uint32_t maxLayerZ)
Mathias Agopian74c40c02010-09-29 13:02:36 -07002171{
2172 status_t result = PERMISSION_DENIED;
2173
2174 // only one display supported for now
2175 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
2176 return BAD_VALUE;
2177
Jamie Gennis7a4d0df2011-03-09 17:05:02 -08002178 // make sure none of the layers are protected
2179 const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
2180 const size_t count = layers.size();
2181 for (size_t i=0 ; i<count ; ++i) {
2182 const sp<LayerBase>& layer(layers[i]);
2183 const uint32_t z = layer->drawingState().z;
2184 if (z >= minLayerZ && z <= maxLayerZ) {
2185 if (layer->isProtected()) {
2186 return INVALID_OPERATION;
2187 }
2188 }
2189 }
2190
Mathias Agopian74c40c02010-09-29 13:02:36 -07002191 if (!GLExtensions::getInstance().haveFramebufferObject())
2192 return INVALID_OPERATION;
2193
2194 // get screen geometry
2195 const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
2196 const uint32_t hw_w = hw.getWidth();
2197 const uint32_t hw_h = hw.getHeight();
2198
2199 if ((sw > hw_w) || (sh > hw_h))
2200 return BAD_VALUE;
2201
2202 sw = (!sw) ? hw_w : sw;
2203 sh = (!sh) ? hw_h : sh;
2204 const size_t size = sw * sh * 4;
2205
Mathias Agopian1c71a472011-03-02 18:45:50 -08002206 //LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
2207 // sw, sh, minLayerZ, maxLayerZ);
Mathias Agopianc1d1b0d2011-01-16 14:05:02 -08002208
Mathias Agopian74c40c02010-09-29 13:02:36 -07002209 // make sure to clear all GL error flags
2210 while ( glGetError() != GL_NO_ERROR ) ;
2211
2212 // create a FBO
2213 GLuint name, tname;
2214 glGenRenderbuffersOES(1, &tname);
2215 glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
2216 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh);
2217 glGenFramebuffersOES(1, &name);
2218 glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
2219 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
2220 GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
2221
2222 GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
Mathias Agopianc1d1b0d2011-01-16 14:05:02 -08002223
Mathias Agopian74c40c02010-09-29 13:02:36 -07002224 if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
2225
2226 // invert everything, b/c glReadPixel() below will invert the FB
2227 glViewport(0, 0, sw, sh);
Mathias Agopianf653b892010-12-16 18:46:17 -08002228 glScissor(0, 0, sw, sh);
Mathias Agopianffcf4652011-07-07 17:30:31 -07002229 glEnable(GL_SCISSOR_TEST);
Mathias Agopian74c40c02010-09-29 13:02:36 -07002230 glMatrixMode(GL_PROJECTION);
2231 glPushMatrix();
2232 glLoadIdentity();
Mathias Agopianffcf4652011-07-07 17:30:31 -07002233 glOrthof(0, hw_w, hw_h, 0, 0, 1);
Mathias Agopian74c40c02010-09-29 13:02:36 -07002234 glMatrixMode(GL_MODELVIEW);
2235
2236 // redraw the screen entirely...
2237 glClearColor(0,0,0,1);
2238 glClear(GL_COLOR_BUFFER_BIT);
Mathias Agopianf653b892010-12-16 18:46:17 -08002239
Mathias Agopian74c40c02010-09-29 13:02:36 -07002240 for (size_t i=0 ; i<count ; ++i) {
2241 const sp<LayerBase>& layer(layers[i]);
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002242 const uint32_t z = layer->drawingState().z;
2243 if (z >= minLayerZ && z <= maxLayerZ) {
2244 layer->drawForSreenShot();
2245 }
Mathias Agopian74c40c02010-09-29 13:02:36 -07002246 }
2247
2248 // XXX: this is needed on tegra
Mathias Agopianffcf4652011-07-07 17:30:31 -07002249 glEnable(GL_SCISSOR_TEST);
Mathias Agopian74c40c02010-09-29 13:02:36 -07002250 glScissor(0, 0, sw, sh);
2251
2252 // check for errors and return screen capture
2253 if (glGetError() != GL_NO_ERROR) {
2254 // error while rendering
2255 result = INVALID_OPERATION;
2256 } else {
2257 // allocate shared memory large enough to hold the
2258 // screen capture
2259 sp<MemoryHeapBase> base(
2260 new MemoryHeapBase(size, 0, "screen-capture") );
2261 void* const ptr = base->getBase();
2262 if (ptr) {
2263 // capture the screen with glReadPixels()
2264 glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
2265 if (glGetError() == GL_NO_ERROR) {
2266 *heap = base;
2267 *w = sw;
2268 *h = sh;
2269 *f = PIXEL_FORMAT_RGBA_8888;
2270 result = NO_ERROR;
2271 }
2272 } else {
2273 result = NO_MEMORY;
2274 }
2275 }
Mathias Agopian74c40c02010-09-29 13:02:36 -07002276 glEnable(GL_SCISSOR_TEST);
2277 glViewport(0, 0, hw_w, hw_h);
2278 glMatrixMode(GL_PROJECTION);
2279 glPopMatrix();
2280 glMatrixMode(GL_MODELVIEW);
Mathias Agopian74c40c02010-09-29 13:02:36 -07002281 } else {
2282 result = BAD_VALUE;
2283 }
2284
2285 // release FBO resources
2286 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
2287 glDeleteRenderbuffersOES(1, &tname);
2288 glDeleteFramebuffersOES(1, &name);
Mathias Agopiane6f09842010-12-15 14:41:59 -08002289
2290 hw.compositionComplete();
2291
Mathias Agopian1c71a472011-03-02 18:45:50 -08002292 // LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
Mathias Agopianc1d1b0d2011-01-16 14:05:02 -08002293
Mathias Agopian74c40c02010-09-29 13:02:36 -07002294 return result;
2295}
2296
2297
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002298status_t SurfaceFlinger::captureScreen(DisplayID dpy,
2299 sp<IMemoryHeap>* heap,
Mathias Agopian74c40c02010-09-29 13:02:36 -07002300 uint32_t* width, uint32_t* height, PixelFormat* format,
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002301 uint32_t sw, uint32_t sh,
2302 uint32_t minLayerZ, uint32_t maxLayerZ)
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002303{
2304 // only one display supported for now
2305 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
2306 return BAD_VALUE;
2307
2308 if (!GLExtensions::getInstance().haveFramebufferObject())
2309 return INVALID_OPERATION;
2310
2311 class MessageCaptureScreen : public MessageBase {
2312 SurfaceFlinger* flinger;
2313 DisplayID dpy;
2314 sp<IMemoryHeap>* heap;
2315 uint32_t* w;
2316 uint32_t* h;
2317 PixelFormat* f;
Mathias Agopian74c40c02010-09-29 13:02:36 -07002318 uint32_t sw;
2319 uint32_t sh;
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002320 uint32_t minLayerZ;
2321 uint32_t maxLayerZ;
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002322 status_t result;
2323 public:
2324 MessageCaptureScreen(SurfaceFlinger* flinger, DisplayID dpy,
Mathias Agopian74c40c02010-09-29 13:02:36 -07002325 sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f,
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002326 uint32_t sw, uint32_t sh,
2327 uint32_t minLayerZ, uint32_t maxLayerZ)
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002328 : flinger(flinger), dpy(dpy),
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002329 heap(heap), w(w), h(h), f(f), sw(sw), sh(sh),
2330 minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
2331 result(PERMISSION_DENIED)
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002332 {
2333 }
2334 status_t getResult() const {
2335 return result;
2336 }
2337 virtual bool handler() {
2338 Mutex::Autolock _l(flinger->mStateLock);
2339
2340 // if we have secure windows, never allow the screen capture
2341 if (flinger->mSecureFrameBuffer)
2342 return true;
2343
Mathias Agopian74c40c02010-09-29 13:02:36 -07002344 result = flinger->captureScreenImplLocked(dpy,
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002345 heap, w, h, f, sw, sh, minLayerZ, maxLayerZ);
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002346
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002347 return true;
2348 }
2349 };
2350
2351 sp<MessageBase> msg = new MessageCaptureScreen(this,
Mathias Agopianbf2c6a62010-12-10 16:22:31 -08002352 dpy, heap, width, height, format, sw, sh, minLayerZ, maxLayerZ);
Mathias Agopian1b0b30d2010-09-24 11:26:58 -07002353 status_t res = postMessageSync(msg);
2354 if (res == NO_ERROR) {
2355 res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
2356 }
2357 return res;
2358}
2359
2360// ---------------------------------------------------------------------------
2361
Mathias Agopianb7e930d2010-06-01 15:12:58 -07002362sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const
2363{
2364 sp<Layer> result;
2365 Mutex::Autolock _l(mStateLock);
2366 result = mLayerMap.valueFor( sur->asBinder() ).promote();
2367 return result;
2368}
2369
2370// ---------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002371
Mathias Agopian96f08192010-06-02 23:28:45 -07002372Client::Client(const sp<SurfaceFlinger>& flinger)
Mathias Agopianb7e930d2010-06-01 15:12:58 -07002373 : mFlinger(flinger), mNameGenerator(1)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002374{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002375}
2376
Mathias Agopian96f08192010-06-02 23:28:45 -07002377Client::~Client()
2378{
Mathias Agopian96f08192010-06-02 23:28:45 -07002379 const size_t count = mLayers.size();
2380 for (size_t i=0 ; i<count ; i++) {
2381 sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
2382 if (layer != 0) {
2383 mFlinger->removeLayer(layer);
2384 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002385 }
2386}
2387
Mathias Agopian96f08192010-06-02 23:28:45 -07002388status_t Client::initCheck() const {
Mathias Agopianb7e930d2010-06-01 15:12:58 -07002389 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002390}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002391
Mathias Agopian4f113742011-05-03 16:21:41 -07002392size_t Client::attachLayer(const sp<LayerBaseClient>& layer)
Mathias Agopian96f08192010-06-02 23:28:45 -07002393{
Mathias Agopian4f113742011-05-03 16:21:41 -07002394 Mutex::Autolock _l(mLock);
2395 size_t name = mNameGenerator++;
Mathias Agopian96f08192010-06-02 23:28:45 -07002396 mLayers.add(name, layer);
2397 return name;
2398}
2399
Mathias Agopianb7e930d2010-06-01 15:12:58 -07002400void Client::detachLayer(const LayerBaseClient* layer)
Mathias Agopian96f08192010-06-02 23:28:45 -07002401{
Mathias Agopian4f113742011-05-03 16:21:41 -07002402 Mutex::Autolock _l(mLock);
Mathias Agopian96f08192010-06-02 23:28:45 -07002403 // we do a linear search here, because this doesn't happen often
2404 const size_t count = mLayers.size();
2405 for (size_t i=0 ; i<count ; i++) {
2406 if (mLayers.valueAt(i) == layer) {
2407 mLayers.removeItemsAt(i, 1);
2408 break;
2409 }
2410 }
2411}
Mathias Agopian4f113742011-05-03 16:21:41 -07002412sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
2413{
2414 Mutex::Autolock _l(mLock);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002415 sp<LayerBaseClient> lbc;
Mathias Agopian4f113742011-05-03 16:21:41 -07002416 wp<LayerBaseClient> layer(mLayers.valueFor(i));
Mathias Agopian96f08192010-06-02 23:28:45 -07002417 if (layer != 0) {
2418 lbc = layer.promote();
2419 LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002420 }
2421 return lbc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002422}
2423
Mathias Agopiana67932f2011-04-20 14:20:59 -07002424
2425status_t Client::onTransact(
2426 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
2427{
2428 // these must be checked
2429 IPCThreadState* ipc = IPCThreadState::self();
2430 const int pid = ipc->getCallingPid();
2431 const int uid = ipc->getCallingUid();
2432 const int self_pid = getpid();
2433 if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
2434 // we're called from a different process, do the real check
Mathias Agopian99b49842011-06-27 16:05:52 -07002435 if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
Mathias Agopiana67932f2011-04-20 14:20:59 -07002436 {
2437 LOGE("Permission Denial: "
2438 "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
2439 return PERMISSION_DENIED;
2440 }
2441 }
2442 return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
Mathias Agopianb7e930d2010-06-01 15:12:58 -07002443}
Mathias Agopiana67932f2011-04-20 14:20:59 -07002444
2445
Mathias Agopian96f08192010-06-02 23:28:45 -07002446sp<ISurface> Client::createSurface(
Mathias Agopian0ef4e152011-04-20 14:19:32 -07002447 ISurfaceComposerClient::surface_data_t* params,
Mathias Agopianb7e930d2010-06-01 15:12:58 -07002448 const String8& name,
2449 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002450 uint32_t flags)
2451{
Mathias Agopiana67932f2011-04-20 14:20:59 -07002452 /*
2453 * createSurface must be called from the GL thread so that it can
2454 * have access to the GL context.
2455 */
2456
2457 class MessageCreateSurface : public MessageBase {
2458 sp<ISurface> result;
2459 SurfaceFlinger* flinger;
2460 ISurfaceComposerClient::surface_data_t* params;
2461 Client* client;
2462 const String8& name;
2463 DisplayID display;
2464 uint32_t w, h;
2465 PixelFormat format;
2466 uint32_t flags;
2467 public:
2468 MessageCreateSurface(SurfaceFlinger* flinger,
2469 ISurfaceComposerClient::surface_data_t* params,
2470 const String8& name, Client* client,
2471 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
2472 uint32_t flags)
2473 : flinger(flinger), params(params), client(client), name(name),
2474 display(display), w(w), h(h), format(format), flags(flags)
2475 {
2476 }
2477 sp<ISurface> getResult() const { return result; }
2478 virtual bool handler() {
2479 result = flinger->createSurface(params, name, client,
2480 display, w, h, format, flags);
2481 return true;
2482 }
2483 };
2484
2485 sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),
2486 params, name, this, display, w, h, format, flags);
2487 mFlinger->postMessageSync(msg);
2488 return static_cast<MessageCreateSurface*>( msg.get() )->getResult();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002489}
Mathias Agopian96f08192010-06-02 23:28:45 -07002490status_t Client::destroySurface(SurfaceID sid) {
2491 return mFlinger->removeSurface(this, sid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002492}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002493
2494// ---------------------------------------------------------------------------
2495
Jamie Gennis9a78c902011-01-12 18:30:40 -08002496GraphicBufferAlloc::GraphicBufferAlloc() {}
2497
2498GraphicBufferAlloc::~GraphicBufferAlloc() {}
2499
2500sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
Mathias Agopiand9e8c642011-07-01 14:53:49 -07002501 PixelFormat format, uint32_t usage, status_t* error) {
Jamie Gennis9a78c902011-01-12 18:30:40 -08002502 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
2503 status_t err = graphicBuffer->initCheck();
Mathias Agopiand9e8c642011-07-01 14:53:49 -07002504 *error = err;
Mathias Agopiana67932f2011-04-20 14:20:59 -07002505 if (err != 0 || graphicBuffer->handle == 0) {
Mathias Agopiand9e8c642011-07-01 14:53:49 -07002506 if (err == NO_MEMORY) {
2507 GraphicBuffer::dumpAllocationsToSystemLog();
2508 }
Mathias Agopiana67932f2011-04-20 14:20:59 -07002509 LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
2510 "failed (%s), handle=%p",
2511 w, h, strerror(-err), graphicBuffer->handle);
Jamie Gennis9a78c902011-01-12 18:30:40 -08002512 return 0;
2513 }
Jamie Gennis9a78c902011-01-12 18:30:40 -08002514 return graphicBuffer;
2515}
2516
Jamie Gennis9a78c902011-01-12 18:30:40 -08002517// ---------------------------------------------------------------------------
2518
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002519GraphicPlane::GraphicPlane()
2520 : mHw(0)
2521{
2522}
2523
2524GraphicPlane::~GraphicPlane() {
2525 delete mHw;
2526}
2527
2528bool GraphicPlane::initialized() const {
2529 return mHw ? true : false;
2530}
2531
Mathias Agopian2b92d892010-02-08 15:49:35 -08002532int GraphicPlane::getWidth() const {
2533 return mWidth;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002534}
2535
Mathias Agopian2b92d892010-02-08 15:49:35 -08002536int GraphicPlane::getHeight() const {
2537 return mHeight;
2538}
2539
2540void GraphicPlane::setDisplayHardware(DisplayHardware *hw)
2541{
2542 mHw = hw;
2543
2544 // initialize the display orientation transform.
2545 // it's a constant that should come from the display driver.
2546 int displayOrientation = ISurfaceComposer::eOrientationDefault;
2547 char property[PROPERTY_VALUE_MAX];
2548 if (property_get("ro.sf.hwrotation", property, NULL) > 0) {
2549 //displayOrientation
2550 switch (atoi(property)) {
2551 case 90:
2552 displayOrientation = ISurfaceComposer::eOrientation90;
2553 break;
2554 case 270:
2555 displayOrientation = ISurfaceComposer::eOrientation270;
2556 break;
2557 }
2558 }
2559
2560 const float w = hw->getWidth();
2561 const float h = hw->getHeight();
2562 GraphicPlane::orientationToTransfrom(displayOrientation, w, h,
2563 &mDisplayTransform);
2564 if (displayOrientation & ISurfaceComposer::eOrientationSwapMask) {
2565 mDisplayWidth = h;
2566 mDisplayHeight = w;
2567 } else {
2568 mDisplayWidth = w;
2569 mDisplayHeight = h;
2570 }
2571
2572 setOrientation(ISurfaceComposer::eOrientationDefault);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002573}
2574
2575status_t GraphicPlane::orientationToTransfrom(
2576 int orientation, int w, int h, Transform* tr)
Mathias Agopianeda65402010-02-22 03:15:57 -08002577{
2578 uint32_t flags = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002579 switch (orientation) {
2580 case ISurfaceComposer::eOrientationDefault:
Mathias Agopianeda65402010-02-22 03:15:57 -08002581 flags = Transform::ROT_0;
2582 break;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002583 case ISurfaceComposer::eOrientation90:
Mathias Agopianeda65402010-02-22 03:15:57 -08002584 flags = Transform::ROT_90;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002585 break;
2586 case ISurfaceComposer::eOrientation180:
Mathias Agopianeda65402010-02-22 03:15:57 -08002587 flags = Transform::ROT_180;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002588 break;
2589 case ISurfaceComposer::eOrientation270:
Mathias Agopianeda65402010-02-22 03:15:57 -08002590 flags = Transform::ROT_270;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002591 break;
2592 default:
2593 return BAD_VALUE;
2594 }
Mathias Agopianeda65402010-02-22 03:15:57 -08002595 tr->set(flags, w, h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002596 return NO_ERROR;
2597}
2598
2599status_t GraphicPlane::setOrientation(int orientation)
2600{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002601 // If the rotation can be handled in hardware, this is where
2602 // the magic should happen.
Mathias Agopian2b92d892010-02-08 15:49:35 -08002603
2604 const DisplayHardware& hw(displayHardware());
2605 const float w = mDisplayWidth;
2606 const float h = mDisplayHeight;
2607 mWidth = int(w);
2608 mHeight = int(h);
2609
2610 Transform orientationTransform;
Mathias Agopianeda65402010-02-22 03:15:57 -08002611 GraphicPlane::orientationToTransfrom(orientation, w, h,
2612 &orientationTransform);
2613 if (orientation & ISurfaceComposer::eOrientationSwapMask) {
2614 mWidth = int(h);
2615 mHeight = int(w);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002616 }
Mathias Agopianeda65402010-02-22 03:15:57 -08002617
Mathias Agopian0d1318b2009-03-27 17:58:20 -07002618 mOrientation = orientation;
Mathias Agopian2b92d892010-02-08 15:49:35 -08002619 mGlobalTransform = mDisplayTransform * orientationTransform;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002620 return NO_ERROR;
2621}
2622
2623const DisplayHardware& GraphicPlane::displayHardware() const {
2624 return *mHw;
2625}
2626
Mathias Agopian59119e62010-10-11 12:37:43 -07002627DisplayHardware& GraphicPlane::editDisplayHardware() {
2628 return *mHw;
2629}
2630
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002631const Transform& GraphicPlane::transform() const {
2632 return mGlobalTransform;
2633}
2634
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002635EGLDisplay GraphicPlane::getEGLDisplay() const {
2636 return mHw->getEGLDisplay();
2637}
2638
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002639// ---------------------------------------------------------------------------
2640
2641}; // namespace android