blob: a63a28268b999b5d09880679b7d6be50cc043a80 [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;
1036 sp<LayerBaseClient> layer = LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
1037 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001038 mLayerMap.removeItem(layer->serverIndex());
1039 }
1040 return NO_ERROR;
1041 }
1042 // it's possible that we don't find a layer, because it might
1043 // have been destroyed already -- this is not technically an error
1044 // from the user because there is a race between destroySurface,
1045 // destroyclient and destroySurface-from-a-transaction.
1046 return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
1047}
1048
1049void SurfaceFlinger::free_resources_l()
1050{
1051 // Destroy layers that were removed
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001052 mLayersRemoved = false;
1053
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001054 // free resources associated with disconnected clients
1055 SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
1056 Vector<Client*>& disconnectedClients(mDisconnectedClients);
1057 const size_t count = disconnectedClients.size();
1058 for (size_t i=0 ; i<count ; i++) {
1059 Client* client = disconnectedClients[i];
1060 // if this client is the scheduled broadcast list,
1061 // remove it from there (and we don't need to signal it
1062 // since it is dead).
1063 int32_t index = scheduledBroadcasts.indexOf(client);
1064 if (index >= 0) {
1065 scheduledBroadcasts.removeItemsAt(index);
1066 }
1067 mTokens.release(client->cid);
1068 delete client;
1069 }
1070 disconnectedClients.clear();
1071}
1072
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001073uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
1074{
1075 return android_atomic_and(~flags, &mTransactionFlags) & flags;
1076}
1077
1078uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
1079{
1080 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
1081 if ((old & flags)==0) { // wake the server up
1082 if (delay > 0) {
1083 signalDelayedEvent(delay);
1084 } else {
1085 signalEvent();
1086 }
1087 }
1088 return old;
1089}
1090
1091void SurfaceFlinger::openGlobalTransaction()
1092{
1093 android_atomic_inc(&mTransactionCount);
1094}
1095
1096void SurfaceFlinger::closeGlobalTransaction()
1097{
1098 if (android_atomic_dec(&mTransactionCount) == 1) {
1099 signalEvent();
1100 }
1101}
1102
1103status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
1104{
1105 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1106 return BAD_VALUE;
1107
1108 Mutex::Autolock _l(mStateLock);
1109 mCurrentState.freezeDisplay = 1;
1110 setTransactionFlags(eTransactionNeeded);
1111
1112 // flags is intended to communicate some sort of animation behavior
Mathias Agopian62b74442009-04-14 23:02:51 -07001113 // (for instance fading)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001114 return NO_ERROR;
1115}
1116
1117status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
1118{
1119 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1120 return BAD_VALUE;
1121
1122 Mutex::Autolock _l(mStateLock);
1123 mCurrentState.freezeDisplay = 0;
1124 setTransactionFlags(eTransactionNeeded);
1125
1126 // flags is intended to communicate some sort of animation behavior
Mathias Agopian62b74442009-04-14 23:02:51 -07001127 // (for instance fading)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128 return NO_ERROR;
1129}
1130
Mathias Agopianc08731e2009-03-27 18:11:38 -07001131int SurfaceFlinger::setOrientation(DisplayID dpy,
1132 int orientation, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001133{
1134 if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
1135 return BAD_VALUE;
1136
1137 Mutex::Autolock _l(mStateLock);
1138 if (mCurrentState.orientation != orientation) {
1139 if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
Mathias Agopianc08731e2009-03-27 18:11:38 -07001140 mCurrentState.orientationType = flags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001141 mCurrentState.orientation = orientation;
1142 setTransactionFlags(eTransactionNeeded);
1143 mTransactionCV.wait(mStateLock);
1144 } else {
1145 orientation = BAD_VALUE;
1146 }
1147 }
1148 return orientation;
1149}
1150
1151sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
1152 ISurfaceFlingerClient::surface_data_t* params,
1153 DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
1154 uint32_t flags)
1155{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001156 sp<LayerBaseClient> layer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001157 sp<LayerBaseClient::Surface> surfaceHandle;
1158 Mutex::Autolock _l(mStateLock);
1159 Client* const c = mClientsMap.valueFor(clientId);
1160 if (UNLIKELY(!c)) {
1161 LOGE("createSurface() failed, client not found (id=%d)", clientId);
1162 return surfaceHandle;
1163 }
1164
1165 //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
1166 int32_t id = c->generateId(pid);
1167 if (uint32_t(id) >= NUM_LAYERS_MAX) {
1168 LOGE("createSurface() failed, generateId = %d", id);
1169 return surfaceHandle;
1170 }
1171
1172 switch (flags & eFXSurfaceMask) {
1173 case eFXSurfaceNormal:
1174 if (UNLIKELY(flags & ePushBuffers)) {
1175 layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
1176 } else {
1177 layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
1178 }
1179 break;
1180 case eFXSurfaceBlur:
1181 layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
1182 break;
1183 case eFXSurfaceDim:
1184 layer = createDimSurfaceLocked(c, d, id, w, h, flags);
1185 break;
1186 }
1187
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001188 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001189 setTransactionFlags(eTransactionNeeded);
1190 surfaceHandle = layer->getSurface();
1191 if (surfaceHandle != 0)
1192 surfaceHandle->getSurfaceData(params);
1193 }
1194
1195 return surfaceHandle;
1196}
1197
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001198sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001199 Client* client, DisplayID display,
1200 int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
1201{
1202 // initialize the surfaces
1203 switch (format) { // TODO: take h/w into account
1204 case PIXEL_FORMAT_TRANSPARENT:
1205 case PIXEL_FORMAT_TRANSLUCENT:
1206 format = PIXEL_FORMAT_RGBA_8888;
1207 break;
1208 case PIXEL_FORMAT_OPAQUE:
1209 format = PIXEL_FORMAT_RGB_565;
1210 break;
1211 }
1212
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001213 sp<Layer> layer = new Layer(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001214 status_t err = layer->setBuffers(client, w, h, format, flags);
1215 if (LIKELY(err == NO_ERROR)) {
1216 layer->initStates(w, h, flags);
1217 addLayer_l(layer);
1218 } else {
1219 LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001220 layer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001221 }
1222 return layer;
1223}
1224
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001225sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001226 Client* client, DisplayID display,
1227 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1228{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001229 sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001230 layer->initStates(w, h, flags);
1231 addLayer_l(layer);
1232 return layer;
1233}
1234
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001235sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001236 Client* client, DisplayID display,
1237 int32_t id, uint32_t w, uint32_t h, uint32_t flags)
1238{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001239 sp<LayerDim> layer = new LayerDim(this, display, client, id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001240 layer->initStates(w, h, flags);
1241 addLayer_l(layer);
1242 return layer;
1243}
1244
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001245sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
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<LayerBuffer> layer = new LayerBuffer(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
1255status_t SurfaceFlinger::destroySurface(SurfaceID index)
1256{
1257 Mutex::Autolock _l(mStateLock);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001258 const sp<LayerBaseClient>& layer = getLayerUser_l(index);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001259 status_t err = removeLayer_l(layer);
1260 if (err < 0)
1261 return err;
1262 setTransactionFlags(eTransactionNeeded);
1263 return NO_ERROR;
1264}
1265
1266status_t SurfaceFlinger::setClientState(
1267 ClientID cid,
1268 int32_t count,
1269 const layer_state_t* states)
1270{
1271 Mutex::Autolock _l(mStateLock);
1272 uint32_t flags = 0;
1273 cid <<= 16;
1274 for (int i=0 ; i<count ; i++) {
1275 const layer_state_t& s = states[i];
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001276 const sp<LayerBaseClient>& layer = getLayerUser_l(s.surface | cid);
1277 if (layer != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001278 const uint32_t what = s.what;
1279 // check if it has been destroyed first
1280 if (what & eDestroyed) {
1281 if (removeLayer_l(layer) == NO_ERROR) {
1282 flags |= eTransactionNeeded;
1283 // we skip everything else... well, no, not really
1284 // we skip ONLY that transaction.
1285 continue;
1286 }
1287 }
1288 if (what & ePositionChanged) {
1289 if (layer->setPosition(s.x, s.y))
1290 flags |= eTraversalNeeded;
1291 }
1292 if (what & eLayerChanged) {
1293 if (layer->setLayer(s.z)) {
1294 mCurrentState.layersSortedByZ.reorder(
1295 layer, &Layer::compareCurrentStateZ);
1296 // we need traversal (state changed)
1297 // AND transaction (list changed)
1298 flags |= eTransactionNeeded|eTraversalNeeded;
1299 }
1300 }
1301 if (what & eSizeChanged) {
1302 if (layer->setSize(s.w, s.h))
1303 flags |= eTraversalNeeded;
1304 }
1305 if (what & eAlphaChanged) {
1306 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
1307 flags |= eTraversalNeeded;
1308 }
1309 if (what & eMatrixChanged) {
1310 if (layer->setMatrix(s.matrix))
1311 flags |= eTraversalNeeded;
1312 }
1313 if (what & eTransparentRegionChanged) {
1314 if (layer->setTransparentRegionHint(s.transparentRegion))
1315 flags |= eTraversalNeeded;
1316 }
1317 if (what & eVisibilityChanged) {
1318 if (layer->setFlags(s.flags, s.mask))
1319 flags |= eTraversalNeeded;
1320 }
1321 }
1322 }
1323 if (flags) {
1324 setTransactionFlags(flags);
1325 }
1326 return NO_ERROR;
1327}
1328
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001329sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001330{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001331 sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
1332 return layer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001333}
1334
1335void SurfaceFlinger::screenReleased(int dpy)
1336{
1337 // this may be called by a signal handler, we can't do too much in here
1338 android_atomic_or(eConsoleReleased, &mConsoleSignals);
1339 signalEvent();
1340}
1341
1342void SurfaceFlinger::screenAcquired(int dpy)
1343{
1344 // this may be called by a signal handler, we can't do too much in here
1345 android_atomic_or(eConsoleAcquired, &mConsoleSignals);
1346 signalEvent();
1347}
1348
1349status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
1350{
1351 const size_t SIZE = 1024;
1352 char buffer[SIZE];
1353 String8 result;
1354 if (checkCallingPermission(
1355 String16("android.permission.DUMP")) == false)
1356 { // not allowed
1357 snprintf(buffer, SIZE, "Permission Denial: "
1358 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1359 IPCThreadState::self()->getCallingPid(),
1360 IPCThreadState::self()->getCallingUid());
1361 result.append(buffer);
1362 } else {
1363 Mutex::Autolock _l(mStateLock);
1364 size_t s = mClientsMap.size();
1365 char name[64];
1366 for (size_t i=0 ; i<s ; i++) {
1367 Client* client = mClientsMap.valueAt(i);
1368 sprintf(name, " Client (id=0x%08x)", client->cid);
1369 client->dump(name);
1370 }
1371 const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
1372 const size_t count = currentLayers.size();
1373 for (size_t i=0 ; i<count ; i++) {
1374 /*** LayerBase ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001375 const sp<LayerBase>& layer = currentLayers[i];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001376 const Layer::State& s = layer->drawingState();
1377 snprintf(buffer, SIZE,
1378 "+ %s %p\n"
1379 " "
1380 "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
1381 "needsBlending=%1d, invalidate=%1d, "
1382 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001383 layer->getTypeID(), layer.get(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001384 s.z, layer->tx(), layer->ty(), s.w, s.h,
1385 layer->needsBlending(), layer->contentDirty,
1386 s.alpha, s.flags,
1387 s.transform[0], s.transform[1],
1388 s.transform[2], s.transform[3]);
1389 result.append(buffer);
1390 buffer[0] = 0;
1391 /*** LayerBaseClient ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001392 sp<LayerBaseClient> lbc =
1393 LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
1394 if (lbc != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001395 snprintf(buffer, SIZE,
1396 " "
1397 "id=0x%08x, client=0x%08x, identity=%u\n",
1398 lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
1399 lbc->getIdentity());
1400 }
1401 result.append(buffer);
1402 buffer[0] = 0;
1403 /*** Layer ***/
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001404 sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
1405 if (l != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001406 const LayerBitmap& buf0(l->getBuffer(0));
1407 const LayerBitmap& buf1(l->getBuffer(1));
1408 snprintf(buffer, SIZE,
1409 " "
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001410 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001411 " freezeLock=%p, swapState=0x%08x\n",
1412 l->pixelFormat(),
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001413 buf0.getWidth(), buf0.getHeight(),
1414 buf0.getBuffer()->getStride(),
1415 buf1.getWidth(), buf1.getHeight(),
1416 buf1.getBuffer()->getStride(),
1417 l->getFreezeLock().get(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001418 l->lcblk->swapState);
1419 }
1420 result.append(buffer);
1421 buffer[0] = 0;
1422 s.transparentRegion.dump(result, "transparentRegion");
1423 layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
1424 layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
1425 }
1426 mWormholeRegion.dump(result, "WormholeRegion");
1427 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1428 snprintf(buffer, SIZE,
1429 " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1430 mFreezeDisplay?"yes":"no", mFreezeCount,
1431 mCurrentState.orientation, hw.canDraw());
1432 result.append(buffer);
1433
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001434 const BufferAllocator& alloc(BufferAllocator::get());
1435 alloc.dump(result);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001436 }
1437 write(fd, result.string(), result.size());
1438 return NO_ERROR;
1439}
1440
1441status_t SurfaceFlinger::onTransact(
1442 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1443{
1444 switch (code) {
1445 case CREATE_CONNECTION:
1446 case OPEN_GLOBAL_TRANSACTION:
1447 case CLOSE_GLOBAL_TRANSACTION:
1448 case SET_ORIENTATION:
1449 case FREEZE_DISPLAY:
1450 case UNFREEZE_DISPLAY:
1451 case BOOT_FINISHED:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001452 {
1453 // codes that require permission check
1454 IPCThreadState* ipc = IPCThreadState::self();
1455 const int pid = ipc->getCallingPid();
1456 const int self_pid = getpid();
1457 if (UNLIKELY(pid != self_pid)) {
1458 // we're called from a different process, do the real check
1459 if (!checkCallingPermission(
1460 String16("android.permission.ACCESS_SURFACE_FLINGER")))
1461 {
1462 const int uid = ipc->getCallingUid();
1463 LOGE("Permission Denial: "
1464 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
1465 return PERMISSION_DENIED;
1466 }
1467 }
1468 }
1469 }
1470
1471 status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
1472 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1473 // HARDWARE_TEST stuff...
1474 if (UNLIKELY(checkCallingPermission(
1475 String16("android.permission.HARDWARE_TEST")) == false))
1476 { // not allowed
1477 LOGE("Permission Denial: pid=%d, uid=%d\n",
1478 IPCThreadState::self()->getCallingPid(),
1479 IPCThreadState::self()->getCallingUid());
1480 return PERMISSION_DENIED;
1481 }
1482 int n;
1483 switch (code) {
Mathias Agopian01b76682009-04-16 20:04:08 -07001484 case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001485 return NO_ERROR;
1486 case 1001: // SHOW_FPS
1487 n = data.readInt32();
1488 mDebugFps = n ? 1 : 0;
1489 return NO_ERROR;
1490 case 1002: // SHOW_UPDATES
1491 n = data.readInt32();
1492 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
1493 return NO_ERROR;
1494 case 1003: // SHOW_BACKGROUND
1495 n = data.readInt32();
1496 mDebugBackground = n ? 1 : 0;
1497 return NO_ERROR;
1498 case 1004:{ // repaint everything
1499 Mutex::Autolock _l(mStateLock);
1500 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1501 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
1502 signalEvent();
1503 }
1504 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001505 case 1007: // set mFreezeCount
1506 mFreezeCount = data.readInt32();
1507 return NO_ERROR;
1508 case 1010: // interrogate.
Mathias Agopian01b76682009-04-16 20:04:08 -07001509 reply->writeInt32(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001510 reply->writeInt32(0);
1511 reply->writeInt32(mDebugRegion);
1512 reply->writeInt32(mDebugBackground);
1513 return NO_ERROR;
1514 case 1013: {
1515 Mutex::Autolock _l(mStateLock);
1516 const DisplayHardware& hw(graphicPlane(0).displayHardware());
1517 reply->writeInt32(hw.getPageFlipCount());
1518 }
1519 return NO_ERROR;
1520 }
1521 }
1522 return err;
1523}
1524
1525// ---------------------------------------------------------------------------
1526#if 0
1527#pragma mark -
1528#endif
1529
1530Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
1531 : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
1532{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001533 const int pgsize = getpagesize();
1534 const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
1535 mCblkHeap = new MemoryDealer(cblksize);
1536 mCblkMemory = mCblkHeap->allocate(cblksize);
1537 if (mCblkMemory != 0) {
1538 ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
1539 if (ctrlblk) { // construct the shared structure in-place.
1540 new(ctrlblk) per_client_cblk_t;
1541 }
1542 }
1543}
1544
1545Client::~Client() {
1546 if (ctrlblk) {
1547 const int pgsize = getpagesize();
1548 ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
1549 }
1550}
1551
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001552int32_t Client::generateId(int pid)
1553{
1554 const uint32_t i = clz( ~mBitmap );
1555 if (i >= NUM_LAYERS_MAX) {
1556 return NO_MEMORY;
1557 }
1558 mPid = pid;
1559 mInUse.add(uint8_t(i));
1560 mBitmap |= 1<<(31-i);
1561 return i;
1562}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001563
1564status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001565{
1566 ssize_t idx = mInUse.indexOf(id);
1567 if (idx < 0)
1568 return NAME_NOT_FOUND;
1569 return mLayers.insertAt(layer, idx);
1570}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001571
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001572void Client::free(int32_t id)
1573{
1574 ssize_t idx = mInUse.remove(uint8_t(id));
1575 if (idx >= 0) {
1576 mBitmap &= ~(1<<(31-id));
1577 mLayers.removeItemsAt(idx);
1578 }
1579}
1580
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001581bool Client::isValid(int32_t i) const {
1582 return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
1583}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001584
1585sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
1586 sp<LayerBaseClient> lbc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001587 ssize_t idx = mInUse.indexOf(uint8_t(i));
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001588 if (idx >= 0) {
1589 lbc = mLayers[idx].promote();
1590 LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
1591 }
1592 return lbc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001593}
1594
1595void Client::dump(const char* what)
1596{
1597}
1598
1599// ---------------------------------------------------------------------------
1600#if 0
1601#pragma mark -
1602#endif
1603
1604BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
1605 : mId(cid), mFlinger(flinger), mCblk(cblk)
1606{
1607}
1608
1609BClient::~BClient() {
1610 // destroy all resources attached to this client
1611 mFlinger->destroyConnection(mId);
1612}
1613
1614void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
1615 *ctrl = mCblk;
1616}
1617
1618sp<ISurface> BClient::createSurface(
1619 ISurfaceFlingerClient::surface_data_t* params, int pid,
1620 DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
1621 uint32_t flags)
1622{
1623 return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags);
1624}
1625
1626status_t BClient::destroySurface(SurfaceID sid)
1627{
1628 sid |= (mId << 16); // add the client-part to id
1629 return mFlinger->destroySurface(sid);
1630}
1631
1632status_t BClient::setState(int32_t count, const layer_state_t* states)
1633{
1634 return mFlinger->setClientState(mId, count, states);
1635}
1636
1637// ---------------------------------------------------------------------------
1638
1639GraphicPlane::GraphicPlane()
1640 : mHw(0)
1641{
1642}
1643
1644GraphicPlane::~GraphicPlane() {
1645 delete mHw;
1646}
1647
1648bool GraphicPlane::initialized() const {
1649 return mHw ? true : false;
1650}
1651
1652void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
1653 mHw = hw;
1654}
1655
1656void GraphicPlane::setTransform(const Transform& tr) {
1657 mTransform = tr;
1658 mGlobalTransform = mOrientationTransform * mTransform;
1659}
1660
1661status_t GraphicPlane::orientationToTransfrom(
1662 int orientation, int w, int h, Transform* tr)
1663{
1664 float a, b, c, d, x, y;
1665 switch (orientation) {
1666 case ISurfaceComposer::eOrientationDefault:
1667 a=1; b=0; c=0; d=1; x=0; y=0;
1668 break;
1669 case ISurfaceComposer::eOrientation90:
1670 a=0; b=-1; c=1; d=0; x=w; y=0;
1671 break;
1672 case ISurfaceComposer::eOrientation180:
1673 a=-1; b=0; c=0; d=-1; x=w; y=h;
1674 break;
1675 case ISurfaceComposer::eOrientation270:
1676 a=0; b=1; c=-1; d=0; x=0; y=h;
1677 break;
1678 default:
1679 return BAD_VALUE;
1680 }
1681 tr->set(a, b, c, d);
1682 tr->set(x, y);
1683 return NO_ERROR;
1684}
1685
1686status_t GraphicPlane::setOrientation(int orientation)
1687{
1688 const DisplayHardware& hw(displayHardware());
1689 const float w = hw.getWidth();
1690 const float h = hw.getHeight();
1691
1692 if (orientation == ISurfaceComposer::eOrientationDefault) {
1693 // make sure the default orientation is optimal
1694 mOrientationTransform.reset();
Mathias Agopian0d1318b2009-03-27 17:58:20 -07001695 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001696 mGlobalTransform = mTransform;
1697 return NO_ERROR;
1698 }
1699
1700 // If the rotation can be handled in hardware, this is where
1701 // the magic should happen.
1702 if (UNLIKELY(orientation == 42)) {
1703 float a, b, c, d, x, y;
1704 const float r = (3.14159265f / 180.0f) * 42.0f;
1705 const float si = sinf(r);
1706 const float co = cosf(r);
1707 a=co; b=-si; c=si; d=co;
1708 x = si*(h*0.5f) + (1-co)*(w*0.5f);
1709 y =-si*(w*0.5f) + (1-co)*(h*0.5f);
1710 mOrientationTransform.set(a, b, c, d);
1711 mOrientationTransform.set(x, y);
1712 } else {
1713 GraphicPlane::orientationToTransfrom(orientation, w, h,
1714 &mOrientationTransform);
1715 }
Mathias Agopian0d1318b2009-03-27 17:58:20 -07001716 mOrientation = orientation;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001717 mGlobalTransform = mOrientationTransform * mTransform;
1718 return NO_ERROR;
1719}
1720
1721const DisplayHardware& GraphicPlane::displayHardware() const {
1722 return *mHw;
1723}
1724
1725const Transform& GraphicPlane::transform() const {
1726 return mGlobalTransform;
1727}
1728
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001729EGLDisplay GraphicPlane::getEGLDisplay() const {
1730 return mHw->getEGLDisplay();
1731}
1732
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001733// ---------------------------------------------------------------------------
1734
1735}; // namespace android