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