blob: 6b2a103d61ce59beaab114e4cf29222ddce27c80 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <stdlib.h>
18#include <stdio.h>
19#include <stdint.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <math.h>
Jean-Baptiste Querua837ba72009-01-26 11:51:12 -080024#include <limits.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/ioctl.h>
28
29#include <cutils/log.h>
30#include <cutils/properties.h>
31
32#include <utils/IPCThreadState.h>
33#include <utils/IServiceManager.h>
34#include <utils/MemoryDealer.h>
35#include <utils/MemoryBase.h>
36#include <utils/String8.h>
37#include <utils/String16.h>
38#include <utils/StopWatch.h>
39
40#include <ui/PixelFormat.h>
41#include <ui/DisplayInfo.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042
43#include <pixelflinger/pixelflinger.h>
44#include <GLES/gl.h>
45
46#include "clz.h"
Mathias Agopian076b1cc2009-04-10 14:24:30 -070047#include "BufferAllocator.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048#include "Layer.h"
49#include "LayerBlur.h"
50#include "LayerBuffer.h"
51#include "LayerDim.h"
52#include "LayerBitmap.h"
53#include "LayerOrientationAnim.h"
54#include "OrientationAnimation.h"
55#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080056
57#include "DisplayHardware/DisplayHardware.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080058
59
60#define DISPLAY_COUNT 1
61
62namespace android {
63
64// ---------------------------------------------------------------------------
65
66void SurfaceFlinger::instantiate() {
67 defaultServiceManager()->addService(
68 String16("SurfaceFlinger"), new SurfaceFlinger());
69}
70
71void SurfaceFlinger::shutdown() {
72 // we should unregister here, but not really because
73 // when (if) the service manager goes away, all the services
74 // it has a reference to will leave too.
75}
76
77// ---------------------------------------------------------------------------
78
79SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs)
80 : lookup(rhs.lookup), layers(rhs.layers)
81{
82}
83
84ssize_t SurfaceFlinger::LayerVector::indexOf(
Mathias Agopian076b1cc2009-04-10 14:24:30 -070085 const sp<LayerBase>& key, size_t guess) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080086{
87 if (guess<size() && lookup.keyAt(guess) == key)
88 return guess;
89 const ssize_t i = lookup.indexOfKey(key);
90 if (i>=0) {
91 const size_t idx = lookup.valueAt(i);
Mathias Agopian076b1cc2009-04-10 14:24:30 -070092 LOGE_IF(layers[idx]!=key,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080093 "LayerVector[%p]: layers[%d]=%p, key=%p",
Mathias Agopian076b1cc2009-04-10 14:24:30 -070094 this, int(idx), layers[idx].get(), key.get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080095 return idx;
96 }
97 return i;
98}
99
100ssize_t SurfaceFlinger::LayerVector::add(
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700101 const sp<LayerBase>& layer,
102 Vector< sp<LayerBase> >::compar_t cmp)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800103{
104 size_t count = layers.size();
105 ssize_t l = 0;
106 ssize_t h = count-1;
107 ssize_t mid;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700108 sp<LayerBase> const* a = layers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800109 while (l <= h) {
110 mid = l + (h - l)/2;
111 const int c = cmp(a+mid, &layer);
112 if (c == 0) { l = mid; break; }
113 else if (c<0) { l = mid+1; }
114 else { h = mid-1; }
115 }
116 size_t order = l;
117 while (order<count && !cmp(&layer, a+order)) {
118 order++;
119 }
120 count = lookup.size();
121 for (size_t i=0 ; i<count ; i++) {
122 if (lookup.valueAt(i) >= order) {
123 lookup.editValueAt(i)++;
124 }
125 }
126 layers.insertAt(layer, order);
127 lookup.add(layer, order);
128 return order;
129}
130
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700131ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800132{
133 const ssize_t keyIndex = lookup.indexOfKey(layer);
134 if (keyIndex >= 0) {
135 const size_t index = lookup.valueAt(keyIndex);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700136 LOGE_IF(layers[index]!=layer,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137 "LayerVector[%p]: layers[%u]=%p, layer=%p",
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700138 this, int(index), layers[index].get(), layer.get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800139 layers.removeItemsAt(index);
140 lookup.removeItemsAt(keyIndex);
141 const size_t count = lookup.size();
142 for (size_t i=0 ; i<count ; i++) {
143 if (lookup.valueAt(i) >= size_t(index)) {
144 lookup.editValueAt(i)--;
145 }
146 }
147 return index;
148 }
149 return NAME_NOT_FOUND;
150}
151
152ssize_t SurfaceFlinger::LayerVector::reorder(
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700153 const sp<LayerBase>& layer,
154 Vector< sp<LayerBase> >::compar_t cmp)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800155{
156 // XXX: it's a little lame. but oh well...
157 ssize_t err = remove(layer);
158 if (err >=0)
159 err = add(layer, cmp);
160 return err;
161}
162
163// ---------------------------------------------------------------------------
164#if 0
165#pragma mark -
166#endif
167
168SurfaceFlinger::SurfaceFlinger()
169 : BnSurfaceComposer(), Thread(false),
170 mTransactionFlags(0),
171 mTransactionCount(0),
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700172 mLayersRemoved(false),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800173 mBootTime(systemTime()),
174 mLastScheduledBroadcast(NULL),
175 mVisibleRegionsDirty(false),
176 mDeferReleaseConsole(false),
177 mFreezeDisplay(false),
178 mFreezeCount(0),
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700179 mFreezeDisplayTime(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800180 mDebugRegion(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800181 mDebugFps(0),
182 mDebugBackground(0),
183 mDebugNoBootAnimation(0),
184 mSyncObject(),
185 mDeplayedTransactionPending(0),
186 mConsoleSignals(0),
187 mSecureFrameBuffer(0)
188{
189 init();
190}
191
192void SurfaceFlinger::init()
193{
194 LOGI("SurfaceFlinger is starting");
195
196 // debugging stuff...
197 char value[PROPERTY_VALUE_MAX];
198 property_get("debug.sf.showupdates", value, "0");
199 mDebugRegion = atoi(value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200 property_get("debug.sf.showbackground", value, "0");
201 mDebugBackground = atoi(value);
202 property_get("debug.sf.showfps", value, "0");
203 mDebugFps = atoi(value);
204 property_get("debug.sf.nobootanimation", value, "0");
205 mDebugNoBootAnimation = atoi(value);
206
207 LOGI_IF(mDebugRegion, "showupdates enabled");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800208 LOGI_IF(mDebugBackground, "showbackground enabled");
209 LOGI_IF(mDebugFps, "showfps enabled");
210 LOGI_IF(mDebugNoBootAnimation, "boot animation disabled");
211}
212
213SurfaceFlinger::~SurfaceFlinger()
214{
215 glDeleteTextures(1, &mWormholeTexName);
216 delete mOrientationAnimation;
217}
218
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800219overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
220{
221 return graphicPlane(0).displayHardware().getOverlayEngine();
222}
223
224sp<IMemory> SurfaceFlinger::getCblk() const
225{
226 return mServerCblkMemory;
227}
228
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800229sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
230{
231 Mutex::Autolock _l(mStateLock);
232 uint32_t token = mTokens.acquire();
233
234 Client* client = new Client(token, this);
235 if ((client == 0) || (client->ctrlblk == 0)) {
236 mTokens.release(token);
237 return 0;
238 }
239 status_t err = mClientsMap.add(token, client);
240 if (err < 0) {
241 delete client;
242 mTokens.release(token);
243 return 0;
244 }
245 sp<BClient> bclient =
246 new BClient(this, token, client->controlBlockMemory());
247 return bclient;
248}
249
250void SurfaceFlinger::destroyConnection(ClientID cid)
251{
252 Mutex::Autolock _l(mStateLock);
253 Client* const client = mClientsMap.valueFor(cid);
254 if (client) {
255 // free all the layers this client owns
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700256 const Vector< wp<LayerBaseClient> >& layers = client->getLayers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800257 const size_t count = layers.size();
258 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700259 sp<LayerBaseClient> layer(layers[i].promote());
260 if (layer != 0) {
261 removeLayer_l(layer);
262 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800263 }
264
265 // the resources associated with this client will be freed
266 // during the next transaction, after these surfaces have been
267 // properly removed from the screen
268
269 // remove this client from our ClientID->Client mapping.
270 mClientsMap.removeItem(cid);
271
272 // and add it to the list of disconnected clients
273 mDisconnectedClients.add(client);
274
275 // request a transaction
276 setTransactionFlags(eTransactionNeeded);
277 }
278}
279
280const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
281{
282 LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
283 const GraphicPlane& plane(mGraphicPlanes[dpy]);
284 return plane;
285}
286
287GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
288{
289 return const_cast<GraphicPlane&>(
290 const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
291}
292
293void SurfaceFlinger::bootFinished()
294{
295 const nsecs_t now = systemTime();
296 const nsecs_t duration = now - mBootTime;
297 LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
298 if (mBootAnimation != 0) {
299 mBootAnimation->requestExit();
300 mBootAnimation.clear();
301 }
302}
303
304void SurfaceFlinger::onFirstRef()
305{
306 run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
307
308 // Wait for the main thread to be done with its initialization
309 mReadyToRunBarrier.wait();
310}
311
312
313static inline uint16_t pack565(int r, int g, int b) {
314 return (r<<11)|(g<<5)|b;
315}
316
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800317status_t SurfaceFlinger::readyToRun()
318{
319 LOGI( "SurfaceFlinger's main thread ready to run. "
320 "Initializing graphics H/W...");
321
322 // create the shared control-block
323 mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY);
324 LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
325
326 mServerCblkMemory = mServerHeap->allocate(4096);
327 LOGE_IF(mServerCblkMemory==0, "can't create shared control block");
328
329 mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer());
330 LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
331 new(mServerCblk) surface_flinger_cblk_t;
332
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333 // we only support one display currently
334 int dpy = 0;
335
336 {
337 // initialize the main display
338 GraphicPlane& plane(graphicPlane(dpy));
339 DisplayHardware* const hw = new DisplayHardware(this, dpy);
340 plane.setDisplayHardware(hw);
341 }
342
343 // initialize primary screen
344 // (other display should be initialized in the same manner, but
345 // asynchronously, as they could come and go. None of this is supported
346 // yet).
347 const GraphicPlane& plane(graphicPlane(dpy));
348 const DisplayHardware& hw = plane.displayHardware();
349 const uint32_t w = hw.getWidth();
350 const uint32_t h = hw.getHeight();
351 const uint32_t f = hw.getFormat();
352 hw.makeCurrent();
353
354 // initialize the shared control block
355 mServerCblk->connected |= 1<<dpy;
356 display_cblk_t* dcblk = mServerCblk->displays + dpy;
357 memset(dcblk, 0, sizeof(display_cblk_t));
358 dcblk->w = w;
359 dcblk->h = h;
360 dcblk->format = f;
361 dcblk->orientation = ISurfaceComposer::eOrientationDefault;
362 dcblk->xdpi = hw.getDpiX();
363 dcblk->ydpi = hw.getDpiY();
364 dcblk->fps = hw.getRefreshRate();
365 dcblk->density = hw.getDensity();
366 asm volatile ("":::"memory");
367
368 // Initialize OpenGL|ES
369 glActiveTexture(GL_TEXTURE0);
370 glBindTexture(GL_TEXTURE_2D, 0);
371 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
372 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
373 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
374 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
375 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
376 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
377 glPixelStorei(GL_PACK_ALIGNMENT, 4);
378 glEnableClientState(GL_VERTEX_ARRAY);
379 glEnable(GL_SCISSOR_TEST);
380 glShadeModel(GL_FLAT);
381 glDisable(GL_DITHER);
382 glDisable(GL_CULL_FACE);
383
384 const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
385 const uint16_t g1 = pack565(0x17,0x2f,0x17);
386 const uint16_t textureData[4] = { g0, g1, g1, g0 };
387 glGenTextures(1, &mWormholeTexName);
388 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
389 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
390 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
391 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
392 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
393 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
394 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);
395
396 glViewport(0, 0, w, h);
397 glMatrixMode(GL_PROJECTION);
398 glLoadIdentity();
399 glOrthof(0, w, h, 0, 0, 1);
400
401 LayerDim::initDimmer(this, w, h);
402
403 mReadyToRunBarrier.open();
404
405 /*
406 * We're now ready to accept clients...
407 */
408
409 mOrientationAnimation = new OrientationAnimation(this);
410
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411 // the boot animation!
412 if (mDebugNoBootAnimation == false)
413 mBootAnimation = new BootAnimation(this);
414
415 return NO_ERROR;
416}
417
418// ----------------------------------------------------------------------------
419#if 0
420#pragma mark -
421#pragma mark Events Handler
422#endif
423
424void SurfaceFlinger::waitForEvent()
425{
426 // wait for something to do
427 if (UNLIKELY(isFrozen())) {
428 // wait 5 seconds
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700429 const nsecs_t freezeDisplayTimeout = ms2ns(5000);
430 const nsecs_t now = systemTime();
431 if (mFreezeDisplayTime == 0) {
432 mFreezeDisplayTime = now;
433 }
434 nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
435 int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800436 if (err != NO_ERROR) {
437 if (isFrozen()) {
438 // we timed out and are still frozen
439 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
440 mFreezeDisplay, mFreezeCount);
441 mFreezeCount = 0;
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700442 mFreezeDisplay = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800443 }
444 }
445 } else {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700446 mFreezeDisplayTime = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800447 mSyncObject.wait();
448 }
449}
450
451void SurfaceFlinger::signalEvent() {
452 mSyncObject.open();
453}
454
455void SurfaceFlinger::signal() const {
456 mSyncObject.open();
457}
458
459void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
460{
461 if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) {
462 sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay));
463 delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY);
464 }
465}
466
467// ----------------------------------------------------------------------------
468#if 0
469#pragma mark -
470#pragma mark Main loop
471#endif
472
473bool SurfaceFlinger::threadLoop()
474{
475 waitForEvent();
476
477 // check for transactions
478 if (UNLIKELY(mConsoleSignals)) {
479 handleConsoleEvents();
480 }
481
482 if (LIKELY(mTransactionCount == 0)) {
483 // if we're in a global transaction, don't do anything.
484 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
485 uint32_t transactionFlags = getTransactionFlags(mask);
486 if (LIKELY(transactionFlags)) {
487 handleTransaction(transactionFlags);
488 }
489 }
490
491 // post surfaces (if needed)
492 handlePageFlip();
493
494 const DisplayHardware& hw(graphicPlane(0).displayHardware());
495 if (LIKELY(hw.canDraw())) {
496 // repaint the framebuffer (if needed)
497 handleRepaint();
498
499 // release the clients before we flip ('cause flip might block)
500 unlockClients();
501 executeScheduledBroadcasts();
502
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800503 postFramebuffer();
504 } else {
505 // pretend we did the post
506 unlockClients();
507 executeScheduledBroadcasts();
508 usleep(16667); // 60 fps period
509 }
510 return true;
511}
512
513void SurfaceFlinger::postFramebuffer()
514{
515 const bool skip = mOrientationAnimation->run();
516 if (UNLIKELY(skip)) {
517 return;
518 }
519
520 if (!mInvalidRegion.isEmpty()) {
521 const DisplayHardware& hw(graphicPlane(0).displayHardware());
522
523 if (UNLIKELY(mDebugFps)) {
524 debugShowFPS();
525 }
526
527 hw.flip(mInvalidRegion);
528
529 mInvalidRegion.clear();
530
531 if (Layer::deletedTextures.size()) {
532 glDeleteTextures(
533 Layer::deletedTextures.size(),
534 Layer::deletedTextures.array());
535 Layer::deletedTextures.clear();
536 }
537 }
538}
539
540void SurfaceFlinger::handleConsoleEvents()
541{
542 // something to do with the console
543 const DisplayHardware& hw = graphicPlane(0).displayHardware();
544
545 int what = android_atomic_and(0, &mConsoleSignals);
546 if (what & eConsoleAcquired) {
547 hw.acquireScreen();
548 }
549
550 if (mDeferReleaseConsole && hw.canDraw()) {
Mathias Agopian62b74442009-04-14 23:02:51 -0700551 // We got the release signal before the acquire signal
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800552 mDeferReleaseConsole = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800553 hw.releaseScreen();
554 }
555
556 if (what & eConsoleReleased) {
557 if (hw.canDraw()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800558 hw.releaseScreen();
559 } else {
560 mDeferReleaseConsole = true;
561 }
562 }
563
564 mDirtyRegion.set(hw.bounds());
565}
566
567void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
568{
569 Mutex::Autolock _l(mStateLock);
570
571 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
572 const size_t count = currentLayers.size();
573
574 /*
575 * Traversal of the children
576 * (perform the transaction for each of them if needed)
577 */
578
579 const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
580 if (layersNeedTransaction) {
581 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700582 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800583 uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
584 if (!trFlags) continue;
585
586 const uint32_t flags = layer->doTransaction(0);
587 if (flags & Layer::eVisibleRegion)
588 mVisibleRegionsDirty = true;
589
590 if (flags & Layer::eRestartTransaction) {
591 // restart the transaction, but back-off a little
592 layer->setTransactionFlags(eTransactionNeeded);
593 setTransactionFlags(eTraversalNeeded, ms2ns(8));
594 }
595 }
596 }
597
598 /*
599 * Perform our own transaction if needed
600 */
601
602 if (transactionFlags & eTransactionNeeded) {
603 if (mCurrentState.orientation != mDrawingState.orientation) {
604 // the orientation has changed, recompute all visible regions
605 // and invalidate everything.
606
607 const int dpy = 0;
608 const int orientation = mCurrentState.orientation;
Mathias Agopianc08731e2009-03-27 18:11:38 -0700609 const uint32_t type = mCurrentState.orientationType;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800610 GraphicPlane& plane(graphicPlane(dpy));
611 plane.setOrientation(orientation);
612
613 // update the shared control block
614 const DisplayHardware& hw(plane.displayHardware());
615 volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
616 dcblk->orientation = orientation;
617 if (orientation & eOrientationSwapMask) {
618 // 90 or 270 degrees orientation
619 dcblk->w = hw.getHeight();
620 dcblk->h = hw.getWidth();
621 } else {
622 dcblk->w = hw.getWidth();
623 dcblk->h = hw.getHeight();
624 }
625
626 mVisibleRegionsDirty = true;
627 mDirtyRegion.set(hw.bounds());
Mathias Agopianc08731e2009-03-27 18:11:38 -0700628 mFreezeDisplayTime = 0;
629 mOrientationAnimation->onOrientationChanged(type);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800630 }
631
632 if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
633 // freezing or unfreezing the display -> trigger animation if needed
634 mFreezeDisplay = mCurrentState.freezeDisplay;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800635 }
636
637 // some layers might have been removed, so
638 // we need to update the regions they're exposing.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700639 if (mLayersRemoved) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800640 mVisibleRegionsDirty = true;
641 }
642
643 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
644 if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
645 // layers have been added
646 mVisibleRegionsDirty = true;
647 }
648
649 // get rid of all resources we don't need anymore
650 // (layers and clients)
651 free_resources_l();
652 }
653
654 commitTransaction();
655}
656
657sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
658{
659 return new FreezeLock(const_cast<SurfaceFlinger *>(this));
660}
661
662void SurfaceFlinger::computeVisibleRegions(
663 LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
664{
665 const GraphicPlane& plane(graphicPlane(0));
666 const Transform& planeTransform(plane.transform());
667
668 Region aboveOpaqueLayers;
669 Region aboveCoveredLayers;
670 Region dirty;
671
672 bool secureFrameBuffer = false;
673
674 size_t i = currentLayers.size();
675 while (i--) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700676 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800677 layer->validateVisibility(planeTransform);
678
679 // start with the whole surface at its current location
680 const Layer::State& s = layer->drawingState();
681 const Rect bounds(layer->visibleBounds());
682
683 // handle hidden surfaces by setting the visible region to empty
684 Region opaqueRegion;
685 Region visibleRegion;
686 Region coveredRegion;
687 if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) {
688 visibleRegion.clear();
689 } else {
690 const bool translucent = layer->needsBlending();
691 visibleRegion.set(bounds);
692 coveredRegion = visibleRegion;
693
694 // Remove the transparent area from the visible region
695 if (translucent) {
696 visibleRegion.subtractSelf(layer->transparentRegionScreen);
697 }
698
699 // compute the opaque region
700 if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
701 // the opaque region is the visible region
702 opaqueRegion = visibleRegion;
703 }
704 }
705
706 // subtract the opaque region covered by the layers above us
707 visibleRegion.subtractSelf(aboveOpaqueLayers);
708 coveredRegion.andSelf(aboveCoveredLayers);
709
710 // compute this layer's dirty region
711 if (layer->contentDirty) {
712 // we need to invalidate the whole region
713 dirty = visibleRegion;
714 // as well, as the old visible region
715 dirty.orSelf(layer->visibleRegionScreen);
716 layer->contentDirty = false;
717 } else {
718 // compute the exposed region
719 // dirty = what's visible now - what's wasn't covered before
720 // = what's visible now & what's was covered before
721 dirty = visibleRegion.intersect(layer->coveredRegionScreen);
722 }
723 dirty.subtractSelf(aboveOpaqueLayers);
724
725 // accumulate to the screen dirty region
726 dirtyRegion.orSelf(dirty);
727
Mathias Agopian62b74442009-04-14 23:02:51 -0700728 // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800729 aboveOpaqueLayers.orSelf(opaqueRegion);
730 aboveCoveredLayers.orSelf(bounds);
731
732 // Store the visible region is screen space
733 layer->setVisibleRegion(visibleRegion);
734 layer->setCoveredRegion(coveredRegion);
735
Mathias Agopian62b74442009-04-14 23:02:51 -0700736 // If a secure layer is partially visible, lock down the screen!
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800737 if (layer->isSecure() && !visibleRegion.isEmpty()) {
738 secureFrameBuffer = true;
739 }
740 }
741
742 mSecureFrameBuffer = secureFrameBuffer;
743 opaqueRegion = aboveOpaqueLayers;
744}
745
746
747void SurfaceFlinger::commitTransaction()
748{
749 mDrawingState = mCurrentState;
750 mTransactionCV.signal();
751}
752
753void SurfaceFlinger::handlePageFlip()
754{
755 bool visibleRegions = mVisibleRegionsDirty;
756 LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
757 visibleRegions |= lockPageFlip(currentLayers);
758
759 const DisplayHardware& hw = graphicPlane(0).displayHardware();
760 const Region screenRegion(hw.bounds());
761 if (visibleRegions) {
762 Region opaqueRegion;
763 computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
764 mWormholeRegion = screenRegion.subtract(opaqueRegion);
765 mVisibleRegionsDirty = false;
766 }
767
768 unlockPageFlip(currentLayers);
769 mDirtyRegion.andSelf(screenRegion);
770}
771
772bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
773{
774 bool recomputeVisibleRegions = false;
775 size_t count = currentLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700776 sp<LayerBase> const* layers = currentLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800777 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700778 const sp<LayerBase>& layer = layers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800779 layer->lockPageFlip(recomputeVisibleRegions);
780 }
781 return recomputeVisibleRegions;
782}
783
784void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
785{
786 const GraphicPlane& plane(graphicPlane(0));
787 const Transform& planeTransform(plane.transform());
788 size_t count = currentLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700789 sp<LayerBase> const* layers = currentLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800790 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700791 const sp<LayerBase>& layer = layers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800792 layer->unlockPageFlip(planeTransform, mDirtyRegion);
793 }
794}
795
796void SurfaceFlinger::handleRepaint()
797{
798 // set the frame buffer
799 const DisplayHardware& hw(graphicPlane(0).displayHardware());
800 glMatrixMode(GL_MODELVIEW);
801 glLoadIdentity();
802
803 if (UNLIKELY(mDebugRegion)) {
804 debugFlashRegions();
805 }
806
807 // compute the invalid region
808 mInvalidRegion.orSelf(mDirtyRegion);
809
810 uint32_t flags = hw.getFlags();
811 if (flags & DisplayHardware::BUFFER_PRESERVED) {
812 // here we assume DisplayHardware::flip()'s implementation
813 // performs the copy-back optimization.
814 } else {
815 if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
816 // we need to fully redraw the part that will be updated
817 mDirtyRegion.set(mInvalidRegion.bounds());
818 } else {
819 // we need to redraw everything
820 mDirtyRegion.set(hw.bounds());
821 mInvalidRegion = mDirtyRegion;
822 }
823 }
824
825 // compose all surfaces
826 composeSurfaces(mDirtyRegion);
827
828 // clear the dirty regions
829 mDirtyRegion.clear();
830}
831
832void SurfaceFlinger::composeSurfaces(const Region& dirty)
833{
834 if (UNLIKELY(!mWormholeRegion.isEmpty())) {
835 // should never happen unless the window manager has a bug
836 // draw something...
837 drawWormhole();
838 }
839 const SurfaceFlinger& flinger(*this);
840 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
841 const size_t count = drawingLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700842 sp<LayerBase> const* const layers = drawingLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800843 for (size_t i=0 ; i<count ; ++i) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700844 const sp<LayerBase>& layer = layers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800845 const Region& visibleRegion(layer->visibleRegionScreen);
846 if (!visibleRegion.isEmpty()) {
847 const Region clip(dirty.intersect(visibleRegion));
848 if (!clip.isEmpty()) {
849 layer->draw(clip);
850 }
851 }
852 }
853}
854
855void SurfaceFlinger::unlockClients()
856{
857 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
858 const size_t count = drawingLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700859 sp<LayerBase> const* const layers = drawingLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800860 for (size_t i=0 ; i<count ; ++i) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700861 const sp<LayerBase>& layer = layers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800862 layer->finishPageFlip();
863 }
864}
865
866void SurfaceFlinger::scheduleBroadcast(Client* client)
867{
868 if (mLastScheduledBroadcast != client) {
869 mLastScheduledBroadcast = client;
870 mScheduledBroadcasts.add(client);
871 }
872}
873
874void SurfaceFlinger::executeScheduledBroadcasts()
875{
876 SortedVector<Client*>& list = mScheduledBroadcasts;
877 size_t count = list.size();
878 while (count--) {
879 per_client_cblk_t* const cblk = list[count]->ctrlblk;
880 if (cblk->lock.tryLock() == NO_ERROR) {
881 cblk->cv.broadcast();
882 list.removeAt(count);
883 cblk->lock.unlock();
884 } else {
885 // schedule another round
886 LOGW("executeScheduledBroadcasts() skipped, "
887 "contention on the client. We'll try again later...");
888 signalDelayedEvent(ms2ns(4));
889 }
890 }
891 mLastScheduledBroadcast = 0;
892}
893
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800894void SurfaceFlinger::debugFlashRegions()
895{
896 if (UNLIKELY(!mDirtyRegion.isRect())) {
897 // TODO: do this only if we don't have preserving
898 // swapBuffer. If we don't have update-on-demand,
899 // redraw everything.
900 composeSurfaces(Region(mDirtyRegion.bounds()));
901 }
902
903 glDisable(GL_TEXTURE_2D);
904 glDisable(GL_BLEND);
905 glDisable(GL_DITHER);
906 glDisable(GL_SCISSOR_TEST);
907
908 glColor4x(0x10000, 0, 0x10000, 0x10000);
909
910 Rect r;
911 Region::iterator iterator(mDirtyRegion);
912 while (iterator.iterate(&r)) {
913 GLfloat vertices[][2] = {
914 { r.left, r.top },
915 { r.left, r.bottom },
916 { r.right, r.bottom },
917 { r.right, r.top }
918 };
919 glVertexPointer(2, GL_FLOAT, 0, vertices);
920 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
921 }
922
923 const DisplayHardware& hw(graphicPlane(0).displayHardware());
924 hw.flip(mDirtyRegion.merge(mInvalidRegion));
925 mInvalidRegion.clear();
926
927 if (mDebugRegion > 1)
928 usleep(mDebugRegion * 1000);
929
930 glEnable(GL_SCISSOR_TEST);
931 //mDirtyRegion.dump("mDirtyRegion");
932}
933
934void SurfaceFlinger::drawWormhole() const
935{
936 const Region region(mWormholeRegion.intersect(mDirtyRegion));
937 if (region.isEmpty())
938 return;
939
940 const DisplayHardware& hw(graphicPlane(0).displayHardware());
941 const int32_t width = hw.getWidth();
942 const int32_t height = hw.getHeight();
943
944 glDisable(GL_BLEND);
945 glDisable(GL_DITHER);
946
947 if (LIKELY(!mDebugBackground)) {
948 glClearColorx(0,0,0,0);
949 Rect r;
950 Region::iterator iterator(region);
951 while (iterator.iterate(&r)) {
952 const GLint sy = height - (r.top + r.height());
953 glScissor(r.left, sy, r.width(), r.height());
954 glClear(GL_COLOR_BUFFER_BIT);
955 }
956 } else {
957 const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
958 { width, height }, { 0, height } };
959 const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
960 glVertexPointer(2, GL_SHORT, 0, vertices);
961 glTexCoordPointer(2, GL_SHORT, 0, tcoords);
962 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
963 glEnable(GL_TEXTURE_2D);
964 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
965 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
966 glMatrixMode(GL_TEXTURE);
967 glLoadIdentity();
968 glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
969 Rect r;
970 Region::iterator iterator(region);
971 while (iterator.iterate(&r)) {
972 const GLint sy = height - (r.top + r.height());
973 glScissor(r.left, sy, r.width(), r.height());
974 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
975 }
976 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
977 }
978}
979
980void SurfaceFlinger::debugShowFPS() const
981{
982 static int mFrameCount;
983 static int mLastFrameCount = 0;
984 static nsecs_t mLastFpsTime = 0;
985 static float mFps = 0;
986 mFrameCount++;
987 nsecs_t now = systemTime();
988 nsecs_t diff = now - mLastFpsTime;
989 if (diff > ms2ns(250)) {
990 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
991 mLastFpsTime = now;
992 mLastFrameCount = mFrameCount;
993 }
994 // XXX: mFPS has the value we want
995 }
996
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700997status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800998{
999 Mutex::Autolock _l(mStateLock);
1000 addLayer_l(layer);
1001 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1002 return NO_ERROR;
1003}
1004
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001005status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001006{
1007 Mutex::Autolock _l(mStateLock);
1008 removeLayer_l(layer);
1009 setTransactionFlags(eTransactionNeeded);
1010 return NO_ERROR;
1011}
1012
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001013status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001014{
1015 layer->forceVisibilityTransaction();
1016 setTransactionFlags(eTraversalNeeded);
1017 return NO_ERROR;
1018}
1019
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001020status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001021{
1022 ssize_t i = mCurrentState.layersSortedByZ.add(
1023 layer, &LayerBase::compareCurrentStateZ);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001024 sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
1025 if (lbc != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001026 mLayerMap.add(lbc->serverIndex(), lbc);
1027 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001028 return NO_ERROR;
1029}
1030
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001031status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001032{
1033 ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
1034 if (index >= 0) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001035 mLayersRemoved = true;
Mathias Agopian9a112062009-04-17 19:36:26 -07001036 sp<LayerBaseClient> layer =
1037 LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001038 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001039 mLayerMap.removeItem(layer->serverIndex());
1040 }
1041 return NO_ERROR;
1042 }
1043 // it's possible that we don't find a layer, because it might
1044 // have been destroyed already -- this is not technically an error
Mathias Agopian9a112062009-04-17 19:36:26 -07001045 // from the user because there is a race between BClient::destroySurface(),
1046 // ~BClient() and destroySurface-from-a-transaction.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001047 return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
1048}
1049
Mathias Agopian9a112062009-04-17 19:36:26 -07001050status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
1051{
1052 // First add the layer to the purgatory list, which makes sure it won't
1053 // go away, then remove it from the main list (through a transaction).
1054 ssize_t err = removeLayer_l(layerBase);
1055 if (err >= 0) {
1056 mLayerPurgatory.add(layerBase);
1057 }
1058 return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
1059}
1060
1061
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001062void SurfaceFlinger::free_resources_l()
1063{
1064 // Destroy layers that were removed
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001065 mLayersRemoved = false;
1066
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001067 // free resources associated with disconnected clients
1068 SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
1069 Vector<Client*>& disconnectedClients(mDisconnectedClients);
1070 const size_t count = disconnectedClients.size();
1071 for (size_t i=0 ; i<count ; i++) {
1072 Client* client = disconnectedClients[i];
1073 // if this client is the scheduled broadcast list,
1074 // remove it from there (and we don't need to signal it
1075 // since it is dead).
1076 int32_t index = scheduledBroadcasts.indexOf(client);
1077 if (index >= 0) {
1078 scheduledBroadcasts.removeItemsAt(index);
1079 }
1080 mTokens.release(client->cid);
1081 delete client;
1082 }
1083 disconnectedClients.clear();
1084}
1085
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001086uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
1087{
1088 return android_atomic_and(~flags, &mTransactionFlags) & flags;
1089}
1090
1091uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
1092{
1093 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
1094 if ((old & flags)==0) { // wake the server up
1095 if (delay > 0) {
1096 signalDelayedEvent(delay);
1097 } else {
1098 signalEvent();
1099 }
1100 }
1101 return old;
1102}
1103
1104void SurfaceFlinger::openGlobalTransaction()
1105{
1106 android_atomic_inc(&mTransactionCount);
1107}
1108
1109void SurfaceFlinger::closeGlobalTransaction()
1110{
1111 if (android_atomic_dec(&mTransactionCount) == 1) {
1112 signalEvent();
1113 }
1114}
1115
1116status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
1117{
1118 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1119 return BAD_VALUE;
1120
1121 Mutex::Autolock _l(mStateLock);
1122 mCurrentState.freezeDisplay = 1;
1123 setTransactionFlags(eTransactionNeeded);
1124
1125 // flags is intended to communicate some sort of animation behavior
Mathias Agopian62b74442009-04-14 23:02:51 -07001126 // (for instance fading)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001127 return NO_ERROR;
1128}
1129
1130status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
1131{
1132 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1133 return BAD_VALUE;
1134
1135 Mutex::Autolock _l(mStateLock);
1136 mCurrentState.freezeDisplay = 0;
1137 setTransactionFlags(eTransactionNeeded);
1138
1139 // flags is intended to communicate some sort of animation behavior
Mathias Agopian62b74442009-04-14 23:02:51 -07001140 // (for instance fading)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001141 return NO_ERROR;
1142}
1143
Mathias Agopianc08731e2009-03-27 18:11:38 -07001144int SurfaceFlinger::setOrientation(DisplayID dpy,
1145 int orientation, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001146{
1147 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1148 return BAD_VALUE;
1149
1150 Mutex::Autolock _l(mStateLock);
1151 if (mCurrentState.orientation != orientation) {
1152 if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
Mathias Agopianc08731e2009-03-27 18:11:38 -07001153 mCurrentState.orientationType = flags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001154 mCurrentState.orientation = orientation;
1155 setTransactionFlags(eTransactionNeeded);
1156 mTransactionCV.wait(mStateLock);
1157 } else {
1158 orientation = BAD_VALUE;
1159 }
1160 }
1161 return orientation;
1162}
1163
1164sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
1165 ISurfaceFlingerClient::surface_data_t* params,
1166 DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
1167 uint32_t flags)
1168{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001169 sp<LayerBaseClient> layer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001170 sp<LayerBaseClient::Surface> surfaceHandle;
1171 Mutex::Autolock _l(mStateLock);
1172 Client* const c = mClientsMap.valueFor(clientId);
1173 if (UNLIKELY(!c)) {
1174 LOGE("createSurface() failed, client not found (id=%d)", clientId);
1175 return surfaceHandle;
1176 }
1177
1178 //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
1179 int32_t id = c->generateId(pid);
1180 if (uint32_t(id) >= NUM_LAYERS_MAX) {
1181 LOGE("createSurface() failed, generateId = %d", id);
1182 return surfaceHandle;
1183 }
1184
1185 switch (flags & eFXSurfaceMask) {
1186 case eFXSurfaceNormal:
1187 if (UNLIKELY(flags & ePushBuffers)) {
1188 layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
1189 } else {
1190 layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
1191 }
1192 break;
1193 case eFXSurfaceBlur:
1194 layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
1195 break;
1196 case eFXSurfaceDim:
1197 layer = createDimSurfaceLocked(c, d, id, w, h, flags);
1198 break;
1199 }
1200
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001201 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001202 setTransactionFlags(eTransactionNeeded);
1203 surfaceHandle = layer->getSurface();
1204 if (surfaceHandle != 0)
1205 surfaceHandle->getSurfaceData(params);
1206 }
1207
1208 return surfaceHandle;
1209}
1210
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001211sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001212 Client* client, DisplayID display,
1213 int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
1214{
1215 // initialize the surfaces
1216 switch (format) { // TODO: take h/w into account
1217 case PIXEL_FORMAT_TRANSPARENT:
1218 case PIXEL_FORMAT_TRANSLUCENT:
1219 format = PIXEL_FORMAT_RGBA_8888;
1220 break;
1221 case PIXEL_FORMAT_OPAQUE:
1222 format = PIXEL_FORMAT_RGB_565;
1223 break;
1224 }
1225
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001226 sp<Layer> layer = new Layer(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001227 status_t err = layer->setBuffers(client, w, h, format, flags);
1228 if (LIKELY(err == NO_ERROR)) {
1229 layer->initStates(w, h, flags);
1230 addLayer_l(layer);
1231 } else {
1232 LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001233 layer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001234 }
1235 return layer;
1236}
1237
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001238sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001239 Client* client, DisplayID display,
1240 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1241{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001242 sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001243 layer->initStates(w, h, flags);
1244 addLayer_l(layer);
1245 return layer;
1246}
1247
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001248sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001249 Client* client, DisplayID display,
1250 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1251{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001252 sp<LayerDim> layer = new LayerDim(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001253 layer->initStates(w, h, flags);
1254 addLayer_l(layer);
1255 return layer;
1256}
1257
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001258sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001259 Client* client, DisplayID display,
1260 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1261{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001262 sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001263 layer->initStates(w, h, flags);
1264 addLayer_l(layer);
1265 return layer;
1266}
1267
Mathias Agopian9a112062009-04-17 19:36:26 -07001268status_t SurfaceFlinger::removeSurface(SurfaceID index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001269{
Mathias Agopian9a112062009-04-17 19:36:26 -07001270 /*
1271 * called by the window manager, when a surface should be marked for
1272 * destruction.
1273 */
1274
1275 // TODO: here we should make the surface disappear from the screen
1276 // and mark it for removal. however, we can't free anything until all
1277 // client are done. All operations on this surface should return errors.
1278
1279 status_t err = NAME_NOT_FOUND;
1280 sp<LayerBaseClient> layer;
1281
1282 { // scope for the lock
1283 Mutex::Autolock _l(mStateLock);
1284 layer = getLayerUser_l(index);
1285 err = purgatorizeLayer_l(layer);
1286 if (err == NO_ERROR) {
1287 setTransactionFlags(eTransactionNeeded);
1288 }
1289 }
1290
1291 if (layer != 0) {
1292 // do this outside of mStateLock
1293 layer->ditch();
1294 }
1295 return err;
1296}
1297
1298status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
1299{
1300 /*
1301 * called by ~ISurface() when all references are gone
1302 */
1303
1304 /* FIXME:
1305 * - this can calls ~Layer(), which is wrong because we're not in the
1306 * GL thread, and ~Layer() currently calls OpenGL.
1307 * - ideally we want to release as much GL state as possible after
1308 * purgatorizeLayer_l() has been called and the surface is not in any
1309 * active list.
1310 * - ideally we'd call ~Layer() without mStateLock held
1311 */
1312
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001313 Mutex::Autolock _l(mStateLock);
Mathias Agopian9a112062009-04-17 19:36:26 -07001314 mLayerPurgatory.remove(layer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001315 return NO_ERROR;
1316}
1317
1318status_t SurfaceFlinger::setClientState(
1319 ClientID cid,
1320 int32_t count,
1321 const layer_state_t* states)
1322{
1323 Mutex::Autolock _l(mStateLock);
1324 uint32_t flags = 0;
1325 cid <<= 16;
1326 for (int i=0 ; i<count ; i++) {
1327 const layer_state_t& s = states[i];
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001328 const sp<LayerBaseClient>& layer = getLayerUser_l(s.surface | cid);
1329 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001330 const uint32_t what = s.what;
1331 // check if it has been destroyed first
1332 if (what & eDestroyed) {
1333 if (removeLayer_l(layer) == NO_ERROR) {
1334 flags |= eTransactionNeeded;
1335 // we skip everything else... well, no, not really
1336 // we skip ONLY that transaction.
1337 continue;
1338 }
1339 }
1340 if (what & ePositionChanged) {
1341 if (layer->setPosition(s.x, s.y))
1342 flags |= eTraversalNeeded;
1343 }
1344 if (what & eLayerChanged) {
1345 if (layer->setLayer(s.z)) {
1346 mCurrentState.layersSortedByZ.reorder(
1347 layer, &Layer::compareCurrentStateZ);
1348 // we need traversal (state changed)
1349 // AND transaction (list changed)
1350 flags |= eTransactionNeeded|eTraversalNeeded;
1351 }
1352 }
1353 if (what & eSizeChanged) {
1354 if (layer->setSize(s.w, s.h))
1355 flags |= eTraversalNeeded;
1356 }
1357 if (what & eAlphaChanged) {
1358 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
1359 flags |= eTraversalNeeded;
1360 }
1361 if (what & eMatrixChanged) {
1362 if (layer->setMatrix(s.matrix))
1363 flags |= eTraversalNeeded;
1364 }
1365 if (what & eTransparentRegionChanged) {
1366 if (layer->setTransparentRegionHint(s.transparentRegion))
1367 flags |= eTraversalNeeded;
1368 }
1369 if (what & eVisibilityChanged) {
1370 if (layer->setFlags(s.flags, s.mask))
1371 flags |= eTraversalNeeded;
1372 }
1373 }
1374 }
1375 if (flags) {
1376 setTransactionFlags(flags);
1377 }
1378 return NO_ERROR;
1379}
1380
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001381sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001382{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001383 sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
1384 return layer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001385}
1386
1387void SurfaceFlinger::screenReleased(int dpy)
1388{
1389 // this may be called by a signal handler, we can't do too much in here
1390 android_atomic_or(eConsoleReleased, &mConsoleSignals);
1391 signalEvent();
1392}
1393
1394void SurfaceFlinger::screenAcquired(int dpy)
1395{
1396 // this may be called by a signal handler, we can't do too much in here
1397 android_atomic_or(eConsoleAcquired, &mConsoleSignals);
1398 signalEvent();
1399}
1400
1401status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
1402{
1403 const size_t SIZE = 1024;
1404 char buffer[SIZE];
1405 String8 result;
1406 if (checkCallingPermission(
1407 String16("android.permission.DUMP")) == false)
1408 { // not allowed
1409 snprintf(buffer, SIZE, "Permission Denial: "
1410 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1411 IPCThreadState::self()->getCallingPid(),
1412 IPCThreadState::self()->getCallingUid());
1413 result.append(buffer);
1414 } else {
1415 Mutex::Autolock _l(mStateLock);
1416 size_t s = mClientsMap.size();
1417 char name[64];
1418 for (size_t i=0 ; i<s ; i++) {
1419 Client* client = mClientsMap.valueAt(i);
1420 sprintf(name, " Client (id=0x%08x)", client->cid);
1421 client->dump(name);
1422 }
1423 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
1424 const size_t count = currentLayers.size();
1425 for (size_t i=0 ; i<count ; i++) {
1426 /*** LayerBase ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001427 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001428 const Layer::State& s = layer->drawingState();
1429 snprintf(buffer, SIZE,
1430 "+ %s %p\n"
1431 " "
1432 "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
1433 "needsBlending=%1d, invalidate=%1d, "
1434 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001435 layer->getTypeID(), layer.get(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001436 s.z, layer->tx(), layer->ty(), s.w, s.h,
1437 layer->needsBlending(), layer->contentDirty,
1438 s.alpha, s.flags,
1439 s.transform[0], s.transform[1],
1440 s.transform[2], s.transform[3]);
1441 result.append(buffer);
1442 buffer[0] = 0;
1443 /*** LayerBaseClient ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001444 sp<LayerBaseClient> lbc =
1445 LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
1446 if (lbc != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001447 snprintf(buffer, SIZE,
1448 " "
1449 "id=0x%08x, client=0x%08x, identity=%u\n",
1450 lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
1451 lbc->getIdentity());
1452 }
1453 result.append(buffer);
1454 buffer[0] = 0;
1455 /*** Layer ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001456 sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
1457 if (l != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001458 const LayerBitmap& buf0(l->getBuffer(0));
1459 const LayerBitmap& buf1(l->getBuffer(1));
1460 snprintf(buffer, SIZE,
1461 " "
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001462 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001463 " freezeLock=%p, swapState=0x%08x\n",
1464 l->pixelFormat(),
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001465 buf0.getWidth(), buf0.getHeight(),
1466 buf0.getBuffer()->getStride(),
1467 buf1.getWidth(), buf1.getHeight(),
1468 buf1.getBuffer()->getStride(),
1469 l->getFreezeLock().get(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001470 l->lcblk->swapState);
1471 }
1472 result.append(buffer);
1473 buffer[0] = 0;
1474 s.transparentRegion.dump(result, "transparentRegion");
1475 layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
1476 layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
1477 }
1478 mWormholeRegion.dump(result, "WormholeRegion");
1479 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1480 snprintf(buffer, SIZE,
1481 " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1482 mFreezeDisplay?"yes":"no", mFreezeCount,
1483 mCurrentState.orientation, hw.canDraw());
1484 result.append(buffer);
1485
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001486 const BufferAllocator& alloc(BufferAllocator::get());
1487 alloc.dump(result);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001488 }
1489 write(fd, result.string(), result.size());
1490 return NO_ERROR;
1491}
1492
1493status_t SurfaceFlinger::onTransact(
1494 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1495{
1496 switch (code) {
1497 case CREATE_CONNECTION:
1498 case OPEN_GLOBAL_TRANSACTION:
1499 case CLOSE_GLOBAL_TRANSACTION:
1500 case SET_ORIENTATION:
1501 case FREEZE_DISPLAY:
1502 case UNFREEZE_DISPLAY:
1503 case BOOT_FINISHED:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001504 {
1505 // codes that require permission check
1506 IPCThreadState* ipc = IPCThreadState::self();
1507 const int pid = ipc->getCallingPid();
1508 const int self_pid = getpid();
1509 if (UNLIKELY(pid != self_pid)) {
1510 // we're called from a different process, do the real check
1511 if (!checkCallingPermission(
1512 String16("android.permission.ACCESS_SURFACE_FLINGER")))
1513 {
1514 const int uid = ipc->getCallingUid();
1515 LOGE("Permission Denial: "
1516 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
1517 return PERMISSION_DENIED;
1518 }
1519 }
1520 }
1521 }
1522
1523 status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
1524 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1525 // HARDWARE_TEST stuff...
1526 if (UNLIKELY(checkCallingPermission(
1527 String16("android.permission.HARDWARE_TEST")) == false))
1528 { // not allowed
1529 LOGE("Permission Denial: pid=%d, uid=%d\n",
1530 IPCThreadState::self()->getCallingPid(),
1531 IPCThreadState::self()->getCallingUid());
1532 return PERMISSION_DENIED;
1533 }
1534 int n;
1535 switch (code) {
Mathias Agopian01b76682009-04-16 20:04:08 -07001536 case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001537 return NO_ERROR;
1538 case 1001: // SHOW_FPS
1539 n = data.readInt32();
1540 mDebugFps = n ? 1 : 0;
1541 return NO_ERROR;
1542 case 1002: // SHOW_UPDATES
1543 n = data.readInt32();
1544 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
1545 return NO_ERROR;
1546 case 1003: // SHOW_BACKGROUND
1547 n = data.readInt32();
1548 mDebugBackground = n ? 1 : 0;
1549 return NO_ERROR;
1550 case 1004:{ // repaint everything
1551 Mutex::Autolock _l(mStateLock);
1552 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1553 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
1554 signalEvent();
1555 }
1556 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001557 case 1007: // set mFreezeCount
1558 mFreezeCount = data.readInt32();
1559 return NO_ERROR;
1560 case 1010: // interrogate.
Mathias Agopian01b76682009-04-16 20:04:08 -07001561 reply->writeInt32(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001562 reply->writeInt32(0);
1563 reply->writeInt32(mDebugRegion);
1564 reply->writeInt32(mDebugBackground);
1565 return NO_ERROR;
1566 case 1013: {
1567 Mutex::Autolock _l(mStateLock);
1568 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1569 reply->writeInt32(hw.getPageFlipCount());
1570 }
1571 return NO_ERROR;
1572 }
1573 }
1574 return err;
1575}
1576
1577// ---------------------------------------------------------------------------
1578#if 0
1579#pragma mark -
1580#endif
1581
1582Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
1583 : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
1584{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001585 const int pgsize = getpagesize();
1586 const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
1587 mCblkHeap = new MemoryDealer(cblksize);
1588 mCblkMemory = mCblkHeap->allocate(cblksize);
1589 if (mCblkMemory != 0) {
1590 ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
1591 if (ctrlblk) { // construct the shared structure in-place.
1592 new(ctrlblk) per_client_cblk_t;
1593 }
1594 }
1595}
1596
1597Client::~Client() {
1598 if (ctrlblk) {
1599 const int pgsize = getpagesize();
1600 ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
1601 }
1602}
1603
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001604int32_t Client::generateId(int pid)
1605{
1606 const uint32_t i = clz( ~mBitmap );
1607 if (i >= NUM_LAYERS_MAX) {
1608 return NO_MEMORY;
1609 }
1610 mPid = pid;
1611 mInUse.add(uint8_t(i));
1612 mBitmap |= 1<<(31-i);
1613 return i;
1614}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001615
1616status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001617{
1618 ssize_t idx = mInUse.indexOf(id);
1619 if (idx < 0)
1620 return NAME_NOT_FOUND;
1621 return mLayers.insertAt(layer, idx);
1622}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001623
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001624void Client::free(int32_t id)
1625{
1626 ssize_t idx = mInUse.remove(uint8_t(id));
1627 if (idx >= 0) {
1628 mBitmap &= ~(1<<(31-id));
1629 mLayers.removeItemsAt(idx);
1630 }
1631}
1632
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001633bool Client::isValid(int32_t i) const {
1634 return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
1635}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001636
1637sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
1638 sp<LayerBaseClient> lbc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001639 ssize_t idx = mInUse.indexOf(uint8_t(i));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001640 if (idx >= 0) {
1641 lbc = mLayers[idx].promote();
1642 LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
1643 }
1644 return lbc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001645}
1646
1647void Client::dump(const char* what)
1648{
1649}
1650
1651// ---------------------------------------------------------------------------
1652#if 0
1653#pragma mark -
1654#endif
1655
1656BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
1657 : mId(cid), mFlinger(flinger), mCblk(cblk)
1658{
1659}
1660
1661BClient::~BClient() {
1662 // destroy all resources attached to this client
1663 mFlinger->destroyConnection(mId);
1664}
1665
1666void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
1667 *ctrl = mCblk;
1668}
1669
1670sp<ISurface> BClient::createSurface(
1671 ISurfaceFlingerClient::surface_data_t* params, int pid,
1672 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
1673 uint32_t flags)
1674{
1675 return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags);
1676}
1677
1678status_t BClient::destroySurface(SurfaceID sid)
1679{
1680 sid |= (mId << 16); // add the client-part to id
Mathias Agopian9a112062009-04-17 19:36:26 -07001681 return mFlinger->removeSurface(sid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001682}
1683
1684status_t BClient::setState(int32_t count, const layer_state_t* states)
1685{
1686 return mFlinger->setClientState(mId, count, states);
1687}
1688
1689// ---------------------------------------------------------------------------
1690
1691GraphicPlane::GraphicPlane()
1692 : mHw(0)
1693{
1694}
1695
1696GraphicPlane::~GraphicPlane() {
1697 delete mHw;
1698}
1699
1700bool GraphicPlane::initialized() const {
1701 return mHw ? true : false;
1702}
1703
1704void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
1705 mHw = hw;
1706}
1707
1708void GraphicPlane::setTransform(const Transform& tr) {
1709 mTransform = tr;
1710 mGlobalTransform = mOrientationTransform * mTransform;
1711}
1712
1713status_t GraphicPlane::orientationToTransfrom(
1714 int orientation, int w, int h, Transform* tr)
1715{
1716 float a, b, c, d, x, y;
1717 switch (orientation) {
1718 case ISurfaceComposer::eOrientationDefault:
1719 a=1; b=0; c=0; d=1; x=0; y=0;
1720 break;
1721 case ISurfaceComposer::eOrientation90:
1722 a=0; b=-1; c=1; d=0; x=w; y=0;
1723 break;
1724 case ISurfaceComposer::eOrientation180:
1725 a=-1; b=0; c=0; d=-1; x=w; y=h;
1726 break;
1727 case ISurfaceComposer::eOrientation270:
1728 a=0; b=1; c=-1; d=0; x=0; y=h;
1729 break;
1730 default:
1731 return BAD_VALUE;
1732 }
1733 tr->set(a, b, c, d);
1734 tr->set(x, y);
1735 return NO_ERROR;
1736}
1737
1738status_t GraphicPlane::setOrientation(int orientation)
1739{
1740 const DisplayHardware& hw(displayHardware());
1741 const float w = hw.getWidth();
1742 const float h = hw.getHeight();
1743
1744 if (orientation == ISurfaceComposer::eOrientationDefault) {
1745 // make sure the default orientation is optimal
1746 mOrientationTransform.reset();
Mathias Agopian0d1318b2009-03-27 17:58:20 -07001747 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001748 mGlobalTransform = mTransform;
1749 return NO_ERROR;
1750 }
1751
1752 // If the rotation can be handled in hardware, this is where
1753 // the magic should happen.
1754 if (UNLIKELY(orientation == 42)) {
1755 float a, b, c, d, x, y;
1756 const float r = (3.14159265f / 180.0f) * 42.0f;
1757 const float si = sinf(r);
1758 const float co = cosf(r);
1759 a=co; b=-si; c=si; d=co;
1760 x = si*(h*0.5f) + (1-co)*(w*0.5f);
1761 y =-si*(w*0.5f) + (1-co)*(h*0.5f);
1762 mOrientationTransform.set(a, b, c, d);
1763 mOrientationTransform.set(x, y);
1764 } else {
1765 GraphicPlane::orientationToTransfrom(orientation, w, h,
1766 &mOrientationTransform);
1767 }
Mathias Agopian0d1318b2009-03-27 17:58:20 -07001768 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001769 mGlobalTransform = mOrientationTransform * mTransform;
1770 return NO_ERROR;
1771}
1772
1773const DisplayHardware& GraphicPlane::displayHardware() const {
1774 return *mHw;
1775}
1776
1777const Transform& GraphicPlane::transform() const {
1778 return mGlobalTransform;
1779}
1780
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001781EGLDisplay GraphicPlane::getEGLDisplay() const {
1782 return mHw->getEGLDisplay();
1783}
1784
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001785// ---------------------------------------------------------------------------
1786
1787}; // namespace android