blob: 4ccd3965c35f68c57df5a8c40090fb3b7b628bce [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "SurfaceComposerClient"
18
19#include <stdint.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25
26#include <cutils/memory.h>
27
28#include <utils/Atomic.h>
29#include <utils/Errors.h>
30#include <utils/threads.h>
31#include <utils/KeyedVector.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032#include <utils/IServiceManager.h>
33#include <utils/IMemory.h>
34#include <utils/Log.h>
35
Mathias Agopian076b1cc2009-04-10 14:24:30 -070036#include <ui/DisplayInfo.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037#include <ui/ISurfaceComposer.h>
38#include <ui/ISurfaceFlingerClient.h>
39#include <ui/ISurface.h>
40#include <ui/SurfaceComposerClient.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041#include <ui/Rect.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042
43#include <private/ui/SharedState.h>
44#include <private/ui/LayerState.h>
45#include <private/ui/SurfaceFlingerSynchro.h>
46
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047#define VERBOSE(...) ((void)0)
48//#define VERBOSE LOGD
49
50#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
51#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
52
53namespace android {
54
55// ---------------------------------------------------------------------------
56
57// Must not be holding SurfaceComposerClient::mLock when acquiring gLock here.
58static Mutex gLock;
59static sp<ISurfaceComposer> gSurfaceManager;
60static DefaultKeyedVector< sp<IBinder>, sp<SurfaceComposerClient> > gActiveConnections;
61static SortedVector<sp<SurfaceComposerClient> > gOpenTransactions;
62static sp<IMemory> gServerCblkMemory;
63static volatile surface_flinger_cblk_t* gServerCblk;
64
65const sp<ISurfaceComposer>& _get_surface_manager()
66{
67 if (gSurfaceManager != 0) {
68 return gSurfaceManager;
69 }
70
71 sp<IBinder> binder;
72 sp<IServiceManager> sm = defaultServiceManager();
73 do {
74 binder = sm->getService(String16("SurfaceFlinger"));
75 if (binder == 0) {
76 LOGW("SurfaceFlinger not published, waiting...");
77 usleep(500000); // 0.5 s
78 }
79 } while(binder == 0);
80 sp<ISurfaceComposer> sc(interface_cast<ISurfaceComposer>(binder));
81
82 Mutex::Autolock _l(gLock);
83 if (gSurfaceManager == 0) {
84 gSurfaceManager = sc;
85 }
86 return gSurfaceManager;
87}
88
89static volatile surface_flinger_cblk_t const * get_cblk()
90{
91 if (gServerCblk == 0) {
92 const sp<ISurfaceComposer>& sm(_get_surface_manager());
93 Mutex::Autolock _l(gLock);
94 if (gServerCblk == 0) {
95 gServerCblkMemory = sm->getCblk();
96 LOGE_IF(gServerCblkMemory==0, "Can't get server control block");
97 gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->pointer();
98 LOGE_IF(gServerCblk==0, "Can't get server control block address");
99 }
100 }
101 return gServerCblk;
102}
103
104// ---------------------------------------------------------------------------
105
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800106// these functions are used by the clients
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700107status_t per_client_cblk_t::validate(size_t i) const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800108 if (uint32_t(i) >= NUM_LAYERS_MAX)
109 return BAD_INDEX;
110 if (layers[i].swapState & eInvalidSurface)
111 return NO_MEMORY;
112 return NO_ERROR;
113}
114
115int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags)
116{
117 int32_t index;
118 uint32_t state;
119 int timeout = 0;
120 status_t result;
121 layer_cblk_t * const layer = layers + i;
122 const bool blocking = flags & BLOCKING;
123 const bool inspect = flags & INSPECT;
124
125 do {
126 state = layer->swapState;
127
128 if (UNLIKELY((state&(eFlipRequested|eNextFlipPending)) == eNextFlipPending)) {
129 LOGE("eNextFlipPending set but eFlipRequested not set, "
130 "layer=%d (lcblk=%p), state=%08x",
131 int(i), layer, int(state));
132 return INVALID_OPERATION;
133 }
134
135 if (UNLIKELY(state&eLocked)) {
136 LOGE("eLocked set when entering lock_layer(), "
137 "layer=%d (lcblk=%p), state=%08x",
138 int(i), layer, int(state));
139 return WOULD_BLOCK;
140 }
141
142
143 if (state & (eFlipRequested | eNextFlipPending | eResizeRequested
144 | eInvalidSurface))
145 {
146 int32_t resizeIndex;
147 Mutex::Autolock _l(lock);
148 // might block for a very short amount of time
149 // will never cause the server to block (trylock())
150
151 goto start_loop_here;
152
153 // We block the client if:
154 // eNextFlipPending: we've used both buffers already, so we need to
155 // wait for one to become availlable.
156 // eResizeRequested: the buffer we're going to acquire is being
157 // resized. Block until it is done.
158 // eFlipRequested && eBusy: the buffer we're going to acquire is
159 // currently in use by the server.
160 // eInvalidSurface: this is a special case, we don't block in this
161 // case, we just return an error.
162
163 while((state & (eNextFlipPending|eInvalidSurface)) ||
164 (state & ((resizeIndex) ? eResizeBuffer1 : eResizeBuffer0)) ||
165 ((state & (eFlipRequested|eBusy)) == (eFlipRequested|eBusy)) )
166 {
167 if (state & eInvalidSurface)
168 return NO_MEMORY;
169
170 if (!blocking)
171 return WOULD_BLOCK;
172
173 timeout = 0;
174 result = cv.waitRelative(lock, seconds(1));
175 if (__builtin_expect(result!=NO_ERROR, false)) {
176 const int newState = layer->swapState;
177 LOGW( "lock_layer timed out (is the CPU pegged?) "
178 "layer=%d, lcblk=%p, state=%08x (was %08x)",
179 int(i), layer, newState, int(state));
180 timeout = newState != int(state);
181 }
182
183 start_loop_here:
184 state = layer->swapState;
185 resizeIndex = (state&eIndex) ^ ((state&eFlipRequested)>>1);
186 }
187
188 LOGW_IF(timeout,
189 "lock_layer() timed out but didn't appear to need "
190 "to be locked and we recovered "
191 "(layer=%d, lcblk=%p, state=%08x)",
192 int(i), layer, int(state));
193 }
194
195 // eFlipRequested is not set and cannot be set by another thread: it's
196 // safe to use the first buffer without synchronization.
197
198 // Choose the index depending on eFlipRequested.
199 // When it's set, choose the 'other' buffer.
200 index = (state&eIndex) ^ ((state&eFlipRequested)>>1);
201
202 // make sure this buffer is valid
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700203 status_t err = layer->surface[index].status;
204 if (err < 0) {
205 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800206 }
207
208 if (inspect) {
209 // we just want to inspect this layer. don't lock it.
210 goto done;
211 }
212
213 // last thing before we're done, we need to atomically lock the state
214 } while (android_atomic_cmpxchg(state, state|eLocked, &(layer->swapState)));
215
216 VERBOSE("locked layer=%d (lcblk=%p), buffer=%d, state=0x%08x",
217 int(i), layer, int(index), int(state));
218
219 // store the index of the locked buffer (for client use only)
220 layer->flags &= ~eBufferIndex;
221 layer->flags |= ((index << eBufferIndexShift) & eBufferIndex);
222
223done:
224 return index;
225}
226
227uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
228{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700229 // atomically set eFlipRequested and clear eLocked and optionally
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800230 // set eNextFlipPending if eFlipRequested was already set
231
232 layer_cblk_t * const layer = layers + i;
233 int32_t oldvalue, newvalue;
234 do {
235 oldvalue = layer->swapState;
236 // get current value
237
238 newvalue = oldvalue & ~eLocked;
239 // clear eLocked
240
241 newvalue |= eFlipRequested;
242 // set eFlipRequested
243
244 if (oldvalue & eFlipRequested)
245 newvalue |= eNextFlipPending;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700246 // if eFlipRequested was already set, set eNextFlipPending
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800247
248 } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState)));
249
250 VERBOSE("request pageflip for layer=%d, buffer=%d, state=0x%08x",
251 int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift),
252 int(newvalue));
253
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700254 // from this point, the server can kick in at any time and use the first
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800255 // buffer, so we cannot use it anymore, and we must use the 'other'
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700256 // buffer instead (or wait if it is not available yet, see lock_layer).
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800257
258 return newvalue;
259}
260
261void per_client_cblk_t::unlock_layer(size_t i)
262{
263 layer_cblk_t * const layer = layers + i;
264 android_atomic_and(~eLocked, &layer->swapState);
265}
266
267// ---------------------------------------------------------------------------
268
269static inline int compare_type( const layer_state_t& lhs,
270 const layer_state_t& rhs) {
271 if (lhs.surface < rhs.surface) return -1;
272 if (lhs.surface > rhs.surface) return 1;
273 return 0;
274}
275
276SurfaceComposerClient::SurfaceComposerClient()
277{
278 const sp<ISurfaceComposer>& sm(_get_surface_manager());
279 if (sm == 0) {
280 _init(0, 0);
281 return;
282 }
283
284 _init(sm, sm->createConnection());
285
286 if (mClient != 0) {
287 Mutex::Autolock _l(gLock);
288 VERBOSE("Adding client %p to map", this);
289 gActiveConnections.add(mClient->asBinder(), this);
290 }
291}
292
293SurfaceComposerClient::SurfaceComposerClient(
294 const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn)
295{
296 _init(sm, interface_cast<ISurfaceFlingerClient>(conn));
297}
298
299void SurfaceComposerClient::_init(
300 const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)
301{
302 VERBOSE("Creating client %p, conn %p", this, conn.get());
303
304 mSignalServer = 0;
305 mPrebuiltLayerState = 0;
306 mTransactionOpen = 0;
307 mStatus = NO_ERROR;
308 mControl = 0;
309
310 mClient = conn;
311 if (mClient == 0) {
312 mStatus = NO_INIT;
313 return;
314 }
315
316 mClient->getControlBlocks(&mControlMemory);
317 mSignalServer = new SurfaceFlingerSynchro(sm);
318 mControl = static_cast<per_client_cblk_t *>(mControlMemory->pointer());
319}
320
321SurfaceComposerClient::~SurfaceComposerClient()
322{
323 VERBOSE("Destroying client %p, conn %p", this, mClient.get());
324 dispose();
325}
326
327status_t SurfaceComposerClient::initCheck() const
328{
329 return mStatus;
330}
331
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800332sp<IBinder> SurfaceComposerClient::connection() const
333{
334 return (mClient != 0) ? mClient->asBinder() : 0;
335}
336
337sp<SurfaceComposerClient>
338SurfaceComposerClient::clientForConnection(const sp<IBinder>& conn)
339{
340 sp<SurfaceComposerClient> client;
341
342 { // scope for lock
343 Mutex::Autolock _l(gLock);
344 client = gActiveConnections.valueFor(conn);
345 }
346
347 if (client == 0) {
348 // Need to make a new client.
349 const sp<ISurfaceComposer>& sm(_get_surface_manager());
350 client = new SurfaceComposerClient(sm, conn);
351 if (client != 0 && client->initCheck() == NO_ERROR) {
352 Mutex::Autolock _l(gLock);
353 gActiveConnections.add(conn, client);
354 //LOGD("we have %d connections", gActiveConnections.size());
355 } else {
356 client.clear();
357 }
358 }
359
360 return client;
361}
362
363void SurfaceComposerClient::dispose()
364{
365 // this can be called more than once.
366
367 sp<IMemory> controlMemory;
368 sp<ISurfaceFlingerClient> client;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800369
370 {
371 Mutex::Autolock _lg(gLock);
372 Mutex::Autolock _lm(mLock);
373
374 delete mSignalServer;
375 mSignalServer = 0;
376
377 if (mClient != 0) {
378 client = mClient;
379 mClient.clear();
380
381 ssize_t i = gActiveConnections.indexOfKey(client->asBinder());
382 if (i >= 0 && gActiveConnections.valueAt(i) == this) {
383 VERBOSE("Removing client %p from map at %d", this, int(i));
384 gActiveConnections.removeItemsAt(i);
385 }
386 }
387
388 delete mPrebuiltLayerState;
389 mPrebuiltLayerState = 0;
390 controlMemory = mControlMemory;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800391 mControlMemory.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800392 mControl = 0;
393 mStatus = NO_INIT;
394 }
395}
396
397status_t SurfaceComposerClient::getDisplayInfo(
398 DisplayID dpy, DisplayInfo* info)
399{
400 if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
401 return BAD_VALUE;
402
403 volatile surface_flinger_cblk_t const * cblk = get_cblk();
404 volatile display_cblk_t const * dcblk = cblk->displays + dpy;
405
406 info->w = dcblk->w;
407 info->h = dcblk->h;
408 info->orientation = dcblk->orientation;
409 info->xdpi = dcblk->xdpi;
410 info->ydpi = dcblk->ydpi;
411 info->fps = dcblk->fps;
412 info->density = dcblk->density;
413 return getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo));
414}
415
416ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
417{
418 if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
419 return BAD_VALUE;
420 volatile surface_flinger_cblk_t const * cblk = get_cblk();
421 volatile display_cblk_t const * dcblk = cblk->displays + dpy;
422 return dcblk->w;
423}
424
425ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
426{
427 if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
428 return BAD_VALUE;
429 volatile surface_flinger_cblk_t const * cblk = get_cblk();
430 volatile display_cblk_t const * dcblk = cblk->displays + dpy;
431 return dcblk->h;
432}
433
434ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
435{
436 if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
437 return BAD_VALUE;
438 volatile surface_flinger_cblk_t const * cblk = get_cblk();
439 volatile display_cblk_t const * dcblk = cblk->displays + dpy;
440 return dcblk->orientation;
441}
442
443ssize_t SurfaceComposerClient::getNumberOfDisplays()
444{
445 volatile surface_flinger_cblk_t const * cblk = get_cblk();
446 uint32_t connected = cblk->connected;
447 int n = 0;
448 while (connected) {
449 if (connected&1) n++;
450 connected >>= 1;
451 }
452 return n;
453}
454
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700455
456void SurfaceComposerClient::signalServer()
457{
458 mSignalServer->signal();
459}
460
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461sp<Surface> SurfaceComposerClient::createSurface(
462 int pid,
463 DisplayID display,
464 uint32_t w,
465 uint32_t h,
466 PixelFormat format,
467 uint32_t flags)
468{
469 sp<Surface> result;
470 if (mStatus == NO_ERROR) {
471 ISurfaceFlingerClient::surface_data_t data;
472 sp<ISurface> surface = mClient->createSurface(&data, pid,
473 display, w, h, format, flags);
474 if (surface != 0) {
475 if (uint32_t(data.token) < NUM_LAYERS_MAX) {
476 result = new Surface(this, surface, data, w, h, format, flags);
477 }
478 }
479 }
480 return result;
481}
482
483status_t SurfaceComposerClient::destroySurface(SurfaceID sid)
484{
485 if (mStatus != NO_ERROR)
486 return mStatus;
487
488 // it's okay to destroy a surface while a transaction is open,
489 // (transactions really are a client-side concept)
490 // however, this indicates probably a misuse of the API or a bug
491 // in the client code.
492 LOGW_IF(mTransactionOpen,
493 "Destroying surface while a transaction is open. "
494 "Client %p: destroying surface %d, mTransactionOpen=%d",
495 this, sid, mTransactionOpen);
496
497 status_t err = mClient->destroySurface(sid);
498 return err;
499}
500
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800501void SurfaceComposerClient::openGlobalTransaction()
502{
503 Mutex::Autolock _l(gLock);
504
505 if (gOpenTransactions.size()) {
506 LOGE("openGlobalTransaction() called more than once. skipping.");
507 return;
508 }
509
510 const size_t N = gActiveConnections.size();
511 VERBOSE("openGlobalTransaction (%ld clients)", N);
512 for (size_t i=0; i<N; i++) {
513 sp<SurfaceComposerClient> client(gActiveConnections.valueAt(i));
514 if (gOpenTransactions.indexOf(client) < 0) {
515 if (client->openTransaction() == NO_ERROR) {
516 if (gOpenTransactions.add(client) < 0) {
517 // Ooops!
518 LOGE( "Unable to add a SurfaceComposerClient "
519 "to the global transaction set (out of memory?)");
520 client->closeTransaction();
521 // let it go, it'll fail later when the user
522 // tries to do something with the transaction
523 }
524 } else {
525 LOGE("openTransaction on client %p failed", client.get());
526 // let it go, it'll fail later when the user
527 // tries to do something with the transaction
528 }
529 }
530 }
531}
532
533void SurfaceComposerClient::closeGlobalTransaction()
534{
535 gLock.lock();
536 SortedVector< sp<SurfaceComposerClient> > clients(gOpenTransactions);
537 gOpenTransactions.clear();
538 gLock.unlock();
539
540 const size_t N = clients.size();
541 VERBOSE("closeGlobalTransaction (%ld clients)", N);
542 if (N == 1) {
543 clients[0]->closeTransaction();
544 } else {
545 const sp<ISurfaceComposer>& sm(_get_surface_manager());
546 sm->openGlobalTransaction();
547 for (size_t i=0; i<N; i++) {
548 clients[i]->closeTransaction();
549 }
550 sm->closeGlobalTransaction();
551 }
552}
553
554status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
555{
556 const sp<ISurfaceComposer>& sm(_get_surface_manager());
557 return sm->freezeDisplay(dpy, flags);
558}
559
560status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags)
561{
562 const sp<ISurfaceComposer>& sm(_get_surface_manager());
563 return sm->unfreezeDisplay(dpy, flags);
564}
565
Mathias Agopianc08731e2009-03-27 18:11:38 -0700566int SurfaceComposerClient::setOrientation(DisplayID dpy,
567 int orientation, uint32_t flags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800568{
569 const sp<ISurfaceComposer>& sm(_get_surface_manager());
Mathias Agopianc08731e2009-03-27 18:11:38 -0700570 return sm->setOrientation(dpy, orientation, flags);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800571}
572
573status_t SurfaceComposerClient::openTransaction()
574{
575 if (mStatus != NO_ERROR)
576 return mStatus;
577 Mutex::Autolock _l(mLock);
578 VERBOSE( "openTransaction (client %p, mTransactionOpen=%d)",
579 this, mTransactionOpen);
580 mTransactionOpen++;
581 if (mPrebuiltLayerState == 0) {
582 mPrebuiltLayerState = new layer_state_t;
583 }
584 return NO_ERROR;
585}
586
587
588status_t SurfaceComposerClient::closeTransaction()
589{
590 if (mStatus != NO_ERROR)
591 return mStatus;
592
593 Mutex::Autolock _l(mLock);
594
595 VERBOSE( "closeTransaction (client %p, mTransactionOpen=%d)",
596 this, mTransactionOpen);
597
598 if (mTransactionOpen <= 0) {
599 LOGE( "closeTransaction (client %p, mTransactionOpen=%d) "
600 "called more times than openTransaction()",
601 this, mTransactionOpen);
602 return INVALID_OPERATION;
603 }
604
605 if (mTransactionOpen >= 2) {
606 mTransactionOpen--;
607 return NO_ERROR;
608 }
609
610 mTransactionOpen = 0;
611 const ssize_t count = mStates.size();
612 if (count) {
613 mClient->setState(count, mStates.array());
614 mStates.clear();
615 }
616 return NO_ERROR;
617}
618
Mathias Agopian62185b72009-04-16 16:19:50 -0700619layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800620{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800621 // API usage error, do nothing.
622 if (mTransactionOpen<=0) {
623 LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d",
624 this, int(index), mTransactionOpen);
625 return 0;
626 }
627
628 // use mPrebuiltLayerState just to find out if we already have it
629 layer_state_t& dummy = *mPrebuiltLayerState;
630 dummy.surface = index;
631 ssize_t i = mStates.indexOf(dummy);
632 if (i < 0) {
633 // we don't have it, add an initialized layer_state to our list
634 i = mStates.add(dummy);
635 }
636 return mStates.editArray() + i;
637}
638
Mathias Agopian62185b72009-04-16 16:19:50 -0700639layer_state_t* SurfaceComposerClient::_lockLayerState(SurfaceID id)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800640{
641 layer_state_t* s;
642 mLock.lock();
Mathias Agopian62185b72009-04-16 16:19:50 -0700643 s = _get_state_l(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800644 if (!s) mLock.unlock();
645 return s;
646}
647
648void SurfaceComposerClient::_unlockLayerState()
649{
650 mLock.unlock();
651}
652
Mathias Agopian62185b72009-04-16 16:19:50 -0700653status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800654{
Mathias Agopian62185b72009-04-16 16:19:50 -0700655 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800656 if (!s) return BAD_INDEX;
657 s->what |= ISurfaceComposer::ePositionChanged;
658 s->x = x;
659 s->y = y;
660 _unlockLayerState();
661 return NO_ERROR;
662}
663
Mathias Agopian62185b72009-04-16 16:19:50 -0700664status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665{
Mathias Agopian62185b72009-04-16 16:19:50 -0700666 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667 if (!s) return BAD_INDEX;
668 s->what |= ISurfaceComposer::eSizeChanged;
669 s->w = w;
670 s->h = h;
671 _unlockLayerState();
672 return NO_ERROR;
673}
674
Mathias Agopian62185b72009-04-16 16:19:50 -0700675status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800676{
Mathias Agopian62185b72009-04-16 16:19:50 -0700677 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800678 if (!s) return BAD_INDEX;
679 s->what |= ISurfaceComposer::eLayerChanged;
680 s->z = z;
681 _unlockLayerState();
682 return NO_ERROR;
683}
684
Mathias Agopian62185b72009-04-16 16:19:50 -0700685status_t SurfaceComposerClient::hide(SurfaceID id)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800686{
Mathias Agopian62185b72009-04-16 16:19:50 -0700687 return setFlags(id, ISurfaceComposer::eLayerHidden,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800688 ISurfaceComposer::eLayerHidden);
689}
690
Mathias Agopian62185b72009-04-16 16:19:50 -0700691status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800692{
Mathias Agopian62185b72009-04-16 16:19:50 -0700693 return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800694}
695
Mathias Agopian62185b72009-04-16 16:19:50 -0700696status_t SurfaceComposerClient::freeze(SurfaceID id)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800697{
Mathias Agopian62185b72009-04-16 16:19:50 -0700698 return setFlags(id, ISurfaceComposer::eLayerFrozen,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800699 ISurfaceComposer::eLayerFrozen);
700}
701
Mathias Agopian62185b72009-04-16 16:19:50 -0700702status_t SurfaceComposerClient::unfreeze(SurfaceID id)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800703{
Mathias Agopian62185b72009-04-16 16:19:50 -0700704 return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800705}
706
Mathias Agopian62185b72009-04-16 16:19:50 -0700707status_t SurfaceComposerClient::setFlags(SurfaceID id,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800708 uint32_t flags, uint32_t mask)
709{
Mathias Agopian62185b72009-04-16 16:19:50 -0700710 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800711 if (!s) return BAD_INDEX;
712 s->what |= ISurfaceComposer::eVisibilityChanged;
713 s->flags &= ~mask;
714 s->flags |= (flags & mask);
715 s->mask |= mask;
716 _unlockLayerState();
717 return NO_ERROR;
718}
719
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720status_t SurfaceComposerClient::setTransparentRegionHint(
Mathias Agopian62185b72009-04-16 16:19:50 -0700721 SurfaceID id, const Region& transparentRegion)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800722{
Mathias Agopian62185b72009-04-16 16:19:50 -0700723 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800724 if (!s) return BAD_INDEX;
725 s->what |= ISurfaceComposer::eTransparentRegionChanged;
726 s->transparentRegion = transparentRegion;
727 _unlockLayerState();
728 return NO_ERROR;
729}
730
Mathias Agopian62185b72009-04-16 16:19:50 -0700731status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800732{
Mathias Agopian62185b72009-04-16 16:19:50 -0700733 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800734 if (!s) return BAD_INDEX;
735 s->what |= ISurfaceComposer::eAlphaChanged;
736 s->alpha = alpha;
737 _unlockLayerState();
738 return NO_ERROR;
739}
740
741status_t SurfaceComposerClient::setMatrix(
Mathias Agopian62185b72009-04-16 16:19:50 -0700742 SurfaceID id,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800743 float dsdx, float dtdx,
744 float dsdy, float dtdy )
745{
Mathias Agopian62185b72009-04-16 16:19:50 -0700746 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800747 if (!s) return BAD_INDEX;
748 s->what |= ISurfaceComposer::eMatrixChanged;
749 layer_state_t::matrix22_t matrix;
750 matrix.dsdx = dsdx;
751 matrix.dtdx = dtdx;
752 matrix.dsdy = dsdy;
753 matrix.dtdy = dtdy;
754 s->matrix = matrix;
755 _unlockLayerState();
756 return NO_ERROR;
757}
758
Mathias Agopian62185b72009-04-16 16:19:50 -0700759status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800760{
Mathias Agopian62185b72009-04-16 16:19:50 -0700761 layer_state_t* s = _lockLayerState(id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800762 if (!s) return BAD_INDEX;
763 s->what |= ISurfaceComposer::eFreezeTintChanged;
764 s->tint = tint;
765 _unlockLayerState();
766 return NO_ERROR;
767}
768
769}; // namespace android
770