blob: 782eac46beb85f9d765bd0f9cc68f7d38d5905df [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>
The Android Open Source Projectedbf3b62009-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 Agopian076b1cc2009-04-10 14:24:30 -070039#include <EGL/android_natives.h>
40
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041#include <private/ui/SharedState.h>
42#include <private/ui/LayerState.h>
43
Mathias Agopian076b1cc2009-04-10 14:24:30 -070044#include <pixelflinger/pixelflinger.h>
45
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080046namespace android {
47
Mathias Agopian076b1cc2009-04-10 14:24:30 -070048// ============================================================================
49// SurfaceBuffer
50// ============================================================================
51
Mathias Agopian9f88afb2009-04-17 14:15:18 -070052ANDROID_SINGLETON_STATIC_INSTANCE( SurfaceBuffer )
Mathias Agopian4243e662009-04-15 18:34:24 -070053
Mathias Agopian076b1cc2009-04-10 14:24:30 -070054SurfaceBuffer::SurfaceBuffer()
Mathias Agopian21c59d02009-05-05 00:59:23 -070055 : BASE(), mOwner(false), mBufferMapper(BufferMapper::get())
Mathias Agopian076b1cc2009-04-10 14:24:30 -070056{
57 width =
58 height =
59 stride =
60 format =
61 usage = 0;
Mathias Agopian21c59d02009-05-05 00:59:23 -070062 handle = NULL;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070063}
64
65SurfaceBuffer::SurfaceBuffer(const Parcel& data)
Mathias Agopian21c59d02009-05-05 00:59:23 -070066 : BASE(), mOwner(true), mBufferMapper(BufferMapper::get())
Mathias Agopian076b1cc2009-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();
Mathias Agopian076b1cc2009-04-10 14:24:30 -070075}
76
77SurfaceBuffer::~SurfaceBuffer()
78{
79 if (handle && mOwner) {
80 native_handle_close(handle);
81 native_handle_delete(const_cast<native_handle*>(handle));
82 }
83}
84
Mathias Agopiane71212b2009-05-05 00:37:46 -070085status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr)
Mathias Agopian0926f502009-05-04 14:17:04 -070086{
87 const Rect lockBounds(width, height);
Mathias Agopiane71212b2009-05-05 00:37:46 -070088 status_t res = lock(usage, lockBounds, vaddr);
Mathias Agopian0926f502009-05-04 14:17:04 -070089 return res;
90}
91
Mathias Agopiane71212b2009-05-05 00:37:46 -070092status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
Mathias Agopian0926f502009-05-04 14:17:04 -070093{
Mathias Agopiane71212b2009-05-05 00:37:46 -070094 status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
Mathias Agopian0926f502009-05-04 14:17:04 -070095 return res;
96}
97
98status_t SurfaceBuffer::unlock()
99{
100 status_t res = getBufferMapper().unlock(handle);
Mathias Agopian0926f502009-05-04 14:17:04 -0700101 return res;
102}
103
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700104status_t SurfaceBuffer::writeToParcel(Parcel* reply,
105 android_native_buffer_t const* buffer)
106{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700107 reply->writeInt32(buffer->width);
108 reply->writeInt32(buffer->height);
109 reply->writeInt32(buffer->stride);
110 reply->writeInt32(buffer->format);
111 reply->writeInt32(buffer->usage);
Mathias Agopian21c59d02009-05-05 00:59:23 -0700112 reply->writeNativeHandle(buffer->handle);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700113 return NO_ERROR;
114}
115
116// ----------------------------------------------------------------------
117
Mathias Agopian0926f502009-05-04 14:17:04 -0700118static void copyBlt(
119 const sp<SurfaceBuffer>& dst,
120 const sp<SurfaceBuffer>& src,
121 const Region& reg)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700122{
Mathias Agopiane71212b2009-05-05 00:37:46 -0700123 uint8_t const * src_bits;
124 src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
Mathias Agopian0926f502009-05-04 14:17:04 -0700125
Mathias Agopiane71212b2009-05-05 00:37:46 -0700126 uint8_t* dst_bits;
127 dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
Mathias Agopian0926f502009-05-04 14:17:04 -0700128
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700129 Region::iterator iterator(reg);
130 if (iterator) {
131 // NOTE: dst and src must be the same format
132 Rect r;
133 const size_t bpp = bytesPerPixel(src->format);
134 const size_t dbpr = dst->stride * bpp;
135 const size_t sbpr = src->stride * bpp;
Mathias Agopian0926f502009-05-04 14:17:04 -0700136
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700137 while (iterator.iterate(&r)) {
Mathias Agopian0926f502009-05-04 14:17:04 -0700138 ssize_t h = r.height();
139 if (h <= 0) continue;
140 size_t size = r.width() * bpp;
141 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
142 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
143 if (dbpr==sbpr && size==sbpr) {
144 size *= h;
145 h = 1;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700146 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700147 do {
148 memcpy(d, s, size);
149 d += dbpr;
150 s += sbpr;
151 } while (--h > 0);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700152 }
153 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700154
155 src->unlock();
156 dst->unlock();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700157}
158
Mathias Agopian62185b72009-04-16 16:19:50 -0700159// ============================================================================
160// SurfaceControl
161// ============================================================================
162
Mathias Agopian01b76682009-04-16 20:04:08 -0700163SurfaceControl::SurfaceControl(
164 const sp<SurfaceComposerClient>& client,
Mathias Agopian62185b72009-04-16 16:19:50 -0700165 const sp<ISurface>& surface,
166 const ISurfaceFlingerClient::surface_data_t& data,
Mathias Agopian18d84462009-04-16 20:30:22 -0700167 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
Mathias Agopian62185b72009-04-16 16:19:50 -0700168 : mClient(client), mSurface(surface),
169 mToken(data.token), mIdentity(data.identity),
Mathias Agopian18d84462009-04-16 20:30:22 -0700170 mFormat(format), mFlags(flags)
Mathias Agopian62185b72009-04-16 16:19:50 -0700171{
172}
Mathias Agopian18d84462009-04-16 20:30:22 -0700173
Mathias Agopian62185b72009-04-16 16:19:50 -0700174SurfaceControl::~SurfaceControl()
175{
176 destroy();
177}
178
179void SurfaceControl::destroy()
180{
Mathias Agopian18d84462009-04-16 20:30:22 -0700181 if (isValid()) {
Mathias Agopian62185b72009-04-16 16:19:50 -0700182 mClient->destroySurface(mToken);
183 }
184
185 // clear all references and trigger an IPC now, to make sure things
186 // happen without delay, since these resources are quite heavy.
187 mClient.clear();
188 mSurface.clear();
189 IPCThreadState::self()->flushCommands();
190}
191
192void SurfaceControl::clear()
193{
194 // here, the window manager tells us explicitly that we should destroy
195 // the surface's resource. Soon after this call, it will also release
196 // its last reference (which will call the dtor); however, it is possible
197 // that a client living in the same process still holds references which
198 // would delay the call to the dtor -- that is why we need this explicit
199 // "clear()" call.
200 destroy();
201}
202
Mathias Agopian62185b72009-04-16 16:19:50 -0700203bool SurfaceControl::isSameSurface(
204 const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
205{
206 if (lhs == 0 || rhs == 0)
207 return false;
208 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
209}
210
Mathias Agopian01b76682009-04-16 20:04:08 -0700211status_t SurfaceControl::setLayer(int32_t layer) {
212 const sp<SurfaceComposerClient>& client(mClient);
213 if (client == 0) return NO_INIT;
214 status_t err = validate(client->mControl);
215 if (err < 0) return err;
216 return client->setLayer(mToken, layer);
217}
218status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
219 const sp<SurfaceComposerClient>& client(mClient);
220 if (client == 0) return NO_INIT;
221 status_t err = validate(client->mControl);
222 if (err < 0) return err;
223 return client->setPosition(mToken, x, y);
224}
225status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
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->setSize(mToken, w, h);
231}
232status_t SurfaceControl::hide() {
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->hide(mToken);
238}
239status_t SurfaceControl::show(int32_t layer) {
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->show(mToken, layer);
245}
246status_t SurfaceControl::freeze() {
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->freeze(mToken);
252}
253status_t SurfaceControl::unfreeze() {
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->unfreeze(mToken);
259}
260status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
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->setFlags(mToken, flags, mask);
266}
267status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
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->setTransparentRegionHint(mToken, transparent);
273}
274status_t SurfaceControl::setAlpha(float alpha) {
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->setAlpha(mToken, alpha);
280}
281status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
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->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
287}
288status_t SurfaceControl::setFreezeTint(uint32_t tint) {
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->setFreezeTint(mToken, tint);
294}
Mathias Agopian62185b72009-04-16 16:19:50 -0700295
296status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
297{
298 if (mToken<0 || mClient==0) {
299 LOGE("invalid token (%d, identity=%u) or client (%p)",
300 mToken, mIdentity, mClient.get());
301 return NO_INIT;
302 }
303 if (cblk == 0) {
304 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
305 return NO_INIT;
306 }
307 status_t err = cblk->validate(mToken);
308 if (err != NO_ERROR) {
309 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
310 mToken, mIdentity, err, strerror(-err));
311 return err;
312 }
313 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
314 LOGE("using an invalid surface id=%d, identity=%u should be %d",
315 mToken, mIdentity, cblk->layers[mToken].identity);
316 return NO_INIT;
317 }
318 return NO_ERROR;
319}
320
Mathias Agopian01b76682009-04-16 20:04:08 -0700321status_t SurfaceControl::writeSurfaceToParcel(
322 const sp<SurfaceControl>& control, Parcel* parcel)
323{
324 uint32_t flags = 0;
325 uint32_t format = 0;
326 SurfaceID token = -1;
327 uint32_t identity = 0;
328 sp<SurfaceComposerClient> client;
329 sp<ISurface> sur;
330 if (SurfaceControl::isValid(control)) {
331 token = control->mToken;
332 identity = control->mIdentity;
333 client = control->mClient;
334 sur = control->mSurface;
335 format = control->mFormat;
336 flags = control->mFlags;
337 }
338 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
339 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
340 parcel->writeInt32(token);
341 parcel->writeInt32(identity);
342 parcel->writeInt32(format);
343 parcel->writeInt32(flags);
344 return NO_ERROR;
345}
346
347sp<Surface> SurfaceControl::getSurface() const
348{
349 Mutex::Autolock _l(mLock);
350 if (mSurfaceData == 0) {
351 mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
352 }
353 return mSurfaceData;
354}
355
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700356// ============================================================================
357// Surface
358// ============================================================================
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800359
Mathias Agopian01b76682009-04-16 20:04:08 -0700360Surface::Surface(const sp<SurfaceControl>& surface)
361 : mClient(surface->mClient), mSurface(surface->mSurface),
362 mToken(surface->mToken), mIdentity(surface->mIdentity),
Mathias Agopian0926f502009-05-04 14:17:04 -0700363 mFormat(surface->mFormat), mFlags(surface->mFlags),
364 mBufferMapper(BufferMapper::get())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800365{
Mathias Agopian01b76682009-04-16 20:04:08 -0700366 init();
367}
Mathias Agopian62185b72009-04-16 16:19:50 -0700368
Mathias Agopian01b76682009-04-16 20:04:08 -0700369Surface::Surface(const Parcel& parcel)
Mathias Agopian0926f502009-05-04 14:17:04 -0700370 : mBufferMapper(BufferMapper::get())
Mathias Agopian01b76682009-04-16 20:04:08 -0700371{
372 sp<IBinder> clientBinder = parcel.readStrongBinder();
373 mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
374 mToken = parcel.readInt32();
375 mIdentity = parcel.readInt32();
376 mFormat = parcel.readInt32();
377 mFlags = parcel.readInt32();
378
379 if (clientBinder != NULL)
380 mClient = SurfaceComposerClient::clientForConnection(clientBinder);
381
382 init();
383}
384
385void Surface::init()
386{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700387 android_native_window_t::setSwapInterval = setSwapInterval;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700388 android_native_window_t::dequeueBuffer = dequeueBuffer;
389 android_native_window_t::lockBuffer = lockBuffer;
390 android_native_window_t::queueBuffer = queueBuffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800391 mSwapRectangle.makeInvalid();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700392 DisplayInfo dinfo;
393 SurfaceComposerClient::getDisplayInfo(0, &dinfo);
394 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
395 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
396 // FIXME: set real values here
397 const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
398 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
399 const_cast<uint32_t&>(android_native_window_t::flags) = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800400}
401
Mathias Agopian01b76682009-04-16 20:04:08 -0700402
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800403Surface::~Surface()
404{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700405 // this is a client-side operation, the surface is destroyed, unmap
406 // its buffers in this process.
407 for (int i=0 ; i<2 ; i++) {
408 if (mBuffers[i] != 0) {
Mathias Agopian21c59d02009-05-05 00:59:23 -0700409 getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700410 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411 }
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700412
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700413 // clear all references and trigger an IPC now, to make sure things
414 // happen without delay, since these resources are quite heavy.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800415 mClient.clear();
416 mSurface.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800417 IPCThreadState::self()->flushCommands();
418}
419
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700420status_t Surface::validate(per_client_cblk_t const* cblk) const
421{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700422 if (mToken<0 || mClient==0) {
423 LOGE("invalid token (%d, identity=%u) or client (%p)",
424 mToken, mIdentity, mClient.get());
425 return NO_INIT;
426 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700427 if (cblk == 0) {
428 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
429 return NO_INIT;
430 }
431 status_t err = cblk->validate(mToken);
432 if (err != NO_ERROR) {
433 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
434 mToken, mIdentity, err, strerror(-err));
435 return err;
436 }
437 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
438 LOGE("using an invalid surface id=%d, identity=%u should be %d",
439 mToken, mIdentity, cblk->layers[mToken].identity);
440 return NO_INIT;
441 }
442 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800443}
444
Mathias Agopian01b76682009-04-16 20:04:08 -0700445
446bool Surface::isSameSurface(
447 const sp<Surface>& lhs, const sp<Surface>& rhs)
448{
449 if (lhs == 0 || rhs == 0)
450 return false;
451 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
452}
453
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700454// ----------------------------------------------------------------------------
455
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700456int Surface::setSwapInterval(android_native_window_t* window, int interval)
457{
458 return 0;
459}
460
461int Surface::dequeueBuffer(android_native_window_t* window,
462 android_native_buffer_t** buffer)
463{
464 Surface* self = getSelf(window);
465 return self->dequeueBuffer(buffer);
466}
467
468int Surface::lockBuffer(android_native_window_t* window,
469 android_native_buffer_t* buffer)
470{
471 Surface* self = getSelf(window);
472 return self->lockBuffer(buffer);
473}
474
475int Surface::queueBuffer(android_native_window_t* window,
476 android_native_buffer_t* buffer)
477{
478 Surface* self = getSelf(window);
479 return self->queueBuffer(buffer);
480}
481
482// ----------------------------------------------------------------------------
483
Mathias Agopian0926f502009-05-04 14:17:04 -0700484status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
485{
486 android_native_buffer_t* out;
487 status_t err = dequeueBuffer(&out);
488 *buffer = SurfaceBuffer::getSelf(out);
489 return err;
490}
491
492status_t Surface::lockBuffer(const sp<SurfaceBuffer>& buffer)
493{
494 return lockBuffer(buffer.get());
495}
496
497status_t Surface::queueBuffer(const sp<SurfaceBuffer>& buffer)
498{
499 return queueBuffer(buffer.get());
500}
501
502// ----------------------------------------------------------------------------
503
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700504int Surface::dequeueBuffer(android_native_buffer_t** buffer)
505{
506 // FIXME: dequeueBuffer() needs proper implementation
507
508 Mutex::Autolock _l(mSurfaceLock);
509
510 per_client_cblk_t* const cblk = mClient->mControl;
511 status_t err = validate(cblk);
512 if (err != NO_ERROR)
513 return err;
514
515 SurfaceID index(mToken);
516
517 int32_t backIdx = cblk->lock_layer(size_t(index),
518 per_client_cblk_t::BLOCKING);
519
520 if (backIdx < 0)
521 return status_t(backIdx);
522
523 mBackbufferIndex = backIdx;
524 layer_cblk_t* const lcblk = &(cblk->layers[index]);
525
526 volatile const surface_info_t* const back = lcblk->surface + backIdx;
527 if (back->flags & surface_info_t::eNeedNewBuffer) {
528 getBufferLocked(backIdx);
529 }
530
531 const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
Mathias Agopian0926f502009-05-04 14:17:04 -0700532 mDirtyRegion.set(backBuffer->width, backBuffer->height);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700533 *buffer = backBuffer.get();
Mathias Agopian0926f502009-05-04 14:17:04 -0700534
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700535 return NO_ERROR;
536}
537
538int Surface::lockBuffer(android_native_buffer_t* buffer)
539{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700540 Mutex::Autolock _l(mSurfaceLock);
541
542 per_client_cblk_t* const cblk = mClient->mControl;
543 status_t err = validate(cblk);
544 if (err != NO_ERROR)
545 return err;
546
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700547 // FIXME: lockBuffer() needs proper implementation
548 return 0;
549}
550
551int Surface::queueBuffer(android_native_buffer_t* buffer)
552{
553 Mutex::Autolock _l(mSurfaceLock);
554
555 per_client_cblk_t* const cblk = mClient->mControl;
556 status_t err = validate(cblk);
557 if (err != NO_ERROR)
558 return err;
559
Mathias Agopian0926f502009-05-04 14:17:04 -0700560 if (mSwapRectangle.isValid()) {
561 mDirtyRegion.set(mSwapRectangle);
562 }
563
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700564 // transmit the dirty region
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700565 SurfaceID index(mToken);
566 layer_cblk_t* const lcblk = &(cblk->layers[index]);
Mathias Agopian0926f502009-05-04 14:17:04 -0700567 _send_dirty_region(lcblk, mDirtyRegion);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700568
569 uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
570 if (!(newstate & eNextFlipPending))
571 mClient->signalServer();
572
573 return NO_ERROR;
574}
575
576// ----------------------------------------------------------------------------
577
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800578status_t Surface::lock(SurfaceInfo* info, bool blocking) {
579 return Surface::lock(info, NULL, blocking);
580}
581
Mathias Agopian0926f502009-05-04 14:17:04 -0700582status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700583{
584 // FIXME: needs some locking here
Mathias Agopian0926f502009-05-04 14:17:04 -0700585
586 sp<SurfaceBuffer> backBuffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700587 status_t err = dequeueBuffer(&backBuffer);
588 if (err == NO_ERROR) {
589 err = lockBuffer(backBuffer);
590 if (err == NO_ERROR) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700591 // we handle copy-back here...
592
593 const Rect bounds(backBuffer->width, backBuffer->height);
Mathias Agopian0926f502009-05-04 14:17:04 -0700594 Region scratch(bounds);
595 Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700596
597 per_client_cblk_t* const cblk = mClient->mControl;
598 layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
599 volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
600 if (back->flags & surface_info_t::eBufferDirty) {
601 // content is meaningless in this case and the whole surface
602 // needs to be redrawn.
603 newDirtyRegion.set(bounds);
Mathias Agopian0926f502009-05-04 14:17:04 -0700604 } else {
605 newDirtyRegion.andSelf(bounds);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700606 if (!(lcblk->flags & eNoCopyBack)) {
Mathias Agopian0926f502009-05-04 14:17:04 -0700607 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
608 const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
609 if (!copyback.isEmpty() && frontBuffer!=0) {
610 // copy front to back
611 copyBlt(backBuffer, frontBuffer, copyback);
612 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700613 }
614 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700615 mDirtyRegion = newDirtyRegion;
616 mOldDirtyRegion = newDirtyRegion;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700617
Mathias Agopiane71212b2009-05-05 00:37:46 -0700618 void* vaddr;
Mathias Agopian0926f502009-05-04 14:17:04 -0700619 status_t res = backBuffer->lock(
620 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
Mathias Agopiane71212b2009-05-05 00:37:46 -0700621 newDirtyRegion.bounds(), &vaddr);
Mathias Agopian0926f502009-05-04 14:17:04 -0700622
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700623 LOGW_IF(res, "failed locking buffer %d (%p)",
Mathias Agopian0926f502009-05-04 14:17:04 -0700624 mBackbufferIndex, backBuffer->handle);
625
626 mLockedBuffer = backBuffer;
627 other->w = backBuffer->width;
628 other->h = backBuffer->height;
629 other->s = backBuffer->stride;
630 other->usage = backBuffer->usage;
631 other->format = backBuffer->format;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700632 other->bits = vaddr;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700633 }
634 }
635 return err;
636}
637
638status_t Surface::unlockAndPost()
639{
640 // FIXME: needs some locking here
641
642 if (mLockedBuffer == 0)
643 return BAD_VALUE;
644
Mathias Agopian0926f502009-05-04 14:17:04 -0700645 status_t res = mLockedBuffer->unlock();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700646 LOGW_IF(res, "failed unlocking buffer %d (%p)",
Mathias Agopian0926f502009-05-04 14:17:04 -0700647 mBackbufferIndex, mLockedBuffer->handle);
648
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700649 status_t err = queueBuffer(mLockedBuffer);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700650 mLockedBuffer = 0;
651 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800652}
653
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700654void Surface::_send_dirty_region(
655 layer_cblk_t* lcblk, const Region& dirty)
656{
657 const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
658 flat_region_t* flat_region = lcblk->region + index;
659 status_t err = dirty.write(flat_region, sizeof(flat_region_t));
660 if (err < NO_ERROR) {
661 // region doesn't fit, use the bounds
662 const Region reg(dirty.bounds());
663 reg.write(flat_region, sizeof(flat_region_t));
664 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665}
666
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667void Surface::setSwapRectangle(const Rect& r) {
668 mSwapRectangle = r;
669}
670
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700671status_t Surface::getBufferLocked(int index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800672{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700673 status_t err = NO_MEMORY;
674 sp<SurfaceBuffer> buffer = mSurface->getBuffer();
675 LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
676 if (buffer != 0) {
677 sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
678 if (currentBuffer != 0) {
Mathias Agopian21c59d02009-05-05 00:59:23 -0700679 getBufferMapper().unregisterBuffer(currentBuffer->handle);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700680 currentBuffer.clear();
681 }
Mathias Agopian21c59d02009-05-05 00:59:23 -0700682 err = getBufferMapper().registerBuffer(buffer->handle);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700683 LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
684 if (err == NO_ERROR) {
685 currentBuffer = buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800686 }
687 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700688 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800689}
690
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800691}; // namespace android
692