blob: fc0a603f7f507df1da4c80a474a194b8818dc3dd [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
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -080028#include <utils/IPCThreadState.h>
29#include <utils/IServiceManager.h>
30
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070031#include <ui/PixelFormat.h>
32#include <ui/EGLDisplaySurface.h>
33
34#include "LayerBuffer.h"
35#include "SurfaceFlinger.h"
36#include "VRamHeap.h"
37#include "DisplayHardware/DisplayHardware.h"
38
39
40namespace android {
41
42// ---------------------------------------------------------------------------
43
44const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
45const char* const LayerBuffer::typeID = "LayerBuffer";
46
47// ---------------------------------------------------------------------------
48
49LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
50 Client* client, int32_t i)
51 : LayerBaseClient(flinger, display, client, i),
The Android Open Source Project27629322009-01-09 17:51:23 -080052 mNeedsBlending(false)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070053{
54}
55
56LayerBuffer::~LayerBuffer()
57{
58 sp<SurfaceBuffer> s(getClientSurface());
59 if (s != 0) {
60 s->disown();
61 mClientSurface.clear();
62 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070063}
64
65sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
66{
67 Mutex::Autolock _l(mLock);
68 return mClientSurface.promote();
69}
70
71sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const
72{
73 sp<SurfaceBuffer> s;
74 Mutex::Autolock _l(mLock);
75 s = mClientSurface.promote();
76 if (s == 0) {
77 s = new SurfaceBuffer(clientIndex(),
78 const_cast<LayerBuffer *>(this));
79 mClientSurface = s;
80 }
81 return s;
82}
83
The Android Open Source Project27629322009-01-09 17:51:23 -080084bool LayerBuffer::needsBlending() const {
85 return mNeedsBlending;
86}
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070087
The Android Open Source Project27629322009-01-09 17:51:23 -080088void LayerBuffer::setNeedsBlending(bool blending) {
89 mNeedsBlending = blending;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070090}
91
92void LayerBuffer::postBuffer(ssize_t offset)
93{
The Android Open Source Project27629322009-01-09 17:51:23 -080094 sp<Source> source(getSource());
95 if (source != 0)
96 source->postBuffer(offset);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070097}
98
99void LayerBuffer::unregisterBuffers()
100{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800101 sp<Source> source(clearSource());
The Android Open Source Project27629322009-01-09 17:51:23 -0800102 if (source != 0)
103 source->unregisterBuffers();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700104}
105
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800106Transform LayerBuffer::getDrawingStateTransform() const
107{
108 Transform tr(LayerBaseClient::getDrawingStateTransform());
109 sp<Source> source(getSource());
110 if (source != 0)
111 source->updateTransform(&tr);
112 return tr;
113}
114
The Android Open Source Project27629322009-01-09 17:51:23 -0800115uint32_t LayerBuffer::doTransaction(uint32_t flags)
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800116{
The Android Open Source Project27629322009-01-09 17:51:23 -0800117 sp<Source> source(getSource());
118 if (source != 0)
119 source->onTransaction(flags);
120 return LayerBase::doTransaction(flags);
121}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800122
The Android Open Source Project27629322009-01-09 17:51:23 -0800123void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
124 Region& outDirtyRegion)
125{
126 // this code-path must be as tight as possible, it's called each time
127 // the screen is composited.
128 sp<Source> source(getSource());
129 if (source != 0)
130 source->onVisibilityResolved(planeTransform);
131 LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
132}
133
134void LayerBuffer::onDraw(const Region& clip) const
135{
136 sp<Source> source(getSource());
137 if (LIKELY(source != 0)) {
138 source->onDraw(clip);
139 } else {
140 clearWithOpenGL(clip);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800141 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800142}
143
144/**
145 * This creates a "buffer" source for this surface
146 */
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800147status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
The Android Open Source Project27629322009-01-09 17:51:23 -0800148{
149 Mutex::Autolock _l(mLock);
150 if (mSource != 0)
151 return INVALID_OPERATION;
152
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800153 sp<BufferSource> source = new BufferSource(*this, buffers);
The Android Open Source Project27629322009-01-09 17:51:23 -0800154
155 status_t result = source->getStatus();
156 if (result == NO_ERROR) {
157 mSource = source;
158 }
159 return result;
160}
161
162/**
163 * This creates an "overlay" source for this surface
164 */
165sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
166{
167 sp<OverlayRef> result;
168 Mutex::Autolock _l(mLock);
169 if (mSource != 0)
170 return result;
171
172 sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f);
173 if (result != 0) {
174 mSource = source;
175 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800176 return result;
177}
178
The Android Open Source Project27629322009-01-09 17:51:23 -0800179sp<LayerBuffer::Source> LayerBuffer::getSource() const {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700180 Mutex::Autolock _l(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800181 return mSource;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700182}
183
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800184sp<LayerBuffer::Source> LayerBuffer::clearSource() {
185 sp<Source> source;
186 Mutex::Autolock _l(mLock);
187 source = mSource;
188 mSource.clear();
189 return source;
190}
191
The Android Open Source Project27629322009-01-09 17:51:23 -0800192// ============================================================================
193// LayerBuffer::SurfaceBuffer
194// ============================================================================
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700195
196LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
The Android Open Source Project27629322009-01-09 17:51:23 -0800197: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700198{
199}
200
201LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
202{
203 unregisterBuffers();
204 mOwner = 0;
205}
206
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800207status_t LayerBuffer::SurfaceBuffer::onTransact(
208 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
209{
210 switch (code) {
211 case REGISTER_BUFFERS:
212 case UNREGISTER_BUFFERS:
213 case CREATE_OVERLAY:
214 {
215 // codes that require permission check
216 IPCThreadState* ipc = IPCThreadState::self();
217 const int pid = ipc->getCallingPid();
218 const int self_pid = getpid();
219 if (LIKELY(pid != self_pid)) {
220 // we're called from a different process, do the real check
221 if (!checkCallingPermission(
222 String16("android.permission.ACCESS_SURFACE_FLINGER")))
223 {
224 const int uid = ipc->getCallingUid();
225 LOGE("Permission Denial: "
226 "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
227 return PERMISSION_DENIED;
228 }
229 }
230 }
231 }
232 return LayerBaseClient::Surface::onTransact(code, data, reply, flags);
233}
234
235status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700236{
237 LayerBuffer* owner(getOwner());
238 if (owner)
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800239 return owner->registerBuffers(buffers);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700240 return NO_INIT;
241}
242
243void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
244{
245 LayerBuffer* owner(getOwner());
246 if (owner)
247 owner->postBuffer(offset);
248}
249
250void LayerBuffer::SurfaceBuffer::unregisterBuffers()
251{
252 LayerBuffer* owner(getOwner());
253 if (owner)
254 owner->unregisterBuffers();
255}
256
The Android Open Source Project27629322009-01-09 17:51:23 -0800257sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800258 uint32_t w, uint32_t h, int32_t format) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800259 sp<OverlayRef> result;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800260 LayerBuffer* owner(getOwner());
261 if (owner)
262 result = owner->createOverlay(w, h, format);
263 return result;
264}
265
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700266void LayerBuffer::SurfaceBuffer::disown()
267{
268 Mutex::Autolock _l(mLock);
269 mOwner = 0;
270}
271
The Android Open Source Project27629322009-01-09 17:51:23 -0800272// ============================================================================
273// LayerBuffer::Buffer
274// ============================================================================
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700275
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800276LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
277 : mBufferHeap(buffers)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700278{
279 NativeBuffer& src(mNativeBuffer);
280 src.crop.l = 0;
281 src.crop.t = 0;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800282 src.crop.r = buffers.w;
283 src.crop.b = buffers.h;
284 src.img.w = buffers.hor_stride ?: buffers.w;
285 src.img.h = buffers.ver_stride ?: buffers.h;
286 src.img.format = buffers.format;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700287 src.img.offset = offset;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800288 src.img.base = buffers.heap->base();
289 src.img.fd = buffers.heap->heapID();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700290}
291
292LayerBuffer::Buffer::~Buffer()
293{
294}
295
The Android Open Source Project27629322009-01-09 17:51:23 -0800296// ============================================================================
297// LayerBuffer::Source
298// LayerBuffer::BufferSource
299// LayerBuffer::OverlaySource
300// ============================================================================
301
302LayerBuffer::Source::Source(LayerBuffer& layer)
303 : mLayer(layer)
304{
305}
306LayerBuffer::Source::~Source() {
307}
308void LayerBuffer::Source::onDraw(const Region& clip) const {
309}
310void LayerBuffer::Source::onTransaction(uint32_t flags) {
311}
312void LayerBuffer::Source::onVisibilityResolved(
313 const Transform& planeTransform) {
314}
315void LayerBuffer::Source::postBuffer(ssize_t offset) {
316}
317void LayerBuffer::Source::unregisterBuffers() {
318}
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800319void LayerBuffer::Source::updateTransform(Transform* tr) const {
320}
The Android Open Source Project27629322009-01-09 17:51:23 -0800321
322// ---------------------------------------------------------------------------
323
324LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800325 const ISurface::BufferHeap& buffers)
326 : Source(layer), mStatus(NO_ERROR),
327 mBufferSize(0), mTextureName(-1U)
The Android Open Source Project27629322009-01-09 17:51:23 -0800328{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800329 if (buffers.heap == NULL) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800330 // this is allowed, but in this case, it is illegal to receive
331 // postBuffer(). The surface just erases the framebuffer with
332 // fully transparent pixels.
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800333 mBufferHeap = buffers;
The Android Open Source Project27629322009-01-09 17:51:23 -0800334 mLayer.setNeedsBlending(false);
335 return;
336 }
337
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800338 status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
The Android Open Source Project27629322009-01-09 17:51:23 -0800339 if (err != NO_ERROR) {
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800340 LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
341 mStatus = err;
342 return;
343 }
344
345 PixelFormatInfo info;
346 err = getPixelFormatInfo(buffers.format, &info);
347 if (err != NO_ERROR) {
348 LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
349 buffers.format, strerror(err));
The Android Open Source Project27629322009-01-09 17:51:23 -0800350 mStatus = err;
351 return;
352 }
353
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800354 if (buffers.hor_stride<0 || buffers.ver_stride<0) {
355 LOGE("LayerBuffer::BufferSource: invalid parameters "
356 "(w=%d, h=%d, xs=%d, ys=%d)",
357 buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
358 mStatus = BAD_VALUE;
359 return;
360 }
361
362 mBufferHeap = buffers;
363 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
364 mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
365 mLayer.forceVisibilityTransaction();
The Android Open Source Project27629322009-01-09 17:51:23 -0800366}
367
368LayerBuffer::BufferSource::~BufferSource()
369{
370 if (mTextureName != -1U) {
371 LayerBase::deletedTextures.add(mTextureName);
372 }
373}
374
375void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
376{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800377 ISurface::BufferHeap buffers;
The Android Open Source Project27629322009-01-09 17:51:23 -0800378 { // scope for the lock
379 Mutex::Autolock _l(mLock);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800380 buffers = mBufferHeap;
381 if (buffers.heap != 0) {
382 const size_t memorySize = buffers.heap->getSize();
383 if ((size_t(offset) + mBufferSize) > memorySize) {
384 LOGE("LayerBuffer::BufferSource::postBuffer() "
385 "invalid buffer (offset=%d, size=%d, heap-size=%d",
386 int(offset), int(mBufferSize), int(memorySize));
387 return;
388 }
389 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800390 }
391
392 sp<Buffer> buffer;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800393 if (buffers.heap != 0) {
394 buffer = new LayerBuffer::Buffer(buffers, offset);
The Android Open Source Project27629322009-01-09 17:51:23 -0800395 if (buffer->getStatus() != NO_ERROR)
396 buffer.clear();
397 setBuffer(buffer);
398 mLayer.invalidate();
399 }
400}
401
402void LayerBuffer::BufferSource::unregisterBuffers()
403{
404 Mutex::Autolock _l(mLock);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800405 mBufferHeap.heap.clear();
The Android Open Source Project27629322009-01-09 17:51:23 -0800406 mBuffer.clear();
407 mLayer.invalidate();
408}
409
410sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
411{
412 Mutex::Autolock _l(mLock);
413 return mBuffer;
414}
415
416void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
417{
418 Mutex::Autolock _l(mLock);
419 mBuffer = buffer;
420}
421
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800422void LayerBuffer::BufferSource::updateTransform(Transform* tr) const
423{
424 uint32_t bufTransform = mBufferHeap.transform;
425 // TODO: handle all transforms
426 if (bufTransform == ISurface::BufferHeap::ROT_90) {
427 Transform rot90;
428 rot90.set(0, -1, 1, 0);
429 *tr = (*tr) * rot90;
430 }
431}
432
The Android Open Source Project27629322009-01-09 17:51:23 -0800433void LayerBuffer::BufferSource::onDraw(const Region& clip) const
434{
435 sp<Buffer> buffer(getBuffer());
436 if (UNLIKELY(buffer == 0)) {
437 // nothing to do, we don't have a buffer
438 mLayer.clearWithOpenGL(clip);
439 return;
440 }
441
442 status_t err = NO_ERROR;
443 NativeBuffer src(buffer->getBuffer());
444 const Rect& transformedBounds = mLayer.getTransformedBounds();
445 const int can_use_copybit = mLayer.canUseCopybit();
446
447 if (can_use_copybit) {
448 const int src_width = src.crop.r - src.crop.l;
449 const int src_height = src.crop.b - src.crop.t;
450 int W = transformedBounds.width();
451 int H = transformedBounds.height();
452 if (mLayer.getOrientation() & Transform::ROT_90) {
453 int t(W); W=H; H=t;
454 }
455
456 /* With LayerBuffer, it is likely that we'll have to rescale the
457 * surface, because this is often used for video playback or
458 * camera-preview. Since we want these operation as fast as possible
459 * we make sure we can use the 2D H/W even if it doesn't support
460 * the requested scale factor, in which case we perform the scaling
461 * in several passes. */
462
463 copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine();
464 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
465 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
466
467 float xscale = 1.0f;
468 if (src_width > W*min) xscale = 1.0f / min;
469 else if (src_width*mag < W) xscale = mag;
470
471 float yscale = 1.0f;
472 if (src_height > H*min) yscale = 1.0f / min;
473 else if (src_height*mag < H) yscale = mag;
474
475 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
476 if (UNLIKELY(mTemporaryDealer == 0)) {
477 // allocate a memory-dealer for this the first time
478 mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
479 ->createHeap(ISurfaceComposer::eHardware);
480 mTempBitmap.init(mTemporaryDealer);
481 }
482
483 const int tmp_w = floorf(src_width * xscale);
484 const int tmp_h = floorf(src_height * yscale);
485 err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
486
487 if (LIKELY(err == NO_ERROR)) {
488 NativeBuffer tmp;
489 mTempBitmap.getBitmapSurface(&tmp.img);
490 tmp.crop.l = 0;
491 tmp.crop.t = 0;
492 tmp.crop.r = tmp.img.w;
493 tmp.crop.b = tmp.img.h;
494
495 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
496 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
497 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
498 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
499 err = copybit->stretch(copybit,
500 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
501 src = tmp;
502 }
503 }
504
505 const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware());
506 copybit_image_t dst;
507 hw.getDisplaySurface(&dst);
508 const copybit_rect_t& drect
509 = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
510 const State& s(mLayer.drawingState());
511 region_iterator it(clip);
512 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, mLayer.getOrientation());
513 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800514 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
515
The Android Open Source Project27629322009-01-09 17:51:23 -0800516 err = copybit->stretch(copybit,
517 &dst, &src.img, &drect, &src.crop, &it);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800518 if (err != NO_ERROR) {
519 LOGE("copybit failed (%s)", strerror(err));
520 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800521 }
522
523 if (!can_use_copybit || err) {
524 if (UNLIKELY(mTextureName == -1LU)) {
525 mTextureName = mLayer.createTexture();
526 }
527 GLuint w = 0;
528 GLuint h = 0;
529 GGLSurface t;
530 t.version = sizeof(GGLSurface);
531 t.width = src.crop.r;
532 t.height = src.crop.b;
533 t.stride = src.img.w;
534 t.vstride= src.img.h;
535 t.format = src.img.format;
536 t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
537 const Region dirty(Rect(t.width, t.height));
538 mLayer.loadTexture(dirty, mTextureName, t, w, h);
539 mLayer.drawWithOpenGL(clip, mTextureName, t);
540 }
541}
542
543// ---------------------------------------------------------------------------
544
545LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
546 sp<OverlayRef>* overlayRef,
547 uint32_t w, uint32_t h, int32_t format)
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800548 : Source(layer), mVisibilityChanged(false),
549 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
The Android Open Source Project27629322009-01-09 17:51:23 -0800550{
551 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
The Android Open Source Project27629322009-01-09 17:51:23 -0800552 if (overlay_dev == NULL) {
553 // overlays not supported
554 return;
555 }
556
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800557 mOverlayDevice = overlay_dev;
The Android Open Source Project27629322009-01-09 17:51:23 -0800558 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
559 if (overlay == NULL) {
560 // couldn't create the overlay (no memory? no more overlays?)
561 return;
562 }
563
564 // enable dithering...
565 overlay_dev->setParameter(overlay_dev, overlay,
566 OVERLAY_DITHER, OVERLAY_ENABLE);
567
568 mOverlay = overlay;
569 mWidth = overlay->w;
570 mHeight = overlay->h;
571 mFormat = overlay->format;
572 mWidthStride = overlay->w_stride;
573 mHeightStride = overlay->h_stride;
574
575 mOverlayHandle = overlay->getHandleRef(overlay);
576
577 // NOTE: here it's okay to acquire a reference to "this"m as long as
578 // the reference is not released before we leave the ctor.
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800579 sp<OverlayChannel> channel = new OverlayChannel(this);
The Android Open Source Project27629322009-01-09 17:51:23 -0800580
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800581 *overlayRef = new OverlayRef(mOverlayHandle, channel,
The Android Open Source Project27629322009-01-09 17:51:23 -0800582 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
583}
584
585LayerBuffer::OverlaySource::~OverlaySource()
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800586{
587 if (mOverlay && mOverlayDevice) {
588 overlay_control_device_t* overlay_dev = mOverlayDevice;
589 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
590 }
The Android Open Source Project27629322009-01-09 17:51:23 -0800591}
592
593void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
594{
595 const Layer::State& front(mLayer.drawingState());
596 const Layer::State& temp(mLayer.currentState());
597 if (temp.sequence != front.sequence) {
598 mVisibilityChanged = true;
599 }
600}
601
602void LayerBuffer::OverlaySource::onVisibilityResolved(
603 const Transform& planeTransform)
604{
605 // this code-path must be as tight as possible, it's called each time
606 // the screen is composited.
607 if (UNLIKELY(mOverlay != 0)) {
608 if (mVisibilityChanged) {
609 mVisibilityChanged = false;
610 const Rect& bounds = mLayer.getTransformedBounds();
611 int x = bounds.left;
612 int y = bounds.top;
613 int w = bounds.width();
614 int h = bounds.height();
615
616 // we need a lock here to protect "destroy"
617 Mutex::Autolock _l(mLock);
618 if (mOverlay) {
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800619 overlay_control_device_t* overlay_dev = mOverlayDevice;
The Android Open Source Project27629322009-01-09 17:51:23 -0800620 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
621 overlay_dev->setParameter(overlay_dev, mOverlay,
622 OVERLAY_TRANSFORM, mLayer.getOrientation());
623 }
624 }
625 }
626}
627
628void LayerBuffer::OverlaySource::serverDestroy()
629{
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800630 mLayer.clearSource();
631 destroyOverlay();
632}
633
634void LayerBuffer::OverlaySource::destroyOverlay()
635{
The Android Open Source Project27629322009-01-09 17:51:23 -0800636 // we need a lock here to protect "onVisibilityResolved"
637 Mutex::Autolock _l(mLock);
638 if (mOverlay) {
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800639 overlay_control_device_t* overlay_dev = mOverlayDevice;
The Android Open Source Project27629322009-01-09 17:51:23 -0800640 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
641 mOverlay = 0;
642 }
643}
644
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700645// ---------------------------------------------------------------------------
646}; // namespace android