blob: 68fd9632cc1245ae246a87f31ecbea27681a65d1 [file] [log] [blame]
The Android Open Source Project9066cfe2009-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 Project9066cfe2009-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 Agopian1473f462009-04-10 14:24:30 -070032#include <ui/DisplayInfo.h>
33#include <ui/BufferMapper.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034#include <ui/ISurface.h>
35#include <ui/Surface.h>
36#include <ui/SurfaceComposerClient.h>
37#include <ui/Rect.h>
38
Mathias Agopian1473f462009-04-10 14:24:30 -070039#include <EGL/android_natives.h>
40
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041#include <private/ui/SharedState.h>
42#include <private/ui/LayerState.h>
43
Mathias Agopian1473f462009-04-10 14:24:30 -070044#include <pixelflinger/pixelflinger.h>
45
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046namespace android {
47
Mathias Agopian1473f462009-04-10 14:24:30 -070048// ============================================================================
49// SurfaceBuffer
50// ============================================================================
51
Mathias Agopian2b1927f2009-04-17 14:15:18 -070052ANDROID_SINGLETON_STATIC_INSTANCE( SurfaceBuffer )
Mathias Agopiana6b40ba2009-04-15 18:34:24 -070053
Mathias Agopian1473f462009-04-10 14:24:30 -070054SurfaceBuffer::SurfaceBuffer()
Mathias Agopiandff8e582009-05-04 14:17:04 -070055 : BASE(), handle(0), mOwner(false), mBufferMapper(BufferMapper::get())
Mathias Agopian1473f462009-04-10 14:24:30 -070056{
57 width =
58 height =
59 stride =
60 format =
61 usage = 0;
62 android_native_buffer_t::getHandle = getHandle;
63}
64
65SurfaceBuffer::SurfaceBuffer(const Parcel& data)
Mathias Agopiandff8e582009-05-04 14:17:04 -070066 : BASE(), handle(0), mOwner(true), mBufferMapper(BufferMapper::get())
Mathias Agopian1473f462009-04-10 14:24:30 -070067{
68 // we own the handle in this case
69 width = data.readInt32();
70 height = data.readInt32();
71 stride = data.readInt32();
72 format = data.readInt32();
73 usage = data.readInt32();
74 handle = data.readNativeHandle();
75 android_native_buffer_t::getHandle = getHandle;
76}
77
78SurfaceBuffer::~SurfaceBuffer()
79{
80 if (handle && mOwner) {
81 native_handle_close(handle);
82 native_handle_delete(const_cast<native_handle*>(handle));
83 }
84}
85
86int SurfaceBuffer::getHandle(android_native_buffer_t const * base,
87 buffer_handle_t* handle)
88{
89 *handle = getSelf(base)->handle;
90 return 0;
91}
92
Mathias Agopiandff8e582009-05-04 14:17:04 -070093status_t SurfaceBuffer::lock(uint32_t usage)
94{
95 const Rect lockBounds(width, height);
96 status_t res = lock(usage, lockBounds);
97 return res;
98}
99
100status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect)
101{
102 status_t res = getBufferMapper().lock(handle, usage, rect, &bits);
103 return res;
104}
105
106status_t SurfaceBuffer::unlock()
107{
108 status_t res = getBufferMapper().unlock(handle);
109 bits = NULL;
110 return res;
111}
112
Mathias Agopian1473f462009-04-10 14:24:30 -0700113status_t SurfaceBuffer::writeToParcel(Parcel* reply,
114 android_native_buffer_t const* buffer)
115{
116 buffer_handle_t handle;
117 status_t err = buffer->getHandle(buffer, &handle);
118 if (err < 0) {
119 return err;
120 }
121 reply->writeInt32(buffer->width);
122 reply->writeInt32(buffer->height);
123 reply->writeInt32(buffer->stride);
124 reply->writeInt32(buffer->format);
125 reply->writeInt32(buffer->usage);
126 reply->writeNativeHandle(handle);
127 return NO_ERROR;
128}
129
130// ----------------------------------------------------------------------
131
Mathias Agopiandff8e582009-05-04 14:17:04 -0700132static void copyBlt(
133 const sp<SurfaceBuffer>& dst,
134 const sp<SurfaceBuffer>& src,
135 const Region& reg)
Mathias Agopian1473f462009-04-10 14:24:30 -0700136{
Mathias Agopiandff8e582009-05-04 14:17:04 -0700137 src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds());
138 uint8_t const * const src_bits = (uint8_t const *)src->bits;
139
140 dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds());
141 uint8_t* const dst_bits = (uint8_t*)dst->bits;
142
Mathias Agopian1473f462009-04-10 14:24:30 -0700143 Region::iterator iterator(reg);
144 if (iterator) {
145 // NOTE: dst and src must be the same format
146 Rect r;
147 const size_t bpp = bytesPerPixel(src->format);
148 const size_t dbpr = dst->stride * bpp;
149 const size_t sbpr = src->stride * bpp;
Mathias Agopiandff8e582009-05-04 14:17:04 -0700150
Mathias Agopian1473f462009-04-10 14:24:30 -0700151 while (iterator.iterate(&r)) {
Mathias Agopiandff8e582009-05-04 14:17:04 -0700152 ssize_t h = r.height();
153 if (h <= 0) continue;
154 size_t size = r.width() * bpp;
155 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
156 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
157 if (dbpr==sbpr && size==sbpr) {
158 size *= h;
159 h = 1;
Mathias Agopian1473f462009-04-10 14:24:30 -0700160 }
Mathias Agopiandff8e582009-05-04 14:17:04 -0700161 do {
162 memcpy(d, s, size);
163 d += dbpr;
164 s += sbpr;
165 } while (--h > 0);
Mathias Agopian1473f462009-04-10 14:24:30 -0700166 }
167 }
Mathias Agopiandff8e582009-05-04 14:17:04 -0700168
169 src->unlock();
170 dst->unlock();
Mathias Agopian1473f462009-04-10 14:24:30 -0700171}
172
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700173// ============================================================================
174// SurfaceControl
175// ============================================================================
176
Mathias Agopian17f638b2009-04-16 20:04:08 -0700177SurfaceControl::SurfaceControl(
178 const sp<SurfaceComposerClient>& client,
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700179 const sp<ISurface>& surface,
180 const ISurfaceFlingerClient::surface_data_t& data,
Mathias Agopian69d62092009-04-16 20:30:22 -0700181 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700182 : mClient(client), mSurface(surface),
183 mToken(data.token), mIdentity(data.identity),
Mathias Agopian69d62092009-04-16 20:30:22 -0700184 mFormat(format), mFlags(flags)
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700185{
186}
Mathias Agopian69d62092009-04-16 20:30:22 -0700187
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700188SurfaceControl::~SurfaceControl()
189{
190 destroy();
191}
192
193void SurfaceControl::destroy()
194{
Mathias Agopian69d62092009-04-16 20:30:22 -0700195 if (isValid()) {
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700196 mClient->destroySurface(mToken);
197 }
198
199 // clear all references and trigger an IPC now, to make sure things
200 // happen without delay, since these resources are quite heavy.
201 mClient.clear();
202 mSurface.clear();
203 IPCThreadState::self()->flushCommands();
204}
205
206void SurfaceControl::clear()
207{
208 // here, the window manager tells us explicitly that we should destroy
209 // the surface's resource. Soon after this call, it will also release
210 // its last reference (which will call the dtor); however, it is possible
211 // that a client living in the same process still holds references which
212 // would delay the call to the dtor -- that is why we need this explicit
213 // "clear()" call.
214 destroy();
215}
216
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700217bool SurfaceControl::isSameSurface(
218 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
219{
220 if (lhs == 0 || rhs == 0)
221 return false;
222 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
223}
224
Mathias Agopian17f638b2009-04-16 20:04:08 -0700225status_t SurfaceControl::setLayer(int32_t layer) {
226 const sp<SurfaceComposerClient>& client(mClient);
227 if (client == 0) return NO_INIT;
228 status_t err = validate(client->mControl);
229 if (err < 0) return err;
230 return client->setLayer(mToken, layer);
231}
232status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
233 const sp<SurfaceComposerClient>& client(mClient);
234 if (client == 0) return NO_INIT;
235 status_t err = validate(client->mControl);
236 if (err < 0) return err;
237 return client->setPosition(mToken, x, y);
238}
239status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
240 const sp<SurfaceComposerClient>& client(mClient);
241 if (client == 0) return NO_INIT;
242 status_t err = validate(client->mControl);
243 if (err < 0) return err;
244 return client->setSize(mToken, w, h);
245}
246status_t SurfaceControl::hide() {
247 const sp<SurfaceComposerClient>& client(mClient);
248 if (client == 0) return NO_INIT;
249 status_t err = validate(client->mControl);
250 if (err < 0) return err;
251 return client->hide(mToken);
252}
253status_t SurfaceControl::show(int32_t layer) {
254 const sp<SurfaceComposerClient>& client(mClient);
255 if (client == 0) return NO_INIT;
256 status_t err = validate(client->mControl);
257 if (err < 0) return err;
258 return client->show(mToken, layer);
259}
260status_t SurfaceControl::freeze() {
261 const sp<SurfaceComposerClient>& client(mClient);
262 if (client == 0) return NO_INIT;
263 status_t err = validate(client->mControl);
264 if (err < 0) return err;
265 return client->freeze(mToken);
266}
267status_t SurfaceControl::unfreeze() {
268 const sp<SurfaceComposerClient>& client(mClient);
269 if (client == 0) return NO_INIT;
270 status_t err = validate(client->mControl);
271 if (err < 0) return err;
272 return client->unfreeze(mToken);
273}
274status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
275 const sp<SurfaceComposerClient>& client(mClient);
276 if (client == 0) return NO_INIT;
277 status_t err = validate(client->mControl);
278 if (err < 0) return err;
279 return client->setFlags(mToken, flags, mask);
280}
281status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
282 const sp<SurfaceComposerClient>& client(mClient);
283 if (client == 0) return NO_INIT;
284 status_t err = validate(client->mControl);
285 if (err < 0) return err;
286 return client->setTransparentRegionHint(mToken, transparent);
287}
288status_t SurfaceControl::setAlpha(float alpha) {
289 const sp<SurfaceComposerClient>& client(mClient);
290 if (client == 0) return NO_INIT;
291 status_t err = validate(client->mControl);
292 if (err < 0) return err;
293 return client->setAlpha(mToken, alpha);
294}
295status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
296 const sp<SurfaceComposerClient>& client(mClient);
297 if (client == 0) return NO_INIT;
298 status_t err = validate(client->mControl);
299 if (err < 0) return err;
300 return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
301}
302status_t SurfaceControl::setFreezeTint(uint32_t tint) {
303 const sp<SurfaceComposerClient>& client(mClient);
304 if (client == 0) return NO_INIT;
305 status_t err = validate(client->mControl);
306 if (err < 0) return err;
307 return client->setFreezeTint(mToken, tint);
308}
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700309
310status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
311{
312 if (mToken<0 || mClient==0) {
313 LOGE("invalid token (%d, identity=%u) or client (%p)",
314 mToken, mIdentity, mClient.get());
315 return NO_INIT;
316 }
317 if (cblk == 0) {
318 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
319 return NO_INIT;
320 }
321 status_t err = cblk->validate(mToken);
322 if (err != NO_ERROR) {
323 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
324 mToken, mIdentity, err, strerror(-err));
325 return err;
326 }
327 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
328 LOGE("using an invalid surface id=%d, identity=%u should be %d",
329 mToken, mIdentity, cblk->layers[mToken].identity);
330 return NO_INIT;
331 }
332 return NO_ERROR;
333}
334
Mathias Agopian17f638b2009-04-16 20:04:08 -0700335status_t SurfaceControl::writeSurfaceToParcel(
336 const sp<SurfaceControl>& control, Parcel* parcel)
337{
338 uint32_t flags = 0;
339 uint32_t format = 0;
340 SurfaceID token = -1;
341 uint32_t identity = 0;
342 sp<SurfaceComposerClient> client;
343 sp<ISurface> sur;
344 if (SurfaceControl::isValid(control)) {
345 token = control->mToken;
346 identity = control->mIdentity;
347 client = control->mClient;
348 sur = control->mSurface;
349 format = control->mFormat;
350 flags = control->mFlags;
351 }
352 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
353 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
354 parcel->writeInt32(token);
355 parcel->writeInt32(identity);
356 parcel->writeInt32(format);
357 parcel->writeInt32(flags);
358 return NO_ERROR;
359}
360
361sp<Surface> SurfaceControl::getSurface() const
362{
363 Mutex::Autolock _l(mLock);
364 if (mSurfaceData == 0) {
365 mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
366 }
367 return mSurfaceData;
368}
369
Mathias Agopian1473f462009-04-10 14:24:30 -0700370// ============================================================================
371// Surface
372// ============================================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373
Mathias Agopian17f638b2009-04-16 20:04:08 -0700374Surface::Surface(const sp<SurfaceControl>& surface)
375 : mClient(surface->mClient), mSurface(surface->mSurface),
376 mToken(surface->mToken), mIdentity(surface->mIdentity),
Mathias Agopiandff8e582009-05-04 14:17:04 -0700377 mFormat(surface->mFormat), mFlags(surface->mFlags),
378 mBufferMapper(BufferMapper::get())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379{
Mathias Agopian17f638b2009-04-16 20:04:08 -0700380 init();
381}
Mathias Agopian6d2c0bc2009-04-16 16:19:50 -0700382
Mathias Agopian17f638b2009-04-16 20:04:08 -0700383Surface::Surface(const Parcel& parcel)
Mathias Agopiandff8e582009-05-04 14:17:04 -0700384 : mBufferMapper(BufferMapper::get())
Mathias Agopian17f638b2009-04-16 20:04:08 -0700385{
386 sp<IBinder> clientBinder = parcel.readStrongBinder();
387 mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
388 mToken = parcel.readInt32();
389 mIdentity = parcel.readInt32();
390 mFormat = parcel.readInt32();
391 mFlags = parcel.readInt32();
392
393 if (clientBinder != NULL)
394 mClient = SurfaceComposerClient::clientForConnection(clientBinder);
395
396 init();
397}
398
399void Surface::init()
400{
Mathias Agopian1473f462009-04-10 14:24:30 -0700401 android_native_window_t::setSwapInterval = setSwapInterval;
Mathias Agopian1473f462009-04-10 14:24:30 -0700402 android_native_window_t::dequeueBuffer = dequeueBuffer;
403 android_native_window_t::lockBuffer = lockBuffer;
404 android_native_window_t::queueBuffer = queueBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 mSwapRectangle.makeInvalid();
Mathias Agopian1473f462009-04-10 14:24:30 -0700406 DisplayInfo dinfo;
407 SurfaceComposerClient::getDisplayInfo(0, &dinfo);
408 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
409 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
410 // FIXME: set real values here
411 const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
412 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
413 const_cast<uint32_t&>(android_native_window_t::flags) = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414}
415
Mathias Agopian17f638b2009-04-16 20:04:08 -0700416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417Surface::~Surface()
418{
Mathias Agopian402c3462009-04-14 18:21:47 -0700419 // this is a client-side operation, the surface is destroyed, unmap
420 // its buffers in this process.
421 for (int i=0 ; i<2 ; i++) {
422 if (mBuffers[i] != 0) {
Mathias Agopiandff8e582009-05-04 14:17:04 -0700423 getBufferMapper().unregisterBuffer(mBuffers[i]->getHandle());
Mathias Agopian1473f462009-04-10 14:24:30 -0700424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 }
Mathias Agopian402c3462009-04-14 18:21:47 -0700426
Mathias Agopian402c3462009-04-14 18:21:47 -0700427 // clear all references and trigger an IPC now, to make sure things
428 // happen without delay, since these resources are quite heavy.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 mClient.clear();
430 mSurface.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 IPCThreadState::self()->flushCommands();
432}
433
Mathias Agopian1473f462009-04-10 14:24:30 -0700434status_t Surface::validate(per_client_cblk_t const* cblk) const
435{
Mathias Agopian402c3462009-04-14 18:21:47 -0700436 if (mToken<0 || mClient==0) {
437 LOGE("invalid token (%d, identity=%u) or client (%p)",
438 mToken, mIdentity, mClient.get());
439 return NO_INIT;
440 }
Mathias Agopian1473f462009-04-10 14:24:30 -0700441 if (cblk == 0) {
442 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
443 return NO_INIT;
444 }
445 status_t err = cblk->validate(mToken);
446 if (err != NO_ERROR) {
447 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
448 mToken, mIdentity, err, strerror(-err));
449 return err;
450 }
451 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
452 LOGE("using an invalid surface id=%d, identity=%u should be %d",
453 mToken, mIdentity, cblk->layers[mToken].identity);
454 return NO_INIT;
455 }
456 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457}
458
Mathias Agopian17f638b2009-04-16 20:04:08 -0700459
460bool Surface::isSameSurface(
461 const sp<Surface>& lhs, const sp<Surface>& rhs)
462{
463 if (lhs == 0 || rhs == 0)
464 return false;
465 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
466}
467
Mathias Agopian1473f462009-04-10 14:24:30 -0700468// ----------------------------------------------------------------------------
469
Mathias Agopian1473f462009-04-10 14:24:30 -0700470int Surface::setSwapInterval(android_native_window_t* window, int interval)
471{
472 return 0;
473}
474
475int Surface::dequeueBuffer(android_native_window_t* window,
476 android_native_buffer_t** buffer)
477{
478 Surface* self = getSelf(window);
479 return self->dequeueBuffer(buffer);
480}
481
482int Surface::lockBuffer(android_native_window_t* window,
483 android_native_buffer_t* buffer)
484{
485 Surface* self = getSelf(window);
486 return self->lockBuffer(buffer);
487}
488
489int Surface::queueBuffer(android_native_window_t* window,
490 android_native_buffer_t* buffer)
491{
492 Surface* self = getSelf(window);
493 return self->queueBuffer(buffer);
494}
495
496// ----------------------------------------------------------------------------
497
Mathias Agopiandff8e582009-05-04 14:17:04 -0700498status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
499{
500 android_native_buffer_t* out;
501 status_t err = dequeueBuffer(&out);
502 *buffer = SurfaceBuffer::getSelf(out);
503 return err;
504}
505
506status_t Surface::lockBuffer(const sp<SurfaceBuffer>& buffer)
507{
508 return lockBuffer(buffer.get());
509}
510
511status_t Surface::queueBuffer(const sp<SurfaceBuffer>& buffer)
512{
513 return queueBuffer(buffer.get());
514}
515
516// ----------------------------------------------------------------------------
517
Mathias Agopian1473f462009-04-10 14:24:30 -0700518int Surface::dequeueBuffer(android_native_buffer_t** buffer)
519{
520 // FIXME: dequeueBuffer() needs proper implementation
521
522 Mutex::Autolock _l(mSurfaceLock);
523
524 per_client_cblk_t* const cblk = mClient->mControl;
525 status_t err = validate(cblk);
526 if (err != NO_ERROR)
527 return err;
528
529 SurfaceID index(mToken);
530
531 int32_t backIdx = cblk->lock_layer(size_t(index),
532 per_client_cblk_t::BLOCKING);
533
534 if (backIdx < 0)
535 return status_t(backIdx);
536
537 mBackbufferIndex = backIdx;
538 layer_cblk_t* const lcblk = &(cblk->layers[index]);
539
540 volatile const surface_info_t* const back = lcblk->surface + backIdx;
541 if (back->flags & surface_info_t::eNeedNewBuffer) {
542 getBufferLocked(backIdx);
543 }
544
545 const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700546 mDirtyRegion.set(backBuffer->width, backBuffer->height);
Mathias Agopian1473f462009-04-10 14:24:30 -0700547 *buffer = backBuffer.get();
Mathias Agopiandff8e582009-05-04 14:17:04 -0700548
Mathias Agopian1473f462009-04-10 14:24:30 -0700549 return NO_ERROR;
550}
551
552int Surface::lockBuffer(android_native_buffer_t* buffer)
553{
Mathias Agopian402c3462009-04-14 18:21:47 -0700554 Mutex::Autolock _l(mSurfaceLock);
555
556 per_client_cblk_t* const cblk = mClient->mControl;
557 status_t err = validate(cblk);
558 if (err != NO_ERROR)
559 return err;
560
Mathias Agopian1473f462009-04-10 14:24:30 -0700561 // FIXME: lockBuffer() needs proper implementation
562 return 0;
563}
564
565int Surface::queueBuffer(android_native_buffer_t* buffer)
566{
567 Mutex::Autolock _l(mSurfaceLock);
568
569 per_client_cblk_t* const cblk = mClient->mControl;
570 status_t err = validate(cblk);
571 if (err != NO_ERROR)
572 return err;
573
Mathias Agopiandff8e582009-05-04 14:17:04 -0700574 if (mSwapRectangle.isValid()) {
575 mDirtyRegion.set(mSwapRectangle);
576 }
577
Mathias Agopian1473f462009-04-10 14:24:30 -0700578 // transmit the dirty region
Mathias Agopian1473f462009-04-10 14:24:30 -0700579 SurfaceID index(mToken);
580 layer_cblk_t* const lcblk = &(cblk->layers[index]);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700581 _send_dirty_region(lcblk, mDirtyRegion);
Mathias Agopian1473f462009-04-10 14:24:30 -0700582
583 uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
584 if (!(newstate & eNextFlipPending))
585 mClient->signalServer();
586
587 return NO_ERROR;
588}
589
590// ----------------------------------------------------------------------------
591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592status_t Surface::lock(SurfaceInfo* info, bool blocking) {
593 return Surface::lock(info, NULL, blocking);
594}
595
Mathias Agopiandff8e582009-05-04 14:17:04 -0700596status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
Mathias Agopian1473f462009-04-10 14:24:30 -0700597{
598 // FIXME: needs some locking here
Mathias Agopiandff8e582009-05-04 14:17:04 -0700599
600 sp<SurfaceBuffer> backBuffer;
Mathias Agopian1473f462009-04-10 14:24:30 -0700601 status_t err = dequeueBuffer(&backBuffer);
602 if (err == NO_ERROR) {
603 err = lockBuffer(backBuffer);
604 if (err == NO_ERROR) {
Mathias Agopian1473f462009-04-10 14:24:30 -0700605 // we handle copy-back here...
606
607 const Rect bounds(backBuffer->width, backBuffer->height);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700608 Region scratch(bounds);
609 Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
Mathias Agopian1473f462009-04-10 14:24:30 -0700610
611 per_client_cblk_t* const cblk = mClient->mControl;
612 layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
613 volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
614 if (back->flags & surface_info_t::eBufferDirty) {
615 // content is meaningless in this case and the whole surface
616 // needs to be redrawn.
617 newDirtyRegion.set(bounds);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700618 } else {
619 newDirtyRegion.andSelf(bounds);
Mathias Agopian1473f462009-04-10 14:24:30 -0700620 if (!(lcblk->flags & eNoCopyBack)) {
Mathias Agopiandff8e582009-05-04 14:17:04 -0700621 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
622 const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
623 if (!copyback.isEmpty() && frontBuffer!=0) {
624 // copy front to back
625 copyBlt(backBuffer, frontBuffer, copyback);
626 }
Mathias Agopian1473f462009-04-10 14:24:30 -0700627 }
628 }
Mathias Agopiandff8e582009-05-04 14:17:04 -0700629 mDirtyRegion = newDirtyRegion;
630 mOldDirtyRegion = newDirtyRegion;
Mathias Agopian1473f462009-04-10 14:24:30 -0700631
Mathias Agopiandff8e582009-05-04 14:17:04 -0700632 status_t res = backBuffer->lock(
633 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
634 newDirtyRegion.bounds());
635
Mathias Agopian1473f462009-04-10 14:24:30 -0700636 LOGW_IF(res, "failed locking buffer %d (%p)",
Mathias Agopiandff8e582009-05-04 14:17:04 -0700637 mBackbufferIndex, backBuffer->handle);
638
639 mLockedBuffer = backBuffer;
640 other->w = backBuffer->width;
641 other->h = backBuffer->height;
642 other->s = backBuffer->stride;
643 other->usage = backBuffer->usage;
644 other->format = backBuffer->format;
645 other->bits = backBuffer->bits;
Mathias Agopian1473f462009-04-10 14:24:30 -0700646 }
647 }
648 return err;
649}
650
651status_t Surface::unlockAndPost()
652{
653 // FIXME: needs some locking here
654
655 if (mLockedBuffer == 0)
656 return BAD_VALUE;
657
Mathias Agopiandff8e582009-05-04 14:17:04 -0700658 status_t res = mLockedBuffer->unlock();
Mathias Agopian1473f462009-04-10 14:24:30 -0700659 LOGW_IF(res, "failed unlocking buffer %d (%p)",
Mathias Agopiandff8e582009-05-04 14:17:04 -0700660 mBackbufferIndex, mLockedBuffer->handle);
661
Mathias Agopian1473f462009-04-10 14:24:30 -0700662 status_t err = queueBuffer(mLockedBuffer);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700663 mLockedBuffer->bits = NULL;
Mathias Agopian1473f462009-04-10 14:24:30 -0700664 mLockedBuffer = 0;
665 return err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666}
667
Mathias Agopian1473f462009-04-10 14:24:30 -0700668void Surface::_send_dirty_region(
669 layer_cblk_t* lcblk, const Region& dirty)
670{
671 const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
672 flat_region_t* flat_region = lcblk->region + index;
673 status_t err = dirty.write(flat_region, sizeof(flat_region_t));
674 if (err < NO_ERROR) {
675 // region doesn't fit, use the bounds
676 const Region reg(dirty.bounds());
677 reg.write(flat_region, sizeof(flat_region_t));
678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679}
680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681void Surface::setSwapRectangle(const Rect& r) {
682 mSwapRectangle = r;
683}
684
Mathias Agopian1473f462009-04-10 14:24:30 -0700685status_t Surface::getBufferLocked(int index)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686{
Mathias Agopian1473f462009-04-10 14:24:30 -0700687 status_t err = NO_MEMORY;
688 sp<SurfaceBuffer> buffer = mSurface->getBuffer();
689 LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
690 if (buffer != 0) {
691 sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
692 if (currentBuffer != 0) {
Mathias Agopiandff8e582009-05-04 14:17:04 -0700693 getBufferMapper().unregisterBuffer(currentBuffer->getHandle());
Mathias Agopian1473f462009-04-10 14:24:30 -0700694 currentBuffer.clear();
695 }
Mathias Agopiandff8e582009-05-04 14:17:04 -0700696 err = getBufferMapper().registerBuffer(buffer->getHandle());
Mathias Agopian1473f462009-04-10 14:24:30 -0700697 LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
698 if (err == NO_ERROR) {
699 currentBuffer = buffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 }
701 }
Mathias Agopian1473f462009-04-10 14:24:30 -0700702 return err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703}
704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705}; // namespace android
706