blob: 51abd95faa051079f7fb4ad7d321436db5513bb8 [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
146// ============================================================================
147// Surface
148// ============================================================================
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800149
150Surface::Surface(const sp<SurfaceComposerClient>& client,
151 const sp<ISurface>& surface,
152 const ISurfaceFlingerClient::surface_data_t& data,
153 uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
154 bool owner)
155 : mClient(client), mSurface(surface),
156 mToken(data.token), mIdentity(data.identity),
157 mFormat(format), mFlags(flags), mOwner(owner)
158{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700159 android_native_window_t::connect = connect;
160 android_native_window_t::disconnect = disconnect;
161 android_native_window_t::setSwapInterval = setSwapInterval;
162 android_native_window_t::setSwapRectangle = setSwapRectangle;
163 android_native_window_t::dequeueBuffer = dequeueBuffer;
164 android_native_window_t::lockBuffer = lockBuffer;
165 android_native_window_t::queueBuffer = queueBuffer;
166
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800167 mSwapRectangle.makeInvalid();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700168
169 DisplayInfo dinfo;
170 SurfaceComposerClient::getDisplayInfo(0, &dinfo);
171 const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
172 const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
173 // FIXME: set real values here
174 const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
175 const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
176 const_cast<uint32_t&>(android_native_window_t::flags) = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800177}
178
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800179Surface::~Surface()
180{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700181 // this is a client-side operation, the surface is destroyed, unmap
182 // its buffers in this process.
183 for (int i=0 ; i<2 ; i++) {
184 if (mBuffers[i] != 0) {
185 BufferMapper::get().unmap(mBuffers[i]->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700186 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800187 }
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700188
189 destroy();
190}
191
192void Surface::destroy()
193{
194 // Destroy the surface in SurfaceFlinger if we were the owner
195 // (in any case, a client won't be able to, because it won't have the
196 // right permission).
197 if (mOwner && mToken>=0 && mClient!=0) {
198 mClient->destroySurface(mToken);
199 }
200
201 // clear all references and trigger an IPC now, to make sure things
202 // happen without delay, since these resources are quite heavy.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203 mClient.clear();
204 mSurface.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800205 IPCThreadState::self()->flushCommands();
206}
207
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700208void Surface::clear()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700210 // here, the window manager tells us explicitly that we should destroy
211 // the surface's resource. Soon after this call, it will also release
212 // its last reference (which will call the dtor); however, it is possible
213 // that a client living in the same process still holds references which
214 // would delay the call to the dtor -- that is why we need this explicit
215 // "clear()" call.
216
217 // FIXME: we should probably unmap the buffers here. The problem is that
218 // the app could be in the middle of using them, and if we don't unmap now
219 // and we're in the system process, the mapping will be lost (because
220 // the buffer will be freed, and the handles destroyed)
221
222 Mutex::Autolock _l(mSurfaceLock);
223 destroy();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224}
225
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700226status_t Surface::validate(per_client_cblk_t const* cblk) const
227{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700228 if (mToken<0 || mClient==0) {
229 LOGE("invalid token (%d, identity=%u) or client (%p)",
230 mToken, mIdentity, mClient.get());
231 return NO_INIT;
232 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700233 if (cblk == 0) {
234 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
235 return NO_INIT;
236 }
237 status_t err = cblk->validate(mToken);
238 if (err != NO_ERROR) {
239 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
240 mToken, mIdentity, err, strerror(-err));
241 return err;
242 }
243 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
244 LOGE("using an invalid surface id=%d, identity=%u should be %d",
245 mToken, mIdentity, cblk->layers[mToken].identity);
246 return NO_INIT;
247 }
248 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800249}
250
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700251// ----------------------------------------------------------------------------
252
253int Surface::setSwapRectangle(android_native_window_t* window,
254 int l, int t, int w, int h)
255{
256 Surface* self = getSelf(window);
257 self->setSwapRectangle(Rect(l, t, l+w, t+h));
258 return 0;
259}
260
261void Surface::connect(android_native_window_t* window)
262{
263}
264
265void Surface::disconnect(android_native_window_t* window)
266{
267}
268
269int Surface::setSwapInterval(android_native_window_t* window, int interval)
270{
271 return 0;
272}
273
274int Surface::dequeueBuffer(android_native_window_t* window,
275 android_native_buffer_t** buffer)
276{
277 Surface* self = getSelf(window);
278 return self->dequeueBuffer(buffer);
279}
280
281int Surface::lockBuffer(android_native_window_t* window,
282 android_native_buffer_t* buffer)
283{
284 Surface* self = getSelf(window);
285 return self->lockBuffer(buffer);
286}
287
288int Surface::queueBuffer(android_native_window_t* window,
289 android_native_buffer_t* buffer)
290{
291 Surface* self = getSelf(window);
292 return self->queueBuffer(buffer);
293}
294
295// ----------------------------------------------------------------------------
296
297int Surface::dequeueBuffer(android_native_buffer_t** buffer)
298{
299 // FIXME: dequeueBuffer() needs proper implementation
300
301 Mutex::Autolock _l(mSurfaceLock);
302
303 per_client_cblk_t* const cblk = mClient->mControl;
304 status_t err = validate(cblk);
305 if (err != NO_ERROR)
306 return err;
307
308 SurfaceID index(mToken);
309
310 int32_t backIdx = cblk->lock_layer(size_t(index),
311 per_client_cblk_t::BLOCKING);
312
313 if (backIdx < 0)
314 return status_t(backIdx);
315
316 mBackbufferIndex = backIdx;
317 layer_cblk_t* const lcblk = &(cblk->layers[index]);
318
319 volatile const surface_info_t* const back = lcblk->surface + backIdx;
320 if (back->flags & surface_info_t::eNeedNewBuffer) {
321 getBufferLocked(backIdx);
322 }
323
324 const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
325 *buffer = backBuffer.get();
326
327 return NO_ERROR;
328}
329
330int Surface::lockBuffer(android_native_buffer_t* buffer)
331{
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700332 Mutex::Autolock _l(mSurfaceLock);
333
334 per_client_cblk_t* const cblk = mClient->mControl;
335 status_t err = validate(cblk);
336 if (err != NO_ERROR)
337 return err;
338
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700339 // FIXME: lockBuffer() needs proper implementation
340 return 0;
341}
342
343int Surface::queueBuffer(android_native_buffer_t* buffer)
344{
345 Mutex::Autolock _l(mSurfaceLock);
346
347 per_client_cblk_t* const cblk = mClient->mControl;
348 status_t err = validate(cblk);
349 if (err != NO_ERROR)
350 return err;
351
352 // transmit the dirty region
353 const Region dirty(swapRectangle());
354 SurfaceID index(mToken);
355 layer_cblk_t* const lcblk = &(cblk->layers[index]);
356 _send_dirty_region(lcblk, dirty);
357
358 uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
359 if (!(newstate & eNextFlipPending))
360 mClient->signalServer();
361
362 return NO_ERROR;
363}
364
365// ----------------------------------------------------------------------------
366
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800367status_t Surface::lock(SurfaceInfo* info, bool blocking) {
368 return Surface::lock(info, NULL, blocking);
369}
370
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700371status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
372{
373 // FIXME: needs some locking here
374 android_native_buffer_t* backBuffer;
375 status_t err = dequeueBuffer(&backBuffer);
376 if (err == NO_ERROR) {
377 err = lockBuffer(backBuffer);
378 if (err == NO_ERROR) {
379 backBuffer->common.incRef(&backBuffer->common);
380 mLockedBuffer = backBuffer;
381 other->w = backBuffer->width;
382 other->h = backBuffer->height;
383 other->s = backBuffer->stride;
384 other->usage = backBuffer->usage;
385 other->format = backBuffer->format;
386 other->bits = backBuffer->bits;
387
388 // we handle copy-back here...
389
390 const Rect bounds(backBuffer->width, backBuffer->height);
391 Region newDirtyRegion;
392
393 per_client_cblk_t* const cblk = mClient->mControl;
394 layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
395 volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
396 if (back->flags & surface_info_t::eBufferDirty) {
397 // content is meaningless in this case and the whole surface
398 // needs to be redrawn.
399 newDirtyRegion.set(bounds);
400 if (dirty) {
401 *dirty = newDirtyRegion;
402 }
403 } else
404 {
405 if (dirty) {
406 dirty->andSelf(Region(bounds));
407 newDirtyRegion = *dirty;
408 } else {
409 newDirtyRegion.set(bounds);
410 }
411 Region copyback;
412 if (!(lcblk->flags & eNoCopyBack)) {
413 const Region previousDirtyRegion(dirtyRegion());
414 copyback = previousDirtyRegion.subtract(newDirtyRegion);
415 }
416 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
417 if (!copyback.isEmpty() && frontBuffer!=0) {
418 // copy front to back
419 copyBlt(backBuffer, frontBuffer.get(), copyback);
420 }
421 }
422 setDirtyRegion(newDirtyRegion);
423
424
425 Rect lockBounds(backBuffer->width, backBuffer->height);
426 if (dirty) {
427 lockBounds = dirty->bounds();
428 }
429 buffer_handle_t handle;
430 backBuffer->getHandle(backBuffer, &handle);
431 status_t res = BufferMapper::get().lock(handle,
432 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
433 lockBounds);
434 LOGW_IF(res, "failed locking buffer %d (%p)",
435 mBackbufferIndex, handle);
436 setSwapRectangle(lockBounds);
437 }
438 }
439 return err;
440}
441
442status_t Surface::unlockAndPost()
443{
444 // FIXME: needs some locking here
445
446 if (mLockedBuffer == 0)
447 return BAD_VALUE;
448
449 buffer_handle_t handle;
450 mLockedBuffer->getHandle(mLockedBuffer, &handle);
451 status_t res = BufferMapper::get().unlock(handle);
452 LOGW_IF(res, "failed unlocking buffer %d (%p)",
453 mBackbufferIndex, handle);
454
455 const Rect dirty(dirtyRegion().bounds());
456 setSwapRectangle(dirty);
457 status_t err = queueBuffer(mLockedBuffer);
458 mLockedBuffer->common.decRef(&mLockedBuffer->common);
459 mLockedBuffer = 0;
460 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461}
462
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700463void Surface::_send_dirty_region(
464 layer_cblk_t* lcblk, const Region& dirty)
465{
466 const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
467 flat_region_t* flat_region = lcblk->region + index;
468 status_t err = dirty.write(flat_region, sizeof(flat_region_t));
469 if (err < NO_ERROR) {
470 // region doesn't fit, use the bounds
471 const Region reg(dirty.bounds());
472 reg.write(flat_region, sizeof(flat_region_t));
473 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800474}
475
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800476
477status_t Surface::setLayer(int32_t layer) {
478 return mClient->setLayer(this, layer);
479}
480status_t Surface::setPosition(int32_t x, int32_t y) {
481 return mClient->setPosition(this, x, y);
482}
483status_t Surface::setSize(uint32_t w, uint32_t h) {
484 return mClient->setSize(this, w, h);
485}
486status_t Surface::hide() {
487 return mClient->hide(this);
488}
489status_t Surface::show(int32_t layer) {
490 return mClient->show(this, layer);
491}
492status_t Surface::freeze() {
493 return mClient->freeze(this);
494}
495status_t Surface::unfreeze() {
496 return mClient->unfreeze(this);
497}
498status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
499 return mClient->setFlags(this, flags, mask);
500}
501status_t Surface::setTransparentRegionHint(const Region& transparent) {
502 return mClient->setTransparentRegionHint(this, transparent);
503}
504status_t Surface::setAlpha(float alpha) {
505 return mClient->setAlpha(this, alpha);
506}
507status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
508 return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy);
509}
510status_t Surface::setFreezeTint(uint32_t tint) {
511 return mClient->setFreezeTint(this, tint);
512}
513
514Region Surface::dirtyRegion() const {
515 return mDirtyRegion;
516}
517void Surface::setDirtyRegion(const Region& region) const {
518 mDirtyRegion = region;
519}
520const Rect& Surface::swapRectangle() const {
521 return mSwapRectangle;
522}
523void Surface::setSwapRectangle(const Rect& r) {
524 mSwapRectangle = r;
525}
526
527sp<Surface> Surface::readFromParcel(Parcel* parcel)
528{
529 sp<SurfaceComposerClient> client;
530 ISurfaceFlingerClient::surface_data_t data;
531 sp<IBinder> clientBinder= parcel->readStrongBinder();
532 sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800533 data.token = parcel->readInt32();
534 data.identity = parcel->readInt32();
535 PixelFormat format = parcel->readInt32();
536 uint32_t flags = parcel->readInt32();
537
538 if (clientBinder != NULL)
539 client = SurfaceComposerClient::clientForConnection(clientBinder);
540
541 return new Surface(client, surface, data, 0, 0, format, flags, false);
542}
543
544status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel)
545{
546 uint32_t flags=0;
547 uint32_t format=0;
548 SurfaceID token = -1;
549 uint32_t identity = 0;
550 sp<SurfaceComposerClient> client;
551 sp<ISurface> sur;
Mathias Agopian40b7f6e2009-04-14 18:21:47 -0700552 if (Surface::isValid(surface)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800553 token = surface->mToken;
554 identity = surface->mIdentity;
555 client = surface->mClient;
556 sur = surface->mSurface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800557 format = surface->mFormat;
558 flags = surface->mFlags;
559 }
560 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
561 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800562 parcel->writeInt32(token);
563 parcel->writeInt32(identity);
564 parcel->writeInt32(format);
565 parcel->writeInt32(flags);
566 return NO_ERROR;
567}
568
569bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs)
570{
571 if (lhs == 0 || rhs == 0)
572 return false;
573 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
574}
575
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700576status_t Surface::getBufferLocked(int index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800577{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700578 status_t err = NO_MEMORY;
579 sp<SurfaceBuffer> buffer = mSurface->getBuffer();
580 LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
581 if (buffer != 0) {
582 sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
583 if (currentBuffer != 0) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700584 BufferMapper::get().unmap(currentBuffer->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700585 currentBuffer.clear();
586 }
Mathias Agopian4243e662009-04-15 18:34:24 -0700587 err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700588 LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
589 if (err == NO_ERROR) {
590 currentBuffer = buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800591 }
592 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700593 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800594}
595
596}; // namespace android
597