blob: 700e4f5e6f1baf6b905a1f08cb2bd1d57c55d880 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
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 "SurfaceFlinger"
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <math.h>
22#include <sys/types.h>
23
24#include <utils/Errors.h>
25#include <utils/Log.h>
26#include <utils/StopWatch.h>
27
28#include <ui/PixelFormat.h>
29#include <ui/EGLDisplaySurface.h>
30
31#include "LayerBuffer.h"
32#include "SurfaceFlinger.h"
33#include "VRamHeap.h"
34#include "DisplayHardware/DisplayHardware.h"
35
36
37namespace android {
38
39// ---------------------------------------------------------------------------
40
41const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
42const char* const LayerBuffer::typeID = "LayerBuffer";
43
44// ---------------------------------------------------------------------------
45
46LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
47 Client* client, int32_t i)
48 : LayerBaseClient(flinger, display, client, i),
The Android Open Source Project27629322009-01-09 17:51:23 -080049 mNeedsBlending(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070050{
51}
52
53LayerBuffer::~LayerBuffer()
54{
55 sp<SurfaceBuffer> s(getClientSurface());
56 if (s != 0) {
57 s->disown();
58 mClientSurface.clear();
59 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070060}
61
62sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
63{
64 Mutex::Autolock _l(mLock);
65 return mClientSurface.promote();
66}
67
68sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const
69{
70 sp<SurfaceBuffer> s;
71 Mutex::Autolock _l(mLock);
72 s = mClientSurface.promote();
73 if (s == 0) {
74 s = new SurfaceBuffer(clientIndex(),
75 const_cast<LayerBuffer *>(this));
76 mClientSurface = s;
77 }
78 return s;
79}
80
The Android Open Source Project27629322009-01-09 17:51:23 -080081bool LayerBuffer::needsBlending() const {
82 return mNeedsBlending;
83}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070084
The Android Open Source Project27629322009-01-09 17:51:23 -080085void LayerBuffer::setNeedsBlending(bool blending) {
86 mNeedsBlending = blending;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070087}
88
89void LayerBuffer::postBuffer(ssize_t offset)
90{
The Android Open Source Project27629322009-01-09 17:51:23 -080091 sp<Source> source(getSource());
92 if (source != 0)
93 source->postBuffer(offset);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070094}
95
96void LayerBuffer::unregisterBuffers()
97{
The Android Open Source Project27629322009-01-09 17:51:23 -080098 sp<Source> source(getSource());
99 if (source != 0)
100 source->unregisterBuffers();
101 // XXX: clear mSource
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700102}
103
The Android Open Source Project27629322009-01-09 17:51:23 -0800104uint32_t LayerBuffer::doTransaction(uint32_t flags)
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800105{
The Android Open Source Project27629322009-01-09 17:51:23 -0800106 sp<Source> source(getSource());
107 if (source != 0)
108 source->onTransaction(flags);
109 return LayerBase::doTransaction(flags);
110}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800111
The Android Open Source Project27629322009-01-09 17:51:23 -0800112void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
113 Region& outDirtyRegion)
114{
115 // this code-path must be as tight as possible, it's called each time
116 // the screen is composited.
117 sp<Source> source(getSource());
118 if (source != 0)
119 source->onVisibilityResolved(planeTransform);
120 LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
121}
122
123void LayerBuffer::onDraw(const Region& clip) const
124{
125 sp<Source> source(getSource());
126 if (LIKELY(source != 0)) {
127 source->onDraw(clip);
128 } else {
129 clearWithOpenGL(clip);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800130 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800131}
132
133/**
134 * This creates a "buffer" source for this surface
135 */
136status_t LayerBuffer::registerBuffers(int w, int h, int hstride, int vstride,
137 PixelFormat format, const sp<IMemoryHeap>& memoryHeap)
138{
139 Mutex::Autolock _l(mLock);
140 if (mSource != 0)
141 return INVALID_OPERATION;
142
143 sp<BufferSource> source = new BufferSource(*this, w, h,
144 hstride, vstride, format, memoryHeap);
145
146 status_t result = source->getStatus();
147 if (result == NO_ERROR) {
148 mSource = source;
149 }
150 return result;
151}
152
153/**
154 * This creates an "overlay" source for this surface
155 */
156sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
157{
158 sp<OverlayRef> result;
159 Mutex::Autolock _l(mLock);
160 if (mSource != 0)
161 return result;
162
163 sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f);
164 if (result != 0) {
165 mSource = source;
166 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800167 return result;
168}
169
The Android Open Source Project27629322009-01-09 17:51:23 -0800170sp<LayerBuffer::Source> LayerBuffer::getSource() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700171 Mutex::Autolock _l(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800172 return mSource;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700173}
174
The Android Open Source Project27629322009-01-09 17:51:23 -0800175// ============================================================================
176// LayerBuffer::SurfaceBuffer
177// ============================================================================
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700178
179LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
The Android Open Source Project27629322009-01-09 17:51:23 -0800180: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700181{
182}
183
184LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
185{
186 unregisterBuffers();
187 mOwner = 0;
188}
189
190status_t LayerBuffer::SurfaceBuffer::registerBuffers(
191 int w, int h, int hs, int vs,
192 PixelFormat format, const sp<IMemoryHeap>& heap)
193{
194 LayerBuffer* owner(getOwner());
195 if (owner)
196 return owner->registerBuffers(w, h, hs, vs, format, heap);
197 return NO_INIT;
198}
199
200void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
201{
202 LayerBuffer* owner(getOwner());
203 if (owner)
204 owner->postBuffer(offset);
205}
206
207void LayerBuffer::SurfaceBuffer::unregisterBuffers()
208{
209 LayerBuffer* owner(getOwner());
210 if (owner)
211 owner->unregisterBuffers();
212}
213
The Android Open Source Project27629322009-01-09 17:51:23 -0800214sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800215 uint32_t w, uint32_t h, int32_t format) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800216 sp<OverlayRef> result;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800217 LayerBuffer* owner(getOwner());
218 if (owner)
219 result = owner->createOverlay(w, h, format);
220 return result;
221}
222
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700223void LayerBuffer::SurfaceBuffer::disown()
224{
225 Mutex::Autolock _l(mLock);
226 mOwner = 0;
227}
228
The Android Open Source Project27629322009-01-09 17:51:23 -0800229// ============================================================================
230// LayerBuffer::Buffer
231// ============================================================================
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700232
233LayerBuffer::Buffer::Buffer(const sp<IMemoryHeap>& heap, ssize_t offset,
234 int w, int h, int hs, int vs, int f)
The Android Open Source Project27629322009-01-09 17:51:23 -0800235: mHeap(heap)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700236{
237 NativeBuffer& src(mNativeBuffer);
238 src.crop.l = 0;
239 src.crop.t = 0;
240 src.crop.r = w;
241 src.crop.b = h;
242 src.img.w = hs ?: w;
243 src.img.h = vs ?: h;
244 src.img.format = f;
245 src.img.offset = offset;
246 src.img.base = heap->base();
247 src.img.fd = heap->heapID();
248 // FIXME: make sure this buffer lies within the heap, in which case, set
249 // mHeap to null
250}
251
252LayerBuffer::Buffer::~Buffer()
253{
254}
255
The Android Open Source Project27629322009-01-09 17:51:23 -0800256// ============================================================================
257// LayerBuffer::Source
258// LayerBuffer::BufferSource
259// LayerBuffer::OverlaySource
260// ============================================================================
261
262LayerBuffer::Source::Source(LayerBuffer& layer)
263 : mLayer(layer)
264{
265}
266LayerBuffer::Source::~Source() {
267}
268void LayerBuffer::Source::onDraw(const Region& clip) const {
269}
270void LayerBuffer::Source::onTransaction(uint32_t flags) {
271}
272void LayerBuffer::Source::onVisibilityResolved(
273 const Transform& planeTransform) {
274}
275void LayerBuffer::Source::postBuffer(ssize_t offset) {
276}
277void LayerBuffer::Source::unregisterBuffers() {
278}
279
280// ---------------------------------------------------------------------------
281
282LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
283 int w, int h, int hstride, int vstride,
284 PixelFormat format, const sp<IMemoryHeap>& memoryHeap)
285 : Source(layer), mStatus(NO_ERROR), mTextureName(-1U)
286{
287 if (memoryHeap == NULL) {
288 // this is allowed, but in this case, it is illegal to receive
289 // postBuffer(). The surface just erases the framebuffer with
290 // fully transparent pixels.
291 mHeap.clear();
292 mWidth = w;
293 mHeight = h;
294 mLayer.setNeedsBlending(false);
295 return;
296 }
297
298 status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT;
299 if (err != NO_ERROR) {
300 mStatus = err;
301 return;
302 }
303
304 // TODO: validate format/parameters
305 mHeap = memoryHeap;
306 mWidth = w;
307 mHeight = h;
308 mHStride = hstride;
309 mVStride = vstride;
310 mFormat = format;
311 PixelFormatInfo info;
312 getPixelFormatInfo(format, &info);
313 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
314}
315
316LayerBuffer::BufferSource::~BufferSource()
317{
318 if (mTextureName != -1U) {
319 LayerBase::deletedTextures.add(mTextureName);
320 }
321}
322
323void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
324{
325 sp<IMemoryHeap> heap;
326 int w, h, hs, vs, f;
327 { // scope for the lock
328 Mutex::Autolock _l(mLock);
329 w = mWidth;
330 h = mHeight;
331 hs= mHStride;
332 vs= mVStride;
333 f = mFormat;
334 heap = mHeap;
335 }
336
337 sp<Buffer> buffer;
338 if (heap != 0) {
339 buffer = new LayerBuffer::Buffer(heap, offset, w, h, hs, vs, f);
340 if (buffer->getStatus() != NO_ERROR)
341 buffer.clear();
342 setBuffer(buffer);
343 mLayer.invalidate();
344 }
345}
346
347void LayerBuffer::BufferSource::unregisterBuffers()
348{
349 Mutex::Autolock _l(mLock);
350 mHeap.clear();
351 mBuffer.clear();
352 mLayer.invalidate();
353}
354
355sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
356{
357 Mutex::Autolock _l(mLock);
358 return mBuffer;
359}
360
361void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
362{
363 Mutex::Autolock _l(mLock);
364 mBuffer = buffer;
365}
366
367void LayerBuffer::BufferSource::onDraw(const Region& clip) const
368{
369 sp<Buffer> buffer(getBuffer());
370 if (UNLIKELY(buffer == 0)) {
371 // nothing to do, we don't have a buffer
372 mLayer.clearWithOpenGL(clip);
373 return;
374 }
375
376 status_t err = NO_ERROR;
377 NativeBuffer src(buffer->getBuffer());
378 const Rect& transformedBounds = mLayer.getTransformedBounds();
379 const int can_use_copybit = mLayer.canUseCopybit();
380
381 if (can_use_copybit) {
382 const int src_width = src.crop.r - src.crop.l;
383 const int src_height = src.crop.b - src.crop.t;
384 int W = transformedBounds.width();
385 int H = transformedBounds.height();
386 if (mLayer.getOrientation() & Transform::ROT_90) {
387 int t(W); W=H; H=t;
388 }
389
390 /* With LayerBuffer, it is likely that we'll have to rescale the
391 * surface, because this is often used for video playback or
392 * camera-preview. Since we want these operation as fast as possible
393 * we make sure we can use the 2D H/W even if it doesn't support
394 * the requested scale factor, in which case we perform the scaling
395 * in several passes. */
396
397 copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine();
398 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
399 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
400
401 float xscale = 1.0f;
402 if (src_width > W*min) xscale = 1.0f / min;
403 else if (src_width*mag < W) xscale = mag;
404
405 float yscale = 1.0f;
406 if (src_height > H*min) yscale = 1.0f / min;
407 else if (src_height*mag < H) yscale = mag;
408
409 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
410 if (UNLIKELY(mTemporaryDealer == 0)) {
411 // allocate a memory-dealer for this the first time
412 mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
413 ->createHeap(ISurfaceComposer::eHardware);
414 mTempBitmap.init(mTemporaryDealer);
415 }
416
417 const int tmp_w = floorf(src_width * xscale);
418 const int tmp_h = floorf(src_height * yscale);
419 err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
420
421 if (LIKELY(err == NO_ERROR)) {
422 NativeBuffer tmp;
423 mTempBitmap.getBitmapSurface(&tmp.img);
424 tmp.crop.l = 0;
425 tmp.crop.t = 0;
426 tmp.crop.r = tmp.img.w;
427 tmp.crop.b = tmp.img.h;
428
429 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
430 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
431 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
432 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
433 err = copybit->stretch(copybit,
434 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
435 src = tmp;
436 }
437 }
438
439 const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware());
440 copybit_image_t dst;
441 hw.getDisplaySurface(&dst);
442 const copybit_rect_t& drect
443 = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
444 const State& s(mLayer.drawingState());
445 region_iterator it(clip);
446 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, mLayer.getOrientation());
447 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
448 copybit->set_parameter(copybit, COPYBIT_DITHER,
449 s.flags & ISurfaceComposer::eLayerDither ?
450 COPYBIT_ENABLE : COPYBIT_DISABLE);
451 err = copybit->stretch(copybit,
452 &dst, &src.img, &drect, &src.crop, &it);
453 }
454
455 if (!can_use_copybit || err) {
456 if (UNLIKELY(mTextureName == -1LU)) {
457 mTextureName = mLayer.createTexture();
458 }
459 GLuint w = 0;
460 GLuint h = 0;
461 GGLSurface t;
462 t.version = sizeof(GGLSurface);
463 t.width = src.crop.r;
464 t.height = src.crop.b;
465 t.stride = src.img.w;
466 t.vstride= src.img.h;
467 t.format = src.img.format;
468 t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
469 const Region dirty(Rect(t.width, t.height));
470 mLayer.loadTexture(dirty, mTextureName, t, w, h);
471 mLayer.drawWithOpenGL(clip, mTextureName, t);
472 }
473}
474
475// ---------------------------------------------------------------------------
476
477LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
478 sp<OverlayRef>* overlayRef,
479 uint32_t w, uint32_t h, int32_t format)
480 : Source(layer), mVisibilityChanged(false), mOverlay(0), mOverlayHandle(0)
481{
482 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
483
484 if (overlay_dev == NULL) {
485 // overlays not supported
486 return;
487 }
488
489 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
490 if (overlay == NULL) {
491 // couldn't create the overlay (no memory? no more overlays?)
492 return;
493 }
494
495 // enable dithering...
496 overlay_dev->setParameter(overlay_dev, overlay,
497 OVERLAY_DITHER, OVERLAY_ENABLE);
498
499 mOverlay = overlay;
500 mWidth = overlay->w;
501 mHeight = overlay->h;
502 mFormat = overlay->format;
503 mWidthStride = overlay->w_stride;
504 mHeightStride = overlay->h_stride;
505
506 mOverlayHandle = overlay->getHandleRef(overlay);
507
508 // NOTE: here it's okay to acquire a reference to "this"m as long as
509 // the reference is not released before we leave the ctor.
510 sp<OverlayChanel> chanel = new OverlayChanel(this);
511
512 *overlayRef = new OverlayRef(mOverlayHandle, chanel,
513 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
514}
515
516LayerBuffer::OverlaySource::~OverlaySource()
517{
518}
519
520void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
521{
522 const Layer::State& front(mLayer.drawingState());
523 const Layer::State& temp(mLayer.currentState());
524 if (temp.sequence != front.sequence) {
525 mVisibilityChanged = true;
526 }
527}
528
529void LayerBuffer::OverlaySource::onVisibilityResolved(
530 const Transform& planeTransform)
531{
532 // this code-path must be as tight as possible, it's called each time
533 // the screen is composited.
534 if (UNLIKELY(mOverlay != 0)) {
535 if (mVisibilityChanged) {
536 mVisibilityChanged = false;
537 const Rect& bounds = mLayer.getTransformedBounds();
538 int x = bounds.left;
539 int y = bounds.top;
540 int w = bounds.width();
541 int h = bounds.height();
542
543 // we need a lock here to protect "destroy"
544 Mutex::Autolock _l(mLock);
545 if (mOverlay) {
546 overlay_control_device_t* overlay_dev =
547 mLayer.mFlinger->getOverlayEngine();
548 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
549 overlay_dev->setParameter(overlay_dev, mOverlay,
550 OVERLAY_TRANSFORM, mLayer.getOrientation());
551 }
552 }
553 }
554}
555
556void LayerBuffer::OverlaySource::serverDestroy()
557{
558 // we need a lock here to protect "onVisibilityResolved"
559 Mutex::Autolock _l(mLock);
560 if (mOverlay) {
561 overlay_control_device_t* overlay_dev =
562 mLayer.mFlinger->getOverlayEngine();
563 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
564 mOverlay = 0;
565 }
566}
567
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700568// ---------------------------------------------------------------------------
569}; // namespace android