blob: 1ceece019527ae77e33e535ee3451e68ca632544 [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
179Surface::Surface(Surface const* rhs)
180 : mOwner(false)
181{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700182 // FIXME: we really should get rid of this ctor. the memcpy below
183 //should be safe for now, but android_native_window_t is not supposed
184 // to be clonable.
185 memcpy( static_cast<android_native_window_t*>(this),
186 static_cast<android_native_window_t const *>(rhs),
187 sizeof(android_native_window_t));
188
189 mToken = rhs->mToken;
190 mIdentity = rhs->mIdentity;
191 mClient = rhs->mClient;
192 mSurface = rhs->mSurface;
193 mBuffers[0] = rhs->mBuffers[0];
194 mBuffers[1] = rhs->mBuffers[1];
195 mFormat = rhs->mFormat;
196 mFlags = rhs->mFlags;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800197 mSwapRectangle.makeInvalid();
198}
199
200Surface::~Surface()
201{
202 if (mOwner && mToken>=0 && mClient!=0) {
203 mClient->destroySurface(mToken);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700204 if (mBuffers[0] != 0) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700205 BufferMapper::get().unmap(mBuffers[0]->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700206 }
207 if (mBuffers[1] != 0) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700208 BufferMapper::get().unmap(mBuffers[1]->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700209 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210 }
211 mClient.clear();
212 mSurface.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800213 IPCThreadState::self()->flushCommands();
214}
215
216sp<Surface> Surface::dup() const
217{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700218 // FIXME: we should get rid of Surface::dup()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800219 Surface const * r = this;
220 if (this && mOwner) {
221 // the only reason we need to do this is because of Java's garbage
222 // collector: because we're creating a copy of the Surface
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700223 // instead of a reference, we can guarantee that when our last
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224 // reference goes away, the real surface will be deleted.
225 // Without this hack (the code is correct too), we'd have to
226 // wait for a GC for the surface to go away.
227 r = new Surface(this);
228 }
229 return const_cast<Surface*>(r);
230}
231
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700232status_t Surface::validate(per_client_cblk_t const* cblk) const
233{
234 if (cblk == 0) {
235 LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
236 return NO_INIT;
237 }
238 status_t err = cblk->validate(mToken);
239 if (err != NO_ERROR) {
240 LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
241 mToken, mIdentity, err, strerror(-err));
242 return err;
243 }
244 if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
245 LOGE("using an invalid surface id=%d, identity=%u should be %d",
246 mToken, mIdentity, cblk->layers[mToken].identity);
247 return NO_INIT;
248 }
249 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800250}
251
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700252// ----------------------------------------------------------------------------
253
254int Surface::setSwapRectangle(android_native_window_t* window,
255 int l, int t, int w, int h)
256{
257 Surface* self = getSelf(window);
258 self->setSwapRectangle(Rect(l, t, l+w, t+h));
259 return 0;
260}
261
262void Surface::connect(android_native_window_t* window)
263{
264}
265
266void Surface::disconnect(android_native_window_t* window)
267{
268}
269
270int Surface::setSwapInterval(android_native_window_t* window, int interval)
271{
272 return 0;
273}
274
275int Surface::dequeueBuffer(android_native_window_t* window,
276 android_native_buffer_t** buffer)
277{
278 Surface* self = getSelf(window);
279 return self->dequeueBuffer(buffer);
280}
281
282int Surface::lockBuffer(android_native_window_t* window,
283 android_native_buffer_t* buffer)
284{
285 Surface* self = getSelf(window);
286 return self->lockBuffer(buffer);
287}
288
289int Surface::queueBuffer(android_native_window_t* window,
290 android_native_buffer_t* buffer)
291{
292 Surface* self = getSelf(window);
293 return self->queueBuffer(buffer);
294}
295
296// ----------------------------------------------------------------------------
297
298int Surface::dequeueBuffer(android_native_buffer_t** buffer)
299{
300 // FIXME: dequeueBuffer() needs proper implementation
301
302 Mutex::Autolock _l(mSurfaceLock);
303
304 per_client_cblk_t* const cblk = mClient->mControl;
305 status_t err = validate(cblk);
306 if (err != NO_ERROR)
307 return err;
308
309 SurfaceID index(mToken);
310
311 int32_t backIdx = cblk->lock_layer(size_t(index),
312 per_client_cblk_t::BLOCKING);
313
314 if (backIdx < 0)
315 return status_t(backIdx);
316
317 mBackbufferIndex = backIdx;
318 layer_cblk_t* const lcblk = &(cblk->layers[index]);
319
320 volatile const surface_info_t* const back = lcblk->surface + backIdx;
321 if (back->flags & surface_info_t::eNeedNewBuffer) {
322 getBufferLocked(backIdx);
323 }
324
325 const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
326 *buffer = backBuffer.get();
327
328 return NO_ERROR;
329}
330
331int Surface::lockBuffer(android_native_buffer_t* buffer)
332{
333 // FIXME: lockBuffer() needs proper implementation
334 return 0;
335}
336
337int Surface::queueBuffer(android_native_buffer_t* buffer)
338{
339 Mutex::Autolock _l(mSurfaceLock);
340
341 per_client_cblk_t* const cblk = mClient->mControl;
342 status_t err = validate(cblk);
343 if (err != NO_ERROR)
344 return err;
345
346 // transmit the dirty region
347 const Region dirty(swapRectangle());
348 SurfaceID index(mToken);
349 layer_cblk_t* const lcblk = &(cblk->layers[index]);
350 _send_dirty_region(lcblk, dirty);
351
352 uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
353 if (!(newstate & eNextFlipPending))
354 mClient->signalServer();
355
356 return NO_ERROR;
357}
358
359// ----------------------------------------------------------------------------
360
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800361status_t Surface::lock(SurfaceInfo* info, bool blocking) {
362 return Surface::lock(info, NULL, blocking);
363}
364
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700365status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
366{
367 // FIXME: needs some locking here
368 android_native_buffer_t* backBuffer;
369 status_t err = dequeueBuffer(&backBuffer);
370 if (err == NO_ERROR) {
371 err = lockBuffer(backBuffer);
372 if (err == NO_ERROR) {
373 backBuffer->common.incRef(&backBuffer->common);
374 mLockedBuffer = backBuffer;
375 other->w = backBuffer->width;
376 other->h = backBuffer->height;
377 other->s = backBuffer->stride;
378 other->usage = backBuffer->usage;
379 other->format = backBuffer->format;
380 other->bits = backBuffer->bits;
381
382 // we handle copy-back here...
383
384 const Rect bounds(backBuffer->width, backBuffer->height);
385 Region newDirtyRegion;
386
387 per_client_cblk_t* const cblk = mClient->mControl;
388 layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
389 volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
390 if (back->flags & surface_info_t::eBufferDirty) {
391 // content is meaningless in this case and the whole surface
392 // needs to be redrawn.
393 newDirtyRegion.set(bounds);
394 if (dirty) {
395 *dirty = newDirtyRegion;
396 }
397 } else
398 {
399 if (dirty) {
400 dirty->andSelf(Region(bounds));
401 newDirtyRegion = *dirty;
402 } else {
403 newDirtyRegion.set(bounds);
404 }
405 Region copyback;
406 if (!(lcblk->flags & eNoCopyBack)) {
407 const Region previousDirtyRegion(dirtyRegion());
408 copyback = previousDirtyRegion.subtract(newDirtyRegion);
409 }
410 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
411 if (!copyback.isEmpty() && frontBuffer!=0) {
412 // copy front to back
413 copyBlt(backBuffer, frontBuffer.get(), copyback);
414 }
415 }
416 setDirtyRegion(newDirtyRegion);
417
418
419 Rect lockBounds(backBuffer->width, backBuffer->height);
420 if (dirty) {
421 lockBounds = dirty->bounds();
422 }
423 buffer_handle_t handle;
424 backBuffer->getHandle(backBuffer, &handle);
425 status_t res = BufferMapper::get().lock(handle,
426 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
427 lockBounds);
428 LOGW_IF(res, "failed locking buffer %d (%p)",
429 mBackbufferIndex, handle);
430 setSwapRectangle(lockBounds);
431 }
432 }
433 return err;
434}
435
436status_t Surface::unlockAndPost()
437{
438 // FIXME: needs some locking here
439
440 if (mLockedBuffer == 0)
441 return BAD_VALUE;
442
443 buffer_handle_t handle;
444 mLockedBuffer->getHandle(mLockedBuffer, &handle);
445 status_t res = BufferMapper::get().unlock(handle);
446 LOGW_IF(res, "failed unlocking buffer %d (%p)",
447 mBackbufferIndex, handle);
448
449 const Rect dirty(dirtyRegion().bounds());
450 setSwapRectangle(dirty);
451 status_t err = queueBuffer(mLockedBuffer);
452 mLockedBuffer->common.decRef(&mLockedBuffer->common);
453 mLockedBuffer = 0;
454 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800455}
456
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700457void Surface::_send_dirty_region(
458 layer_cblk_t* lcblk, const Region& dirty)
459{
460 const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
461 flat_region_t* flat_region = lcblk->region + index;
462 status_t err = dirty.write(flat_region, sizeof(flat_region_t));
463 if (err < NO_ERROR) {
464 // region doesn't fit, use the bounds
465 const Region reg(dirty.bounds());
466 reg.write(flat_region, sizeof(flat_region_t));
467 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800468}
469
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800470
471status_t Surface::setLayer(int32_t layer) {
472 return mClient->setLayer(this, layer);
473}
474status_t Surface::setPosition(int32_t x, int32_t y) {
475 return mClient->setPosition(this, x, y);
476}
477status_t Surface::setSize(uint32_t w, uint32_t h) {
478 return mClient->setSize(this, w, h);
479}
480status_t Surface::hide() {
481 return mClient->hide(this);
482}
483status_t Surface::show(int32_t layer) {
484 return mClient->show(this, layer);
485}
486status_t Surface::freeze() {
487 return mClient->freeze(this);
488}
489status_t Surface::unfreeze() {
490 return mClient->unfreeze(this);
491}
492status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
493 return mClient->setFlags(this, flags, mask);
494}
495status_t Surface::setTransparentRegionHint(const Region& transparent) {
496 return mClient->setTransparentRegionHint(this, transparent);
497}
498status_t Surface::setAlpha(float alpha) {
499 return mClient->setAlpha(this, alpha);
500}
501status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
502 return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy);
503}
504status_t Surface::setFreezeTint(uint32_t tint) {
505 return mClient->setFreezeTint(this, tint);
506}
507
508Region Surface::dirtyRegion() const {
509 return mDirtyRegion;
510}
511void Surface::setDirtyRegion(const Region& region) const {
512 mDirtyRegion = region;
513}
514const Rect& Surface::swapRectangle() const {
515 return mSwapRectangle;
516}
517void Surface::setSwapRectangle(const Rect& r) {
518 mSwapRectangle = r;
519}
520
521sp<Surface> Surface::readFromParcel(Parcel* parcel)
522{
523 sp<SurfaceComposerClient> client;
524 ISurfaceFlingerClient::surface_data_t data;
525 sp<IBinder> clientBinder= parcel->readStrongBinder();
526 sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800527 data.token = parcel->readInt32();
528 data.identity = parcel->readInt32();
529 PixelFormat format = parcel->readInt32();
530 uint32_t flags = parcel->readInt32();
531
532 if (clientBinder != NULL)
533 client = SurfaceComposerClient::clientForConnection(clientBinder);
534
535 return new Surface(client, surface, data, 0, 0, format, flags, false);
536}
537
538status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel)
539{
540 uint32_t flags=0;
541 uint32_t format=0;
542 SurfaceID token = -1;
543 uint32_t identity = 0;
544 sp<SurfaceComposerClient> client;
545 sp<ISurface> sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800546 if (surface->isValid()) {
547 token = surface->mToken;
548 identity = surface->mIdentity;
549 client = surface->mClient;
550 sur = surface->mSurface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800551 format = surface->mFormat;
552 flags = surface->mFlags;
553 }
554 parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
555 parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800556 parcel->writeInt32(token);
557 parcel->writeInt32(identity);
558 parcel->writeInt32(format);
559 parcel->writeInt32(flags);
560 return NO_ERROR;
561}
562
563bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs)
564{
565 if (lhs == 0 || rhs == 0)
566 return false;
567 return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
568}
569
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700570status_t Surface::getBufferLocked(int index)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800571{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700572 status_t err = NO_MEMORY;
573 sp<SurfaceBuffer> buffer = mSurface->getBuffer();
574 LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
575 if (buffer != 0) {
576 sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
577 if (currentBuffer != 0) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700578 BufferMapper::get().unmap(currentBuffer->getHandle(), this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700579 currentBuffer.clear();
580 }
Mathias Agopian4243e662009-04-15 18:34:24 -0700581 err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700582 LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
583 if (err == NO_ERROR) {
584 currentBuffer = buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800585 }
586 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700587 return err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800588}
589
590}; // namespace android
591