blob: 0e998bfe4bef66e14029565e852f4f0ec164cf0f [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
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
41#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"
55#include "LayerOrientationAnim.h"
56#include "OrientationAnimation.h"
57#include "SurfaceFlinger.h"
58#include "VRamHeap.h"
59
60#include "DisplayHardware/DisplayHardware.h"
61#include "GPUHardware/GPUHardware.h"
62
63
Mathias Agopiana1ecca92009-05-21 19:21:59 -070064/* ideally AID_GRAPHICS would be in a semi-public header
65 * or there would be a way to map a user/group name to its id
66 */
67#ifndef AID_GRAPHICS
68#define AID_GRAPHICS 1003
69#endif
70
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080071#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),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700189 mFreezeDisplayTime(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800190 mDebugRegion(0),
191 mDebugCpu(0),
192 mDebugFps(0),
193 mDebugBackground(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194 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
206 // 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);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216
217 LOGI_IF(mDebugRegion, "showupdates enabled");
218 LOGI_IF(mDebugCpu, "showcpu enabled");
219 LOGI_IF(mDebugBackground, "showbackground enabled");
220 LOGI_IF(mDebugFps, "showfps enabled");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800221}
222
223SurfaceFlinger::~SurfaceFlinger()
224{
225 glDeleteTextures(1, &mWormholeTexName);
226 delete mOrientationAnimation;
227}
228
229copybit_device_t* SurfaceFlinger::getBlitEngine() const
230{
231 return graphicPlane(0).displayHardware().getBlitEngine();
232}
233
234overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
235{
236 return graphicPlane(0).displayHardware().getOverlayEngine();
237}
238
239sp<IMemory> SurfaceFlinger::getCblk() const
240{
241 return mServerCblkMemory;
242}
243
244status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
245 gpu_info_t* gpu)
246{
Mathias Agopian2b42fa72009-04-27 18:50:06 -0700247 if (mGPU == 0)
248 return INVALID_OPERATION;
249
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800250 IPCThreadState* ipc = IPCThreadState::self();
251 const int pid = ipc->getCallingPid();
252 status_t err = mGPU->request(pid, callback, gpu);
253 return err;
254}
255
256status_t SurfaceFlinger::revokeGPU()
257{
Mathias Agopian2b42fa72009-04-27 18:50:06 -0700258 if (mGPU == 0)
259 return INVALID_OPERATION;
260
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800261 return mGPU->friendlyRevoke();
262}
263
264sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
265{
266 Mutex::Autolock _l(mStateLock);
267 uint32_t token = mTokens.acquire();
268
269 Client* client = new Client(token, this);
270 if ((client == 0) || (client->ctrlblk == 0)) {
271 mTokens.release(token);
272 return 0;
273 }
274 status_t err = mClientsMap.add(token, client);
275 if (err < 0) {
276 delete client;
277 mTokens.release(token);
278 return 0;
279 }
280 sp<BClient> bclient =
281 new BClient(this, token, client->controlBlockMemory());
282 return bclient;
283}
284
285void SurfaceFlinger::destroyConnection(ClientID cid)
286{
287 Mutex::Autolock _l(mStateLock);
288 Client* const client = mClientsMap.valueFor(cid);
289 if (client) {
290 // free all the layers this client owns
291 const Vector<LayerBaseClient*>& layers = client->getLayers();
292 const size_t count = layers.size();
293 for (size_t i=0 ; i<count ; i++) {
294 LayerBaseClient* const layer = layers[i];
295 removeLayer_l(layer);
296 }
297
298 // the resources associated with this client will be freed
299 // during the next transaction, after these surfaces have been
300 // properly removed from the screen
301
302 // remove this client from our ClientID->Client mapping.
303 mClientsMap.removeItem(cid);
304
305 // and add it to the list of disconnected clients
306 mDisconnectedClients.add(client);
307
308 // request a transaction
309 setTransactionFlags(eTransactionNeeded);
310 }
311}
312
313const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
314{
315 LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
316 const GraphicPlane& plane(mGraphicPlanes[dpy]);
317 return plane;
318}
319
320GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
321{
322 return const_cast<GraphicPlane&>(
323 const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
324}
325
326void SurfaceFlinger::bootFinished()
327{
328 const nsecs_t now = systemTime();
329 const nsecs_t duration = now - mBootTime;
Mathias Agopiana1ecca92009-05-21 19:21:59 -0700330 LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
331 property_set("ctl.stop", "bootanim");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800332}
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
355 // 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
375 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();
409 dcblk->density = hw.getDensity();
410 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);
421 glPixelStorei(GL_PACK_ALIGNMENT, 4);
422 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
453 mOrientationAnimation = new OrientationAnimation(this);
454
455 // start CPU gauge display
456 if (mDebugCpu)
457 mCpuGauge = new CPUGauge(this, ms2ns(500));
458
Mathias Agopiana1ecca92009-05-21 19:21:59 -0700459
460 // start boot animation
461 property_set("ctl.start", "bootanim");
462
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800463 return NO_ERROR;
464}
465
466// ----------------------------------------------------------------------------
467#if 0
468#pragma mark -
469#pragma mark Events Handler
470#endif
471
472void SurfaceFlinger::waitForEvent()
473{
474 // wait for something to do
475 if (UNLIKELY(isFrozen())) {
476 // wait 5 seconds
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700477 const nsecs_t freezeDisplayTimeout = ms2ns(5000);
478 const nsecs_t now = systemTime();
479 if (mFreezeDisplayTime == 0) {
480 mFreezeDisplayTime = now;
481 }
482 nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
483 int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800484 if (err != NO_ERROR) {
485 if (isFrozen()) {
486 // we timed out and are still frozen
487 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
488 mFreezeDisplay, mFreezeCount);
489 mFreezeCount = 0;
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700490 mFreezeDisplay = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800491 }
492 }
493 } else {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700494 mFreezeDisplayTime = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800495 mSyncObject.wait();
496 }
497}
498
499void SurfaceFlinger::signalEvent() {
500 mSyncObject.open();
501}
502
503void SurfaceFlinger::signal() const {
504 mSyncObject.open();
505}
506
507void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
508{
509 if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) {
510 sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay));
511 delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY);
512 }
513}
514
515// ----------------------------------------------------------------------------
516#if 0
517#pragma mark -
518#pragma mark Main loop
519#endif
520
521bool SurfaceFlinger::threadLoop()
522{
523 waitForEvent();
524
525 // check for transactions
526 if (UNLIKELY(mConsoleSignals)) {
527 handleConsoleEvents();
528 }
529
530 if (LIKELY(mTransactionCount == 0)) {
531 // if we're in a global transaction, don't do anything.
532 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
533 uint32_t transactionFlags = getTransactionFlags(mask);
534 if (LIKELY(transactionFlags)) {
535 handleTransaction(transactionFlags);
536 }
537 }
538
539 // post surfaces (if needed)
540 handlePageFlip();
541
542 const DisplayHardware& hw(graphicPlane(0).displayHardware());
543 if (LIKELY(hw.canDraw())) {
544 // repaint the framebuffer (if needed)
545 handleRepaint();
546
547 // release the clients before we flip ('cause flip might block)
548 unlockClients();
549 executeScheduledBroadcasts();
550
551 // sample the cpu gauge
552 if (UNLIKELY(mDebugCpu)) {
553 handleDebugCpu();
554 }
555
556 postFramebuffer();
557 } else {
558 // pretend we did the post
559 unlockClients();
560 executeScheduledBroadcasts();
561 usleep(16667); // 60 fps period
562 }
563 return true;
564}
565
566void SurfaceFlinger::postFramebuffer()
567{
568 const bool skip = mOrientationAnimation->run();
569 if (UNLIKELY(skip)) {
570 return;
571 }
572
573 if (!mInvalidRegion.isEmpty()) {
574 const DisplayHardware& hw(graphicPlane(0).displayHardware());
575
576 if (UNLIKELY(mDebugFps)) {
577 debugShowFPS();
578 }
579
580 hw.flip(mInvalidRegion);
581
582 mInvalidRegion.clear();
583
584 if (Layer::deletedTextures.size()) {
585 glDeleteTextures(
586 Layer::deletedTextures.size(),
587 Layer::deletedTextures.array());
588 Layer::deletedTextures.clear();
589 }
590 }
591}
592
593void SurfaceFlinger::handleConsoleEvents()
594{
595 // something to do with the console
596 const DisplayHardware& hw = graphicPlane(0).displayHardware();
597
598 int what = android_atomic_and(0, &mConsoleSignals);
599 if (what & eConsoleAcquired) {
600 hw.acquireScreen();
601 }
602
603 if (mDeferReleaseConsole && hw.canDraw()) {
604 // We got the release signal before the aquire signal
605 mDeferReleaseConsole = false;
606 revokeGPU();
607 hw.releaseScreen();
608 }
609
610 if (what & eConsoleReleased) {
611 if (hw.canDraw()) {
612 revokeGPU();
613 hw.releaseScreen();
614 } else {
615 mDeferReleaseConsole = true;
616 }
617 }
618
619 mDirtyRegion.set(hw.bounds());
620}
621
622void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
623{
624 Mutex::Autolock _l(mStateLock);
625
626 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
627 const size_t count = currentLayers.size();
628
629 /*
630 * Traversal of the children
631 * (perform the transaction for each of them if needed)
632 */
633
634 const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
635 if (layersNeedTransaction) {
636 for (size_t i=0 ; i<count ; i++) {
637 LayerBase* const layer = currentLayers[i];
638 uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
639 if (!trFlags) continue;
640
641 const uint32_t flags = layer->doTransaction(0);
642 if (flags & Layer::eVisibleRegion)
643 mVisibleRegionsDirty = true;
644
645 if (flags & Layer::eRestartTransaction) {
646 // restart the transaction, but back-off a little
647 layer->setTransactionFlags(eTransactionNeeded);
648 setTransactionFlags(eTraversalNeeded, ms2ns(8));
649 }
650 }
651 }
652
653 /*
654 * Perform our own transaction if needed
655 */
656
657 if (transactionFlags & eTransactionNeeded) {
658 if (mCurrentState.orientation != mDrawingState.orientation) {
659 // the orientation has changed, recompute all visible regions
660 // and invalidate everything.
661
662 const int dpy = 0;
663 const int orientation = mCurrentState.orientation;
Mathias Agopian24fd77d2009-03-27 16:10:37 -0700664 const uint32_t type = mCurrentState.orientationType;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665 GraphicPlane& plane(graphicPlane(dpy));
666 plane.setOrientation(orientation);
667
668 // update the shared control block
669 const DisplayHardware& hw(plane.displayHardware());
670 volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
671 dcblk->orientation = orientation;
672 if (orientation & eOrientationSwapMask) {
673 // 90 or 270 degrees orientation
674 dcblk->w = hw.getHeight();
675 dcblk->h = hw.getWidth();
676 } else {
677 dcblk->w = hw.getWidth();
678 dcblk->h = hw.getHeight();
679 }
680
681 mVisibleRegionsDirty = true;
682 mDirtyRegion.set(hw.bounds());
Mathias Agopian24fd77d2009-03-27 16:10:37 -0700683 mFreezeDisplayTime = 0;
684 mOrientationAnimation->onOrientationChanged(type);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800685 }
686
687 if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
688 // freezing or unfreezing the display -> trigger animation if needed
689 mFreezeDisplay = mCurrentState.freezeDisplay;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800690 }
691
692 // some layers might have been removed, so
693 // we need to update the regions they're exposing.
694 size_t c = mRemovedLayers.size();
695 if (c) {
696 mVisibleRegionsDirty = true;
697 }
698
699 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
700 if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
701 // layers have been added
702 mVisibleRegionsDirty = true;
703 }
704
705 // get rid of all resources we don't need anymore
706 // (layers and clients)
707 free_resources_l();
708 }
709
710 commitTransaction();
711}
712
713sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
714{
715 return new FreezeLock(const_cast<SurfaceFlinger *>(this));
716}
717
718void SurfaceFlinger::computeVisibleRegions(
719 LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
720{
721 const GraphicPlane& plane(graphicPlane(0));
722 const Transform& planeTransform(plane.transform());
723
724 Region aboveOpaqueLayers;
725 Region aboveCoveredLayers;
726 Region dirty;
727
728 bool secureFrameBuffer = false;
729
730 size_t i = currentLayers.size();
731 while (i--) {
732 LayerBase* const layer = currentLayers[i];
733 layer->validateVisibility(planeTransform);
734
735 // start with the whole surface at its current location
736 const Layer::State& s = layer->drawingState();
737 const Rect bounds(layer->visibleBounds());
738
739 // handle hidden surfaces by setting the visible region to empty
740 Region opaqueRegion;
741 Region visibleRegion;
742 Region coveredRegion;
743 if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) {
744 visibleRegion.clear();
745 } else {
746 const bool translucent = layer->needsBlending();
747 visibleRegion.set(bounds);
748 coveredRegion = visibleRegion;
749
750 // Remove the transparent area from the visible region
751 if (translucent) {
752 visibleRegion.subtractSelf(layer->transparentRegionScreen);
753 }
754
755 // compute the opaque region
756 if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
757 // the opaque region is the visible region
758 opaqueRegion = visibleRegion;
759 }
760 }
761
762 // subtract the opaque region covered by the layers above us
763 visibleRegion.subtractSelf(aboveOpaqueLayers);
764 coveredRegion.andSelf(aboveCoveredLayers);
765
766 // compute this layer's dirty region
767 if (layer->contentDirty) {
768 // we need to invalidate the whole region
769 dirty = visibleRegion;
770 // as well, as the old visible region
771 dirty.orSelf(layer->visibleRegionScreen);
772 layer->contentDirty = false;
773 } else {
774 // compute the exposed region
775 // dirty = what's visible now - what's wasn't covered before
776 // = what's visible now & what's was covered before
777 dirty = visibleRegion.intersect(layer->coveredRegionScreen);
778 }
779 dirty.subtractSelf(aboveOpaqueLayers);
780
781 // accumulate to the screen dirty region
782 dirtyRegion.orSelf(dirty);
783
784 // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
785 aboveOpaqueLayers.orSelf(opaqueRegion);
786 aboveCoveredLayers.orSelf(bounds);
787
788 // Store the visible region is screen space
789 layer->setVisibleRegion(visibleRegion);
790 layer->setCoveredRegion(coveredRegion);
791
792 // If a secure layer is partially visible, lockdown the screen!
793 if (layer->isSecure() && !visibleRegion.isEmpty()) {
794 secureFrameBuffer = true;
795 }
796 }
797
798 mSecureFrameBuffer = secureFrameBuffer;
799 opaqueRegion = aboveOpaqueLayers;
800}
801
802
803void SurfaceFlinger::commitTransaction()
804{
805 mDrawingState = mCurrentState;
806 mTransactionCV.signal();
807}
808
809void SurfaceFlinger::handlePageFlip()
810{
811 bool visibleRegions = mVisibleRegionsDirty;
812 LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
813 visibleRegions |= lockPageFlip(currentLayers);
814
815 const DisplayHardware& hw = graphicPlane(0).displayHardware();
816 const Region screenRegion(hw.bounds());
817 if (visibleRegions) {
818 Region opaqueRegion;
819 computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
820 mWormholeRegion = screenRegion.subtract(opaqueRegion);
821 mVisibleRegionsDirty = false;
822 }
823
824 unlockPageFlip(currentLayers);
825 mDirtyRegion.andSelf(screenRegion);
826}
827
828bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
829{
830 bool recomputeVisibleRegions = false;
831 size_t count = currentLayers.size();
832 LayerBase* const* layers = currentLayers.array();
833 for (size_t i=0 ; i<count ; i++) {
834 LayerBase* const layer = layers[i];
835 layer->lockPageFlip(recomputeVisibleRegions);
836 }
837 return recomputeVisibleRegions;
838}
839
840void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
841{
842 const GraphicPlane& plane(graphicPlane(0));
843 const Transform& planeTransform(plane.transform());
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->unlockPageFlip(planeTransform, mDirtyRegion);
849 }
850}
851
852void SurfaceFlinger::handleRepaint()
853{
854 // set the frame buffer
855 const DisplayHardware& hw(graphicPlane(0).displayHardware());
856 glMatrixMode(GL_MODELVIEW);
857 glLoadIdentity();
858
859 if (UNLIKELY(mDebugRegion)) {
860 debugFlashRegions();
861 }
862
863 // compute the invalid region
864 mInvalidRegion.orSelf(mDirtyRegion);
865
866 uint32_t flags = hw.getFlags();
867 if (flags & DisplayHardware::BUFFER_PRESERVED) {
868 // here we assume DisplayHardware::flip()'s implementation
869 // performs the copy-back optimization.
870 } else {
871 if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
872 // we need to fully redraw the part that will be updated
873 mDirtyRegion.set(mInvalidRegion.bounds());
874 } else {
875 // we need to redraw everything
876 mDirtyRegion.set(hw.bounds());
877 mInvalidRegion = mDirtyRegion;
878 }
879 }
880
881 // compose all surfaces
882 composeSurfaces(mDirtyRegion);
883
884 // clear the dirty regions
885 mDirtyRegion.clear();
886}
887
888void SurfaceFlinger::composeSurfaces(const Region& dirty)
889{
890 if (UNLIKELY(!mWormholeRegion.isEmpty())) {
891 // should never happen unless the window manager has a bug
892 // draw something...
893 drawWormhole();
894 }
895 const SurfaceFlinger& flinger(*this);
896 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
897 const size_t count = drawingLayers.size();
898 LayerBase const* const* const layers = drawingLayers.array();
899 for (size_t i=0 ; i<count ; ++i) {
900 LayerBase const * const layer = layers[i];
901 const Region& visibleRegion(layer->visibleRegionScreen);
902 if (!visibleRegion.isEmpty()) {
903 const Region clip(dirty.intersect(visibleRegion));
904 if (!clip.isEmpty()) {
905 layer->draw(clip);
906 }
907 }
908 }
909}
910
911void SurfaceFlinger::unlockClients()
912{
913 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
914 const size_t count = drawingLayers.size();
915 LayerBase* const* const layers = drawingLayers.array();
916 for (size_t i=0 ; i<count ; ++i) {
917 LayerBase* const layer = layers[i];
918 layer->finishPageFlip();
919 }
920}
921
922void SurfaceFlinger::scheduleBroadcast(Client* client)
923{
924 if (mLastScheduledBroadcast != client) {
925 mLastScheduledBroadcast = client;
926 mScheduledBroadcasts.add(client);
927 }
928}
929
930void SurfaceFlinger::executeScheduledBroadcasts()
931{
932 SortedVector<Client*>& list = mScheduledBroadcasts;
933 size_t count = list.size();
934 while (count--) {
935 per_client_cblk_t* const cblk = list[count]->ctrlblk;
936 if (cblk->lock.tryLock() == NO_ERROR) {
937 cblk->cv.broadcast();
938 list.removeAt(count);
939 cblk->lock.unlock();
940 } else {
941 // schedule another round
942 LOGW("executeScheduledBroadcasts() skipped, "
943 "contention on the client. We'll try again later...");
944 signalDelayedEvent(ms2ns(4));
945 }
946 }
947 mLastScheduledBroadcast = 0;
948}
949
950void SurfaceFlinger::handleDebugCpu()
951{
952 Mutex::Autolock _l(mDebugLock);
953 if (mCpuGauge != 0)
954 mCpuGauge->sample();
955}
956
957void SurfaceFlinger::debugFlashRegions()
958{
959 if (UNLIKELY(!mDirtyRegion.isRect())) {
960 // TODO: do this only if we don't have preserving
961 // swapBuffer. If we don't have update-on-demand,
962 // redraw everything.
963 composeSurfaces(Region(mDirtyRegion.bounds()));
964 }
965
966 glDisable(GL_TEXTURE_2D);
967 glDisable(GL_BLEND);
968 glDisable(GL_DITHER);
969 glDisable(GL_SCISSOR_TEST);
970
971 glColor4x(0x10000, 0, 0x10000, 0x10000);
972
973 Rect r;
974 Region::iterator iterator(mDirtyRegion);
975 while (iterator.iterate(&r)) {
976 GLfloat vertices[][2] = {
977 { r.left, r.top },
978 { r.left, r.bottom },
979 { r.right, r.bottom },
980 { r.right, r.top }
981 };
982 glVertexPointer(2, GL_FLOAT, 0, vertices);
983 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
984 }
985
986 const DisplayHardware& hw(graphicPlane(0).displayHardware());
987 hw.flip(mDirtyRegion.merge(mInvalidRegion));
988 mInvalidRegion.clear();
989
990 if (mDebugRegion > 1)
991 usleep(mDebugRegion * 1000);
992
993 glEnable(GL_SCISSOR_TEST);
994 //mDirtyRegion.dump("mDirtyRegion");
995}
996
997void SurfaceFlinger::drawWormhole() const
998{
999 const Region region(mWormholeRegion.intersect(mDirtyRegion));
1000 if (region.isEmpty())
1001 return;
1002
1003 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1004 const int32_t width = hw.getWidth();
1005 const int32_t height = hw.getHeight();
1006
1007 glDisable(GL_BLEND);
1008 glDisable(GL_DITHER);
1009
1010 if (LIKELY(!mDebugBackground)) {
1011 glClearColorx(0,0,0,0);
1012 Rect r;
1013 Region::iterator iterator(region);
1014 while (iterator.iterate(&r)) {
1015 const GLint sy = height - (r.top + r.height());
1016 glScissor(r.left, sy, r.width(), r.height());
1017 glClear(GL_COLOR_BUFFER_BIT);
1018 }
1019 } else {
1020 const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
1021 { width, height }, { 0, height } };
1022 const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
1023 glVertexPointer(2, GL_SHORT, 0, vertices);
1024 glTexCoordPointer(2, GL_SHORT, 0, tcoords);
1025 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1026 glEnable(GL_TEXTURE_2D);
1027 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
1028 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1029 glMatrixMode(GL_TEXTURE);
1030 glLoadIdentity();
1031 glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
1032 Rect r;
1033 Region::iterator iterator(region);
1034 while (iterator.iterate(&r)) {
1035 const GLint sy = height - (r.top + r.height());
1036 glScissor(r.left, sy, r.width(), r.height());
1037 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1038 }
1039 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1040 }
1041}
1042
1043void SurfaceFlinger::debugShowFPS() const
1044{
1045 static int mFrameCount;
1046 static int mLastFrameCount = 0;
1047 static nsecs_t mLastFpsTime = 0;
1048 static float mFps = 0;
1049 mFrameCount++;
1050 nsecs_t now = systemTime();
1051 nsecs_t diff = now - mLastFpsTime;
1052 if (diff > ms2ns(250)) {
1053 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
1054 mLastFpsTime = now;
1055 mLastFrameCount = mFrameCount;
1056 }
1057 // XXX: mFPS has the value we want
1058 }
1059
1060status_t SurfaceFlinger::addLayer(LayerBase* layer)
1061{
1062 Mutex::Autolock _l(mStateLock);
1063 addLayer_l(layer);
1064 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1065 return NO_ERROR;
1066}
1067
1068status_t SurfaceFlinger::removeLayer(LayerBase* layer)
1069{
1070 Mutex::Autolock _l(mStateLock);
1071 removeLayer_l(layer);
1072 setTransactionFlags(eTransactionNeeded);
1073 return NO_ERROR;
1074}
1075
1076status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer)
1077{
1078 layer->forceVisibilityTransaction();
1079 setTransactionFlags(eTraversalNeeded);
1080 return NO_ERROR;
1081}
1082
1083status_t SurfaceFlinger::addLayer_l(LayerBase* layer)
1084{
1085 ssize_t i = mCurrentState.layersSortedByZ.add(
1086 layer, &LayerBase::compareCurrentStateZ);
1087 LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer);
1088 if (lbc) {
1089 mLayerMap.add(lbc->serverIndex(), lbc);
1090 }
1091 mRemovedLayers.remove(layer);
1092 return NO_ERROR;
1093}
1094
1095status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase)
1096{
1097 ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
1098 if (index >= 0) {
1099 mRemovedLayers.add(layerBase);
1100 LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase);
1101 if (layer) {
1102 mLayerMap.removeItem(layer->serverIndex());
1103 }
1104 return NO_ERROR;
1105 }
1106 // it's possible that we don't find a layer, because it might
1107 // have been destroyed already -- this is not technically an error
1108 // from the user because there is a race between destroySurface,
1109 // destroyclient and destroySurface-from-a-transaction.
1110 return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
1111}
1112
1113void SurfaceFlinger::free_resources_l()
1114{
1115 // Destroy layers that were removed
1116 destroy_all_removed_layers_l();
1117
1118 // free resources associated with disconnected clients
1119 SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
1120 Vector<Client*>& disconnectedClients(mDisconnectedClients);
1121 const size_t count = disconnectedClients.size();
1122 for (size_t i=0 ; i<count ; i++) {
1123 Client* client = disconnectedClients[i];
1124 // if this client is the scheduled broadcast list,
1125 // remove it from there (and we don't need to signal it
1126 // since it is dead).
1127 int32_t index = scheduledBroadcasts.indexOf(client);
1128 if (index >= 0) {
1129 scheduledBroadcasts.removeItemsAt(index);
1130 }
1131 mTokens.release(client->cid);
1132 delete client;
1133 }
1134 disconnectedClients.clear();
1135}
1136
1137void SurfaceFlinger::destroy_all_removed_layers_l()
1138{
1139 size_t c = mRemovedLayers.size();
1140 while (c--) {
1141 LayerBase* const removed_layer = mRemovedLayers[c];
1142
1143 LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0,
1144 "layer %p removed but still in the current state list",
1145 removed_layer);
1146
1147 delete removed_layer;
1148 }
1149 mRemovedLayers.clear();
1150}
1151
1152
1153uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
1154{
1155 return android_atomic_and(~flags, &mTransactionFlags) & flags;
1156}
1157
1158uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
1159{
1160 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
1161 if ((old & flags)==0) { // wake the server up
1162 if (delay > 0) {
1163 signalDelayedEvent(delay);
1164 } else {
1165 signalEvent();
1166 }
1167 }
1168 return old;
1169}
1170
1171void SurfaceFlinger::openGlobalTransaction()
1172{
1173 android_atomic_inc(&mTransactionCount);
1174}
1175
1176void SurfaceFlinger::closeGlobalTransaction()
1177{
1178 if (android_atomic_dec(&mTransactionCount) == 1) {
1179 signalEvent();
1180 }
1181}
1182
1183status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
1184{
1185 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1186 return BAD_VALUE;
1187
1188 Mutex::Autolock _l(mStateLock);
1189 mCurrentState.freezeDisplay = 1;
1190 setTransactionFlags(eTransactionNeeded);
1191
1192 // flags is intended to communicate some sort of animation behavior
1193 // (for instance fadding)
1194 return NO_ERROR;
1195}
1196
1197status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
1198{
1199 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1200 return BAD_VALUE;
1201
1202 Mutex::Autolock _l(mStateLock);
1203 mCurrentState.freezeDisplay = 0;
1204 setTransactionFlags(eTransactionNeeded);
1205
1206 // flags is intended to communicate some sort of animation behavior
1207 // (for instance fadding)
1208 return NO_ERROR;
1209}
1210
Mathias Agopian24fd77d2009-03-27 16:10:37 -07001211int SurfaceFlinger::setOrientation(DisplayID dpy,
1212 int orientation, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001213{
1214 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1215 return BAD_VALUE;
1216
1217 Mutex::Autolock _l(mStateLock);
1218 if (mCurrentState.orientation != orientation) {
1219 if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
Mathias Agopian24fd77d2009-03-27 16:10:37 -07001220 mCurrentState.orientationType = flags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001221 mCurrentState.orientation = orientation;
1222 setTransactionFlags(eTransactionNeeded);
1223 mTransactionCV.wait(mStateLock);
1224 } else {
1225 orientation = BAD_VALUE;
1226 }
1227 }
1228 return orientation;
1229}
1230
1231sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
1232 ISurfaceFlingerClient::surface_data_t* params,
1233 DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
1234 uint32_t flags)
1235{
1236 LayerBaseClient* layer = 0;
1237 sp<LayerBaseClient::Surface> surfaceHandle;
1238 Mutex::Autolock _l(mStateLock);
1239 Client* const c = mClientsMap.valueFor(clientId);
1240 if (UNLIKELY(!c)) {
1241 LOGE("createSurface() failed, client not found (id=%d)", clientId);
1242 return surfaceHandle;
1243 }
1244
1245 //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
1246 int32_t id = c->generateId(pid);
1247 if (uint32_t(id) >= NUM_LAYERS_MAX) {
1248 LOGE("createSurface() failed, generateId = %d", id);
1249 return surfaceHandle;
1250 }
1251
1252 switch (flags & eFXSurfaceMask) {
1253 case eFXSurfaceNormal:
1254 if (UNLIKELY(flags & ePushBuffers)) {
1255 layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
1256 } else {
1257 layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
1258 }
1259 break;
1260 case eFXSurfaceBlur:
1261 layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
1262 break;
1263 case eFXSurfaceDim:
1264 layer = createDimSurfaceLocked(c, d, id, w, h, flags);
1265 break;
1266 }
1267
1268 if (layer) {
1269 setTransactionFlags(eTransactionNeeded);
1270 surfaceHandle = layer->getSurface();
1271 if (surfaceHandle != 0)
1272 surfaceHandle->getSurfaceData(params);
1273 }
1274
1275 return surfaceHandle;
1276}
1277
1278LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
1279 Client* client, DisplayID display,
1280 int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
1281{
1282 // initialize the surfaces
1283 switch (format) { // TODO: take h/w into account
1284 case PIXEL_FORMAT_TRANSPARENT:
1285 case PIXEL_FORMAT_TRANSLUCENT:
1286 format = PIXEL_FORMAT_RGBA_8888;
1287 break;
1288 case PIXEL_FORMAT_OPAQUE:
1289 format = PIXEL_FORMAT_RGB_565;
1290 break;
1291 }
1292
1293 Layer* layer = new Layer(this, display, client, id);
1294 status_t err = layer->setBuffers(client, w, h, format, flags);
1295 if (LIKELY(err == NO_ERROR)) {
1296 layer->initStates(w, h, flags);
1297 addLayer_l(layer);
1298 } else {
1299 LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
1300 delete layer;
1301 return 0;
1302 }
1303 return layer;
1304}
1305
1306LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked(
1307 Client* client, DisplayID display,
1308 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1309{
1310 LayerBlur* layer = new LayerBlur(this, display, client, id);
1311 layer->initStates(w, h, flags);
1312 addLayer_l(layer);
1313 return layer;
1314}
1315
1316LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked(
1317 Client* client, DisplayID display,
1318 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1319{
1320 LayerDim* layer = new LayerDim(this, display, client, id);
1321 layer->initStates(w, h, flags);
1322 addLayer_l(layer);
1323 return layer;
1324}
1325
1326LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked(
1327 Client* client, DisplayID display,
1328 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1329{
1330 LayerBuffer* layer = new LayerBuffer(this, display, client, id);
1331 layer->initStates(w, h, flags);
1332 addLayer_l(layer);
1333 return layer;
1334}
1335
1336status_t SurfaceFlinger::destroySurface(SurfaceID index)
1337{
1338 Mutex::Autolock _l(mStateLock);
1339 LayerBaseClient* const layer = getLayerUser_l(index);
1340 status_t err = removeLayer_l(layer);
1341 if (err < 0)
1342 return err;
1343 setTransactionFlags(eTransactionNeeded);
1344 return NO_ERROR;
1345}
1346
1347status_t SurfaceFlinger::setClientState(
1348 ClientID cid,
1349 int32_t count,
1350 const layer_state_t* states)
1351{
1352 Mutex::Autolock _l(mStateLock);
1353 uint32_t flags = 0;
1354 cid <<= 16;
1355 for (int i=0 ; i<count ; i++) {
1356 const layer_state_t& s = states[i];
1357 LayerBaseClient* layer = getLayerUser_l(s.surface | cid);
1358 if (layer) {
1359 const uint32_t what = s.what;
1360 // check if it has been destroyed first
1361 if (what & eDestroyed) {
1362 if (removeLayer_l(layer) == NO_ERROR) {
1363 flags |= eTransactionNeeded;
1364 // we skip everything else... well, no, not really
1365 // we skip ONLY that transaction.
1366 continue;
1367 }
1368 }
1369 if (what & ePositionChanged) {
1370 if (layer->setPosition(s.x, s.y))
1371 flags |= eTraversalNeeded;
1372 }
1373 if (what & eLayerChanged) {
1374 if (layer->setLayer(s.z)) {
1375 mCurrentState.layersSortedByZ.reorder(
1376 layer, &Layer::compareCurrentStateZ);
1377 // we need traversal (state changed)
1378 // AND transaction (list changed)
1379 flags |= eTransactionNeeded|eTraversalNeeded;
1380 }
1381 }
1382 if (what & eSizeChanged) {
1383 if (layer->setSize(s.w, s.h))
1384 flags |= eTraversalNeeded;
1385 }
1386 if (what & eAlphaChanged) {
1387 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
1388 flags |= eTraversalNeeded;
1389 }
1390 if (what & eMatrixChanged) {
1391 if (layer->setMatrix(s.matrix))
1392 flags |= eTraversalNeeded;
1393 }
1394 if (what & eTransparentRegionChanged) {
1395 if (layer->setTransparentRegionHint(s.transparentRegion))
1396 flags |= eTraversalNeeded;
1397 }
1398 if (what & eVisibilityChanged) {
1399 if (layer->setFlags(s.flags, s.mask))
1400 flags |= eTraversalNeeded;
1401 }
1402 }
1403 }
1404 if (flags) {
1405 setTransactionFlags(flags);
1406 }
1407 return NO_ERROR;
1408}
1409
1410LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const
1411{
1412 return mLayerMap.valueFor(s);
1413}
1414
1415void SurfaceFlinger::screenReleased(int dpy)
1416{
1417 // this may be called by a signal handler, we can't do too much in here
1418 android_atomic_or(eConsoleReleased, &mConsoleSignals);
1419 signalEvent();
1420}
1421
1422void SurfaceFlinger::screenAcquired(int dpy)
1423{
1424 // this may be called by a signal handler, we can't do too much in here
1425 android_atomic_or(eConsoleAcquired, &mConsoleSignals);
1426 signalEvent();
1427}
1428
1429status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
1430{
1431 const size_t SIZE = 1024;
1432 char buffer[SIZE];
1433 String8 result;
1434 if (checkCallingPermission(
1435 String16("android.permission.DUMP")) == false)
1436 { // not allowed
1437 snprintf(buffer, SIZE, "Permission Denial: "
1438 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1439 IPCThreadState::self()->getCallingPid(),
1440 IPCThreadState::self()->getCallingUid());
1441 result.append(buffer);
1442 } else {
1443 Mutex::Autolock _l(mStateLock);
1444 size_t s = mClientsMap.size();
1445 char name[64];
1446 for (size_t i=0 ; i<s ; i++) {
1447 Client* client = mClientsMap.valueAt(i);
1448 sprintf(name, " Client (id=0x%08x)", client->cid);
1449 client->dump(name);
1450 }
1451 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
1452 const size_t count = currentLayers.size();
1453 for (size_t i=0 ; i<count ; i++) {
1454 /*** LayerBase ***/
1455 LayerBase const * const layer = currentLayers[i];
1456 const Layer::State& s = layer->drawingState();
1457 snprintf(buffer, SIZE,
1458 "+ %s %p\n"
1459 " "
1460 "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
1461 "needsBlending=%1d, invalidate=%1d, "
1462 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
1463 layer->getTypeID(), layer,
1464 s.z, layer->tx(), layer->ty(), s.w, s.h,
1465 layer->needsBlending(), layer->contentDirty,
1466 s.alpha, s.flags,
1467 s.transform[0], s.transform[1],
1468 s.transform[2], s.transform[3]);
1469 result.append(buffer);
1470 buffer[0] = 0;
1471 /*** LayerBaseClient ***/
1472 LayerBaseClient* const lbc =
1473 LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer);
1474 if (lbc) {
1475 snprintf(buffer, SIZE,
1476 " "
1477 "id=0x%08x, client=0x%08x, identity=%u\n",
1478 lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
1479 lbc->getIdentity());
1480 }
1481 result.append(buffer);
1482 buffer[0] = 0;
1483 /*** Layer ***/
1484 Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer);
1485 if (l) {
1486 const LayerBitmap& buf0(l->getBuffer(0));
1487 const LayerBitmap& buf1(l->getBuffer(1));
1488 snprintf(buffer, SIZE,
1489 " "
1490 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d,"
1491 " freezeLock=%p, swapState=0x%08x\n",
1492 l->pixelFormat(),
1493 buf0.width(), buf0.height(), buf0.stride(),
1494 buf1.width(), buf1.height(), buf1.stride(),
1495 l->getTextureName(), l->getFreezeLock().get(),
1496 l->lcblk->swapState);
1497 }
1498 result.append(buffer);
1499 buffer[0] = 0;
1500 s.transparentRegion.dump(result, "transparentRegion");
1501 layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
1502 layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
1503 }
1504 mWormholeRegion.dump(result, "WormholeRegion");
1505 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1506 snprintf(buffer, SIZE,
1507 " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1508 mFreezeDisplay?"yes":"no", mFreezeCount,
1509 mCurrentState.orientation, hw.canDraw());
1510 result.append(buffer);
1511
1512 sp<AllocatorInterface> allocator;
1513 if (mGPU != 0) {
1514 snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner());
1515 result.append(buffer);
1516 allocator = mGPU->getAllocator();
1517 if (allocator != 0) {
1518 allocator->dump(result, "GPU Allocator");
1519 }
1520 }
1521 allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM);
1522 if (allocator != 0) {
1523 allocator->dump(result, "PMEM Allocator");
1524 }
1525 }
1526 write(fd, result.string(), result.size());
1527 return NO_ERROR;
1528}
1529
1530status_t SurfaceFlinger::onTransact(
1531 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1532{
1533 switch (code) {
1534 case CREATE_CONNECTION:
1535 case OPEN_GLOBAL_TRANSACTION:
1536 case CLOSE_GLOBAL_TRANSACTION:
1537 case SET_ORIENTATION:
1538 case FREEZE_DISPLAY:
1539 case UNFREEZE_DISPLAY:
1540 case BOOT_FINISHED:
1541 case REVOKE_GPU:
1542 {
1543 // codes that require permission check
1544 IPCThreadState* ipc = IPCThreadState::self();
1545 const int pid = ipc->getCallingPid();
Mathias Agopiana1ecca92009-05-21 19:21:59 -07001546 const int uid = ipc->getCallingUid();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001547 const int self_pid = getpid();
Mathias Agopiana1ecca92009-05-21 19:21:59 -07001548 if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001549 // we're called from a different process, do the real check
1550 if (!checkCallingPermission(
1551 String16("android.permission.ACCESS_SURFACE_FLINGER")))
1552 {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001553 LOGE("Permission Denial: "
1554 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
1555 return PERMISSION_DENIED;
1556 }
1557 }
1558 }
1559 }
1560
1561 status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
1562 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1563 // HARDWARE_TEST stuff...
1564 if (UNLIKELY(checkCallingPermission(
1565 String16("android.permission.HARDWARE_TEST")) == false))
1566 { // not allowed
1567 LOGE("Permission Denial: pid=%d, uid=%d\n",
1568 IPCThreadState::self()->getCallingPid(),
1569 IPCThreadState::self()->getCallingUid());
1570 return PERMISSION_DENIED;
1571 }
1572 int n;
1573 switch (code) {
1574 case 1000: // SHOW_CPU
1575 n = data.readInt32();
1576 mDebugCpu = n ? 1 : 0;
1577 if (mDebugCpu) {
1578 if (mCpuGauge == 0) {
1579 mCpuGauge = new CPUGauge(this, ms2ns(500));
1580 }
1581 } else {
1582 if (mCpuGauge != 0) {
1583 mCpuGauge->requestExitAndWait();
1584 Mutex::Autolock _l(mDebugLock);
1585 mCpuGauge.clear();
1586 }
1587 }
1588 return NO_ERROR;
1589 case 1001: // SHOW_FPS
1590 n = data.readInt32();
1591 mDebugFps = n ? 1 : 0;
1592 return NO_ERROR;
1593 case 1002: // SHOW_UPDATES
1594 n = data.readInt32();
1595 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
1596 return NO_ERROR;
1597 case 1003: // SHOW_BACKGROUND
1598 n = data.readInt32();
1599 mDebugBackground = n ? 1 : 0;
1600 return NO_ERROR;
1601 case 1004:{ // repaint everything
1602 Mutex::Autolock _l(mStateLock);
1603 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1604 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
1605 signalEvent();
1606 }
1607 return NO_ERROR;
1608 case 1005: // ask GPU revoke
Mathias Agopian2b42fa72009-04-27 18:50:06 -07001609 if (mGPU != 0) {
1610 mGPU->friendlyRevoke();
1611 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001612 return NO_ERROR;
1613 case 1006: // revoke GPU
Mathias Agopian2b42fa72009-04-27 18:50:06 -07001614 if (mGPU != 0) {
1615 mGPU->unconditionalRevoke();
1616 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001617 return NO_ERROR;
1618 case 1007: // set mFreezeCount
1619 mFreezeCount = data.readInt32();
1620 return NO_ERROR;
1621 case 1010: // interrogate.
1622 reply->writeInt32(mDebugCpu);
1623 reply->writeInt32(0);
1624 reply->writeInt32(mDebugRegion);
1625 reply->writeInt32(mDebugBackground);
1626 return NO_ERROR;
1627 case 1013: {
1628 Mutex::Autolock _l(mStateLock);
1629 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1630 reply->writeInt32(hw.getPageFlipCount());
1631 }
1632 return NO_ERROR;
1633 }
1634 }
1635 return err;
1636}
1637
1638// ---------------------------------------------------------------------------
1639#if 0
1640#pragma mark -
1641#endif
1642
1643Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
1644 : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
1645{
1646 mSharedHeapAllocator = getSurfaceHeapManager()->createHeap();
1647 const int pgsize = getpagesize();
1648 const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
1649 mCblkHeap = new MemoryDealer(cblksize);
1650 mCblkMemory = mCblkHeap->allocate(cblksize);
1651 if (mCblkMemory != 0) {
1652 ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
1653 if (ctrlblk) { // construct the shared structure in-place.
1654 new(ctrlblk) per_client_cblk_t;
1655 }
1656 }
1657}
1658
1659Client::~Client() {
1660 if (ctrlblk) {
1661 const int pgsize = getpagesize();
1662 ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
1663 }
1664}
1665
1666const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const {
1667 return mFlinger->getSurfaceHeapManager();
1668}
1669
1670int32_t Client::generateId(int pid)
1671{
1672 const uint32_t i = clz( ~mBitmap );
1673 if (i >= NUM_LAYERS_MAX) {
1674 return NO_MEMORY;
1675 }
1676 mPid = pid;
1677 mInUse.add(uint8_t(i));
1678 mBitmap |= 1<<(31-i);
1679 return i;
1680}
1681status_t Client::bindLayer(LayerBaseClient* layer, int32_t id)
1682{
1683 ssize_t idx = mInUse.indexOf(id);
1684 if (idx < 0)
1685 return NAME_NOT_FOUND;
1686 return mLayers.insertAt(layer, idx);
1687}
1688void Client::free(int32_t id)
1689{
1690 ssize_t idx = mInUse.remove(uint8_t(id));
1691 if (idx >= 0) {
1692 mBitmap &= ~(1<<(31-id));
1693 mLayers.removeItemsAt(idx);
1694 }
1695}
1696
1697sp<MemoryDealer> Client::createAllocator(uint32_t flags)
1698{
1699 sp<MemoryDealer> allocator;
1700 allocator = getSurfaceHeapManager()->createHeap(
1701 flags, getClientPid(), mSharedHeapAllocator);
1702 return allocator;
1703}
1704
1705bool Client::isValid(int32_t i) const {
1706 return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
1707}
1708const uint8_t* Client::inUseArray() const {
1709 return mInUse.array();
1710}
1711size_t Client::numActiveLayers() const {
1712 return mInUse.size();
1713}
1714LayerBaseClient* Client::getLayerUser(int32_t i) const {
1715 ssize_t idx = mInUse.indexOf(uint8_t(i));
1716 if (idx<0) return 0;
1717 return mLayers[idx];
1718}
1719
1720void Client::dump(const char* what)
1721{
1722}
1723
1724// ---------------------------------------------------------------------------
1725#if 0
1726#pragma mark -
1727#endif
1728
1729BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
1730 : mId(cid), mFlinger(flinger), mCblk(cblk)
1731{
1732}
1733
1734BClient::~BClient() {
1735 // destroy all resources attached to this client
1736 mFlinger->destroyConnection(mId);
1737}
1738
1739void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
1740 *ctrl = mCblk;
1741}
1742
1743sp<ISurface> BClient::createSurface(
1744 ISurfaceFlingerClient::surface_data_t* params, int pid,
1745 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
1746 uint32_t flags)
1747{
1748 return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags);
1749}
1750
1751status_t BClient::destroySurface(SurfaceID sid)
1752{
1753 sid |= (mId << 16); // add the client-part to id
1754 return mFlinger->destroySurface(sid);
1755}
1756
1757status_t BClient::setState(int32_t count, const layer_state_t* states)
1758{
1759 return mFlinger->setClientState(mId, count, states);
1760}
1761
1762// ---------------------------------------------------------------------------
1763
1764GraphicPlane::GraphicPlane()
1765 : mHw(0)
1766{
1767}
1768
1769GraphicPlane::~GraphicPlane() {
1770 delete mHw;
1771}
1772
1773bool GraphicPlane::initialized() const {
1774 return mHw ? true : false;
1775}
1776
1777void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
1778 mHw = hw;
1779}
1780
1781void GraphicPlane::setTransform(const Transform& tr) {
1782 mTransform = tr;
1783 mGlobalTransform = mOrientationTransform * mTransform;
1784}
1785
1786status_t GraphicPlane::orientationToTransfrom(
1787 int orientation, int w, int h, Transform* tr)
1788{
1789 float a, b, c, d, x, y;
1790 switch (orientation) {
1791 case ISurfaceComposer::eOrientationDefault:
1792 a=1; b=0; c=0; d=1; x=0; y=0;
1793 break;
1794 case ISurfaceComposer::eOrientation90:
1795 a=0; b=-1; c=1; d=0; x=w; y=0;
1796 break;
1797 case ISurfaceComposer::eOrientation180:
1798 a=-1; b=0; c=0; d=-1; x=w; y=h;
1799 break;
1800 case ISurfaceComposer::eOrientation270:
1801 a=0; b=1; c=-1; d=0; x=0; y=h;
1802 break;
1803 default:
1804 return BAD_VALUE;
1805 }
1806 tr->set(a, b, c, d);
1807 tr->set(x, y);
1808 return NO_ERROR;
1809}
1810
1811status_t GraphicPlane::setOrientation(int orientation)
1812{
1813 const DisplayHardware& hw(displayHardware());
1814 const float w = hw.getWidth();
1815 const float h = hw.getHeight();
1816
1817 if (orientation == ISurfaceComposer::eOrientationDefault) {
1818 // make sure the default orientation is optimal
1819 mOrientationTransform.reset();
Mathias Agopianecbeaa02009-03-27 15:36:09 -07001820 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001821 mGlobalTransform = mTransform;
1822 return NO_ERROR;
1823 }
1824
1825 // If the rotation can be handled in hardware, this is where
1826 // the magic should happen.
1827 if (UNLIKELY(orientation == 42)) {
1828 float a, b, c, d, x, y;
1829 const float r = (3.14159265f / 180.0f) * 42.0f;
1830 const float si = sinf(r);
1831 const float co = cosf(r);
1832 a=co; b=-si; c=si; d=co;
1833 x = si*(h*0.5f) + (1-co)*(w*0.5f);
1834 y =-si*(w*0.5f) + (1-co)*(h*0.5f);
1835 mOrientationTransform.set(a, b, c, d);
1836 mOrientationTransform.set(x, y);
1837 } else {
1838 GraphicPlane::orientationToTransfrom(orientation, w, h,
1839 &mOrientationTransform);
1840 }
Mathias Agopianecbeaa02009-03-27 15:36:09 -07001841 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001842 mGlobalTransform = mOrientationTransform * mTransform;
1843 return NO_ERROR;
1844}
1845
1846const DisplayHardware& GraphicPlane::displayHardware() const {
1847 return *mHw;
1848}
1849
1850const Transform& GraphicPlane::transform() const {
1851 return mGlobalTransform;
1852}
1853
1854// ---------------------------------------------------------------------------
1855
1856}; // namespace android