blob: cf1b76cd814d5d63bdb6e393a796f1f285fe1d6a [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
Mathias Agopian01b76682009-04-16 20:04:08 -0700151SurfaceControl::SurfaceControl(
152 const sp<SurfaceComposerClient>& client,
Mathias Agopian62185b72009-04-16 16:19:50 -0700153 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}
Mathias Agopian62185b72009-04-16 16:19:50 -0700162SurfaceControl::~SurfaceControl()
163{
164 destroy();
165}
166
167void SurfaceControl::destroy()
168{
169 // Destroy the surface in SurfaceFlinger if we were the owner
170 // (in any case, a client won't be able to, because it won't have the
171 // right permission).
172 if (mOwner && mToken>=0 && mClient!=0) {
173 mClient->destroySurface(mToken);
174 }
175
176 // clear all references and trigger an IPC now, to make sure things
177 // happen without delay, since these resources are quite heavy.
178 mClient.clear();
179 mSurface.clear();
180 IPCThreadState::self()->flushCommands();
181}
182
183void SurfaceControl::clear()
184{
185 // here, the window manager tells us explicitly that we should destroy
186 // the surface's resource. Soon after this call, it will also release
187 // its last reference (which will call the dtor); however, it is possible
188 // that a client living in the same process still holds references which
189 // would delay the call to the dtor -- that is why we need this explicit
190 // "clear()" call.
191 destroy();
192}
193
Mathias Agopian62185b72009-04-16 16:19:50 -0700194bool SurfaceControl::isSameSurface(
195 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
196{
197 if (lhs == 0 || rhs == 0)
198 return false;
199 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
200}
201
Mathias Agopian01b76682009-04-16 20:04:08 -0700202status_t SurfaceControl::setLayer(int32_t layer) {
203 const sp<SurfaceComposerClient>& client(mClient);
204 if (client == 0) return NO_INIT;
205 status_t err = validate(client->mControl);
206 if (err < 0) return err;
207 return client->setLayer(mToken, layer);
208}
209status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
210 const sp<SurfaceComposerClient>& client(mClient);
211 if (client == 0) return NO_INIT;
212 status_t err = validate(client->mControl);
213 if (err < 0) return err;
214 return client->setPosition(mToken, x, y);
215}
216status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
217 const sp<SurfaceComposerClient>& client(mClient);
218 if (client == 0) return NO_INIT;
219 status_t err = validate(client->mControl);
220 if (err < 0) return err;
221 return client->setSize(mToken, w, h);
222}
223status_t SurfaceControl::hide() {
224 const sp<SurfaceComposerClient>& client(mClient);
225 if (client == 0) return NO_INIT;
226 status_t err = validate(client->mControl);
227 if (err < 0) return err;
228 return client->hide(mToken);
229}
230status_t SurfaceControl::show(int32_t layer) {
231 const sp<SurfaceComposerClient>& client(mClient);
232 if (client == 0) return NO_INIT;
233 status_t err = validate(client->mControl);
234 if (err < 0) return err;
235 return client->show(mToken, layer);
236}
237status_t SurfaceControl::freeze() {
238 const sp<SurfaceComposerClient>& client(mClient);
239 if (client == 0) return NO_INIT;
240 status_t err = validate(client->mControl);
241 if (err < 0) return err;
242 return client->freeze(mToken);
243}
244status_t SurfaceControl::unfreeze() {
245 const sp<SurfaceComposerClient>& client(mClient);
246 if (client == 0) return NO_INIT;
247 status_t err = validate(client->mControl);
248 if (err < 0) return err;
249 return client->unfreeze(mToken);
250}
251status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
252 const sp<SurfaceComposerClient>& client(mClient);
253 if (client == 0) return NO_INIT;
254 status_t err = validate(client->mControl);
255 if (err < 0) return err;
256 return client->setFlags(mToken, flags, mask);
257}
258status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
259 const sp<SurfaceComposerClient>& client(mClient);
260 if (client == 0) return NO_INIT;
261 status_t err = validate(client->mControl);
262 if (err < 0) return err;
263 return client->setTransparentRegionHint(mToken, transparent);
264}
265status_t SurfaceControl::setAlpha(float alpha) {
266 const sp<SurfaceComposerClient>& client(mClient);
267 if (client == 0) return NO_INIT;
268 status_t err = validate(client->mControl);
269 if (err < 0) return err;
270 return client->setAlpha(mToken, alpha);
271}
272status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
273 const sp<SurfaceComposerClient>& client(mClient);
274 if (client == 0) return NO_INIT;
275 status_t err = validate(client->mControl);
276 if (err < 0) return err;
277 return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
278}
279status_t SurfaceControl::setFreezeTint(uint32_t tint) {
280 const sp<SurfaceComposerClient>& client(mClient);
281 if (client == 0) return NO_INIT;
282 status_t err = validate(client->mControl);
283 if (err < 0) return err;
284 return client->setFreezeTint(mToken, tint);
285}
Mathias Agopian62185b72009-04-16 16:19:50 -0700286
287status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
288{
289 if (mToken<0 || mClient==0) {
290 LOGE("invalid token (%d, identity=%u) or client (%p)",
291 mToken, mIdentity, mClient.get());
292 return NO_INIT;
293 }
294 if (cblk == 0) {
295 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
296 return NO_INIT;
297 }
298 status_t err = cblk->validate(mToken);
299 if (err != NO_ERROR) {
300 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
301 mToken, mIdentity, err, strerror(-err));
302 return err;
303 }
304 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
305 LOGE("using an invalid surface id=%d, identity=%u should be %d",
306 mToken, mIdentity, cblk->layers[mToken].identity);
307 return NO_INIT;
308 }
309 return NO_ERROR;
310}
311
Mathias Agopian01b76682009-04-16 20:04:08 -0700312status_t SurfaceControl::writeSurfaceToParcel(
313 const sp<SurfaceControl>& control, Parcel* parcel)
314{
315 uint32_t flags = 0;
316 uint32_t format = 0;
317 SurfaceID token = -1;
318 uint32_t identity = 0;
319 sp<SurfaceComposerClient> client;
320 sp<ISurface> sur;
321 if (SurfaceControl::isValid(control)) {
322 token = control->mToken;
323 identity = control->mIdentity;
324 client = control->mClient;
325 sur = control->mSurface;
326 format = control->mFormat;
327 flags = control->mFlags;
328 }
329 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
330 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
331 parcel->writeInt32(token);
332 parcel->writeInt32(identity);
333 parcel->writeInt32(format);
334 parcel->writeInt32(flags);
335 return NO_ERROR;
336}
337
338sp<Surface> SurfaceControl::getSurface() const
339{
340 Mutex::Autolock _l(mLock);
341 if (mSurfaceData == 0) {
342 mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
343 }
344 return mSurfaceData;
345}
346
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700347// ============================================================================
348// Surface
349// ============================================================================
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800350
Mathias Agopian01b76682009-04-16 20:04:08 -0700351Surface::Surface(const sp<SurfaceControl>& surface)
352 : mClient(surface->mClient), mSurface(surface->mSurface),
353 mToken(surface->mToken), mIdentity(surface->mIdentity),
354 mFormat(surface->mFormat), mFlags(surface->mFlags),
355 mOwner(surface->mOwner)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800356{
Mathias Agopian01b76682009-04-16 20:04:08 -0700357 init();
358}
Mathias Agopian62185b72009-04-16 16:19:50 -0700359
Mathias Agopian01b76682009-04-16 20:04:08 -0700360Surface::Surface(const Parcel& parcel)
361 : mOwner(false)
362{
363 sp<IBinder> clientBinder = parcel.readStrongBinder();
364 mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
365 mToken = parcel.readInt32();
366 mIdentity = parcel.readInt32();
367 mFormat = parcel.readInt32();
368 mFlags = parcel.readInt32();
369
370 if (clientBinder != NULL)
371 mClient = SurfaceComposerClient::clientForConnection(clientBinder);
372
373 init();
374}
375
376void Surface::init()
377{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700378 android_native_window_t::connect = connect;
379 android_native_window_t::disconnect = disconnect;
380 android_native_window_t::setSwapInterval = setSwapInterval;
381 android_native_window_t::setSwapRectangle = setSwapRectangle;
382 android_native_window_t::dequeueBuffer = dequeueBuffer;
383 android_native_window_t::lockBuffer = lockBuffer;
384 android_native_window_t::queueBuffer = queueBuffer;
385
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800386 mSwapRectangle.makeInvalid();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700387
388 DisplayInfo dinfo;
389 SurfaceComposerClient::getDisplayInfo(0, &dinfo);
390 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
391 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
392 // FIXME: set real values here
393 const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
394 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
395 const_cast<uint32_t&>(android_native_window_t::flags) = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800396}
397
Mathias Agopian01b76682009-04-16 20:04:08 -0700398
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800399Surface::~Surface()
400{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700401 // this is a client-side operation, the surface is destroyed, unmap
402 // its buffers in this process.
403 for (int i=0 ; i<2 ; i++) {
404 if (mBuffers[i] != 0) {
405 BufferMapper::get().unmap(mBuffers[i]->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700406 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800407 }
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700408
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700409 // 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 Agopian076b1cc2009-04-10 14:24:30 -0700416status_t Surface::validate(per_client_cblk_t const* cblk) const
417{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700418 if (mToken<0 || mClient==0) {
419 LOGE("invalid token (%d, identity=%u) or client (%p)",
420 mToken, mIdentity, mClient.get());
421 return NO_INIT;
422 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700423 if (cblk == 0) {
424 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
425 return NO_INIT;
426 }
427 status_t err = cblk->validate(mToken);
428 if (err != NO_ERROR) {
429 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
430 mToken, mIdentity, err, strerror(-err));
431 return err;
432 }
433 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
434 LOGE("using an invalid surface id=%d, identity=%u should be %d",
435 mToken, mIdentity, cblk->layers[mToken].identity);
436 return NO_INIT;
437 }
438 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800439}
440
Mathias Agopian01b76682009-04-16 20:04:08 -0700441
442bool Surface::isSameSurface(
443 const sp<Surface>& lhs, const sp<Surface>& rhs)
444{
445 if (lhs == 0 || rhs == 0)
446 return false;
447 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
448}
449
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700450// ----------------------------------------------------------------------------
451
452int Surface::setSwapRectangle(android_native_window_t* window,
453 int l, int t, int w, int h)
454{
455 Surface* self = getSelf(window);
456 self->setSwapRectangle(Rect(l, t, l+w, t+h));
457 return 0;
458}
459
460void Surface::connect(android_native_window_t* window)
461{
462}
463
464void Surface::disconnect(android_native_window_t* window)
465{
466}
467
468int Surface::setSwapInterval(android_native_window_t* window, int interval)
469{
470 return 0;
471}
472
473int Surface::dequeueBuffer(android_native_window_t* window,
474 android_native_buffer_t** buffer)
475{
476 Surface* self = getSelf(window);
477 return self->dequeueBuffer(buffer);
478}
479
480int Surface::lockBuffer(android_native_window_t* window,
481 android_native_buffer_t* buffer)
482{
483 Surface* self = getSelf(window);
484 return self->lockBuffer(buffer);
485}
486
487int Surface::queueBuffer(android_native_window_t* window,
488 android_native_buffer_t* buffer)
489{
490 Surface* self = getSelf(window);
491 return self->queueBuffer(buffer);
492}
493
494// ----------------------------------------------------------------------------
495
496int Surface::dequeueBuffer(android_native_buffer_t** buffer)
497{
498 // FIXME: dequeueBuffer() needs proper implementation
499
500 Mutex::Autolock _l(mSurfaceLock);
501
502 per_client_cblk_t* const cblk = mClient->mControl;
503 status_t err = validate(cblk);
504 if (err != NO_ERROR)
505 return err;
506
507 SurfaceID index(mToken);
508
509 int32_t backIdx = cblk->lock_layer(size_t(index),
510 per_client_cblk_t::BLOCKING);
511
512 if (backIdx < 0)
513 return status_t(backIdx);
514
515 mBackbufferIndex = backIdx;
516 layer_cblk_t* const lcblk = &(cblk->layers[index]);
517
518 volatile const surface_info_t* const back = lcblk->surface + backIdx;
519 if (back->flags & surface_info_t::eNeedNewBuffer) {
520 getBufferLocked(backIdx);
521 }
522
523 const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
524 *buffer = backBuffer.get();
525
526 return NO_ERROR;
527}
528
529int Surface::lockBuffer(android_native_buffer_t* buffer)
530{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700531 Mutex::Autolock _l(mSurfaceLock);
532
533 per_client_cblk_t* const cblk = mClient->mControl;
534 status_t err = validate(cblk);
535 if (err != NO_ERROR)
536 return err;
537
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700538 // FIXME: lockBuffer() needs proper implementation
539 return 0;
540}
541
542int Surface::queueBuffer(android_native_buffer_t* buffer)
543{
544 Mutex::Autolock _l(mSurfaceLock);
545
546 per_client_cblk_t* const cblk = mClient->mControl;
547 status_t err = validate(cblk);
548 if (err != NO_ERROR)
549 return err;
550
551 // transmit the dirty region
552 const Region dirty(swapRectangle());
553 SurfaceID index(mToken);
554 layer_cblk_t* const lcblk = &(cblk->layers[index]);
555 _send_dirty_region(lcblk, dirty);
556
557 uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
558 if (!(newstate & eNextFlipPending))
559 mClient->signalServer();
560
561 return NO_ERROR;
562}
563
564// ----------------------------------------------------------------------------
565
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800566status_t Surface::lock(SurfaceInfo* info, bool blocking) {
567 return Surface::lock(info, NULL, blocking);
568}
569
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700570status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
571{
572 // FIXME: needs some locking here
573 android_native_buffer_t* backBuffer;
574 status_t err = dequeueBuffer(&backBuffer);
575 if (err == NO_ERROR) {
576 err = lockBuffer(backBuffer);
577 if (err == NO_ERROR) {
578 backBuffer->common.incRef(&backBuffer->common);
579 mLockedBuffer = backBuffer;
580 other->w = backBuffer->width;
581 other->h = backBuffer->height;
582 other->s = backBuffer->stride;
583 other->usage = backBuffer->usage;
584 other->format = backBuffer->format;
585 other->bits = backBuffer->bits;
586
587 // we handle copy-back here...
588
589 const Rect bounds(backBuffer->width, backBuffer->height);
590 Region newDirtyRegion;
591
592 per_client_cblk_t* const cblk = mClient->mControl;
593 layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
594 volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
595 if (back->flags & surface_info_t::eBufferDirty) {
596 // content is meaningless in this case and the whole surface
597 // needs to be redrawn.
598 newDirtyRegion.set(bounds);
599 if (dirty) {
600 *dirty = newDirtyRegion;
601 }
602 } else
603 {
604 if (dirty) {
605 dirty->andSelf(Region(bounds));
606 newDirtyRegion = *dirty;
607 } else {
608 newDirtyRegion.set(bounds);
609 }
610 Region copyback;
611 if (!(lcblk->flags & eNoCopyBack)) {
612 const Region previousDirtyRegion(dirtyRegion());
613 copyback = previousDirtyRegion.subtract(newDirtyRegion);
614 }
615 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
616 if (!copyback.isEmpty() && frontBuffer!=0) {
617 // copy front to back
618 copyBlt(backBuffer, frontBuffer.get(), copyback);
619 }
620 }
621 setDirtyRegion(newDirtyRegion);
622
623
624 Rect lockBounds(backBuffer->width, backBuffer->height);
625 if (dirty) {
626 lockBounds = dirty->bounds();
627 }
628 buffer_handle_t handle;
629 backBuffer->getHandle(backBuffer, &handle);
630 status_t res = BufferMapper::get().lock(handle,
631 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
632 lockBounds);
633 LOGW_IF(res, "failed locking buffer %d (%p)",
634 mBackbufferIndex, handle);
635 setSwapRectangle(lockBounds);
636 }
637 }
638 return err;
639}
640
641status_t Surface::unlockAndPost()
642{
643 // FIXME: needs some locking here
644
645 if (mLockedBuffer == 0)
646 return BAD_VALUE;
647
648 buffer_handle_t handle;
649 mLockedBuffer->getHandle(mLockedBuffer, &handle);
650 status_t res = BufferMapper::get().unlock(handle);
651 LOGW_IF(res, "failed unlocking buffer %d (%p)",
652 mBackbufferIndex, handle);
653
654 const Rect dirty(dirtyRegion().bounds());
655 setSwapRectangle(dirty);
656 status_t err = queueBuffer(mLockedBuffer);
657 mLockedBuffer->common.decRef(&mLockedBuffer->common);
658 mLockedBuffer = 0;
659 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800660}
661
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700662void Surface::_send_dirty_region(
663 layer_cblk_t* lcblk, const Region& dirty)
664{
665 const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
666 flat_region_t* flat_region = lcblk->region + index;
667 status_t err = dirty.write(flat_region, sizeof(flat_region_t));
668 if (err < NO_ERROR) {
669 // region doesn't fit, use the bounds
670 const Region reg(dirty.bounds());
671 reg.write(flat_region, sizeof(flat_region_t));
672 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800673}
674
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800675Region Surface::dirtyRegion() const {
676 return mDirtyRegion;
677}
678void Surface::setDirtyRegion(const Region& region) const {
679 mDirtyRegion = region;
680}
681const Rect& Surface::swapRectangle() const {
682 return mSwapRectangle;
683}
684void Surface::setSwapRectangle(const Rect& r) {
685 mSwapRectangle = r;
686}
687
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700688status_t Surface::getBufferLocked(int index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800689{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700690 status_t err = NO_MEMORY;
691 sp<SurfaceBuffer> buffer = mSurface->getBuffer();
692 LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
693 if (buffer != 0) {
694 sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
695 if (currentBuffer != 0) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700696 BufferMapper::get().unmap(currentBuffer->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700697 currentBuffer.clear();
698 }
Mathias Agopian4243e662009-04-15 18:34:24 -0700699 err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700700 LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
701 if (err == NO_ERROR) {
702 currentBuffer = buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800703 }
704 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700705 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800706}
707
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800708}; // namespace android
709