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