blob: 63699c7fd7b16bcc9e44a7627650daa12989ce26 [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 "Surface"
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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080026#include <utils/Errors.h>
27#include <utils/threads.h>
28#include <utils/IPCThreadState.h>
29#include <utils/IMemory.h>
30#include <utils/Log.h>
31
Mathias Agopian076b1cc2009-04-10 14:24:30 -070032#include <ui/DisplayInfo.h>
33#include <ui/BufferMapper.h>
34#include <ui/EGLNativeWindowSurface.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080035#include <ui/ISurface.h>
36#include <ui/Surface.h>
37#include <ui/SurfaceComposerClient.h>
38#include <ui/Rect.h>
39
Mathias Agopian076b1cc2009-04-10 14:24:30 -070040#include <EGL/android_natives.h>
41
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042#include <private/ui/SharedState.h>
43#include <private/ui/LayerState.h>
44
Mathias Agopian076b1cc2009-04-10 14:24:30 -070045#include <pixelflinger/pixelflinger.h>
46
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047namespace android {
48
Mathias Agopian076b1cc2009-04-10 14:24:30 -070049// ============================================================================
50// SurfaceBuffer
51// ============================================================================
52
Mathias Agopian4243e662009-04-15 18:34:24 -070053template<class SurfaceBuffer> Mutex Singleton<SurfaceBuffer>::sLock;
54template<> SurfaceBuffer* Singleton<SurfaceBuffer>::sInstance(0);
55
Mathias Agopian076b1cc2009-04-10 14:24:30 -070056SurfaceBuffer::SurfaceBuffer()
57 : BASE(), handle(0), mOwner(false)
58{
59 width =
60 height =
61 stride =
62 format =
63 usage = 0;
64 android_native_buffer_t::getHandle = getHandle;
65}
66
67SurfaceBuffer::SurfaceBuffer(const Parcel& data)
68 : BASE(), handle(0), mOwner(true)
69{
70 // we own the handle in this case
71 width = data.readInt32();
72 height = data.readInt32();
73 stride = data.readInt32();
74 format = data.readInt32();
75 usage = data.readInt32();
76 handle = data.readNativeHandle();
77 android_native_buffer_t::getHandle = getHandle;
78}
79
80SurfaceBuffer::~SurfaceBuffer()
81{
82 if (handle && mOwner) {
83 native_handle_close(handle);
84 native_handle_delete(const_cast<native_handle*>(handle));
85 }
86}
87
88int SurfaceBuffer::getHandle(android_native_buffer_t const * base,
89 buffer_handle_t* handle)
90{
91 *handle = getSelf(base)->handle;
92 return 0;
93}
94
95status_t SurfaceBuffer::writeToParcel(Parcel* reply,
96 android_native_buffer_t const* buffer)
97{
98 buffer_handle_t handle;
99 status_t err = buffer->getHandle(buffer, &handle);
100 if (err < 0) {
101 return err;
102 }
103 reply->writeInt32(buffer->width);
104 reply->writeInt32(buffer->height);
105 reply->writeInt32(buffer->stride);
106 reply->writeInt32(buffer->format);
107 reply->writeInt32(buffer->usage);
108 reply->writeNativeHandle(handle);
109 return NO_ERROR;
110}
111
112// ----------------------------------------------------------------------
113
114static void copyBlt(const android_native_buffer_t* dst,
115 const android_native_buffer_t* src, const Region& reg)
116{
117 Region::iterator iterator(reg);
118 if (iterator) {
119 // NOTE: dst and src must be the same format
120 Rect r;
121 const size_t bpp = bytesPerPixel(src->format);
122 const size_t dbpr = dst->stride * bpp;
123 const size_t sbpr = src->stride * bpp;
124 while (iterator.iterate(&r)) {
125 ssize_t h = r.bottom - r.top;
126 if (h) {
127 size_t size = (r.right - r.left) * bpp;
128 uint8_t* s = (GGLubyte*)src->bits +
129 (r.left + src->stride * r.top) * bpp;
130 uint8_t* d = (GGLubyte*)dst->bits +
131 (r.left + dst->stride * r.top) * bpp;
132 if (dbpr==sbpr && size==sbpr) {
133 size *= h;
134 h = 1;
135 }
136 do {
137 memcpy(d, s, size);
138 d += dbpr;
139 s += sbpr;
140 } while (--h > 0);
141 }
142 }
143 }
144}
145
Mathias Agopian62185b72009-04-16 16:19:50 -0700146
147// ============================================================================
148// SurfaceControl
149// ============================================================================
150
151
152SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client,
153 const sp<ISurface>& surface,
154 const ISurfaceFlingerClient::surface_data_t& data,
155 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
156 bool owner)
157 : mClient(client), mSurface(surface),
158 mToken(data.token), mIdentity(data.identity),
159 mFormat(format), mFlags(flags), mOwner(owner)
160{
161}
162
163SurfaceControl::~SurfaceControl()
164{
165 destroy();
166}
167
168void SurfaceControl::destroy()
169{
170 // Destroy the surface in SurfaceFlinger if we were the owner
171 // (in any case, a client won't be able to, because it won't have the
172 // right permission).
173 if (mOwner && mToken>=0 && mClient!=0) {
174 mClient->destroySurface(mToken);
175 }
176
177 // clear all references and trigger an IPC now, to make sure things
178 // happen without delay, since these resources are quite heavy.
179 mClient.clear();
180 mSurface.clear();
181 IPCThreadState::self()->flushCommands();
182}
183
184void SurfaceControl::clear()
185{
186 // here, the window manager tells us explicitly that we should destroy
187 // the surface's resource. Soon after this call, it will also release
188 // its last reference (which will call the dtor); however, it is possible
189 // that a client living in the same process still holds references which
190 // would delay the call to the dtor -- that is why we need this explicit
191 // "clear()" call.
192 destroy();
193}
194
195status_t SurfaceControl::setLayer(int32_t layer) {
196 const sp<SurfaceComposerClient>& client(mClient);
197 if (client == 0) return INVALID_OPERATION;
198 status_t err = validate(client->mControl);
199 if (err < 0) return err;
200 return client->setLayer(mToken, layer);
201}
202status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
203 const sp<SurfaceComposerClient>& client(mClient);
204 if (client == 0) return INVALID_OPERATION;
205 status_t err = validate(client->mControl);
206 if (err < 0) return err;
207 return client->setPosition(mToken, x, y);
208}
209status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
210 const sp<SurfaceComposerClient>& client(mClient);
211 if (client == 0) return INVALID_OPERATION;
212 status_t err = validate(client->mControl);
213 if (err < 0) return err;
214 return client->setSize(mToken, w, h);
215}
216status_t SurfaceControl::hide() {
217 const sp<SurfaceComposerClient>& client(mClient);
218 if (client == 0) return INVALID_OPERATION;
219 status_t err = validate(client->mControl);
220 if (err < 0) return err;
221 return client->hide(mToken);
222}
223status_t SurfaceControl::show(int32_t layer) {
224 const sp<SurfaceComposerClient>& client(mClient);
225 if (client == 0) return INVALID_OPERATION;
226 status_t err = validate(client->mControl);
227 if (err < 0) return err;
228 return client->show(mToken, layer);
229}
230status_t SurfaceControl::freeze() {
231 const sp<SurfaceComposerClient>& client(mClient);
232 if (client == 0) return INVALID_OPERATION;
233 status_t err = validate(client->mControl);
234 if (err < 0) return err;
235 return client->freeze(mToken);
236}
237status_t SurfaceControl::unfreeze() {
238 const sp<SurfaceComposerClient>& client(mClient);
239 if (client == 0) return INVALID_OPERATION;
240 status_t err = validate(client->mControl);
241 if (err < 0) return err;
242 return client->unfreeze(mToken);
243}
244status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
245 const sp<SurfaceComposerClient>& client(mClient);
246 if (client == 0) return INVALID_OPERATION;
247 status_t err = validate(client->mControl);
248 if (err < 0) return err;
249 return client->setFlags(mToken, flags, mask);
250}
251status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
252 const sp<SurfaceComposerClient>& client(mClient);
253 if (client == 0) return INVALID_OPERATION;
254 status_t err = validate(client->mControl);
255 if (err < 0) return err;
256 return client->setTransparentRegionHint(mToken, transparent);
257}
258status_t SurfaceControl::setAlpha(float alpha) {
259 const sp<SurfaceComposerClient>& client(mClient);
260 if (client == 0) return INVALID_OPERATION;
261 status_t err = validate(client->mControl);
262 if (err < 0) return err;
263 return client->setAlpha(mToken, alpha);
264}
265status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
266 const sp<SurfaceComposerClient>& client(mClient);
267 if (client == 0) return INVALID_OPERATION;
268 status_t err = validate(client->mControl);
269 if (err < 0) return err;
270 return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
271}
272status_t SurfaceControl::setFreezeTint(uint32_t tint) {
273 const sp<SurfaceComposerClient>& client(mClient);
274 if (client == 0) return INVALID_OPERATION;
275 status_t err = validate(client->mControl);
276 if (err < 0) return err;
277 return client->setFreezeTint(mToken, tint);
278}
279
280sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel)
281{
282 sp<SurfaceComposerClient> client;
283 ISurfaceFlingerClient::surface_data_t data;
284 sp<IBinder> clientBinder= parcel->readStrongBinder();
285 sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder());
286 data.token = parcel->readInt32();
287 data.identity = parcel->readInt32();
288 PixelFormat format = parcel->readInt32();
289 uint32_t flags = parcel->readInt32();
290
291 if (clientBinder != NULL)
292 client = SurfaceComposerClient::clientForConnection(clientBinder);
293
294 return new SurfaceControl(client, surface, data, 0, 0, format, flags, false);
295}
296
297status_t SurfaceControl::writeToParcel(const sp<SurfaceControl>& surface, Parcel* parcel)
298{
299 uint32_t flags=0;
300 uint32_t format=0;
301 SurfaceID token = -1;
302 uint32_t identity = 0;
303 sp<SurfaceComposerClient> client;
304 sp<ISurface> sur;
305 if (SurfaceControl::isValid(surface)) {
306 token = surface->mToken;
307 identity = surface->mIdentity;
308 client = surface->mClient;
309 sur = surface->mSurface;
310 format = surface->mFormat;
311 flags = surface->mFlags;
312 }
313 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
314 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
315 parcel->writeInt32(token);
316 parcel->writeInt32(identity);
317 parcel->writeInt32(format);
318 parcel->writeInt32(flags);
319 return NO_ERROR;
320}
321
322bool SurfaceControl::isSameSurface(
323 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
324{
325 if (lhs == 0 || rhs == 0)
326 return false;
327 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
328}
329
330
331status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
332{
333 if (mToken<0 || mClient==0) {
334 LOGE("invalid token (%d, identity=%u) or client (%p)",
335 mToken, mIdentity, mClient.get());
336 return NO_INIT;
337 }
338 if (cblk == 0) {
339 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
340 return NO_INIT;
341 }
342 status_t err = cblk->validate(mToken);
343 if (err != NO_ERROR) {
344 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
345 mToken, mIdentity, err, strerror(-err));
346 return err;
347 }
348 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
349 LOGE("using an invalid surface id=%d, identity=%u should be %d",
350 mToken, mIdentity, cblk->layers[mToken].identity);
351 return NO_INIT;
352 }
353 return NO_ERROR;
354}
355
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700356// ============================================================================
357// Surface
358// ============================================================================
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800359
360Surface::Surface(const sp<SurfaceComposerClient>& client,
361 const sp<ISurface>& surface,
362 const ISurfaceFlingerClient::surface_data_t& data,
363 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
364 bool owner)
365 : mClient(client), mSurface(surface),
366 mToken(data.token), mIdentity(data.identity),
367 mFormat(format), mFlags(flags), mOwner(owner)
368{
Mathias Agopian62185b72009-04-16 16:19:50 -0700369 mSurfaceControl = new SurfaceControl(
370 client, surface, data, w, h, format, flags, owner);
371
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700372 android_native_window_t::connect = connect;
373 android_native_window_t::disconnect = disconnect;
374 android_native_window_t::setSwapInterval = setSwapInterval;
375 android_native_window_t::setSwapRectangle = setSwapRectangle;
376 android_native_window_t::dequeueBuffer = dequeueBuffer;
377 android_native_window_t::lockBuffer = lockBuffer;
378 android_native_window_t::queueBuffer = queueBuffer;
379
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800380 mSwapRectangle.makeInvalid();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700381
382 DisplayInfo dinfo;
383 SurfaceComposerClient::getDisplayInfo(0, &dinfo);
384 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
385 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
386 // FIXME: set real values here
387 const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
388 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
389 const_cast<uint32_t&>(android_native_window_t::flags) = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800390}
391
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800392Surface::~Surface()
393{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700394 // this is a client-side operation, the surface is destroyed, unmap
395 // its buffers in this process.
396 for (int i=0 ; i<2 ; i++) {
397 if (mBuffers[i] != 0) {
398 BufferMapper::get().unmap(mBuffers[i]->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700399 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800400 }
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700401
402 destroy();
403}
404
405void Surface::destroy()
406{
Mathias Agopian62185b72009-04-16 16:19:50 -0700407 mSurfaceControl->destroy();
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700408
409 // clear all references and trigger an IPC now, to make sure things
410 // happen without delay, since these resources are quite heavy.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411 mClient.clear();
412 mSurface.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800413 IPCThreadState::self()->flushCommands();
414}
415
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700416void Surface::clear()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800417{
Mathias Agopian62185b72009-04-16 16:19:50 -0700418 mSurfaceControl->clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800419}
420
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700421status_t Surface::validate(per_client_cblk_t const* cblk) const
422{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700423 if (mToken<0 || mClient==0) {
424 LOGE("invalid token (%d, identity=%u) or client (%p)",
425 mToken, mIdentity, mClient.get());
426 return NO_INIT;
427 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700428 if (cblk == 0) {
429 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
430 return NO_INIT;
431 }
432 status_t err = cblk->validate(mToken);
433 if (err != NO_ERROR) {
434 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
435 mToken, mIdentity, err, strerror(-err));
436 return err;
437 }
438 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
439 LOGE("using an invalid surface id=%d, identity=%u should be %d",
440 mToken, mIdentity, cblk->layers[mToken].identity);
441 return NO_INIT;
442 }
443 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800444}
445
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700446// ----------------------------------------------------------------------------
447
448int Surface::setSwapRectangle(android_native_window_t* window,
449 int l, int t, int w, int h)
450{
451 Surface* self = getSelf(window);
452 self->setSwapRectangle(Rect(l, t, l+w, t+h));
453 return 0;
454}
455
456void Surface::connect(android_native_window_t* window)
457{
458}
459
460void Surface::disconnect(android_native_window_t* window)
461{
462}
463
464int Surface::setSwapInterval(android_native_window_t* window, int interval)
465{
466 return 0;
467}
468
469int Surface::dequeueBuffer(android_native_window_t* window,
470 android_native_buffer_t** buffer)
471{
472 Surface* self = getSelf(window);
473 return self->dequeueBuffer(buffer);
474}
475
476int Surface::lockBuffer(android_native_window_t* window,
477 android_native_buffer_t* buffer)
478{
479 Surface* self = getSelf(window);
480 return self->lockBuffer(buffer);
481}
482
483int Surface::queueBuffer(android_native_window_t* window,
484 android_native_buffer_t* buffer)
485{
486 Surface* self = getSelf(window);
487 return self->queueBuffer(buffer);
488}
489
490// ----------------------------------------------------------------------------
491
492int Surface::dequeueBuffer(android_native_buffer_t** buffer)
493{
494 // FIXME: dequeueBuffer() needs proper implementation
495
496 Mutex::Autolock _l(mSurfaceLock);
497
498 per_client_cblk_t* const cblk = mClient->mControl;
499 status_t err = validate(cblk);
500 if (err != NO_ERROR)
501 return err;
502
503 SurfaceID index(mToken);
504
505 int32_t backIdx = cblk->lock_layer(size_t(index),
506 per_client_cblk_t::BLOCKING);
507
508 if (backIdx < 0)
509 return status_t(backIdx);
510
511 mBackbufferIndex = backIdx;
512 layer_cblk_t* const lcblk = &(cblk->layers[index]);
513
514 volatile const surface_info_t* const back = lcblk->surface + backIdx;
515 if (back->flags & surface_info_t::eNeedNewBuffer) {
516 getBufferLocked(backIdx);
517 }
518
519 const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
520 *buffer = backBuffer.get();
521
522 return NO_ERROR;
523}
524
525int Surface::lockBuffer(android_native_buffer_t* buffer)
526{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700527 Mutex::Autolock _l(mSurfaceLock);
528
529 per_client_cblk_t* const cblk = mClient->mControl;
530 status_t err = validate(cblk);
531 if (err != NO_ERROR)
532 return err;
533
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700534 // FIXME: lockBuffer() needs proper implementation
535 return 0;
536}
537
538int Surface::queueBuffer(android_native_buffer_t* buffer)
539{
540 Mutex::Autolock _l(mSurfaceLock);
541
542 per_client_cblk_t* const cblk = mClient->mControl;
543 status_t err = validate(cblk);
544 if (err != NO_ERROR)
545 return err;
546
547 // transmit the dirty region
548 const Region dirty(swapRectangle());
549 SurfaceID index(mToken);
550 layer_cblk_t* const lcblk = &(cblk->layers[index]);
551 _send_dirty_region(lcblk, dirty);
552
553 uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
554 if (!(newstate & eNextFlipPending))
555 mClient->signalServer();
556
557 return NO_ERROR;
558}
559
560// ----------------------------------------------------------------------------
561
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800562status_t Surface::lock(SurfaceInfo* info, bool blocking) {
563 return Surface::lock(info, NULL, blocking);
564}
565
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700566status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
567{
568 // FIXME: needs some locking here
569 android_native_buffer_t* backBuffer;
570 status_t err = dequeueBuffer(&backBuffer);
571 if (err == NO_ERROR) {
572 err = lockBuffer(backBuffer);
573 if (err == NO_ERROR) {
574 backBuffer->common.incRef(&backBuffer->common);
575 mLockedBuffer = backBuffer;
576 other->w = backBuffer->width;
577 other->h = backBuffer->height;
578 other->s = backBuffer->stride;
579 other->usage = backBuffer->usage;
580 other->format = backBuffer->format;
581 other->bits = backBuffer->bits;
582
583 // we handle copy-back here...
584
585 const Rect bounds(backBuffer->width, backBuffer->height);
586 Region newDirtyRegion;
587
588 per_client_cblk_t* const cblk = mClient->mControl;
589 layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
590 volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
591 if (back->flags & surface_info_t::eBufferDirty) {
592 // content is meaningless in this case and the whole surface
593 // needs to be redrawn.
594 newDirtyRegion.set(bounds);
595 if (dirty) {
596 *dirty = newDirtyRegion;
597 }
598 } else
599 {
600 if (dirty) {
601 dirty->andSelf(Region(bounds));
602 newDirtyRegion = *dirty;
603 } else {
604 newDirtyRegion.set(bounds);
605 }
606 Region copyback;
607 if (!(lcblk->flags & eNoCopyBack)) {
608 const Region previousDirtyRegion(dirtyRegion());
609 copyback = previousDirtyRegion.subtract(newDirtyRegion);
610 }
611 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
612 if (!copyback.isEmpty() && frontBuffer!=0) {
613 // copy front to back
614 copyBlt(backBuffer, frontBuffer.get(), copyback);
615 }
616 }
617 setDirtyRegion(newDirtyRegion);
618
619
620 Rect lockBounds(backBuffer->width, backBuffer->height);
621 if (dirty) {
622 lockBounds = dirty->bounds();
623 }
624 buffer_handle_t handle;
625 backBuffer->getHandle(backBuffer, &handle);
626 status_t res = BufferMapper::get().lock(handle,
627 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
628 lockBounds);
629 LOGW_IF(res, "failed locking buffer %d (%p)",
630 mBackbufferIndex, handle);
631 setSwapRectangle(lockBounds);
632 }
633 }
634 return err;
635}
636
637status_t Surface::unlockAndPost()
638{
639 // FIXME: needs some locking here
640
641 if (mLockedBuffer == 0)
642 return BAD_VALUE;
643
644 buffer_handle_t handle;
645 mLockedBuffer->getHandle(mLockedBuffer, &handle);
646 status_t res = BufferMapper::get().unlock(handle);
647 LOGW_IF(res, "failed unlocking buffer %d (%p)",
648 mBackbufferIndex, handle);
649
650 const Rect dirty(dirtyRegion().bounds());
651 setSwapRectangle(dirty);
652 status_t err = queueBuffer(mLockedBuffer);
653 mLockedBuffer->common.decRef(&mLockedBuffer->common);
654 mLockedBuffer = 0;
655 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800656}
657
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700658void Surface::_send_dirty_region(
659 layer_cblk_t* lcblk, const Region& dirty)
660{
661 const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
662 flat_region_t* flat_region = lcblk->region + index;
663 status_t err = dirty.write(flat_region, sizeof(flat_region_t));
664 if (err < NO_ERROR) {
665 // region doesn't fit, use the bounds
666 const Region reg(dirty.bounds());
667 reg.write(flat_region, sizeof(flat_region_t));
668 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800669}
670
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800671Region Surface::dirtyRegion() const {
672 return mDirtyRegion;
673}
674void Surface::setDirtyRegion(const Region& region) const {
675 mDirtyRegion = region;
676}
677const Rect& Surface::swapRectangle() const {
678 return mSwapRectangle;
679}
680void Surface::setSwapRectangle(const Rect& r) {
681 mSwapRectangle = r;
682}
683
684sp<Surface> Surface::readFromParcel(Parcel* parcel)
685{
686 sp<SurfaceComposerClient> client;
687 ISurfaceFlingerClient::surface_data_t data;
688 sp<IBinder> clientBinder= parcel->readStrongBinder();
689 sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800690 data.token = parcel->readInt32();
691 data.identity = parcel->readInt32();
692 PixelFormat format = parcel->readInt32();
693 uint32_t flags = parcel->readInt32();
694
695 if (clientBinder != NULL)
696 client = SurfaceComposerClient::clientForConnection(clientBinder);
697
698 return new Surface(client, surface, data, 0, 0, format, flags, false);
699}
700
701status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel)
702{
703 uint32_t flags=0;
704 uint32_t format=0;
705 SurfaceID token = -1;
706 uint32_t identity = 0;
707 sp<SurfaceComposerClient> client;
708 sp<ISurface> sur;
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700709 if (Surface::isValid(surface)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800710 token = surface->mToken;
711 identity = surface->mIdentity;
712 client = surface->mClient;
713 sur = surface->mSurface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800714 format = surface->mFormat;
715 flags = surface->mFlags;
716 }
717 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
718 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800719 parcel->writeInt32(token);
720 parcel->writeInt32(identity);
721 parcel->writeInt32(format);
722 parcel->writeInt32(flags);
723 return NO_ERROR;
724}
725
726bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs)
727{
728 if (lhs == 0 || rhs == 0)
729 return false;
730 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
731}
732
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700733status_t Surface::getBufferLocked(int index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800734{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700735 status_t err = NO_MEMORY;
736 sp<SurfaceBuffer> buffer = mSurface->getBuffer();
737 LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
738 if (buffer != 0) {
739 sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
740 if (currentBuffer != 0) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700741 BufferMapper::get().unmap(currentBuffer->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700742 currentBuffer.clear();
743 }
Mathias Agopian4243e662009-04-15 18:34:24 -0700744 err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700745 LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
746 if (err == NO_ERROR) {
747 currentBuffer = buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800748 }
749 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700750 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800751}
752
Mathias Agopian62185b72009-04-16 16:19:50 -0700753
754
755status_t Surface::setLayer(int32_t layer) {
756 return mSurfaceControl->setLayer(layer);
757}
758status_t Surface::setPosition(int32_t x, int32_t y) {
759 return mSurfaceControl->setPosition(x, y);
760}
761status_t Surface::setSize(uint32_t w, uint32_t h) {
762 return mSurfaceControl->setSize(w, h);
763}
764status_t Surface::hide() {
765 return mSurfaceControl->hide();
766}
767status_t Surface::show(int32_t layer) {
768 return mSurfaceControl->show(layer);
769}
770status_t Surface::freeze() {
771 return mSurfaceControl->freeze();
772}
773status_t Surface::unfreeze() {
774 return mSurfaceControl->unfreeze();
775}
776status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
777 return mSurfaceControl->setFlags(flags, mask);
778}
779status_t Surface::setTransparentRegionHint(const Region& transparent) {
780 return mSurfaceControl->setTransparentRegionHint(transparent);
781}
782status_t Surface::setAlpha(float alpha) {
783 return mSurfaceControl->setAlpha(alpha);
784}
785status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
786 return mSurfaceControl->setMatrix(dsdx, dtdx, dsdy, dtdy);
787}
788status_t Surface::setFreezeTint(uint32_t tint) {
789 return mSurfaceControl->setFreezeTint(tint);
790}
791
792
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800793}; // namespace android
794