blob: b4f443fda81c398327245067087f87d6e79820e4 [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>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <sys/ioctl.h>
27
28#include <cutils/log.h>
29#include <cutils/properties.h>
30
31#include <utils/IPCThreadState.h>
32#include <utils/IServiceManager.h>
33#include <utils/MemoryDealer.h>
34#include <utils/MemoryBase.h>
35#include <utils/String8.h>
36#include <utils/String16.h>
37#include <utils/StopWatch.h>
38
39#include <ui/PixelFormat.h>
40#include <ui/DisplayInfo.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041
42#include <pixelflinger/pixelflinger.h>
43#include <GLES/gl.h>
44
45#include "clz.h"
Mathias Agopian076b1cc2009-04-10 14:24:30 -070046#include "BufferAllocator.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047#include "CPUGauge.h"
48#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),
181 mDebugCpu(0),
182 mDebugFps(0),
183 mDebugBackground(0),
184 mDebugNoBootAnimation(0),
185 mSyncObject(),
186 mDeplayedTransactionPending(0),
187 mConsoleSignals(0),
188 mSecureFrameBuffer(0)
189{
190 init();
191}
192
193void SurfaceFlinger::init()
194{
195 LOGI("SurfaceFlinger is starting");
196
197 // debugging stuff...
198 char value[PROPERTY_VALUE_MAX];
199 property_get("debug.sf.showupdates", value, "0");
200 mDebugRegion = atoi(value);
201 property_get("debug.sf.showcpu", value, "0");
202 mDebugCpu = atoi(value);
203 property_get("debug.sf.showbackground", value, "0");
204 mDebugBackground = atoi(value);
205 property_get("debug.sf.showfps", value, "0");
206 mDebugFps = atoi(value);
207 property_get("debug.sf.nobootanimation", value, "0");
208 mDebugNoBootAnimation = atoi(value);
209
210 LOGI_IF(mDebugRegion, "showupdates enabled");
211 LOGI_IF(mDebugCpu, "showcpu enabled");
212 LOGI_IF(mDebugBackground, "showbackground enabled");
213 LOGI_IF(mDebugFps, "showfps enabled");
214 LOGI_IF(mDebugNoBootAnimation, "boot animation disabled");
215}
216
217SurfaceFlinger::~SurfaceFlinger()
218{
219 glDeleteTextures(1, &mWormholeTexName);
220 delete mOrientationAnimation;
221}
222
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800223overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
224{
225 return graphicPlane(0).displayHardware().getOverlayEngine();
226}
227
228sp<IMemory> SurfaceFlinger::getCblk() const
229{
230 return mServerCblkMemory;
231}
232
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800233sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
234{
235 Mutex::Autolock _l(mStateLock);
236 uint32_t token = mTokens.acquire();
237
238 Client* client = new Client(token, this);
239 if ((client == 0) || (client->ctrlblk == 0)) {
240 mTokens.release(token);
241 return 0;
242 }
243 status_t err = mClientsMap.add(token, client);
244 if (err < 0) {
245 delete client;
246 mTokens.release(token);
247 return 0;
248 }
249 sp<BClient> bclient =
250 new BClient(this, token, client->controlBlockMemory());
251 return bclient;
252}
253
254void SurfaceFlinger::destroyConnection(ClientID cid)
255{
256 Mutex::Autolock _l(mStateLock);
257 Client* const client = mClientsMap.valueFor(cid);
258 if (client) {
259 // free all the layers this client owns
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700260 const Vector< wp<LayerBaseClient> >& layers = client->getLayers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800261 const size_t count = layers.size();
262 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700263 sp<LayerBaseClient> layer(layers[i].promote());
264 if (layer != 0) {
265 removeLayer_l(layer);
266 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800267 }
268
269 // the resources associated with this client will be freed
270 // during the next transaction, after these surfaces have been
271 // properly removed from the screen
272
273 // remove this client from our ClientID->Client mapping.
274 mClientsMap.removeItem(cid);
275
276 // and add it to the list of disconnected clients
277 mDisconnectedClients.add(client);
278
279 // request a transaction
280 setTransactionFlags(eTransactionNeeded);
281 }
282}
283
284const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
285{
286 LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
287 const GraphicPlane& plane(mGraphicPlanes[dpy]);
288 return plane;
289}
290
291GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
292{
293 return const_cast<GraphicPlane&>(
294 const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
295}
296
297void SurfaceFlinger::bootFinished()
298{
299 const nsecs_t now = systemTime();
300 const nsecs_t duration = now - mBootTime;
301 LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
302 if (mBootAnimation != 0) {
303 mBootAnimation->requestExit();
304 mBootAnimation.clear();
305 }
306}
307
308void SurfaceFlinger::onFirstRef()
309{
310 run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
311
312 // Wait for the main thread to be done with its initialization
313 mReadyToRunBarrier.wait();
314}
315
316
317static inline uint16_t pack565(int r, int g, int b) {
318 return (r<<11)|(g<<5)|b;
319}
320
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800321status_t SurfaceFlinger::readyToRun()
322{
323 LOGI( "SurfaceFlinger's main thread ready to run. "
324 "Initializing graphics H/W...");
325
326 // create the shared control-block
327 mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY);
328 LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
329
330 mServerCblkMemory = mServerHeap->allocate(4096);
331 LOGE_IF(mServerCblkMemory==0, "can't create shared control block");
332
333 mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer());
334 LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
335 new(mServerCblk) surface_flinger_cblk_t;
336
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800337 // we only support one display currently
338 int dpy = 0;
339
340 {
341 // initialize the main display
342 GraphicPlane& plane(graphicPlane(dpy));
343 DisplayHardware* const hw = new DisplayHardware(this, dpy);
344 plane.setDisplayHardware(hw);
345 }
346
347 // initialize primary screen
348 // (other display should be initialized in the same manner, but
349 // asynchronously, as they could come and go. None of this is supported
350 // yet).
351 const GraphicPlane& plane(graphicPlane(dpy));
352 const DisplayHardware& hw = plane.displayHardware();
353 const uint32_t w = hw.getWidth();
354 const uint32_t h = hw.getHeight();
355 const uint32_t f = hw.getFormat();
356 hw.makeCurrent();
357
358 // initialize the shared control block
359 mServerCblk->connected |= 1<<dpy;
360 display_cblk_t* dcblk = mServerCblk->displays + dpy;
361 memset(dcblk, 0, sizeof(display_cblk_t));
362 dcblk->w = w;
363 dcblk->h = h;
364 dcblk->format = f;
365 dcblk->orientation = ISurfaceComposer::eOrientationDefault;
366 dcblk->xdpi = hw.getDpiX();
367 dcblk->ydpi = hw.getDpiY();
368 dcblk->fps = hw.getRefreshRate();
369 dcblk->density = hw.getDensity();
370 asm volatile ("":::"memory");
371
372 // Initialize OpenGL|ES
373 glActiveTexture(GL_TEXTURE0);
374 glBindTexture(GL_TEXTURE_2D, 0);
375 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
376 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
377 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
378 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
379 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
380 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
381 glPixelStorei(GL_PACK_ALIGNMENT, 4);
382 glEnableClientState(GL_VERTEX_ARRAY);
383 glEnable(GL_SCISSOR_TEST);
384 glShadeModel(GL_FLAT);
385 glDisable(GL_DITHER);
386 glDisable(GL_CULL_FACE);
387
388 const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
389 const uint16_t g1 = pack565(0x17,0x2f,0x17);
390 const uint16_t textureData[4] = { g0, g1, g1, g0 };
391 glGenTextures(1, &mWormholeTexName);
392 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
393 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
394 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
395 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
396 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
397 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
398 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);
399
400 glViewport(0, 0, w, h);
401 glMatrixMode(GL_PROJECTION);
402 glLoadIdentity();
403 glOrthof(0, w, h, 0, 0, 1);
404
405 LayerDim::initDimmer(this, w, h);
406
407 mReadyToRunBarrier.open();
408
409 /*
410 * We're now ready to accept clients...
411 */
412
413 mOrientationAnimation = new OrientationAnimation(this);
414
415 // start CPU gauge display
416 if (mDebugCpu)
417 mCpuGauge = new CPUGauge(this, ms2ns(500));
418
419 // the boot animation!
420 if (mDebugNoBootAnimation == false)
421 mBootAnimation = new BootAnimation(this);
422
423 return NO_ERROR;
424}
425
426// ----------------------------------------------------------------------------
427#if 0
428#pragma mark -
429#pragma mark Events Handler
430#endif
431
432void SurfaceFlinger::waitForEvent()
433{
434 // wait for something to do
435 if (UNLIKELY(isFrozen())) {
436 // wait 5 seconds
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700437 const nsecs_t freezeDisplayTimeout = ms2ns(5000);
438 const nsecs_t now = systemTime();
439 if (mFreezeDisplayTime == 0) {
440 mFreezeDisplayTime = now;
441 }
442 nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
443 int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800444 if (err != NO_ERROR) {
445 if (isFrozen()) {
446 // we timed out and are still frozen
447 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
448 mFreezeDisplay, mFreezeCount);
449 mFreezeCount = 0;
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700450 mFreezeDisplay = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800451 }
452 }
453 } else {
The Android Open Source Projectbcef13b2009-03-11 12:11:56 -0700454 mFreezeDisplayTime = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800455 mSyncObject.wait();
456 }
457}
458
459void SurfaceFlinger::signalEvent() {
460 mSyncObject.open();
461}
462
463void SurfaceFlinger::signal() const {
464 mSyncObject.open();
465}
466
467void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
468{
469 if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) {
470 sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay));
471 delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY);
472 }
473}
474
475// ----------------------------------------------------------------------------
476#if 0
477#pragma mark -
478#pragma mark Main loop
479#endif
480
481bool SurfaceFlinger::threadLoop()
482{
483 waitForEvent();
484
485 // check for transactions
486 if (UNLIKELY(mConsoleSignals)) {
487 handleConsoleEvents();
488 }
489
490 if (LIKELY(mTransactionCount == 0)) {
491 // if we're in a global transaction, don't do anything.
492 const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
493 uint32_t transactionFlags = getTransactionFlags(mask);
494 if (LIKELY(transactionFlags)) {
495 handleTransaction(transactionFlags);
496 }
497 }
498
499 // post surfaces (if needed)
500 handlePageFlip();
501
502 const DisplayHardware& hw(graphicPlane(0).displayHardware());
503 if (LIKELY(hw.canDraw())) {
504 // repaint the framebuffer (if needed)
505 handleRepaint();
506
507 // release the clients before we flip ('cause flip might block)
508 unlockClients();
509 executeScheduledBroadcasts();
510
511 // sample the cpu gauge
512 if (UNLIKELY(mDebugCpu)) {
513 handleDebugCpu();
514 }
515
516 postFramebuffer();
517 } else {
518 // pretend we did the post
519 unlockClients();
520 executeScheduledBroadcasts();
521 usleep(16667); // 60 fps period
522 }
523 return true;
524}
525
526void SurfaceFlinger::postFramebuffer()
527{
528 const bool skip = mOrientationAnimation->run();
529 if (UNLIKELY(skip)) {
530 return;
531 }
532
533 if (!mInvalidRegion.isEmpty()) {
534 const DisplayHardware& hw(graphicPlane(0).displayHardware());
535
536 if (UNLIKELY(mDebugFps)) {
537 debugShowFPS();
538 }
539
540 hw.flip(mInvalidRegion);
541
542 mInvalidRegion.clear();
543
544 if (Layer::deletedTextures.size()) {
545 glDeleteTextures(
546 Layer::deletedTextures.size(),
547 Layer::deletedTextures.array());
548 Layer::deletedTextures.clear();
549 }
550 }
551}
552
553void SurfaceFlinger::handleConsoleEvents()
554{
555 // something to do with the console
556 const DisplayHardware& hw = graphicPlane(0).displayHardware();
557
558 int what = android_atomic_and(0, &mConsoleSignals);
559 if (what & eConsoleAcquired) {
560 hw.acquireScreen();
561 }
562
563 if (mDeferReleaseConsole && hw.canDraw()) {
564 // We got the release signal before the aquire signal
565 mDeferReleaseConsole = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800566 hw.releaseScreen();
567 }
568
569 if (what & eConsoleReleased) {
570 if (hw.canDraw()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800571 hw.releaseScreen();
572 } else {
573 mDeferReleaseConsole = true;
574 }
575 }
576
577 mDirtyRegion.set(hw.bounds());
578}
579
580void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
581{
582 Mutex::Autolock _l(mStateLock);
583
584 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
585 const size_t count = currentLayers.size();
586
587 /*
588 * Traversal of the children
589 * (perform the transaction for each of them if needed)
590 */
591
592 const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
593 if (layersNeedTransaction) {
594 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700595 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800596 uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
597 if (!trFlags) continue;
598
599 const uint32_t flags = layer->doTransaction(0);
600 if (flags & Layer::eVisibleRegion)
601 mVisibleRegionsDirty = true;
602
603 if (flags & Layer::eRestartTransaction) {
604 // restart the transaction, but back-off a little
605 layer->setTransactionFlags(eTransactionNeeded);
606 setTransactionFlags(eTraversalNeeded, ms2ns(8));
607 }
608 }
609 }
610
611 /*
612 * Perform our own transaction if needed
613 */
614
615 if (transactionFlags & eTransactionNeeded) {
616 if (mCurrentState.orientation != mDrawingState.orientation) {
617 // the orientation has changed, recompute all visible regions
618 // and invalidate everything.
619
620 const int dpy = 0;
621 const int orientation = mCurrentState.orientation;
Mathias Agopianc08731e2009-03-27 18:11:38 -0700622 const uint32_t type = mCurrentState.orientationType;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800623 GraphicPlane& plane(graphicPlane(dpy));
624 plane.setOrientation(orientation);
625
626 // update the shared control block
627 const DisplayHardware& hw(plane.displayHardware());
628 volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
629 dcblk->orientation = orientation;
630 if (orientation & eOrientationSwapMask) {
631 // 90 or 270 degrees orientation
632 dcblk->w = hw.getHeight();
633 dcblk->h = hw.getWidth();
634 } else {
635 dcblk->w = hw.getWidth();
636 dcblk->h = hw.getHeight();
637 }
638
639 mVisibleRegionsDirty = true;
640 mDirtyRegion.set(hw.bounds());
Mathias Agopianc08731e2009-03-27 18:11:38 -0700641 mFreezeDisplayTime = 0;
642 mOrientationAnimation->onOrientationChanged(type);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800643 }
644
645 if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
646 // freezing or unfreezing the display -> trigger animation if needed
647 mFreezeDisplay = mCurrentState.freezeDisplay;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800648 }
649
650 // some layers might have been removed, so
651 // we need to update the regions they're exposing.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700652 if (mLayersRemoved) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800653 mVisibleRegionsDirty = true;
654 }
655
656 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
657 if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
658 // layers have been added
659 mVisibleRegionsDirty = true;
660 }
661
662 // get rid of all resources we don't need anymore
663 // (layers and clients)
664 free_resources_l();
665 }
666
667 commitTransaction();
668}
669
670sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
671{
672 return new FreezeLock(const_cast<SurfaceFlinger *>(this));
673}
674
675void SurfaceFlinger::computeVisibleRegions(
676 LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
677{
678 const GraphicPlane& plane(graphicPlane(0));
679 const Transform& planeTransform(plane.transform());
680
681 Region aboveOpaqueLayers;
682 Region aboveCoveredLayers;
683 Region dirty;
684
685 bool secureFrameBuffer = false;
686
687 size_t i = currentLayers.size();
688 while (i--) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700689 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800690 layer->validateVisibility(planeTransform);
691
692 // start with the whole surface at its current location
693 const Layer::State& s = layer->drawingState();
694 const Rect bounds(layer->visibleBounds());
695
696 // handle hidden surfaces by setting the visible region to empty
697 Region opaqueRegion;
698 Region visibleRegion;
699 Region coveredRegion;
700 if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) {
701 visibleRegion.clear();
702 } else {
703 const bool translucent = layer->needsBlending();
704 visibleRegion.set(bounds);
705 coveredRegion = visibleRegion;
706
707 // Remove the transparent area from the visible region
708 if (translucent) {
709 visibleRegion.subtractSelf(layer->transparentRegionScreen);
710 }
711
712 // compute the opaque region
713 if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
714 // the opaque region is the visible region
715 opaqueRegion = visibleRegion;
716 }
717 }
718
719 // subtract the opaque region covered by the layers above us
720 visibleRegion.subtractSelf(aboveOpaqueLayers);
721 coveredRegion.andSelf(aboveCoveredLayers);
722
723 // compute this layer's dirty region
724 if (layer->contentDirty) {
725 // we need to invalidate the whole region
726 dirty = visibleRegion;
727 // as well, as the old visible region
728 dirty.orSelf(layer->visibleRegionScreen);
729 layer->contentDirty = false;
730 } else {
731 // compute the exposed region
732 // dirty = what's visible now - what's wasn't covered before
733 // = what's visible now & what's was covered before
734 dirty = visibleRegion.intersect(layer->coveredRegionScreen);
735 }
736 dirty.subtractSelf(aboveOpaqueLayers);
737
738 // accumulate to the screen dirty region
739 dirtyRegion.orSelf(dirty);
740
741 // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
742 aboveOpaqueLayers.orSelf(opaqueRegion);
743 aboveCoveredLayers.orSelf(bounds);
744
745 // Store the visible region is screen space
746 layer->setVisibleRegion(visibleRegion);
747 layer->setCoveredRegion(coveredRegion);
748
749 // If a secure layer is partially visible, lockdown the screen!
750 if (layer->isSecure() && !visibleRegion.isEmpty()) {
751 secureFrameBuffer = true;
752 }
753 }
754
755 mSecureFrameBuffer = secureFrameBuffer;
756 opaqueRegion = aboveOpaqueLayers;
757}
758
759
760void SurfaceFlinger::commitTransaction()
761{
762 mDrawingState = mCurrentState;
763 mTransactionCV.signal();
764}
765
766void SurfaceFlinger::handlePageFlip()
767{
768 bool visibleRegions = mVisibleRegionsDirty;
769 LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
770 visibleRegions |= lockPageFlip(currentLayers);
771
772 const DisplayHardware& hw = graphicPlane(0).displayHardware();
773 const Region screenRegion(hw.bounds());
774 if (visibleRegions) {
775 Region opaqueRegion;
776 computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
777 mWormholeRegion = screenRegion.subtract(opaqueRegion);
778 mVisibleRegionsDirty = false;
779 }
780
781 unlockPageFlip(currentLayers);
782 mDirtyRegion.andSelf(screenRegion);
783}
784
785bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
786{
787 bool recomputeVisibleRegions = false;
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->lockPageFlip(recomputeVisibleRegions);
793 }
794 return recomputeVisibleRegions;
795}
796
797void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
798{
799 const GraphicPlane& plane(graphicPlane(0));
800 const Transform& planeTransform(plane.transform());
801 size_t count = currentLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700802 sp<LayerBase> const* layers = currentLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800803 for (size_t i=0 ; i<count ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700804 const sp<LayerBase>& layer = layers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800805 layer->unlockPageFlip(planeTransform, mDirtyRegion);
806 }
807}
808
809void SurfaceFlinger::handleRepaint()
810{
811 // set the frame buffer
812 const DisplayHardware& hw(graphicPlane(0).displayHardware());
813 glMatrixMode(GL_MODELVIEW);
814 glLoadIdentity();
815
816 if (UNLIKELY(mDebugRegion)) {
817 debugFlashRegions();
818 }
819
820 // compute the invalid region
821 mInvalidRegion.orSelf(mDirtyRegion);
822
823 uint32_t flags = hw.getFlags();
824 if (flags & DisplayHardware::BUFFER_PRESERVED) {
825 // here we assume DisplayHardware::flip()'s implementation
826 // performs the copy-back optimization.
827 } else {
828 if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
829 // we need to fully redraw the part that will be updated
830 mDirtyRegion.set(mInvalidRegion.bounds());
831 } else {
832 // we need to redraw everything
833 mDirtyRegion.set(hw.bounds());
834 mInvalidRegion = mDirtyRegion;
835 }
836 }
837
838 // compose all surfaces
839 composeSurfaces(mDirtyRegion);
840
841 // clear the dirty regions
842 mDirtyRegion.clear();
843}
844
845void SurfaceFlinger::composeSurfaces(const Region& dirty)
846{
847 if (UNLIKELY(!mWormholeRegion.isEmpty())) {
848 // should never happen unless the window manager has a bug
849 // draw something...
850 drawWormhole();
851 }
852 const SurfaceFlinger& flinger(*this);
853 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
854 const size_t count = drawingLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700855 sp<LayerBase> const* const layers = drawingLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800856 for (size_t i=0 ; i<count ; ++i) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700857 const sp<LayerBase>& layer = layers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800858 const Region& visibleRegion(layer->visibleRegionScreen);
859 if (!visibleRegion.isEmpty()) {
860 const Region clip(dirty.intersect(visibleRegion));
861 if (!clip.isEmpty()) {
862 layer->draw(clip);
863 }
864 }
865 }
866}
867
868void SurfaceFlinger::unlockClients()
869{
870 const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
871 const size_t count = drawingLayers.size();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700872 sp<LayerBase> const* const layers = drawingLayers.array();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800873 for (size_t i=0 ; i<count ; ++i) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700874 const sp<LayerBase>& layer = layers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800875 layer->finishPageFlip();
876 }
877}
878
879void SurfaceFlinger::scheduleBroadcast(Client* client)
880{
881 if (mLastScheduledBroadcast != client) {
882 mLastScheduledBroadcast = client;
883 mScheduledBroadcasts.add(client);
884 }
885}
886
887void SurfaceFlinger::executeScheduledBroadcasts()
888{
889 SortedVector<Client*>& list = mScheduledBroadcasts;
890 size_t count = list.size();
891 while (count--) {
892 per_client_cblk_t* const cblk = list[count]->ctrlblk;
893 if (cblk->lock.tryLock() == NO_ERROR) {
894 cblk->cv.broadcast();
895 list.removeAt(count);
896 cblk->lock.unlock();
897 } else {
898 // schedule another round
899 LOGW("executeScheduledBroadcasts() skipped, "
900 "contention on the client. We'll try again later...");
901 signalDelayedEvent(ms2ns(4));
902 }
903 }
904 mLastScheduledBroadcast = 0;
905}
906
907void SurfaceFlinger::handleDebugCpu()
908{
909 Mutex::Autolock _l(mDebugLock);
910 if (mCpuGauge != 0)
911 mCpuGauge->sample();
912}
913
914void SurfaceFlinger::debugFlashRegions()
915{
916 if (UNLIKELY(!mDirtyRegion.isRect())) {
917 // TODO: do this only if we don't have preserving
918 // swapBuffer. If we don't have update-on-demand,
919 // redraw everything.
920 composeSurfaces(Region(mDirtyRegion.bounds()));
921 }
922
923 glDisable(GL_TEXTURE_2D);
924 glDisable(GL_BLEND);
925 glDisable(GL_DITHER);
926 glDisable(GL_SCISSOR_TEST);
927
928 glColor4x(0x10000, 0, 0x10000, 0x10000);
929
930 Rect r;
931 Region::iterator iterator(mDirtyRegion);
932 while (iterator.iterate(&r)) {
933 GLfloat vertices[][2] = {
934 { r.left, r.top },
935 { r.left, r.bottom },
936 { r.right, r.bottom },
937 { r.right, r.top }
938 };
939 glVertexPointer(2, GL_FLOAT, 0, vertices);
940 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
941 }
942
943 const DisplayHardware& hw(graphicPlane(0).displayHardware());
944 hw.flip(mDirtyRegion.merge(mInvalidRegion));
945 mInvalidRegion.clear();
946
947 if (mDebugRegion > 1)
948 usleep(mDebugRegion * 1000);
949
950 glEnable(GL_SCISSOR_TEST);
951 //mDirtyRegion.dump("mDirtyRegion");
952}
953
954void SurfaceFlinger::drawWormhole() const
955{
956 const Region region(mWormholeRegion.intersect(mDirtyRegion));
957 if (region.isEmpty())
958 return;
959
960 const DisplayHardware& hw(graphicPlane(0).displayHardware());
961 const int32_t width = hw.getWidth();
962 const int32_t height = hw.getHeight();
963
964 glDisable(GL_BLEND);
965 glDisable(GL_DITHER);
966
967 if (LIKELY(!mDebugBackground)) {
968 glClearColorx(0,0,0,0);
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 glClear(GL_COLOR_BUFFER_BIT);
975 }
976 } else {
977 const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
978 { width, height }, { 0, height } };
979 const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
980 glVertexPointer(2, GL_SHORT, 0, vertices);
981 glTexCoordPointer(2, GL_SHORT, 0, tcoords);
982 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
983 glEnable(GL_TEXTURE_2D);
984 glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
985 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
986 glMatrixMode(GL_TEXTURE);
987 glLoadIdentity();
988 glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
989 Rect r;
990 Region::iterator iterator(region);
991 while (iterator.iterate(&r)) {
992 const GLint sy = height - (r.top + r.height());
993 glScissor(r.left, sy, r.width(), r.height());
994 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
995 }
996 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
997 }
998}
999
1000void SurfaceFlinger::debugShowFPS() const
1001{
1002 static int mFrameCount;
1003 static int mLastFrameCount = 0;
1004 static nsecs_t mLastFpsTime = 0;
1005 static float mFps = 0;
1006 mFrameCount++;
1007 nsecs_t now = systemTime();
1008 nsecs_t diff = now - mLastFpsTime;
1009 if (diff > ms2ns(250)) {
1010 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
1011 mLastFpsTime = now;
1012 mLastFrameCount = mFrameCount;
1013 }
1014 // XXX: mFPS has the value we want
1015 }
1016
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001017status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001018{
1019 Mutex::Autolock _l(mStateLock);
1020 addLayer_l(layer);
1021 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
1022 return NO_ERROR;
1023}
1024
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001025status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001026{
1027 Mutex::Autolock _l(mStateLock);
1028 removeLayer_l(layer);
1029 setTransactionFlags(eTransactionNeeded);
1030 return NO_ERROR;
1031}
1032
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001033status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001034{
1035 layer->forceVisibilityTransaction();
1036 setTransactionFlags(eTraversalNeeded);
1037 return NO_ERROR;
1038}
1039
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001040status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001041{
1042 ssize_t i = mCurrentState.layersSortedByZ.add(
1043 layer, &LayerBase::compareCurrentStateZ);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001044 sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
1045 if (lbc != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001046 mLayerMap.add(lbc->serverIndex(), lbc);
1047 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001048 return NO_ERROR;
1049}
1050
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001051status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001052{
1053 ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
1054 if (index >= 0) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001055 mLayersRemoved = true;
1056 sp<LayerBaseClient> layer = LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
1057 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001058 mLayerMap.removeItem(layer->serverIndex());
1059 }
1060 return NO_ERROR;
1061 }
1062 // it's possible that we don't find a layer, because it might
1063 // have been destroyed already -- this is not technically an error
1064 // from the user because there is a race between destroySurface,
1065 // destroyclient and destroySurface-from-a-transaction.
1066 return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
1067}
1068
1069void SurfaceFlinger::free_resources_l()
1070{
1071 // Destroy layers that were removed
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001072 mLayersRemoved = false;
1073
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001074 // free resources associated with disconnected clients
1075 SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
1076 Vector<Client*>& disconnectedClients(mDisconnectedClients);
1077 const size_t count = disconnectedClients.size();
1078 for (size_t i=0 ; i<count ; i++) {
1079 Client* client = disconnectedClients[i];
1080 // if this client is the scheduled broadcast list,
1081 // remove it from there (and we don't need to signal it
1082 // since it is dead).
1083 int32_t index = scheduledBroadcasts.indexOf(client);
1084 if (index >= 0) {
1085 scheduledBroadcasts.removeItemsAt(index);
1086 }
1087 mTokens.release(client->cid);
1088 delete client;
1089 }
1090 disconnectedClients.clear();
1091}
1092
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001093uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
1094{
1095 return android_atomic_and(~flags, &mTransactionFlags) & flags;
1096}
1097
1098uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
1099{
1100 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
1101 if ((old & flags)==0) { // wake the server up
1102 if (delay > 0) {
1103 signalDelayedEvent(delay);
1104 } else {
1105 signalEvent();
1106 }
1107 }
1108 return old;
1109}
1110
1111void SurfaceFlinger::openGlobalTransaction()
1112{
1113 android_atomic_inc(&mTransactionCount);
1114}
1115
1116void SurfaceFlinger::closeGlobalTransaction()
1117{
1118 if (android_atomic_dec(&mTransactionCount) == 1) {
1119 signalEvent();
1120 }
1121}
1122
1123status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
1124{
1125 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1126 return BAD_VALUE;
1127
1128 Mutex::Autolock _l(mStateLock);
1129 mCurrentState.freezeDisplay = 1;
1130 setTransactionFlags(eTransactionNeeded);
1131
1132 // flags is intended to communicate some sort of animation behavior
1133 // (for instance fadding)
1134 return NO_ERROR;
1135}
1136
1137status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
1138{
1139 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1140 return BAD_VALUE;
1141
1142 Mutex::Autolock _l(mStateLock);
1143 mCurrentState.freezeDisplay = 0;
1144 setTransactionFlags(eTransactionNeeded);
1145
1146 // flags is intended to communicate some sort of animation behavior
1147 // (for instance fadding)
1148 return NO_ERROR;
1149}
1150
Mathias Agopianc08731e2009-03-27 18:11:38 -07001151int SurfaceFlinger::setOrientation(DisplayID dpy,
1152 int orientation, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001153{
1154 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1155 return BAD_VALUE;
1156
1157 Mutex::Autolock _l(mStateLock);
1158 if (mCurrentState.orientation != orientation) {
1159 if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
Mathias Agopianc08731e2009-03-27 18:11:38 -07001160 mCurrentState.orientationType = flags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001161 mCurrentState.orientation = orientation;
1162 setTransactionFlags(eTransactionNeeded);
1163 mTransactionCV.wait(mStateLock);
1164 } else {
1165 orientation = BAD_VALUE;
1166 }
1167 }
1168 return orientation;
1169}
1170
1171sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
1172 ISurfaceFlingerClient::surface_data_t* params,
1173 DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
1174 uint32_t flags)
1175{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001176 sp<LayerBaseClient> layer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001177 sp<LayerBaseClient::Surface> surfaceHandle;
1178 Mutex::Autolock _l(mStateLock);
1179 Client* const c = mClientsMap.valueFor(clientId);
1180 if (UNLIKELY(!c)) {
1181 LOGE("createSurface() failed, client not found (id=%d)", clientId);
1182 return surfaceHandle;
1183 }
1184
1185 //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
1186 int32_t id = c->generateId(pid);
1187 if (uint32_t(id) >= NUM_LAYERS_MAX) {
1188 LOGE("createSurface() failed, generateId = %d", id);
1189 return surfaceHandle;
1190 }
1191
1192 switch (flags & eFXSurfaceMask) {
1193 case eFXSurfaceNormal:
1194 if (UNLIKELY(flags & ePushBuffers)) {
1195 layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
1196 } else {
1197 layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
1198 }
1199 break;
1200 case eFXSurfaceBlur:
1201 layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
1202 break;
1203 case eFXSurfaceDim:
1204 layer = createDimSurfaceLocked(c, d, id, w, h, flags);
1205 break;
1206 }
1207
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001208 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001209 setTransactionFlags(eTransactionNeeded);
1210 surfaceHandle = layer->getSurface();
1211 if (surfaceHandle != 0)
1212 surfaceHandle->getSurfaceData(params);
1213 }
1214
1215 return surfaceHandle;
1216}
1217
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001218sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001219 Client* client, DisplayID display,
1220 int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
1221{
1222 // initialize the surfaces
1223 switch (format) { // TODO: take h/w into account
1224 case PIXEL_FORMAT_TRANSPARENT:
1225 case PIXEL_FORMAT_TRANSLUCENT:
1226 format = PIXEL_FORMAT_RGBA_8888;
1227 break;
1228 case PIXEL_FORMAT_OPAQUE:
1229 format = PIXEL_FORMAT_RGB_565;
1230 break;
1231 }
1232
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001233 sp<Layer> layer = new Layer(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001234 status_t err = layer->setBuffers(client, w, h, format, flags);
1235 if (LIKELY(err == NO_ERROR)) {
1236 layer->initStates(w, h, flags);
1237 addLayer_l(layer);
1238 } else {
1239 LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001240 layer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001241 }
1242 return layer;
1243}
1244
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001245sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001246 Client* client, DisplayID display,
1247 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1248{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001249 sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001250 layer->initStates(w, h, flags);
1251 addLayer_l(layer);
1252 return layer;
1253}
1254
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001255sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001256 Client* client, DisplayID display,
1257 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1258{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001259 sp<LayerDim> layer = new LayerDim(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001260 layer->initStates(w, h, flags);
1261 addLayer_l(layer);
1262 return layer;
1263}
1264
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001265sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001266 Client* client, DisplayID display,
1267 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1268{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001269 sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001270 layer->initStates(w, h, flags);
1271 addLayer_l(layer);
1272 return layer;
1273}
1274
1275status_t SurfaceFlinger::destroySurface(SurfaceID index)
1276{
1277 Mutex::Autolock _l(mStateLock);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001278 const sp<LayerBaseClient>& layer = getLayerUser_l(index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001279 status_t err = removeLayer_l(layer);
1280 if (err < 0)
1281 return err;
1282 setTransactionFlags(eTransactionNeeded);
1283 return NO_ERROR;
1284}
1285
1286status_t SurfaceFlinger::setClientState(
1287 ClientID cid,
1288 int32_t count,
1289 const layer_state_t* states)
1290{
1291 Mutex::Autolock _l(mStateLock);
1292 uint32_t flags = 0;
1293 cid <<= 16;
1294 for (int i=0 ; i<count ; i++) {
1295 const layer_state_t& s = states[i];
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001296 const sp<LayerBaseClient>& layer = getLayerUser_l(s.surface | cid);
1297 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001298 const uint32_t what = s.what;
1299 // check if it has been destroyed first
1300 if (what & eDestroyed) {
1301 if (removeLayer_l(layer) == NO_ERROR) {
1302 flags |= eTransactionNeeded;
1303 // we skip everything else... well, no, not really
1304 // we skip ONLY that transaction.
1305 continue;
1306 }
1307 }
1308 if (what & ePositionChanged) {
1309 if (layer->setPosition(s.x, s.y))
1310 flags |= eTraversalNeeded;
1311 }
1312 if (what & eLayerChanged) {
1313 if (layer->setLayer(s.z)) {
1314 mCurrentState.layersSortedByZ.reorder(
1315 layer, &Layer::compareCurrentStateZ);
1316 // we need traversal (state changed)
1317 // AND transaction (list changed)
1318 flags |= eTransactionNeeded|eTraversalNeeded;
1319 }
1320 }
1321 if (what & eSizeChanged) {
1322 if (layer->setSize(s.w, s.h))
1323 flags |= eTraversalNeeded;
1324 }
1325 if (what & eAlphaChanged) {
1326 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
1327 flags |= eTraversalNeeded;
1328 }
1329 if (what & eMatrixChanged) {
1330 if (layer->setMatrix(s.matrix))
1331 flags |= eTraversalNeeded;
1332 }
1333 if (what & eTransparentRegionChanged) {
1334 if (layer->setTransparentRegionHint(s.transparentRegion))
1335 flags |= eTraversalNeeded;
1336 }
1337 if (what & eVisibilityChanged) {
1338 if (layer->setFlags(s.flags, s.mask))
1339 flags |= eTraversalNeeded;
1340 }
1341 }
1342 }
1343 if (flags) {
1344 setTransactionFlags(flags);
1345 }
1346 return NO_ERROR;
1347}
1348
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001349sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001350{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001351 sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
1352 return layer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001353}
1354
1355void SurfaceFlinger::screenReleased(int dpy)
1356{
1357 // this may be called by a signal handler, we can't do too much in here
1358 android_atomic_or(eConsoleReleased, &mConsoleSignals);
1359 signalEvent();
1360}
1361
1362void SurfaceFlinger::screenAcquired(int dpy)
1363{
1364 // this may be called by a signal handler, we can't do too much in here
1365 android_atomic_or(eConsoleAcquired, &mConsoleSignals);
1366 signalEvent();
1367}
1368
1369status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
1370{
1371 const size_t SIZE = 1024;
1372 char buffer[SIZE];
1373 String8 result;
1374 if (checkCallingPermission(
1375 String16("android.permission.DUMP")) == false)
1376 { // not allowed
1377 snprintf(buffer, SIZE, "Permission Denial: "
1378 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1379 IPCThreadState::self()->getCallingPid(),
1380 IPCThreadState::self()->getCallingUid());
1381 result.append(buffer);
1382 } else {
1383 Mutex::Autolock _l(mStateLock);
1384 size_t s = mClientsMap.size();
1385 char name[64];
1386 for (size_t i=0 ; i<s ; i++) {
1387 Client* client = mClientsMap.valueAt(i);
1388 sprintf(name, " Client (id=0x%08x)", client->cid);
1389 client->dump(name);
1390 }
1391 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
1392 const size_t count = currentLayers.size();
1393 for (size_t i=0 ; i<count ; i++) {
1394 /*** LayerBase ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001395 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001396 const Layer::State& s = layer->drawingState();
1397 snprintf(buffer, SIZE,
1398 "+ %s %p\n"
1399 " "
1400 "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
1401 "needsBlending=%1d, invalidate=%1d, "
1402 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001403 layer->getTypeID(), layer.get(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001404 s.z, layer->tx(), layer->ty(), s.w, s.h,
1405 layer->needsBlending(), layer->contentDirty,
1406 s.alpha, s.flags,
1407 s.transform[0], s.transform[1],
1408 s.transform[2], s.transform[3]);
1409 result.append(buffer);
1410 buffer[0] = 0;
1411 /*** LayerBaseClient ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001412 sp<LayerBaseClient> lbc =
1413 LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
1414 if (lbc != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001415 snprintf(buffer, SIZE,
1416 " "
1417 "id=0x%08x, client=0x%08x, identity=%u\n",
1418 lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
1419 lbc->getIdentity());
1420 }
1421 result.append(buffer);
1422 buffer[0] = 0;
1423 /*** Layer ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001424 sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
1425 if (l != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001426 const LayerBitmap& buf0(l->getBuffer(0));
1427 const LayerBitmap& buf1(l->getBuffer(1));
1428 snprintf(buffer, SIZE,
1429 " "
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001430 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001431 " freezeLock=%p, swapState=0x%08x\n",
1432 l->pixelFormat(),
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001433 buf0.getWidth(), buf0.getHeight(),
1434 buf0.getBuffer()->getStride(),
1435 buf1.getWidth(), buf1.getHeight(),
1436 buf1.getBuffer()->getStride(),
1437 l->getFreezeLock().get(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001438 l->lcblk->swapState);
1439 }
1440 result.append(buffer);
1441 buffer[0] = 0;
1442 s.transparentRegion.dump(result, "transparentRegion");
1443 layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
1444 layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
1445 }
1446 mWormholeRegion.dump(result, "WormholeRegion");
1447 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1448 snprintf(buffer, SIZE,
1449 " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1450 mFreezeDisplay?"yes":"no", mFreezeCount,
1451 mCurrentState.orientation, hw.canDraw());
1452 result.append(buffer);
1453
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001454 const BufferAllocator& alloc(BufferAllocator::get());
1455 alloc.dump(result);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001456 }
1457 write(fd, result.string(), result.size());
1458 return NO_ERROR;
1459}
1460
1461status_t SurfaceFlinger::onTransact(
1462 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1463{
1464 switch (code) {
1465 case CREATE_CONNECTION:
1466 case OPEN_GLOBAL_TRANSACTION:
1467 case CLOSE_GLOBAL_TRANSACTION:
1468 case SET_ORIENTATION:
1469 case FREEZE_DISPLAY:
1470 case UNFREEZE_DISPLAY:
1471 case BOOT_FINISHED:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001472 {
1473 // codes that require permission check
1474 IPCThreadState* ipc = IPCThreadState::self();
1475 const int pid = ipc->getCallingPid();
1476 const int self_pid = getpid();
1477 if (UNLIKELY(pid != self_pid)) {
1478 // we're called from a different process, do the real check
1479 if (!checkCallingPermission(
1480 String16("android.permission.ACCESS_SURFACE_FLINGER")))
1481 {
1482 const int uid = ipc->getCallingUid();
1483 LOGE("Permission Denial: "
1484 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
1485 return PERMISSION_DENIED;
1486 }
1487 }
1488 }
1489 }
1490
1491 status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
1492 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1493 // HARDWARE_TEST stuff...
1494 if (UNLIKELY(checkCallingPermission(
1495 String16("android.permission.HARDWARE_TEST")) == false))
1496 { // not allowed
1497 LOGE("Permission Denial: pid=%d, uid=%d\n",
1498 IPCThreadState::self()->getCallingPid(),
1499 IPCThreadState::self()->getCallingUid());
1500 return PERMISSION_DENIED;
1501 }
1502 int n;
1503 switch (code) {
1504 case 1000: // SHOW_CPU
1505 n = data.readInt32();
1506 mDebugCpu = n ? 1 : 0;
1507 if (mDebugCpu) {
1508 if (mCpuGauge == 0) {
1509 mCpuGauge = new CPUGauge(this, ms2ns(500));
1510 }
1511 } else {
1512 if (mCpuGauge != 0) {
1513 mCpuGauge->requestExitAndWait();
1514 Mutex::Autolock _l(mDebugLock);
1515 mCpuGauge.clear();
1516 }
1517 }
1518 return NO_ERROR;
1519 case 1001: // SHOW_FPS
1520 n = data.readInt32();
1521 mDebugFps = n ? 1 : 0;
1522 return NO_ERROR;
1523 case 1002: // SHOW_UPDATES
1524 n = data.readInt32();
1525 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
1526 return NO_ERROR;
1527 case 1003: // SHOW_BACKGROUND
1528 n = data.readInt32();
1529 mDebugBackground = n ? 1 : 0;
1530 return NO_ERROR;
1531 case 1004:{ // repaint everything
1532 Mutex::Autolock _l(mStateLock);
1533 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1534 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
1535 signalEvent();
1536 }
1537 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001538 case 1007: // set mFreezeCount
1539 mFreezeCount = data.readInt32();
1540 return NO_ERROR;
1541 case 1010: // interrogate.
1542 reply->writeInt32(mDebugCpu);
1543 reply->writeInt32(0);
1544 reply->writeInt32(mDebugRegion);
1545 reply->writeInt32(mDebugBackground);
1546 return NO_ERROR;
1547 case 1013: {
1548 Mutex::Autolock _l(mStateLock);
1549 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1550 reply->writeInt32(hw.getPageFlipCount());
1551 }
1552 return NO_ERROR;
1553 }
1554 }
1555 return err;
1556}
1557
1558// ---------------------------------------------------------------------------
1559#if 0
1560#pragma mark -
1561#endif
1562
1563Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
1564 : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
1565{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001566 const int pgsize = getpagesize();
1567 const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
1568 mCblkHeap = new MemoryDealer(cblksize);
1569 mCblkMemory = mCblkHeap->allocate(cblksize);
1570 if (mCblkMemory != 0) {
1571 ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
1572 if (ctrlblk) { // construct the shared structure in-place.
1573 new(ctrlblk) per_client_cblk_t;
1574 }
1575 }
1576}
1577
1578Client::~Client() {
1579 if (ctrlblk) {
1580 const int pgsize = getpagesize();
1581 ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
1582 }
1583}
1584
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001585int32_t Client::generateId(int pid)
1586{
1587 const uint32_t i = clz( ~mBitmap );
1588 if (i >= NUM_LAYERS_MAX) {
1589 return NO_MEMORY;
1590 }
1591 mPid = pid;
1592 mInUse.add(uint8_t(i));
1593 mBitmap |= 1<<(31-i);
1594 return i;
1595}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001596
1597status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001598{
1599 ssize_t idx = mInUse.indexOf(id);
1600 if (idx < 0)
1601 return NAME_NOT_FOUND;
1602 return mLayers.insertAt(layer, idx);
1603}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001604
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001605void Client::free(int32_t id)
1606{
1607 ssize_t idx = mInUse.remove(uint8_t(id));
1608 if (idx >= 0) {
1609 mBitmap &= ~(1<<(31-id));
1610 mLayers.removeItemsAt(idx);
1611 }
1612}
1613
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001614bool Client::isValid(int32_t i) const {
1615 return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
1616}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001617
1618sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
1619 sp<LayerBaseClient> lbc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001620 ssize_t idx = mInUse.indexOf(uint8_t(i));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001621 if (idx >= 0) {
1622 lbc = mLayers[idx].promote();
1623 LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
1624 }
1625 return lbc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001626}
1627
1628void Client::dump(const char* what)
1629{
1630}
1631
1632// ---------------------------------------------------------------------------
1633#if 0
1634#pragma mark -
1635#endif
1636
1637BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
1638 : mId(cid), mFlinger(flinger), mCblk(cblk)
1639{
1640}
1641
1642BClient::~BClient() {
1643 // destroy all resources attached to this client
1644 mFlinger->destroyConnection(mId);
1645}
1646
1647void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
1648 *ctrl = mCblk;
1649}
1650
1651sp<ISurface> BClient::createSurface(
1652 ISurfaceFlingerClient::surface_data_t* params, int pid,
1653 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
1654 uint32_t flags)
1655{
1656 return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags);
1657}
1658
1659status_t BClient::destroySurface(SurfaceID sid)
1660{
1661 sid |= (mId << 16); // add the client-part to id
1662 return mFlinger->destroySurface(sid);
1663}
1664
1665status_t BClient::setState(int32_t count, const layer_state_t* states)
1666{
1667 return mFlinger->setClientState(mId, count, states);
1668}
1669
1670// ---------------------------------------------------------------------------
1671
1672GraphicPlane::GraphicPlane()
1673 : mHw(0)
1674{
1675}
1676
1677GraphicPlane::~GraphicPlane() {
1678 delete mHw;
1679}
1680
1681bool GraphicPlane::initialized() const {
1682 return mHw ? true : false;
1683}
1684
1685void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
1686 mHw = hw;
1687}
1688
1689void GraphicPlane::setTransform(const Transform& tr) {
1690 mTransform = tr;
1691 mGlobalTransform = mOrientationTransform * mTransform;
1692}
1693
1694status_t GraphicPlane::orientationToTransfrom(
1695 int orientation, int w, int h, Transform* tr)
1696{
1697 float a, b, c, d, x, y;
1698 switch (orientation) {
1699 case ISurfaceComposer::eOrientationDefault:
1700 a=1; b=0; c=0; d=1; x=0; y=0;
1701 break;
1702 case ISurfaceComposer::eOrientation90:
1703 a=0; b=-1; c=1; d=0; x=w; y=0;
1704 break;
1705 case ISurfaceComposer::eOrientation180:
1706 a=-1; b=0; c=0; d=-1; x=w; y=h;
1707 break;
1708 case ISurfaceComposer::eOrientation270:
1709 a=0; b=1; c=-1; d=0; x=0; y=h;
1710 break;
1711 default:
1712 return BAD_VALUE;
1713 }
1714 tr->set(a, b, c, d);
1715 tr->set(x, y);
1716 return NO_ERROR;
1717}
1718
1719status_t GraphicPlane::setOrientation(int orientation)
1720{
1721 const DisplayHardware& hw(displayHardware());
1722 const float w = hw.getWidth();
1723 const float h = hw.getHeight();
1724
1725 if (orientation == ISurfaceComposer::eOrientationDefault) {
1726 // make sure the default orientation is optimal
1727 mOrientationTransform.reset();
Mathias Agopian0d1318b2009-03-27 17:58:20 -07001728 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001729 mGlobalTransform = mTransform;
1730 return NO_ERROR;
1731 }
1732
1733 // If the rotation can be handled in hardware, this is where
1734 // the magic should happen.
1735 if (UNLIKELY(orientation == 42)) {
1736 float a, b, c, d, x, y;
1737 const float r = (3.14159265f / 180.0f) * 42.0f;
1738 const float si = sinf(r);
1739 const float co = cosf(r);
1740 a=co; b=-si; c=si; d=co;
1741 x = si*(h*0.5f) + (1-co)*(w*0.5f);
1742 y =-si*(w*0.5f) + (1-co)*(h*0.5f);
1743 mOrientationTransform.set(a, b, c, d);
1744 mOrientationTransform.set(x, y);
1745 } else {
1746 GraphicPlane::orientationToTransfrom(orientation, w, h,
1747 &mOrientationTransform);
1748 }
Mathias Agopian0d1318b2009-03-27 17:58:20 -07001749 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001750 mGlobalTransform = mOrientationTransform * mTransform;
1751 return NO_ERROR;
1752}
1753
1754const DisplayHardware& GraphicPlane::displayHardware() const {
1755 return *mHw;
1756}
1757
1758const Transform& GraphicPlane::transform() const {
1759 return mGlobalTransform;
1760}
1761
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001762EGLDisplay GraphicPlane::getEGLDisplay() const {
1763 return mHw->getEGLDisplay();
1764}
1765
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001766// ---------------------------------------------------------------------------
1767
1768}; // namespace android