blob: fb105b346c7e716aeb69eca3c1038567a1c1a10a [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 Agopian9f88afb2009-04-17 14:15:18 -070053ANDROID_SINGLETON_STATIC_INSTANCE( SurfaceBuffer )
Mathias Agopian4243e662009-04-15 18:34:24 -070054
Mathias Agopian076b1cc2009-04-10 14:24:30 -070055SurfaceBuffer::SurfaceBuffer()
56 : BASE(), handle(0), mOwner(false)
57{
58 width =
59 height =
60 stride =
61 format =
62 usage = 0;
63 android_native_buffer_t::getHandle = getHandle;
64}
65
66SurfaceBuffer::SurfaceBuffer(const Parcel& data)
67 : BASE(), handle(0), mOwner(true)
68{
69 // we own the handle in this case
70 width = data.readInt32();
71 height = data.readInt32();
72 stride = data.readInt32();
73 format = data.readInt32();
74 usage = data.readInt32();
75 handle = data.readNativeHandle();
76 android_native_buffer_t::getHandle = getHandle;
77}
78
79SurfaceBuffer::~SurfaceBuffer()
80{
81 if (handle && mOwner) {
82 native_handle_close(handle);
83 native_handle_delete(const_cast<native_handle*>(handle));
84 }
85}
86
87int SurfaceBuffer::getHandle(android_native_buffer_t const * base,
88 buffer_handle_t* handle)
89{
90 *handle = getSelf(base)->handle;
91 return 0;
92}
93
94status_t SurfaceBuffer::writeToParcel(Parcel* reply,
95 android_native_buffer_t const* buffer)
96{
97 buffer_handle_t handle;
98 status_t err = buffer->getHandle(buffer, &handle);
99 if (err < 0) {
100 return err;
101 }
102 reply->writeInt32(buffer->width);
103 reply->writeInt32(buffer->height);
104 reply->writeInt32(buffer->stride);
105 reply->writeInt32(buffer->format);
106 reply->writeInt32(buffer->usage);
107 reply->writeNativeHandle(handle);
108 return NO_ERROR;
109}
110
111// ----------------------------------------------------------------------
112
113static void copyBlt(const android_native_buffer_t* dst,
114 const android_native_buffer_t* src, const Region& reg)
115{
116 Region::iterator iterator(reg);
117 if (iterator) {
118 // NOTE: dst and src must be the same format
119 Rect r;
120 const size_t bpp = bytesPerPixel(src->format);
121 const size_t dbpr = dst->stride * bpp;
122 const size_t sbpr = src->stride * bpp;
123 while (iterator.iterate(&r)) {
124 ssize_t h = r.bottom - r.top;
125 if (h) {
126 size_t size = (r.right - r.left) * bpp;
127 uint8_t* s = (GGLubyte*)src->bits +
128 (r.left + src->stride * r.top) * bpp;
129 uint8_t* d = (GGLubyte*)dst->bits +
130 (r.left + dst->stride * r.top) * bpp;
131 if (dbpr==sbpr && size==sbpr) {
132 size *= h;
133 h = 1;
134 }
135 do {
136 memcpy(d, s, size);
137 d += dbpr;
138 s += sbpr;
139 } while (--h > 0);
140 }
141 }
142 }
143}
144
Mathias Agopian62185b72009-04-16 16:19:50 -0700145
146// ============================================================================
147// SurfaceControl
148// ============================================================================
149
Mathias Agopian01b76682009-04-16 20:04:08 -0700150SurfaceControl::SurfaceControl(
151 const sp<SurfaceComposerClient>& client,
Mathias Agopian62185b72009-04-16 16:19:50 -0700152 const sp<ISurface>& surface,
153 const ISurfaceFlingerClient::surface_data_t& data,
Mathias Agopian18d84462009-04-16 20:30:22 -0700154 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
Mathias Agopian62185b72009-04-16 16:19:50 -0700155 : mClient(client), mSurface(surface),
156 mToken(data.token), mIdentity(data.identity),
Mathias Agopian18d84462009-04-16 20:30:22 -0700157 mFormat(format), mFlags(flags)
Mathias Agopian62185b72009-04-16 16:19:50 -0700158{
159}
Mathias Agopian18d84462009-04-16 20:30:22 -0700160
Mathias Agopian62185b72009-04-16 16:19:50 -0700161SurfaceControl::~SurfaceControl()
162{
163 destroy();
164}
165
166void SurfaceControl::destroy()
167{
Mathias Agopian18d84462009-04-16 20:30:22 -0700168 if (isValid()) {
Mathias Agopian62185b72009-04-16 16:19:50 -0700169 mClient->destroySurface(mToken);
170 }
171
172 // clear all references and trigger an IPC now, to make sure things
173 // happen without delay, since these resources are quite heavy.
174 mClient.clear();
175 mSurface.clear();
176 IPCThreadState::self()->flushCommands();
177}
178
179void SurfaceControl::clear()
180{
181 // here, the window manager tells us explicitly that we should destroy
182 // the surface's resource. Soon after this call, it will also release
183 // its last reference (which will call the dtor); however, it is possible
184 // that a client living in the same process still holds references which
185 // would delay the call to the dtor -- that is why we need this explicit
186 // "clear()" call.
187 destroy();
188}
189
Mathias Agopian62185b72009-04-16 16:19:50 -0700190bool SurfaceControl::isSameSurface(
191 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
192{
193 if (lhs == 0 || rhs == 0)
194 return false;
195 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
196}
197
Mathias Agopian01b76682009-04-16 20:04:08 -0700198status_t SurfaceControl::setLayer(int32_t layer) {
199 const sp<SurfaceComposerClient>& client(mClient);
200 if (client == 0) return NO_INIT;
201 status_t err = validate(client->mControl);
202 if (err < 0) return err;
203 return client->setLayer(mToken, layer);
204}
205status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
206 const sp<SurfaceComposerClient>& client(mClient);
207 if (client == 0) return NO_INIT;
208 status_t err = validate(client->mControl);
209 if (err < 0) return err;
210 return client->setPosition(mToken, x, y);
211}
212status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
213 const sp<SurfaceComposerClient>& client(mClient);
214 if (client == 0) return NO_INIT;
215 status_t err = validate(client->mControl);
216 if (err < 0) return err;
217 return client->setSize(mToken, w, h);
218}
219status_t SurfaceControl::hide() {
220 const sp<SurfaceComposerClient>& client(mClient);
221 if (client == 0) return NO_INIT;
222 status_t err = validate(client->mControl);
223 if (err < 0) return err;
224 return client->hide(mToken);
225}
226status_t SurfaceControl::show(int32_t layer) {
227 const sp<SurfaceComposerClient>& client(mClient);
228 if (client == 0) return NO_INIT;
229 status_t err = validate(client->mControl);
230 if (err < 0) return err;
231 return client->show(mToken, layer);
232}
233status_t SurfaceControl::freeze() {
234 const sp<SurfaceComposerClient>& client(mClient);
235 if (client == 0) return NO_INIT;
236 status_t err = validate(client->mControl);
237 if (err < 0) return err;
238 return client->freeze(mToken);
239}
240status_t SurfaceControl::unfreeze() {
241 const sp<SurfaceComposerClient>& client(mClient);
242 if (client == 0) return NO_INIT;
243 status_t err = validate(client->mControl);
244 if (err < 0) return err;
245 return client->unfreeze(mToken);
246}
247status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
248 const sp<SurfaceComposerClient>& client(mClient);
249 if (client == 0) return NO_INIT;
250 status_t err = validate(client->mControl);
251 if (err < 0) return err;
252 return client->setFlags(mToken, flags, mask);
253}
254status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
255 const sp<SurfaceComposerClient>& client(mClient);
256 if (client == 0) return NO_INIT;
257 status_t err = validate(client->mControl);
258 if (err < 0) return err;
259 return client->setTransparentRegionHint(mToken, transparent);
260}
261status_t SurfaceControl::setAlpha(float alpha) {
262 const sp<SurfaceComposerClient>& client(mClient);
263 if (client == 0) return NO_INIT;
264 status_t err = validate(client->mControl);
265 if (err < 0) return err;
266 return client->setAlpha(mToken, alpha);
267}
268status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
269 const sp<SurfaceComposerClient>& client(mClient);
270 if (client == 0) return NO_INIT;
271 status_t err = validate(client->mControl);
272 if (err < 0) return err;
273 return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
274}
275status_t SurfaceControl::setFreezeTint(uint32_t tint) {
276 const sp<SurfaceComposerClient>& client(mClient);
277 if (client == 0) return NO_INIT;
278 status_t err = validate(client->mControl);
279 if (err < 0) return err;
280 return client->setFreezeTint(mToken, tint);
281}
Mathias Agopian62185b72009-04-16 16:19:50 -0700282
283status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
284{
285 if (mToken<0 || mClient==0) {
286 LOGE("invalid token (%d, identity=%u) or client (%p)",
287 mToken, mIdentity, mClient.get());
288 return NO_INIT;
289 }
290 if (cblk == 0) {
291 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
292 return NO_INIT;
293 }
294 status_t err = cblk->validate(mToken);
295 if (err != NO_ERROR) {
296 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
297 mToken, mIdentity, err, strerror(-err));
298 return err;
299 }
300 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
301 LOGE("using an invalid surface id=%d, identity=%u should be %d",
302 mToken, mIdentity, cblk->layers[mToken].identity);
303 return NO_INIT;
304 }
305 return NO_ERROR;
306}
307
Mathias Agopian01b76682009-04-16 20:04:08 -0700308status_t SurfaceControl::writeSurfaceToParcel(
309 const sp<SurfaceControl>& control, Parcel* parcel)
310{
311 uint32_t flags = 0;
312 uint32_t format = 0;
313 SurfaceID token = -1;
314 uint32_t identity = 0;
315 sp<SurfaceComposerClient> client;
316 sp<ISurface> sur;
317 if (SurfaceControl::isValid(control)) {
318 token = control->mToken;
319 identity = control->mIdentity;
320 client = control->mClient;
321 sur = control->mSurface;
322 format = control->mFormat;
323 flags = control->mFlags;
324 }
325 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
326 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
327 parcel->writeInt32(token);
328 parcel->writeInt32(identity);
329 parcel->writeInt32(format);
330 parcel->writeInt32(flags);
331 return NO_ERROR;
332}
333
334sp<Surface> SurfaceControl::getSurface() const
335{
336 Mutex::Autolock _l(mLock);
337 if (mSurfaceData == 0) {
338 mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
339 }
340 return mSurfaceData;
341}
342
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700343// ============================================================================
344// Surface
345// ============================================================================
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800346
Mathias Agopian01b76682009-04-16 20:04:08 -0700347Surface::Surface(const sp<SurfaceControl>& surface)
348 : mClient(surface->mClient), mSurface(surface->mSurface),
349 mToken(surface->mToken), mIdentity(surface->mIdentity),
Mathias Agopian18d84462009-04-16 20:30:22 -0700350 mFormat(surface->mFormat), mFlags(surface->mFlags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351{
Mathias Agopian01b76682009-04-16 20:04:08 -0700352 init();
353}
Mathias Agopian62185b72009-04-16 16:19:50 -0700354
Mathias Agopian01b76682009-04-16 20:04:08 -0700355Surface::Surface(const Parcel& parcel)
Mathias Agopian01b76682009-04-16 20:04:08 -0700356{
357 sp<IBinder> clientBinder = parcel.readStrongBinder();
358 mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
359 mToken = parcel.readInt32();
360 mIdentity = parcel.readInt32();
361 mFormat = parcel.readInt32();
362 mFlags = parcel.readInt32();
363
364 if (clientBinder != NULL)
365 mClient = SurfaceComposerClient::clientForConnection(clientBinder);
366
367 init();
368}
369
370void Surface::init()
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
Mathias Agopian01b76682009-04-16 20:04:08 -0700392
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800393Surface::~Surface()
394{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700395 // this is a client-side operation, the surface is destroyed, unmap
396 // its buffers in this process.
397 for (int i=0 ; i<2 ; i++) {
398 if (mBuffers[i] != 0) {
399 BufferMapper::get().unmap(mBuffers[i]->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700400 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800401 }
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700402
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700403 // clear all references and trigger an IPC now, to make sure things
404 // happen without delay, since these resources are quite heavy.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800405 mClient.clear();
406 mSurface.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800407 IPCThreadState::self()->flushCommands();
408}
409
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700410status_t Surface::validate(per_client_cblk_t const* cblk) const
411{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700412 if (mToken<0 || mClient==0) {
413 LOGE("invalid token (%d, identity=%u) or client (%p)",
414 mToken, mIdentity, mClient.get());
415 return NO_INIT;
416 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700417 if (cblk == 0) {
418 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
419 return NO_INIT;
420 }
421 status_t err = cblk->validate(mToken);
422 if (err != NO_ERROR) {
423 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
424 mToken, mIdentity, err, strerror(-err));
425 return err;
426 }
427 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
428 LOGE("using an invalid surface id=%d, identity=%u should be %d",
429 mToken, mIdentity, cblk->layers[mToken].identity);
430 return NO_INIT;
431 }
432 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800433}
434
Mathias Agopian01b76682009-04-16 20:04:08 -0700435
436bool Surface::isSameSurface(
437 const sp<Surface>& lhs, const sp<Surface>& rhs)
438{
439 if (lhs == 0 || rhs == 0)
440 return false;
441 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
442}
443
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700444// ----------------------------------------------------------------------------
445
446int Surface::setSwapRectangle(android_native_window_t* window,
447 int l, int t, int w, int h)
448{
449 Surface* self = getSelf(window);
450 self->setSwapRectangle(Rect(l, t, l+w, t+h));
451 return 0;
452}
453
454void Surface::connect(android_native_window_t* window)
455{
456}
457
458void Surface::disconnect(android_native_window_t* window)
459{
460}
461
462int Surface::setSwapInterval(android_native_window_t* window, int interval)
463{
464 return 0;
465}
466
467int Surface::dequeueBuffer(android_native_window_t* window,
468 android_native_buffer_t** buffer)
469{
470 Surface* self = getSelf(window);
471 return self->dequeueBuffer(buffer);
472}
473
474int Surface::lockBuffer(android_native_window_t* window,
475 android_native_buffer_t* buffer)
476{
477 Surface* self = getSelf(window);
478 return self->lockBuffer(buffer);
479}
480
481int Surface::queueBuffer(android_native_window_t* window,
482 android_native_buffer_t* buffer)
483{
484 Surface* self = getSelf(window);
485 return self->queueBuffer(buffer);
486}
487
488// ----------------------------------------------------------------------------
489
490int Surface::dequeueBuffer(android_native_buffer_t** buffer)
491{
492 // FIXME: dequeueBuffer() needs proper implementation
493
494 Mutex::Autolock _l(mSurfaceLock);
495
496 per_client_cblk_t* const cblk = mClient->mControl;
497 status_t err = validate(cblk);
498 if (err != NO_ERROR)
499 return err;
500
501 SurfaceID index(mToken);
502
503 int32_t backIdx = cblk->lock_layer(size_t(index),
504 per_client_cblk_t::BLOCKING);
505
506 if (backIdx < 0)
507 return status_t(backIdx);
508
509 mBackbufferIndex = backIdx;
510 layer_cblk_t* const lcblk = &(cblk->layers[index]);
511
512 volatile const surface_info_t* const back = lcblk->surface + backIdx;
513 if (back->flags & surface_info_t::eNeedNewBuffer) {
514 getBufferLocked(backIdx);
515 }
516
517 const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
518 *buffer = backBuffer.get();
519
520 return NO_ERROR;
521}
522
523int Surface::lockBuffer(android_native_buffer_t* buffer)
524{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700525 Mutex::Autolock _l(mSurfaceLock);
526
527 per_client_cblk_t* const cblk = mClient->mControl;
528 status_t err = validate(cblk);
529 if (err != NO_ERROR)
530 return err;
531
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700532 // FIXME: lockBuffer() needs proper implementation
533 return 0;
534}
535
536int Surface::queueBuffer(android_native_buffer_t* buffer)
537{
538 Mutex::Autolock _l(mSurfaceLock);
539
540 per_client_cblk_t* const cblk = mClient->mControl;
541 status_t err = validate(cblk);
542 if (err != NO_ERROR)
543 return err;
544
545 // transmit the dirty region
546 const Region dirty(swapRectangle());
547 SurfaceID index(mToken);
548 layer_cblk_t* const lcblk = &(cblk->layers[index]);
549 _send_dirty_region(lcblk, dirty);
550
551 uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
552 if (!(newstate & eNextFlipPending))
553 mClient->signalServer();
554
555 return NO_ERROR;
556}
557
558// ----------------------------------------------------------------------------
559
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800560status_t Surface::lock(SurfaceInfo* info, bool blocking) {
561 return Surface::lock(info, NULL, blocking);
562}
563
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700564status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
565{
566 // FIXME: needs some locking here
567 android_native_buffer_t* backBuffer;
568 status_t err = dequeueBuffer(&backBuffer);
569 if (err == NO_ERROR) {
570 err = lockBuffer(backBuffer);
571 if (err == NO_ERROR) {
572 backBuffer->common.incRef(&backBuffer->common);
573 mLockedBuffer = backBuffer;
574 other->w = backBuffer->width;
575 other->h = backBuffer->height;
576 other->s = backBuffer->stride;
577 other->usage = backBuffer->usage;
578 other->format = backBuffer->format;
579 other->bits = backBuffer->bits;
580
581 // we handle copy-back here...
582
583 const Rect bounds(backBuffer->width, backBuffer->height);
584 Region newDirtyRegion;
585
586 per_client_cblk_t* const cblk = mClient->mControl;
587 layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
588 volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
589 if (back->flags & surface_info_t::eBufferDirty) {
590 // content is meaningless in this case and the whole surface
591 // needs to be redrawn.
592 newDirtyRegion.set(bounds);
593 if (dirty) {
594 *dirty = newDirtyRegion;
595 }
596 } else
597 {
598 if (dirty) {
599 dirty->andSelf(Region(bounds));
600 newDirtyRegion = *dirty;
601 } else {
602 newDirtyRegion.set(bounds);
603 }
604 Region copyback;
605 if (!(lcblk->flags & eNoCopyBack)) {
606 const Region previousDirtyRegion(dirtyRegion());
607 copyback = previousDirtyRegion.subtract(newDirtyRegion);
608 }
609 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
610 if (!copyback.isEmpty() && frontBuffer!=0) {
611 // copy front to back
612 copyBlt(backBuffer, frontBuffer.get(), copyback);
613 }
614 }
615 setDirtyRegion(newDirtyRegion);
616
617
618 Rect lockBounds(backBuffer->width, backBuffer->height);
619 if (dirty) {
620 lockBounds = dirty->bounds();
621 }
622 buffer_handle_t handle;
623 backBuffer->getHandle(backBuffer, &handle);
624 status_t res = BufferMapper::get().lock(handle,
625 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
626 lockBounds);
627 LOGW_IF(res, "failed locking buffer %d (%p)",
628 mBackbufferIndex, handle);
629 setSwapRectangle(lockBounds);
630 }
631 }
632 return err;
633}
634
635status_t Surface::unlockAndPost()
636{
637 // FIXME: needs some locking here
638
639 if (mLockedBuffer == 0)
640 return BAD_VALUE;
641
642 buffer_handle_t handle;
643 mLockedBuffer->getHandle(mLockedBuffer, &handle);
644 status_t res = BufferMapper::get().unlock(handle);
645 LOGW_IF(res, "failed unlocking buffer %d (%p)",
646 mBackbufferIndex, handle);
647
648 const Rect dirty(dirtyRegion().bounds());
649 setSwapRectangle(dirty);
650 status_t err = queueBuffer(mLockedBuffer);
651 mLockedBuffer->common.decRef(&mLockedBuffer->common);
652 mLockedBuffer = 0;
653 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800654}
655
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700656void Surface::_send_dirty_region(
657 layer_cblk_t* lcblk, const Region& dirty)
658{
659 const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
660 flat_region_t* flat_region = lcblk->region + index;
661 status_t err = dirty.write(flat_region, sizeof(flat_region_t));
662 if (err < NO_ERROR) {
663 // region doesn't fit, use the bounds
664 const Region reg(dirty.bounds());
665 reg.write(flat_region, sizeof(flat_region_t));
666 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667}
668
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800669Region Surface::dirtyRegion() const {
670 return mDirtyRegion;
671}
672void Surface::setDirtyRegion(const Region& region) const {
673 mDirtyRegion = region;
674}
675const Rect& Surface::swapRectangle() const {
676 return mSwapRectangle;
677}
678void Surface::setSwapRectangle(const Rect& r) {
679 mSwapRectangle = r;
680}
681
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700682status_t Surface::getBufferLocked(int index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800683{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700684 status_t err = NO_MEMORY;
685 sp<SurfaceBuffer> buffer = mSurface->getBuffer();
686 LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
687 if (buffer != 0) {
688 sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
689 if (currentBuffer != 0) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700690 BufferMapper::get().unmap(currentBuffer->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700691 currentBuffer.clear();
692 }
Mathias Agopian4243e662009-04-15 18:34:24 -0700693 err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700694 LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
695 if (err == NO_ERROR) {
696 currentBuffer = buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800697 }
698 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700699 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800700}
701
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800702}; // namespace android
703