blob: 242d0268822f4f9d0401b18a1462aaa303ba4608 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "SurfaceFlinger"
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <stdint.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <math.h>
Jean-Baptiste Querua837ba72009-01-26 11:51:12 -080026#include <limits.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070027#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/ioctl.h>
30
31#include <cutils/log.h>
32#include <cutils/properties.h>
33
34#include <utils/IPCThreadState.h>
35#include <utils/IServiceManager.h>
36#include <utils/MemoryDealer.h>
37#include <utils/MemoryBase.h>
38#include <utils/String8.h>
39#include <utils/String16.h>
40#include <utils/StopWatch.h>
41
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070042#include <ui/PixelFormat.h>
43#include <ui/DisplayInfo.h>
44#include <ui/EGLDisplaySurface.h>
45
46#include <pixelflinger/pixelflinger.h>
47#include <GLES/gl.h>
48
49#include "clz.h"
50#include "CPUGauge.h"
51#include "Layer.h"
52#include "LayerBlur.h"
53#include "LayerBuffer.h"
54#include "LayerDim.h"
55#include "LayerBitmap.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080056#include "LayerOrientationAnim.h"
57#include "OrientationAnimation.h"
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070058#include "SurfaceFlinger.h"
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070059#include "VRamHeap.h"
60
61#include "DisplayHardware/DisplayHardware.h"
62#include "GPUHardware/GPUHardware.h"
63
64
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070065#define DISPLAY_COUNT 1
66
67namespace android {
68
69// ---------------------------------------------------------------------------
70
71void SurfaceFlinger::instantiate() {
72 defaultServiceManager()->addService(
73 String16("SurfaceFlinger"), new SurfaceFlinger());
74}
75
76void SurfaceFlinger::shutdown() {
77 // we should unregister here, but not really because
78 // when (if) the service manager goes away, all the services
79 // it has a reference to will leave too.
80}
81
82// ---------------------------------------------------------------------------
83
84SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs)
85 : lookup(rhs.lookup), layers(rhs.layers)
86{
87}
88
89ssize_t SurfaceFlinger::LayerVector::indexOf(
90 LayerBase* key, size_t guess) const
91{
92 if (guess<size() && lookup.keyAt(guess) == key)
93 return guess;
94 const ssize_t i = lookup.indexOfKey(key);
95 if (i>=0) {
96 const size_t idx = lookup.valueAt(i);
97 LOG_ASSERT(layers[idx]==key,
98 "LayerVector[%p]: layers[%d]=%p, key=%p",
99 this, int(idx), layers[idx], key);
100 return idx;
101 }
102 return i;
103}
104
105ssize_t SurfaceFlinger::LayerVector::add(
106 LayerBase* layer,
107 Vector<LayerBase*>::compar_t cmp)
108{
109 size_t count = layers.size();
110 ssize_t l = 0;
111 ssize_t h = count-1;
112 ssize_t mid;
113 LayerBase* const* a = layers.array();
114 while (l <= h) {
115 mid = l + (h - l)/2;
116 const int c = cmp(a+mid, &layer);
117 if (c == 0) { l = mid; break; }
118 else if (c<0) { l = mid+1; }
119 else { h = mid-1; }
120 }
121 size_t order = l;
122 while (order<count && !cmp(&layer, a+order)) {
123 order++;
124 }
125 count = lookup.size();
126 for (size_t i=0 ; i<count ; i++) {
127 if (lookup.valueAt(i) >= order) {
128 lookup.editValueAt(i)++;
129 }
130 }
131 layers.insertAt(layer, order);
132 lookup.add(layer, order);
133 return order;
134}
135
136ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer)
137{
138 const ssize_t keyIndex = lookup.indexOfKey(layer);
139 if (keyIndex >= 0) {
140 const size_t index = lookup.valueAt(keyIndex);
141 LOG_ASSERT(layers[index]==layer,
142 "LayerVector[%p]: layers[%u]=%p, layer=%p",
143 this, int(index), layers[index], layer);
144 layers.removeItemsAt(index);
145 lookup.removeItemsAt(keyIndex);
146 const size_t count = lookup.size();
147 for (size_t i=0 ; i<count ; i++) {
148 if (lookup.valueAt(i) >= size_t(index)) {
149 lookup.editValueAt(i)--;
150 }
151 }
152 return index;
153 }
154 return NAME_NOT_FOUND;
155}
156
157ssize_t SurfaceFlinger::LayerVector::reorder(
158 LayerBase* layer,
159 Vector<LayerBase*>::compar_t cmp)
160{
161 // XXX: it's a little lame. but oh well...
162 ssize_t err = remove(layer);
163 if (err >=0)
164 err = add(layer, cmp);
165 return err;
166}
167
168// ---------------------------------------------------------------------------
169#if 0
170#pragma mark -
171#endif
172
173SurfaceFlinger::SurfaceFlinger()
174 : BnSurfaceComposer(), Thread(false),
175 mTransactionFlags(0),
176 mTransactionCount(0),
177 mBootTime(systemTime()),
178 mLastScheduledBroadcast(NULL),
179 mVisibleRegionsDirty(false),
180 mDeferReleaseConsole(false),
181 mFreezeDisplay(false),
182 mFreezeCount(0),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700183 mFreezeDisplayTime(0),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700184 mDebugRegion(0),
185 mDebugCpu(0),
186 mDebugFps(0),
187 mDebugBackground(0),
188 mDebugNoBootAnimation(0),
189 mSyncObject(),
190 mDeplayedTransactionPending(0),
191 mConsoleSignals(0),
192 mSecureFrameBuffer(0)
193{
194 init();
195}
196
197void SurfaceFlinger::init()
198{
199 LOGI("SurfaceFlinger is starting");
200
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700201 // debugging stuff...
202 char value[PROPERTY_VALUE_MAX];
203 property_get("debug.sf.showupdates", value, "0");
204 mDebugRegion = atoi(value);
205 property_get("debug.sf.showcpu", value, "0");
206 mDebugCpu = atoi(value);
207 property_get("debug.sf.showbackground", value, "0");
208 mDebugBackground = atoi(value);
209 property_get("debug.sf.showfps", value, "0");
210 mDebugFps = atoi(value);
211 property_get("debug.sf.nobootanimation", value, "0");
212 mDebugNoBootAnimation = atoi(value);
213
214 LOGI_IF(mDebugRegion, "showupdates enabled");
215 LOGI_IF(mDebugCpu, "showcpu enabled");
216 LOGI_IF(mDebugBackground, "showbackground enabled");
217 LOGI_IF(mDebugFps, "showfps enabled");
218 LOGI_IF(mDebugNoBootAnimation, "boot animation disabled");
219}
220
221SurfaceFlinger::~SurfaceFlinger()
222{
223 glDeleteTextures(1, &mWormholeTexName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224 delete mOrientationAnimation;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700225}
226
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800227copybit_device_t* SurfaceFlinger::getBlitEngine() const
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700228{
229 return graphicPlane(0).displayHardware().getBlitEngine();
230}
231
The Android Open Source Project27629322009-01-09 17:51:23 -0800232overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800233{
234 return graphicPlane(0).displayHardware().getOverlayEngine();
235}
236
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700237sp<IMemory> SurfaceFlinger::getCblk() const
238{
239 return mServerCblkMemory;
240}
241
242status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
243 gpu_info_t* gpu)
244{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800245 IPCThreadState* ipc = IPCThreadState::self();
246 const int pid = ipc->getCallingPid();
247 status_t err = mGPU->request(pid, callback, gpu);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700248 return err;
249}
250
251status_t SurfaceFlinger::revokeGPU()
252{
253 return mGPU->friendlyRevoke();
254}
255
256sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
257{
258 Mutex::Autolock _l(mStateLock);
259 uint32_t token = mTokens.acquire();
260
261 Client* client = new Client(token, this);
262 if ((client == 0) || (client->ctrlblk == 0)) {
263 mTokens.release(token);
264 return 0;
265 }
266 status_t err = mClientsMap.add(token, client);
267 if (err < 0) {
268 delete client;
269 mTokens.release(token);
270 return 0;
271 }
272 sp<BClient> bclient =
273 new BClient(this, token, client->controlBlockMemory());
274 return bclient;
275}
276
277void SurfaceFlinger::destroyConnection(ClientID cid)
278{
279 Mutex::Autolock _l(mStateLock);
280 Client* const client = mClientsMap.valueFor(cid);
281 if (client) {
282 // free all the layers this client owns
283 const Vector<LayerBaseClient*>& layers = client->getLayers();
284 const size_t count = layers.size();
285 for (size_t i=0 ; i<count ; i++) {
286 LayerBaseClient* const layer = layers[i];
287 removeLayer_l(layer);
288 }
289
290 // the resources associated with this client will be freed
291 // during the next transaction, after these surfaces have been
292 // properly removed from the screen
293
294 // remove this client from our ClientID->Client mapping.
295 mClientsMap.removeItem(cid);
296
297 // and add it to the list of disconnected clients
298 mDisconnectedClients.add(client);
299
300 // request a transaction
301 setTransactionFlags(eTransactionNeeded);
302 }
303}
304
305const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
306{
307 LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
308 const GraphicPlane& plane(mGraphicPlanes[dpy]);
309 return plane;
310}
311
312GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
313{
314 return const_cast<GraphicPlane&>(
315 const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
316}
317
318void SurfaceFlinger::bootFinished()
319{
320 const nsecs_t now = systemTime();
321 const nsecs_t duration = now - mBootTime;
322 LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
323 if (mBootAnimation != 0) {
324 mBootAnimation->requestExit();
325 mBootAnimation.clear();
326 }
327}
328
329void SurfaceFlinger::onFirstRef()
330{
331 run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
332
333 // Wait for the main thread to be done with its initialization
334 mReadyToRunBarrier.wait();
335}
336
337
338static inline uint16_t pack565(int r, int g, int b) {
339 return (r<<11)|(g<<5)|b;
340}
341
342// this is defined in libGLES_CM.so
343extern ISurfaceComposer* GLES_localSurfaceManager;
344
345status_t SurfaceFlinger::readyToRun()
346{
347 LOGI( "SurfaceFlinger's main thread ready to run. "
348 "Initializing graphics H/W...");
349
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800350 // create the shared control-block
351 mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY);
352 LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
353
354 mServerCblkMemory = mServerHeap->allocate(4096);
355 LOGE_IF(mServerCblkMemory==0, "can't create shared control block");
356
357 mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer());
358 LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
359 new(mServerCblk) surface_flinger_cblk_t;
360
361 // get a reference to the GPU if we have one
362 mGPU = GPUFactory::getGPU();
363
364 // create the surface Heap manager, which manages the heaps
365 // (be it in RAM or VRAM) where surfaces are allocated
366 // We give 8 MB per client.
367 mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20);
368
369
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700370 GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this);
371
372 // we only support one display currently
373 int dpy = 0;
374
375 {
376 // initialize the main display
377 GraphicPlane& plane(graphicPlane(dpy));
378 DisplayHardware* const hw = new DisplayHardware(this, dpy);
379 plane.setDisplayHardware(hw);
380 }
381
382 // initialize primary screen
383 // (other display should be initialized in the same manner, but
384 // asynchronously, as they could come and go. None of this is supported
385 // yet).
386 const GraphicPlane& plane(graphicPlane(dpy));
387 const DisplayHardware& hw = plane.displayHardware();
388 const uint32_t w = hw.getWidth();
389 const uint32_t h = hw.getHeight();
390 const uint32_t f = hw.getFormat();
391 hw.makeCurrent();
392
393 // initialize the shared control block
394 mServerCblk->connected |= 1<<dpy;
395 display_cblk_t* dcblk = mServerCblk->displays + dpy;
396 memset(dcblk, 0, sizeof(display_cblk_t));
397 dcblk->w = w;
398 dcblk->h = h;
399 dcblk->format = f;
400 dcblk->orientation = ISurfaceComposer::eOrientationDefault;
401 dcblk->xdpi = hw.getDpiX();
402 dcblk->ydpi = hw.getDpiY();
403 dcblk->fps = hw.getRefreshRate();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800404 dcblk->density = hw.getDensity();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700405 asm volatile ("":::"memory");
406
407 // Initialize OpenGL|ES
408 glActiveTexture(GL_TEXTURE0);
409 glBindTexture(GL_TEXTURE_2D, 0);
410 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
411 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
412 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
413 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
414 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
415 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800416 glPixelStorei(GL_PACK_ALIGNMENT, 4);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700417 glEnableClientState(GL_VERTEX_ARRAY);
418 glEnable(GL_SCISSOR_TEST);
419 glShadeModel(GL_FLAT);
420 glDisable(GL_DITHER);
421 glDisable(GL_CULL_FACE);
422
423 const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
424 const uint16_t g1 = pack565(0x17,0x2f,0x17);
425 const uint16_t textureData[4] = { g0, g1, g1, g0 };
426 glGenTextures(1, &mWormholeTexName);
427 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
428 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
429 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
430 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
431 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
432 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
433 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);
434
435 glViewport(0, 0, w, h);
436 glMatrixMode(GL_PROJECTION);
437 glLoadIdentity();
438 glOrthof(0, w, h, 0, 0, 1);
439
440 LayerDim::initDimmer(this, w, h);
441
442 mReadyToRunBarrier.open();
443
444 /*
445 * We're now ready to accept clients...
446 */
447
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800448 mOrientationAnimation = new OrientationAnimation(this);
449
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700450 // start CPU gauge display
451 if (mDebugCpu)
452 mCpuGauge = new CPUGauge(this, ms2ns(500));
453
454 // the boot animation!
455 if (mDebugNoBootAnimation == false)
456 mBootAnimation = new BootAnimation(this);
457
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700458 return NO_ERROR;
459}
460
461// ----------------------------------------------------------------------------
462#if 0
463#pragma mark -
464#pragma mark Events Handler
465#endif
466
467void SurfaceFlinger::waitForEvent()
468{
469 // wait for something to do
470 if (UNLIKELY(isFrozen())) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800471 // wait 5 seconds
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700472 const nsecs_t freezeDisplayTimeout = ms2ns(5000);
473 const nsecs_t now = systemTime();
474 if (mFreezeDisplayTime == 0) {
475 mFreezeDisplayTime = now;
476 }
477 nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
478 int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700479 if (err != NO_ERROR) {
480 if (isFrozen()) {
481 // we timed out and are still frozen
482 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
483 mFreezeDisplay, mFreezeCount);
484 mFreezeCount = 0;
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700485 mFreezeDisplay = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700486 }
487 }
488 } else {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700489 mFreezeDisplayTime = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700490 mSyncObject.wait();
491 }
492}
493
494void SurfaceFlinger::signalEvent() {
495 mSyncObject.open();
496}
497
498void SurfaceFlinger::signal() const {
499 mSyncObject.open();
500}
501
502void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
503{
504 if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) {
505 sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay));
506 delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY);
507 }
508}
509
510// ----------------------------------------------------------------------------
511#if 0
512#pragma mark -
513#pragma mark Main loop
514#endif
515
516bool SurfaceFlinger::threadLoop()
517{
518 waitForEvent();
519
520 // check for transactions
521 if (UNLIKELY(mConsoleSignals)) {
522 handleConsoleEvents();
523 }
524
525 if (LIKELY(mTransactionCount == 0)) {
526 // if we're in a global transaction, don't do anything.
527 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
528 uint32_t transactionFlags = getTransactionFlags(mask);
529 if (LIKELY(transactionFlags)) {
530 handleTransaction(transactionFlags);
531 }
532 }
533
534 // post surfaces (if needed)
535 handlePageFlip();
536
537 const DisplayHardware& hw(graphicPlane(0).displayHardware());
538 if (LIKELY(hw.canDraw())) {
539 // repaint the framebuffer (if needed)
540 handleRepaint();
541
542 // release the clients before we flip ('cause flip might block)
543 unlockClients();
544 executeScheduledBroadcasts();
545
546 // sample the cpu gauge
547 if (UNLIKELY(mDebugCpu)) {
548 handleDebugCpu();
549 }
550
551 postFramebuffer();
552 } else {
553 // pretend we did the post
554 unlockClients();
555 executeScheduledBroadcasts();
556 usleep(16667); // 60 fps period
557 }
558 return true;
559}
560
561void SurfaceFlinger::postFramebuffer()
562{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800563 const bool skip = mOrientationAnimation->run();
564 if (UNLIKELY(skip)) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700565 return;
566 }
567
568 if (!mInvalidRegion.isEmpty()) {
569 const DisplayHardware& hw(graphicPlane(0).displayHardware());
570
571 if (UNLIKELY(mDebugFps)) {
572 debugShowFPS();
573 }
574
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700575 hw.flip(mInvalidRegion);
576
577 mInvalidRegion.clear();
578
579 if (Layer::deletedTextures.size()) {
580 glDeleteTextures(
581 Layer::deletedTextures.size(),
582 Layer::deletedTextures.array());
583 Layer::deletedTextures.clear();
584 }
585 }
586}
587
588void SurfaceFlinger::handleConsoleEvents()
589{
590 // something to do with the console
591 const DisplayHardware& hw = graphicPlane(0).displayHardware();
592
593 int what = android_atomic_and(0, &mConsoleSignals);
594 if (what & eConsoleAcquired) {
595 hw.acquireScreen();
596 }
597
598 if (mDeferReleaseConsole && hw.canDraw()) {
599 // We got the release signal before the aquire signal
600 mDeferReleaseConsole = false;
601 revokeGPU();
602 hw.releaseScreen();
603 }
604
605 if (what & eConsoleReleased) {
606 if (hw.canDraw()) {
607 revokeGPU();
608 hw.releaseScreen();
609 } else {
610 mDeferReleaseConsole = true;
611 }
612 }
613
614 mDirtyRegion.set(hw.bounds());
615}
616
617void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
618{
619 Mutex::Autolock _l(mStateLock);
620
621 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
622 const size_t count = currentLayers.size();
623
624 /*
625 * Traversal of the children
626 * (perform the transaction for each of them if needed)
627 */
628
629 const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
630 if (layersNeedTransaction) {
631 for (size_t i=0 ; i<count ; i++) {
632 LayerBase* const layer = currentLayers[i];
633 uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
634 if (!trFlags) continue;
635
636 const uint32_t flags = layer->doTransaction(0);
637 if (flags & Layer::eVisibleRegion)
638 mVisibleRegionsDirty = true;
639
640 if (flags & Layer::eRestartTransaction) {
641 // restart the transaction, but back-off a little
642 layer->setTransactionFlags(eTransactionNeeded);
643 setTransactionFlags(eTraversalNeeded, ms2ns(8));
644 }
645 }
646 }
647
648 /*
649 * Perform our own transaction if needed
650 */
651
652 if (transactionFlags & eTransactionNeeded) {
653 if (mCurrentState.orientation != mDrawingState.orientation) {
654 // the orientation has changed, recompute all visible regions
655 // and invalidate everything.
656
657 const int dpy = 0;
658 const int orientation = mCurrentState.orientation;
659 GraphicPlane& plane(graphicPlane(dpy));
660 plane.setOrientation(orientation);
661
662 // update the shared control block
663 const DisplayHardware& hw(plane.displayHardware());
664 volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
665 dcblk->orientation = orientation;
666 if (orientation & eOrientationSwapMask) {
667 // 90 or 270 degrees orientation
668 dcblk->w = hw.getHeight();
669 dcblk->h = hw.getWidth();
670 } else {
671 dcblk->w = hw.getWidth();
672 dcblk->h = hw.getHeight();
673 }
674
675 mVisibleRegionsDirty = true;
676 mDirtyRegion.set(hw.bounds());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800677
678 mOrientationAnimation->onOrientationChanged();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700679 }
680
681 if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
682 // freezing or unfreezing the display -> trigger animation if needed
683 mFreezeDisplay = mCurrentState.freezeDisplay;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700684 }
685
686 // some layers might have been removed, so
687 // we need to update the regions they're exposing.
688 size_t c = mRemovedLayers.size();
689 if (c) {
690 mVisibleRegionsDirty = true;
691 }
692
693 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
694 if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
695 // layers have been added
696 mVisibleRegionsDirty = true;
697 }
698
699 // get rid of all resources we don't need anymore
700 // (layers and clients)
701 free_resources_l();
702 }
703
704 commitTransaction();
705}
706
707sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
708{
709 return new FreezeLock(const_cast<SurfaceFlinger *>(this));
710}
711
712void SurfaceFlinger::computeVisibleRegions(
713 LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
714{
715 const GraphicPlane& plane(graphicPlane(0));
716 const Transform& planeTransform(plane.transform());
717
718 Region aboveOpaqueLayers;
719 Region aboveCoveredLayers;
720 Region dirty;
721
722 bool secureFrameBuffer = false;
723
724 size_t i = currentLayers.size();
725 while (i--) {
726 LayerBase* const layer = currentLayers[i];
727 layer->validateVisibility(planeTransform);
728
729 // start with the whole surface at its current location
730 const Layer::State& s = layer->drawingState();
731 const Rect bounds(layer->visibleBounds());
732
733 // handle hidden surfaces by setting the visible region to empty
734 Region opaqueRegion;
735 Region visibleRegion;
736 Region coveredRegion;
737 if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) {
738 visibleRegion.clear();
739 } else {
740 const bool translucent = layer->needsBlending();
741 visibleRegion.set(bounds);
742 coveredRegion = visibleRegion;
743
744 // Remove the transparent area from the visible region
745 if (translucent) {
746 visibleRegion.subtractSelf(layer->transparentRegionScreen);
747 }
748
749 // compute the opaque region
750 if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
751 // the opaque region is the visible region
752 opaqueRegion = visibleRegion;
753 }
754 }
755
756 // subtract the opaque region covered by the layers above us
757 visibleRegion.subtractSelf(aboveOpaqueLayers);
758 coveredRegion.andSelf(aboveCoveredLayers);
759
760 // compute this layer's dirty region
The Android Open Source Project27629322009-01-09 17:51:23 -0800761 if (layer->contentDirty) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700762 // we need to invalidate the whole region
763 dirty = visibleRegion;
764 // as well, as the old visible region
765 dirty.orSelf(layer->visibleRegionScreen);
The Android Open Source Project27629322009-01-09 17:51:23 -0800766 layer->contentDirty = false;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700767 } else {
768 // compute the exposed region
769 // dirty = what's visible now - what's wasn't covered before
770 // = what's visible now & what's was covered before
771 dirty = visibleRegion.intersect(layer->coveredRegionScreen);
772 }
773 dirty.subtractSelf(aboveOpaqueLayers);
774
775 // accumulate to the screen dirty region
776 dirtyRegion.orSelf(dirty);
777
778 // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
779 aboveOpaqueLayers.orSelf(opaqueRegion);
780 aboveCoveredLayers.orSelf(bounds);
781
782 // Store the visible region is screen space
783 layer->setVisibleRegion(visibleRegion);
784 layer->setCoveredRegion(coveredRegion);
785
786 // If a secure layer is partially visible, lockdown the screen!
787 if (layer->isSecure() && !visibleRegion.isEmpty()) {
788 secureFrameBuffer = true;
789 }
790 }
791
792 mSecureFrameBuffer = secureFrameBuffer;
793 opaqueRegion = aboveOpaqueLayers;
794}
795
796
797void SurfaceFlinger::commitTransaction()
798{
799 mDrawingState = mCurrentState;
800 mTransactionCV.signal();
801}
802
803void SurfaceFlinger::handlePageFlip()
804{
805 bool visibleRegions = mVisibleRegionsDirty;
806 LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
807 visibleRegions |= lockPageFlip(currentLayers);
808
809 const DisplayHardware& hw = graphicPlane(0).displayHardware();
810 const Region screenRegion(hw.bounds());
811 if (visibleRegions) {
812 Region opaqueRegion;
813 computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
814 mWormholeRegion = screenRegion.subtract(opaqueRegion);
815 mVisibleRegionsDirty = false;
816 }
817
818 unlockPageFlip(currentLayers);
819 mDirtyRegion.andSelf(screenRegion);
820}
821
822bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
823{
824 bool recomputeVisibleRegions = false;
825 size_t count = currentLayers.size();
826 LayerBase* const* layers = currentLayers.array();
827 for (size_t i=0 ; i<count ; i++) {
828 LayerBase* const layer = layers[i];
829 layer->lockPageFlip(recomputeVisibleRegions);
830 }
831 return recomputeVisibleRegions;
832}
833
834void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
835{
836 const GraphicPlane& plane(graphicPlane(0));
837 const Transform& planeTransform(plane.transform());
838 size_t count = currentLayers.size();
839 LayerBase* const* layers = currentLayers.array();
840 for (size_t i=0 ; i<count ; i++) {
841 LayerBase* const layer = layers[i];
842 layer->unlockPageFlip(planeTransform, mDirtyRegion);
843 }
844}
845
846void SurfaceFlinger::handleRepaint()
847{
848 // set the frame buffer
849 const DisplayHardware& hw(graphicPlane(0).displayHardware());
850 glMatrixMode(GL_MODELVIEW);
851 glLoadIdentity();
852
853 if (UNLIKELY(mDebugRegion)) {
854 debugFlashRegions();
855 }
856
857 // compute the invalid region
858 mInvalidRegion.orSelf(mDirtyRegion);
859
860 uint32_t flags = hw.getFlags();
861 if (flags & DisplayHardware::BUFFER_PRESERVED) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800862 // here we assume DisplayHardware::flip()'s implementation
863 // performs the copy-back optimization.
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700864 } else {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700865 if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
866 // we need to fully redraw the part that will be updated
867 mDirtyRegion.set(mInvalidRegion.bounds());
868 } else {
869 // we need to redraw everything
870 mDirtyRegion.set(hw.bounds());
871 mInvalidRegion = mDirtyRegion;
872 }
873 }
874
875 // compose all surfaces
876 composeSurfaces(mDirtyRegion);
877
878 // clear the dirty regions
879 mDirtyRegion.clear();
880}
881
882void SurfaceFlinger::composeSurfaces(const Region& dirty)
883{
884 if (UNLIKELY(!mWormholeRegion.isEmpty())) {
885 // should never happen unless the window manager has a bug
886 // draw something...
887 drawWormhole();
888 }
889 const SurfaceFlinger& flinger(*this);
890 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
891 const size_t count = drawingLayers.size();
892 LayerBase const* const* const layers = drawingLayers.array();
893 for (size_t i=0 ; i<count ; ++i) {
894 LayerBase const * const layer = layers[i];
895 const Region& visibleRegion(layer->visibleRegionScreen);
896 if (!visibleRegion.isEmpty()) {
897 const Region clip(dirty.intersect(visibleRegion));
898 if (!clip.isEmpty()) {
899 layer->draw(clip);
900 }
901 }
902 }
903}
904
905void SurfaceFlinger::unlockClients()
906{
907 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
908 const size_t count = drawingLayers.size();
909 LayerBase* const* const layers = drawingLayers.array();
910 for (size_t i=0 ; i<count ; ++i) {
911 LayerBase* const layer = layers[i];
912 layer->finishPageFlip();
913 }
914}
915
916void SurfaceFlinger::scheduleBroadcast(Client* client)
917{
918 if (mLastScheduledBroadcast != client) {
919 mLastScheduledBroadcast = client;
920 mScheduledBroadcasts.add(client);
921 }
922}
923
924void SurfaceFlinger::executeScheduledBroadcasts()
925{
926 SortedVector<Client*>& list = mScheduledBroadcasts;
927 size_t count = list.size();
928 while (count--) {
929 per_client_cblk_t* const cblk = list[count]->ctrlblk;
930 if (cblk->lock.tryLock() == NO_ERROR) {
931 cblk->cv.broadcast();
932 list.removeAt(count);
933 cblk->lock.unlock();
934 } else {
935 // schedule another round
936 LOGW("executeScheduledBroadcasts() skipped, "
937 "contention on the client. We'll try again later...");
938 signalDelayedEvent(ms2ns(4));
939 }
940 }
941 mLastScheduledBroadcast = 0;
942}
943
944void SurfaceFlinger::handleDebugCpu()
945{
946 Mutex::Autolock _l(mDebugLock);
947 if (mCpuGauge != 0)
948 mCpuGauge->sample();
949}
950
951void SurfaceFlinger::debugFlashRegions()
952{
953 if (UNLIKELY(!mDirtyRegion.isRect())) {
954 // TODO: do this only if we don't have preserving
955 // swapBuffer. If we don't have update-on-demand,
956 // redraw everything.
957 composeSurfaces(Region(mDirtyRegion.bounds()));
958 }
959
960 glDisable(GL_TEXTURE_2D);
961 glDisable(GL_BLEND);
962 glDisable(GL_DITHER);
963 glDisable(GL_SCISSOR_TEST);
964
965 glColor4x(0x10000, 0, 0x10000, 0x10000);
966
967 Rect r;
968 Region::iterator iterator(mDirtyRegion);
969 while (iterator.iterate(&r)) {
970 GLfloat vertices[][2] = {
971 { r.left, r.top },
972 { r.left, r.bottom },
973 { r.right, r.bottom },
974 { r.right, r.top }
975 };
976 glVertexPointer(2, GL_FLOAT, 0, vertices);
977 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
978 }
979
980 const DisplayHardware& hw(graphicPlane(0).displayHardware());
981 hw.flip(mDirtyRegion.merge(mInvalidRegion));
982 mInvalidRegion.clear();
983
984 if (mDebugRegion > 1)
985 usleep(mDebugRegion * 1000);
986
987 glEnable(GL_SCISSOR_TEST);
988 //mDirtyRegion.dump("mDirtyRegion");
989}
990
991void SurfaceFlinger::drawWormhole() const
992{
993 const Region region(mWormholeRegion.intersect(mDirtyRegion));
994 if (region.isEmpty())
995 return;
996
997 const DisplayHardware& hw(graphicPlane(0).displayHardware());
998 const int32_t width = hw.getWidth();
999 const int32_t height = hw.getHeight();
1000
1001 glDisable(GL_BLEND);
1002 glDisable(GL_DITHER);
1003
1004 if (LIKELY(!mDebugBackground)) {
1005 glClearColorx(0,0,0,0);
1006 Rect r;
1007 Region::iterator iterator(region);
1008 while (iterator.iterate(&r)) {
1009 const GLint sy = height - (r.top + r.height());
1010 glScissor(r.left, sy, r.width(), r.height());
1011 glClear(GL_COLOR_BUFFER_BIT);
1012 }
1013 } else {
1014 const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
1015 { width, height }, { 0, height } };
1016 const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
1017 glVertexPointer(2, GL_SHORT, 0, vertices);
1018 glTexCoordPointer(2, GL_SHORT, 0, tcoords);
1019 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1020 glEnable(GL_TEXTURE_2D);
1021 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
1022 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1023 glMatrixMode(GL_TEXTURE);
1024 glLoadIdentity();
1025 glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
1026 Rect r;
1027 Region::iterator iterator(region);
1028 while (iterator.iterate(&r)) {
1029 const GLint sy = height - (r.top + r.height());
1030 glScissor(r.left, sy, r.width(), r.height());
1031 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1032 }
1033 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1034 }
1035}
1036
1037void SurfaceFlinger::debugShowFPS() const
1038{
1039 static int mFrameCount;
1040 static int mLastFrameCount = 0;
1041 static nsecs_t mLastFpsTime = 0;
1042 static float mFps = 0;
1043 mFrameCount++;
1044 nsecs_t now = systemTime();
1045 nsecs_t diff = now - mLastFpsTime;
1046 if (diff > ms2ns(250)) {
1047 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
1048 mLastFpsTime = now;
1049 mLastFrameCount = mFrameCount;
1050 }
1051 // XXX: mFPS has the value we want
1052 }
1053
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001054status_t SurfaceFlinger::addLayer(LayerBase* layer)
1055{
1056 Mutex::Autolock _l(mStateLock);
1057 addLayer_l(layer);
1058 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1059 return NO_ERROR;
1060}
1061
1062status_t SurfaceFlinger::removeLayer(LayerBase* layer)
1063{
1064 Mutex::Autolock _l(mStateLock);
1065 removeLayer_l(layer);
1066 setTransactionFlags(eTransactionNeeded);
1067 return NO_ERROR;
1068}
1069
1070status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer)
1071{
1072 layer->forceVisibilityTransaction();
1073 setTransactionFlags(eTraversalNeeded);
1074 return NO_ERROR;
1075}
1076
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001077status_t SurfaceFlinger::addLayer_l(LayerBase* layer)
1078{
1079 ssize_t i = mCurrentState.layersSortedByZ.add(
1080 layer, &LayerBase::compareCurrentStateZ);
1081 LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer);
1082 if (lbc) {
1083 mLayerMap.add(lbc->serverIndex(), lbc);
1084 }
1085 mRemovedLayers.remove(layer);
1086 return NO_ERROR;
1087}
1088
1089status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase)
1090{
1091 ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
1092 if (index >= 0) {
1093 mRemovedLayers.add(layerBase);
1094 LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase);
1095 if (layer) {
1096 mLayerMap.removeItem(layer->serverIndex());
1097 }
1098 return NO_ERROR;
1099 }
1100 // it's possible that we don't find a layer, because it might
1101 // have been destroyed already -- this is not technically an error
1102 // from the user because there is a race between destroySurface,
1103 // destroyclient and destroySurface-from-a-transaction.
1104 return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
1105}
1106
1107void SurfaceFlinger::free_resources_l()
1108{
1109 // Destroy layers that were removed
1110 destroy_all_removed_layers_l();
1111
1112 // free resources associated with disconnected clients
1113 SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
1114 Vector<Client*>& disconnectedClients(mDisconnectedClients);
1115 const size_t count = disconnectedClients.size();
1116 for (size_t i=0 ; i<count ; i++) {
1117 Client* client = disconnectedClients[i];
1118 // if this client is the scheduled broadcast list,
1119 // remove it from there (and we don't need to signal it
1120 // since it is dead).
1121 int32_t index = scheduledBroadcasts.indexOf(client);
1122 if (index >= 0) {
1123 scheduledBroadcasts.removeItemsAt(index);
1124 }
1125 mTokens.release(client->cid);
1126 delete client;
1127 }
1128 disconnectedClients.clear();
1129}
1130
1131void SurfaceFlinger::destroy_all_removed_layers_l()
1132{
1133 size_t c = mRemovedLayers.size();
1134 while (c--) {
1135 LayerBase* const removed_layer = mRemovedLayers[c];
1136
1137 LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0,
1138 "layer %p removed but still in the current state list",
1139 removed_layer);
1140
1141 delete removed_layer;
1142 }
1143 mRemovedLayers.clear();
1144}
1145
1146
1147uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
1148{
1149 return android_atomic_and(~flags, &mTransactionFlags) & flags;
1150}
1151
1152uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
1153{
1154 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
1155 if ((old & flags)==0) { // wake the server up
1156 if (delay > 0) {
1157 signalDelayedEvent(delay);
1158 } else {
1159 signalEvent();
1160 }
1161 }
1162 return old;
1163}
1164
1165void SurfaceFlinger::openGlobalTransaction()
1166{
1167 android_atomic_inc(&mTransactionCount);
1168}
1169
1170void SurfaceFlinger::closeGlobalTransaction()
1171{
1172 if (android_atomic_dec(&mTransactionCount) == 1) {
1173 signalEvent();
1174 }
1175}
1176
1177status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
1178{
1179 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1180 return BAD_VALUE;
1181
1182 Mutex::Autolock _l(mStateLock);
1183 mCurrentState.freezeDisplay = 1;
1184 setTransactionFlags(eTransactionNeeded);
1185
1186 // flags is intended to communicate some sort of animation behavior
1187 // (for instance fadding)
1188 return NO_ERROR;
1189}
1190
1191status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
1192{
1193 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1194 return BAD_VALUE;
1195
1196 Mutex::Autolock _l(mStateLock);
1197 mCurrentState.freezeDisplay = 0;
1198 setTransactionFlags(eTransactionNeeded);
1199
1200 // flags is intended to communicate some sort of animation behavior
1201 // (for instance fadding)
1202 return NO_ERROR;
1203}
1204
1205int SurfaceFlinger::setOrientation(DisplayID dpy, int orientation)
1206{
1207 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1208 return BAD_VALUE;
1209
1210 Mutex::Autolock _l(mStateLock);
1211 if (mCurrentState.orientation != orientation) {
1212 if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
1213 mCurrentState.orientation = orientation;
1214 setTransactionFlags(eTransactionNeeded);
1215 mTransactionCV.wait(mStateLock);
1216 } else {
1217 orientation = BAD_VALUE;
1218 }
1219 }
1220 return orientation;
1221}
1222
1223sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
1224 ISurfaceFlingerClient::surface_data_t* params,
1225 DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
1226 uint32_t flags)
1227{
1228 LayerBaseClient* layer = 0;
1229 sp<LayerBaseClient::Surface> surfaceHandle;
1230 Mutex::Autolock _l(mStateLock);
1231 Client* const c = mClientsMap.valueFor(clientId);
1232 if (UNLIKELY(!c)) {
1233 LOGE("createSurface() failed, client not found (id=%d)", clientId);
1234 return surfaceHandle;
1235 }
1236
1237 //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
1238 int32_t id = c->generateId(pid);
1239 if (uint32_t(id) >= NUM_LAYERS_MAX) {
1240 LOGE("createSurface() failed, generateId = %d", id);
1241 return surfaceHandle;
1242 }
1243
1244 switch (flags & eFXSurfaceMask) {
1245 case eFXSurfaceNormal:
1246 if (UNLIKELY(flags & ePushBuffers)) {
1247 layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
1248 } else {
1249 layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
1250 }
1251 break;
1252 case eFXSurfaceBlur:
1253 layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
1254 break;
1255 case eFXSurfaceDim:
1256 layer = createDimSurfaceLocked(c, d, id, w, h, flags);
1257 break;
1258 }
1259
1260 if (layer) {
1261 setTransactionFlags(eTransactionNeeded);
1262 surfaceHandle = layer->getSurface();
1263 if (surfaceHandle != 0)
1264 surfaceHandle->getSurfaceData(params);
1265 }
1266
1267 return surfaceHandle;
1268}
1269
1270LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
1271 Client* client, DisplayID display,
1272 int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
1273{
1274 // initialize the surfaces
1275 switch (format) { // TODO: take h/w into account
1276 case PIXEL_FORMAT_TRANSPARENT:
1277 case PIXEL_FORMAT_TRANSLUCENT:
1278 format = PIXEL_FORMAT_RGBA_8888;
1279 break;
1280 case PIXEL_FORMAT_OPAQUE:
1281 format = PIXEL_FORMAT_RGB_565;
1282 break;
1283 }
1284
1285 Layer* layer = new Layer(this, display, client, id);
1286 status_t err = layer->setBuffers(client, w, h, format, flags);
1287 if (LIKELY(err == NO_ERROR)) {
1288 layer->initStates(w, h, flags);
1289 addLayer_l(layer);
1290 } else {
1291 LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
1292 delete layer;
1293 return 0;
1294 }
1295 return layer;
1296}
1297
1298LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked(
1299 Client* client, DisplayID display,
1300 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1301{
1302 LayerBlur* layer = new LayerBlur(this, display, client, id);
1303 layer->initStates(w, h, flags);
1304 addLayer_l(layer);
1305 return layer;
1306}
1307
1308LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked(
1309 Client* client, DisplayID display,
1310 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1311{
1312 LayerDim* layer = new LayerDim(this, display, client, id);
1313 layer->initStates(w, h, flags);
1314 addLayer_l(layer);
1315 return layer;
1316}
1317
1318LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked(
1319 Client* client, DisplayID display,
1320 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1321{
1322 LayerBuffer* layer = new LayerBuffer(this, display, client, id);
1323 layer->initStates(w, h, flags);
1324 addLayer_l(layer);
1325 return layer;
1326}
1327
1328status_t SurfaceFlinger::destroySurface(SurfaceID index)
1329{
1330 Mutex::Autolock _l(mStateLock);
1331 LayerBaseClient* const layer = getLayerUser_l(index);
1332 status_t err = removeLayer_l(layer);
1333 if (err < 0)
1334 return err;
1335 setTransactionFlags(eTransactionNeeded);
1336 return NO_ERROR;
1337}
1338
1339status_t SurfaceFlinger::setClientState(
1340 ClientID cid,
1341 int32_t count,
1342 const layer_state_t* states)
1343{
1344 Mutex::Autolock _l(mStateLock);
1345 uint32_t flags = 0;
1346 cid <<= 16;
1347 for (int i=0 ; i<count ; i++) {
1348 const layer_state_t& s = states[i];
1349 LayerBaseClient* layer = getLayerUser_l(s.surface | cid);
1350 if (layer) {
1351 const uint32_t what = s.what;
1352 // check if it has been destroyed first
1353 if (what & eDestroyed) {
1354 if (removeLayer_l(layer) == NO_ERROR) {
1355 flags |= eTransactionNeeded;
1356 // we skip everything else... well, no, not really
1357 // we skip ONLY that transaction.
1358 continue;
1359 }
1360 }
1361 if (what & ePositionChanged) {
1362 if (layer->setPosition(s.x, s.y))
1363 flags |= eTraversalNeeded;
1364 }
1365 if (what & eLayerChanged) {
1366 if (layer->setLayer(s.z)) {
1367 mCurrentState.layersSortedByZ.reorder(
1368 layer, &Layer::compareCurrentStateZ);
1369 // we need traversal (state changed)
1370 // AND transaction (list changed)
1371 flags |= eTransactionNeeded|eTraversalNeeded;
1372 }
1373 }
1374 if (what & eSizeChanged) {
1375 if (layer->setSize(s.w, s.h))
1376 flags |= eTraversalNeeded;
1377 }
1378 if (what & eAlphaChanged) {
1379 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
1380 flags |= eTraversalNeeded;
1381 }
1382 if (what & eMatrixChanged) {
1383 if (layer->setMatrix(s.matrix))
1384 flags |= eTraversalNeeded;
1385 }
1386 if (what & eTransparentRegionChanged) {
1387 if (layer->setTransparentRegionHint(s.transparentRegion))
1388 flags |= eTraversalNeeded;
1389 }
1390 if (what & eVisibilityChanged) {
1391 if (layer->setFlags(s.flags, s.mask))
1392 flags |= eTraversalNeeded;
1393 }
1394 }
1395 }
1396 if (flags) {
1397 setTransactionFlags(flags);
1398 }
1399 return NO_ERROR;
1400}
1401
1402LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const
1403{
1404 return mLayerMap.valueFor(s);
1405}
1406
1407void SurfaceFlinger::screenReleased(int dpy)
1408{
1409 // this may be called by a signal handler, we can't do too much in here
1410 android_atomic_or(eConsoleReleased, &mConsoleSignals);
1411 signalEvent();
1412}
1413
1414void SurfaceFlinger::screenAcquired(int dpy)
1415{
1416 // this may be called by a signal handler, we can't do too much in here
1417 android_atomic_or(eConsoleAcquired, &mConsoleSignals);
1418 signalEvent();
1419}
1420
1421status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
1422{
1423 const size_t SIZE = 1024;
1424 char buffer[SIZE];
1425 String8 result;
1426 if (checkCallingPermission(
1427 String16("android.permission.DUMP")) == false)
1428 { // not allowed
1429 snprintf(buffer, SIZE, "Permission Denial: "
1430 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1431 IPCThreadState::self()->getCallingPid(),
1432 IPCThreadState::self()->getCallingUid());
1433 result.append(buffer);
1434 } else {
1435 Mutex::Autolock _l(mStateLock);
1436 size_t s = mClientsMap.size();
1437 char name[64];
1438 for (size_t i=0 ; i<s ; i++) {
1439 Client* client = mClientsMap.valueAt(i);
1440 sprintf(name, " Client (id=0x%08x)", client->cid);
1441 client->dump(name);
1442 }
1443 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
1444 const size_t count = currentLayers.size();
1445 for (size_t i=0 ; i<count ; i++) {
1446 /*** LayerBase ***/
1447 LayerBase const * const layer = currentLayers[i];
1448 const Layer::State& s = layer->drawingState();
1449 snprintf(buffer, SIZE,
1450 "+ %s %p\n"
1451 " "
1452 "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
1453 "needsBlending=%1d, invalidate=%1d, "
1454 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
1455 layer->getTypeID(), layer,
1456 s.z, layer->tx(), layer->ty(), s.w, s.h,
The Android Open Source Project27629322009-01-09 17:51:23 -08001457 layer->needsBlending(), layer->contentDirty,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001458 s.alpha, s.flags,
1459 s.transform[0], s.transform[1],
1460 s.transform[2], s.transform[3]);
1461 result.append(buffer);
1462 buffer[0] = 0;
1463 /*** LayerBaseClient ***/
1464 LayerBaseClient* const lbc =
1465 LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer);
1466 if (lbc) {
1467 snprintf(buffer, SIZE,
1468 " "
1469 "id=0x%08x, client=0x%08x, identity=%u\n",
1470 lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
1471 lbc->getIdentity());
1472 }
1473 result.append(buffer);
1474 buffer[0] = 0;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001475 /*** Layer ***/
1476 Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer);
1477 if (l) {
1478 const LayerBitmap& buf0(l->getBuffer(0));
1479 const LayerBitmap& buf1(l->getBuffer(1));
1480 snprintf(buffer, SIZE,
1481 " "
1482 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d,"
1483 " freezeLock=%p, swapState=0x%08x\n",
1484 l->pixelFormat(),
1485 buf0.width(), buf0.height(), buf0.stride(),
1486 buf1.width(), buf1.height(), buf1.stride(),
1487 l->getTextureName(), l->getFreezeLock().get(),
1488 l->lcblk->swapState);
1489 }
1490 result.append(buffer);
1491 buffer[0] = 0;
1492 s.transparentRegion.dump(result, "transparentRegion");
1493 layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
1494 layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
1495 }
1496 mWormholeRegion.dump(result, "WormholeRegion");
1497 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1498 snprintf(buffer, SIZE,
1499 " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1500 mFreezeDisplay?"yes":"no", mFreezeCount,
1501 mCurrentState.orientation, hw.canDraw());
1502 result.append(buffer);
1503
1504 sp<AllocatorInterface> allocator;
1505 if (mGPU != 0) {
1506 snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner());
1507 result.append(buffer);
1508 allocator = mGPU->getAllocator();
1509 if (allocator != 0) {
1510 allocator->dump(result, "GPU Allocator");
1511 }
1512 }
1513 allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM);
1514 if (allocator != 0) {
1515 allocator->dump(result, "PMEM Allocator");
1516 }
1517 }
1518 write(fd, result.string(), result.size());
1519 return NO_ERROR;
1520}
1521
1522status_t SurfaceFlinger::onTransact(
1523 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1524{
1525 switch (code) {
1526 case CREATE_CONNECTION:
1527 case OPEN_GLOBAL_TRANSACTION:
1528 case CLOSE_GLOBAL_TRANSACTION:
1529 case SET_ORIENTATION:
1530 case FREEZE_DISPLAY:
1531 case UNFREEZE_DISPLAY:
1532 case BOOT_FINISHED:
1533 case REVOKE_GPU:
1534 {
1535 // codes that require permission check
1536 IPCThreadState* ipc = IPCThreadState::self();
1537 const int pid = ipc->getCallingPid();
1538 const int self_pid = getpid();
1539 if (UNLIKELY(pid != self_pid)) {
1540 // we're called from a different process, do the real check
1541 if (!checkCallingPermission(
1542 String16("android.permission.ACCESS_SURFACE_FLINGER")))
1543 {
1544 const int uid = ipc->getCallingUid();
1545 LOGE("Permission Denial: "
1546 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
1547 return PERMISSION_DENIED;
1548 }
1549 }
1550 }
1551 }
1552
1553 status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
1554 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001555 // HARDWARE_TEST stuff...
1556 if (UNLIKELY(checkCallingPermission(
1557 String16("android.permission.HARDWARE_TEST")) == false))
1558 { // not allowed
1559 LOGE("Permission Denial: pid=%d, uid=%d\n",
1560 IPCThreadState::self()->getCallingPid(),
1561 IPCThreadState::self()->getCallingUid());
1562 return PERMISSION_DENIED;
1563 }
1564 int n;
1565 switch (code) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001566 case 1000: // SHOW_CPU
1567 n = data.readInt32();
1568 mDebugCpu = n ? 1 : 0;
1569 if (mDebugCpu) {
1570 if (mCpuGauge == 0) {
1571 mCpuGauge = new CPUGauge(this, ms2ns(500));
1572 }
1573 } else {
1574 if (mCpuGauge != 0) {
1575 mCpuGauge->requestExitAndWait();
1576 Mutex::Autolock _l(mDebugLock);
1577 mCpuGauge.clear();
1578 }
1579 }
1580 return NO_ERROR;
1581 case 1001: // SHOW_FPS
1582 n = data.readInt32();
1583 mDebugFps = n ? 1 : 0;
1584 return NO_ERROR;
1585 case 1002: // SHOW_UPDATES
1586 n = data.readInt32();
1587 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
1588 return NO_ERROR;
1589 case 1003: // SHOW_BACKGROUND
1590 n = data.readInt32();
1591 mDebugBackground = n ? 1 : 0;
1592 return NO_ERROR;
1593 case 1004:{ // repaint everything
1594 Mutex::Autolock _l(mStateLock);
1595 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1596 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
1597 signalEvent();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001598 }
1599 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001600 case 1005: // ask GPU revoke
1601 mGPU->friendlyRevoke();
1602 return NO_ERROR;
1603 case 1006: // revoke GPU
1604 mGPU->unconditionalRevoke();
1605 return NO_ERROR;
1606 case 1007: // set mFreezeCount
1607 mFreezeCount = data.readInt32();
1608 return NO_ERROR;
1609 case 1010: // interrogate.
1610 reply->writeInt32(mDebugCpu);
1611 reply->writeInt32(0);
1612 reply->writeInt32(mDebugRegion);
1613 reply->writeInt32(mDebugBackground);
1614 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001615 case 1013: {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001616 Mutex::Autolock _l(mStateLock);
1617 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1618 reply->writeInt32(hw.getPageFlipCount());
1619 }
1620 return NO_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001621 }
1622 }
1623 return err;
1624}
1625
1626// ---------------------------------------------------------------------------
1627#if 0
1628#pragma mark -
1629#endif
1630
1631Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
1632 : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
1633{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001634 mSharedHeapAllocator = getSurfaceHeapManager()->createHeap();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001635 const int pgsize = getpagesize();
1636 const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
1637 mCblkHeap = new MemoryDealer(cblksize);
1638 mCblkMemory = mCblkHeap->allocate(cblksize);
1639 if (mCblkMemory != 0) {
1640 ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
1641 if (ctrlblk) { // construct the shared structure in-place.
1642 new(ctrlblk) per_client_cblk_t;
1643 }
1644 }
1645}
1646
1647Client::~Client() {
1648 if (ctrlblk) {
1649 const int pgsize = getpagesize();
1650 ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
1651 }
1652}
1653
1654const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const {
1655 return mFlinger->getSurfaceHeapManager();
1656}
1657
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001658int32_t Client::generateId(int pid)
1659{
1660 const uint32_t i = clz( ~mBitmap );
1661 if (i >= NUM_LAYERS_MAX) {
1662 return NO_MEMORY;
1663 }
1664 mPid = pid;
1665 mInUse.add(uint8_t(i));
1666 mBitmap |= 1<<(31-i);
1667 return i;
1668}
1669status_t Client::bindLayer(LayerBaseClient* layer, int32_t id)
1670{
1671 ssize_t idx = mInUse.indexOf(id);
1672 if (idx < 0)
1673 return NAME_NOT_FOUND;
1674 return mLayers.insertAt(layer, idx);
1675}
1676void Client::free(int32_t id)
1677{
1678 ssize_t idx = mInUse.remove(uint8_t(id));
1679 if (idx >= 0) {
1680 mBitmap &= ~(1<<(31-id));
1681 mLayers.removeItemsAt(idx);
1682 }
1683}
1684
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001685sp<MemoryDealer> Client::createAllocator(uint32_t flags)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001686{
1687 sp<MemoryDealer> allocator;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001688 allocator = getSurfaceHeapManager()->createHeap(
1689 flags, getClientPid(), mSharedHeapAllocator);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001690 return allocator;
1691}
1692
1693bool Client::isValid(int32_t i) const {
1694 return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
1695}
1696const uint8_t* Client::inUseArray() const {
1697 return mInUse.array();
1698}
1699size_t Client::numActiveLayers() const {
1700 return mInUse.size();
1701}
1702LayerBaseClient* Client::getLayerUser(int32_t i) const {
1703 ssize_t idx = mInUse.indexOf(uint8_t(i));
1704 if (idx<0) return 0;
1705 return mLayers[idx];
1706}
1707
1708void Client::dump(const char* what)
1709{
1710}
1711
1712// ---------------------------------------------------------------------------
1713#if 0
1714#pragma mark -
1715#endif
1716
1717BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
1718 : mId(cid), mFlinger(flinger), mCblk(cblk)
1719{
1720}
1721
1722BClient::~BClient() {
1723 // destroy all resources attached to this client
1724 mFlinger->destroyConnection(mId);
1725}
1726
1727void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
1728 *ctrl = mCblk;
1729}
1730
1731sp<ISurface> BClient::createSurface(
1732 ISurfaceFlingerClient::surface_data_t* params, int pid,
1733 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
1734 uint32_t flags)
1735{
1736 return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags);
1737}
1738
1739status_t BClient::destroySurface(SurfaceID sid)
1740{
1741 sid |= (mId << 16); // add the client-part to id
1742 return mFlinger->destroySurface(sid);
1743}
1744
1745status_t BClient::setState(int32_t count, const layer_state_t* states)
1746{
1747 return mFlinger->setClientState(mId, count, states);
1748}
1749
1750// ---------------------------------------------------------------------------
1751
1752GraphicPlane::GraphicPlane()
1753 : mHw(0)
1754{
1755}
1756
1757GraphicPlane::~GraphicPlane() {
1758 delete mHw;
1759}
1760
1761bool GraphicPlane::initialized() const {
1762 return mHw ? true : false;
1763}
1764
1765void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
1766 mHw = hw;
1767}
1768
1769void GraphicPlane::setTransform(const Transform& tr) {
1770 mTransform = tr;
1771 mGlobalTransform = mOrientationTransform * mTransform;
1772}
1773
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001774status_t GraphicPlane::orientationToTransfrom(
1775 int orientation, int w, int h, Transform* tr)
1776{
1777 float a, b, c, d, x, y;
1778 switch (orientation) {
1779 case ISurfaceComposer::eOrientationDefault:
1780 a=1; b=0; c=0; d=1; x=0; y=0;
1781 break;
1782 case ISurfaceComposer::eOrientation90:
1783 a=0; b=-1; c=1; d=0; x=w; y=0;
1784 break;
1785 case ISurfaceComposer::eOrientation180:
1786 a=-1; b=0; c=0; d=-1; x=w; y=h;
1787 break;
1788 case ISurfaceComposer::eOrientation270:
1789 a=0; b=1; c=-1; d=0; x=0; y=h;
1790 break;
1791 default:
1792 return BAD_VALUE;
1793 }
1794 tr->set(a, b, c, d);
1795 tr->set(x, y);
1796 return NO_ERROR;
1797}
1798
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001799status_t GraphicPlane::setOrientation(int orientation)
1800{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001801 const DisplayHardware& hw(displayHardware());
1802 const float w = hw.getWidth();
1803 const float h = hw.getHeight();
1804
1805 if (orientation == ISurfaceComposer::eOrientationDefault) {
1806 // make sure the default orientation is optimal
1807 mOrientationTransform.reset();
1808 mGlobalTransform = mTransform;
1809 return NO_ERROR;
1810 }
1811
1812 // If the rotation can be handled in hardware, this is where
1813 // the magic should happen.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001814 if (UNLIKELY(orientation == 42)) {
1815 float a, b, c, d, x, y;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001816 const float r = (3.14159265f / 180.0f) * 42.0f;
1817 const float si = sinf(r);
1818 const float co = cosf(r);
1819 a=co; b=-si; c=si; d=co;
1820 x = si*(h*0.5f) + (1-co)*(w*0.5f);
1821 y =-si*(w*0.5f) + (1-co)*(h*0.5f);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001822 mOrientationTransform.set(a, b, c, d);
1823 mOrientationTransform.set(x, y);
1824 } else {
1825 GraphicPlane::orientationToTransfrom(orientation, w, h,
1826 &mOrientationTransform);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001827 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001828
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001829 mGlobalTransform = mOrientationTransform * mTransform;
1830 return NO_ERROR;
1831}
1832
1833const DisplayHardware& GraphicPlane::displayHardware() const {
1834 return *mHw;
1835}
1836
1837const Transform& GraphicPlane::transform() const {
1838 return mGlobalTransform;
1839}
1840
1841// ---------------------------------------------------------------------------
1842
1843}; // namespace android