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