blob: 1827efad8a7845d82cf9b36d1987e7abcb0cd986 [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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <stdlib.h>
18#include <stdint.h>
19#include <math.h>
20#include <sys/types.h>
21
22#include <utils/Errors.h>
23#include <utils/Log.h>
24#include <utils/StopWatch.h>
25
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080026#include <ui/PixelFormat.h>
Mathias Agopian69029eb2009-06-23 21:11:43 -070027#include <ui/FramebufferNativeWindow.h>
28
29#include <hardware/copybit.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080030
31#include "LayerBuffer.h"
32#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080033#include "DisplayHardware/DisplayHardware.h"
34
Mathias Agopian5911aa92009-06-24 16:55:59 -070035#include "gralloc_priv.h" // needed for msm / copybit
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036
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,
Mathias Agopianf9d93272009-06-19 17:00:27 -070047 const sp<Client>& client, int32_t i)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048 : LayerBaseClient(flinger, display, client, i),
49 mNeedsBlending(false)
50{
51}
52
53LayerBuffer::~LayerBuffer()
54{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080055}
56
Mathias Agopian9a112062009-04-17 19:36:26 -070057void LayerBuffer::onFirstRef()
58{
Mathias Agopian2e123242009-06-23 20:06:46 -070059 LayerBaseClient::onFirstRef();
Mathias Agopian9a112062009-04-17 19:36:26 -070060 mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
61 const_cast<LayerBuffer *>(this));
62}
63
Mathias Agopian076b1cc2009-04-10 14:24:30 -070064sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080065{
Mathias Agopian9a112062009-04-17 19:36:26 -070066 return mSurface;
67}
68
69status_t LayerBuffer::ditch()
70{
71 mSurface.clear();
72 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080073}
74
75bool LayerBuffer::needsBlending() const {
76 return mNeedsBlending;
77}
78
79void LayerBuffer::setNeedsBlending(bool blending) {
80 mNeedsBlending = blending;
81}
82
83void LayerBuffer::postBuffer(ssize_t offset)
84{
85 sp<Source> source(getSource());
86 if (source != 0)
87 source->postBuffer(offset);
88}
89
90void LayerBuffer::unregisterBuffers()
91{
92 sp<Source> source(clearSource());
93 if (source != 0)
94 source->unregisterBuffers();
95}
96
97uint32_t LayerBuffer::doTransaction(uint32_t flags)
98{
99 sp<Source> source(getSource());
100 if (source != 0)
101 source->onTransaction(flags);
102 return LayerBase::doTransaction(flags);
103}
104
105void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
106 Region& outDirtyRegion)
107{
108 // this code-path must be as tight as possible, it's called each time
109 // the screen is composited.
110 sp<Source> source(getSource());
111 if (source != 0)
112 source->onVisibilityResolved(planeTransform);
113 LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
114}
115
116void LayerBuffer::onDraw(const Region& clip) const
117{
118 sp<Source> source(getSource());
119 if (LIKELY(source != 0)) {
120 source->onDraw(clip);
121 } else {
122 clearWithOpenGL(clip);
123 }
124}
125
126bool LayerBuffer::transformed() const
127{
128 sp<Source> source(getSource());
129 if (LIKELY(source != 0))
130 return source->transformed();
131 return false;
132}
133
134/**
135 * This creates a "buffer" source for this surface
136 */
137status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
138{
139 Mutex::Autolock _l(mLock);
140 if (mSource != 0)
141 return INVALID_OPERATION;
142
143 sp<BufferSource> source = new BufferSource(*this, buffers);
144
145 status_t result = source->getStatus();
146 if (result == NO_ERROR) {
147 mSource = source;
148 }
149 return result;
150}
151
152/**
153 * This creates an "overlay" source for this surface
154 */
155sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
156{
157 sp<OverlayRef> result;
158 Mutex::Autolock _l(mLock);
159 if (mSource != 0)
160 return result;
161
162 sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f);
163 if (result != 0) {
164 mSource = source;
165 }
166 return result;
167}
168
169sp<LayerBuffer::Source> LayerBuffer::getSource() const {
170 Mutex::Autolock _l(mLock);
171 return mSource;
172}
173
174sp<LayerBuffer::Source> LayerBuffer::clearSource() {
175 sp<Source> source;
176 Mutex::Autolock _l(mLock);
177 source = mSource;
178 mSource.clear();
179 return source;
180}
181
182// ============================================================================
183// LayerBuffer::SurfaceBuffer
184// ============================================================================
185
Mathias Agopian9a112062009-04-17 19:36:26 -0700186LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
187 SurfaceID id, const sp<LayerBuffer>& owner)
188 : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800189{
190}
191
192LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
193{
194 unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800195}
196
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700197status_t LayerBuffer::SurfaceBuffer::registerBuffers(
198 const ISurface::BufferHeap& buffers)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800199{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700200 sp<LayerBuffer> owner(getOwner());
201 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800202 return owner->registerBuffers(buffers);
203 return NO_INIT;
204}
205
206void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
207{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700208 sp<LayerBuffer> owner(getOwner());
209 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210 owner->postBuffer(offset);
211}
212
213void LayerBuffer::SurfaceBuffer::unregisterBuffers()
214{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700215 sp<LayerBuffer> owner(getOwner());
216 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800217 owner->unregisterBuffers();
218}
219
220sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
221 uint32_t w, uint32_t h, int32_t format) {
222 sp<OverlayRef> result;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700223 sp<LayerBuffer> owner(getOwner());
224 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800225 result = owner->createOverlay(w, h, format);
226 return result;
227}
228
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800229// ============================================================================
230// LayerBuffer::Buffer
231// ============================================================================
232
233LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
234 : mBufferHeap(buffers)
235{
236 NativeBuffer& src(mNativeBuffer);
Mathias Agopian5911aa92009-06-24 16:55:59 -0700237
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238 src.crop.l = 0;
239 src.crop.t = 0;
240 src.crop.r = buffers.w;
241 src.crop.b = buffers.h;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700242
243 src.img.w = buffers.hor_stride ?: buffers.w;
244 src.img.h = buffers.ver_stride ?: buffers.h;
245 src.img.format = buffers.format;
246 src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset);
247
248 private_handle_t* hnd = new private_handle_t(
249 buffers.heap->heapID(), buffers.heap->getSize(), 0);
250 hnd->offset = offset;
251 src.img.handle = hnd;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800252}
253
254LayerBuffer::Buffer::~Buffer()
255{
Mathias Agopian5911aa92009-06-24 16:55:59 -0700256 NativeBuffer& src(mNativeBuffer);
257 if (src.img.handle)
258 delete (private_handle_t*)src.img.handle;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800259}
260
261// ============================================================================
262// LayerBuffer::Source
263// LayerBuffer::BufferSource
264// LayerBuffer::OverlaySource
265// ============================================================================
266
267LayerBuffer::Source::Source(LayerBuffer& layer)
268 : mLayer(layer)
269{
270}
271LayerBuffer::Source::~Source() {
272}
273void LayerBuffer::Source::onDraw(const Region& clip) const {
274}
275void LayerBuffer::Source::onTransaction(uint32_t flags) {
276}
277void LayerBuffer::Source::onVisibilityResolved(
278 const Transform& planeTransform) {
279}
280void LayerBuffer::Source::postBuffer(ssize_t offset) {
281}
282void LayerBuffer::Source::unregisterBuffers() {
283}
284bool LayerBuffer::Source::transformed() const {
285 return mLayer.mTransformed;
286}
287
288// ---------------------------------------------------------------------------
289
290LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
291 const ISurface::BufferHeap& buffers)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700292 : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800293{
294 if (buffers.heap == NULL) {
295 // this is allowed, but in this case, it is illegal to receive
296 // postBuffer(). The surface just erases the framebuffer with
297 // fully transparent pixels.
298 mBufferHeap = buffers;
299 mLayer.setNeedsBlending(false);
300 return;
301 }
302
303 status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
304 if (err != NO_ERROR) {
305 LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
306 mStatus = err;
307 return;
308 }
309
310 PixelFormatInfo info;
311 err = getPixelFormatInfo(buffers.format, &info);
312 if (err != NO_ERROR) {
313 LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
314 buffers.format, strerror(err));
315 mStatus = err;
316 return;
317 }
318
319 if (buffers.hor_stride<0 || buffers.ver_stride<0) {
320 LOGE("LayerBuffer::BufferSource: invalid parameters "
321 "(w=%d, h=%d, xs=%d, ys=%d)",
322 buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
323 mStatus = BAD_VALUE;
324 return;
325 }
326
327 mBufferHeap = buffers;
328 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
329 mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
330 mLayer.forceVisibilityTransaction();
Mathias Agopian69029eb2009-06-23 21:11:43 -0700331
332 hw_module_t const* module;
333 mBlitEngine = NULL;
334 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
335 copybit_open(module, &mBlitEngine);
336 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800337}
338
339LayerBuffer::BufferSource::~BufferSource()
340{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700341 if (mTexture.name != -1U) {
342 glDeleteTextures(1, &mTexture.name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800343 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700344 if (mBlitEngine) {
345 copybit_close(mBlitEngine);
346 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800347}
348
349void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
350{
351 ISurface::BufferHeap buffers;
352 { // scope for the lock
353 Mutex::Autolock _l(mLock);
354 buffers = mBufferHeap;
355 if (buffers.heap != 0) {
356 const size_t memorySize = buffers.heap->getSize();
357 if ((size_t(offset) + mBufferSize) > memorySize) {
358 LOGE("LayerBuffer::BufferSource::postBuffer() "
359 "invalid buffer (offset=%d, size=%d, heap-size=%d",
360 int(offset), int(mBufferSize), int(memorySize));
361 return;
362 }
363 }
364 }
365
366 sp<Buffer> buffer;
367 if (buffers.heap != 0) {
368 buffer = new LayerBuffer::Buffer(buffers, offset);
369 if (buffer->getStatus() != NO_ERROR)
370 buffer.clear();
371 setBuffer(buffer);
372 mLayer.invalidate();
373 }
374}
375
376void LayerBuffer::BufferSource::unregisterBuffers()
377{
378 Mutex::Autolock _l(mLock);
379 mBufferHeap.heap.clear();
380 mBuffer.clear();
381 mLayer.invalidate();
382}
383
384sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
385{
386 Mutex::Autolock _l(mLock);
387 return mBuffer;
388}
389
390void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
391{
392 Mutex::Autolock _l(mLock);
393 mBuffer = buffer;
394}
395
396bool LayerBuffer::BufferSource::transformed() const
397{
398 return mBufferHeap.transform ? true : Source::transformed();
399}
400
401void LayerBuffer::BufferSource::onDraw(const Region& clip) const
402{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700403 sp<Buffer> ourBuffer(getBuffer());
404 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800405 // nothing to do, we don't have a buffer
406 mLayer.clearWithOpenGL(clip);
407 return;
408 }
409
Mathias Agopian69029eb2009-06-23 21:11:43 -0700410 status_t err = NO_ERROR;
411 NativeBuffer src(ourBuffer->getBuffer());
412 const Rect& transformedBounds = mLayer.getTransformedBounds();
413 copybit_device_t* copybit = mBlitEngine;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800414
Mathias Agopian69029eb2009-06-23 21:11:43 -0700415 if (copybit) {
416 const int src_width = src.crop.r - src.crop.l;
417 const int src_height = src.crop.b - src.crop.t;
418 int W = transformedBounds.width();
419 int H = transformedBounds.height();
420 if (mLayer.getOrientation() & Transform::ROT_90) {
421 int t(W); W=H; H=t;
422 }
423
424#if 0
425 /* With LayerBuffer, it is likely that we'll have to rescale the
426 * surface, because this is often used for video playback or
427 * camera-preview. Since we want these operation as fast as possible
428 * we make sure we can use the 2D H/W even if it doesn't support
429 * the requested scale factor, in which case we perform the scaling
430 * in several passes. */
431
432 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
433 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
434
435 float xscale = 1.0f;
436 if (src_width > W*min) xscale = 1.0f / min;
437 else if (src_width*mag < W) xscale = mag;
438
439 float yscale = 1.0f;
440 if (src_height > H*min) yscale = 1.0f / min;
441 else if (src_height*mag < H) yscale = mag;
442
443 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
444 if (UNLIKELY(mTemporaryDealer == 0)) {
445 // allocate a memory-dealer for this the first time
446 mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
447 ->createHeap(ISurfaceComposer::eHardware);
448 mTempBitmap.init(mTemporaryDealer);
449 }
450
451 const int tmp_w = floorf(src_width * xscale);
452 const int tmp_h = floorf(src_height * yscale);
453 err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
454
455 if (LIKELY(err == NO_ERROR)) {
456 NativeBuffer tmp;
457 mTempBitmap.getBitmapSurface(&tmp.img);
458 tmp.crop.l = 0;
459 tmp.crop.t = 0;
460 tmp.crop.r = tmp.img.w;
461 tmp.crop.b = tmp.img.h;
462
463 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
464 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
465 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
466 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
467 err = copybit->stretch(copybit,
468 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
469 src = tmp;
470 }
471 }
472#endif
473
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700474#ifdef EGL_ANDROID_get_render_buffer
475 EGLDisplay dpy = eglGetCurrentDisplay();
476 EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
477 EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
478 android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
479 if (nb == 0) {
480 err = BAD_VALUE;
481 } else {
482 copybit_image_t dst;
483 dst.w = nb->width;
484 dst.h = nb->height;
485 dst.format = nb->format;
486 dst.base = NULL; // unused by copybit on msm7k
487 dst.handle = (native_handle_t *)nb->handle;
Mathias Agopian69029eb2009-06-23 21:11:43 -0700488
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700489 const Rect& transformedBounds = mLayer.getTransformedBounds();
490 const copybit_rect_t& drect
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700491 = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700492 const State& s(mLayer.drawingState());
493 region_iterator it(clip);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700494
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700495 // pick the right orientation for this buffer
496 int orientation = mLayer.getOrientation();
497 if (UNLIKELY(mBufferHeap.transform)) {
498 Transform rot90;
499 GraphicPlane::orientationToTransfrom(
500 ISurfaceComposer::eOrientation90, 0, 0, &rot90);
501 const Transform& planeTransform(mLayer.graphicPlane(0).transform());
502 const Layer::State& s(mLayer.drawingState());
503 Transform tr(planeTransform * s.transform * rot90);
504 orientation = tr.getOrientation();
505 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700506
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700507 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
508 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
509 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700510
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700511 err = copybit->stretch(copybit,
512 &dst, &src.img, &drect, &src.crop, &it);
513 if (err != NO_ERROR) {
514 LOGE("copybit failed (%s)", strerror(err));
515 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700516 }
517 }
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700518#endif
519
Mathias Agopian69029eb2009-06-23 21:11:43 -0700520 if (!copybit || err)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700521 {
522 // OpenGL fall-back
523 if (UNLIKELY(mTexture.name == -1LU)) {
524 mTexture.name = mLayer.createTexture();
525 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700526 GLuint w = 0;
527 GLuint h = 0;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700528 GGLSurface t;
529 t.version = sizeof(GGLSurface);
530 t.width = src.crop.r;
531 t.height = src.crop.b;
532 t.stride = src.img.w;
533 t.vstride= src.img.h;
534 t.format = src.img.format;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700535 t.data = (GGLubyte*)src.img.base;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700536 const Region dirty(Rect(t.width, t.height));
537 mLayer.loadTexture(&mTexture, mTexture.name, dirty, t);
538 mTexture.transform = mBufferHeap.transform;
539 mLayer.drawWithOpenGL(clip, mTexture);
Mathias Agopian0926f502009-05-04 14:17:04 -0700540 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800541}
542
543
544// ---------------------------------------------------------------------------
545
546LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
547 sp<OverlayRef>* overlayRef,
548 uint32_t w, uint32_t h, int32_t format)
549 : Source(layer), mVisibilityChanged(false),
550 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
551{
552 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
553 if (overlay_dev == NULL) {
554 // overlays not supported
555 return;
556 }
557
558 mOverlayDevice = overlay_dev;
559 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
560 if (overlay == NULL) {
561 // couldn't create the overlay (no memory? no more overlays?)
562 return;
563 }
564
565 // enable dithering...
566 overlay_dev->setParameter(overlay_dev, overlay,
567 OVERLAY_DITHER, OVERLAY_ENABLE);
568
569 mOverlay = overlay;
570 mWidth = overlay->w;
571 mHeight = overlay->h;
572 mFormat = overlay->format;
573 mWidthStride = overlay->w_stride;
574 mHeightStride = overlay->h_stride;
575
576 mOverlayHandle = overlay->getHandleRef(overlay);
577
578 // NOTE: here it's okay to acquire a reference to "this"m as long as
579 // the reference is not released before we leave the ctor.
580 sp<OverlayChannel> channel = new OverlayChannel(this);
581
582 *overlayRef = new OverlayRef(mOverlayHandle, channel,
583 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
584}
585
586LayerBuffer::OverlaySource::~OverlaySource()
587{
588 if (mOverlay && mOverlayDevice) {
589 overlay_control_device_t* overlay_dev = mOverlayDevice;
590 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
591 }
592}
593
594void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
595{
596 const Layer::State& front(mLayer.drawingState());
597 const Layer::State& temp(mLayer.currentState());
598 if (temp.sequence != front.sequence) {
599 mVisibilityChanged = true;
600 }
601}
602
603void LayerBuffer::OverlaySource::onVisibilityResolved(
604 const Transform& planeTransform)
605{
606 // this code-path must be as tight as possible, it's called each time
607 // the screen is composited.
608 if (UNLIKELY(mOverlay != 0)) {
609 if (mVisibilityChanged) {
610 mVisibilityChanged = false;
611 const Rect& bounds = mLayer.getTransformedBounds();
612 int x = bounds.left;
613 int y = bounds.top;
614 int w = bounds.width();
615 int h = bounds.height();
616
617 // we need a lock here to protect "destroy"
618 Mutex::Autolock _l(mLock);
619 if (mOverlay) {
620 overlay_control_device_t* overlay_dev = mOverlayDevice;
621 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
622 overlay_dev->setParameter(overlay_dev, mOverlay,
623 OVERLAY_TRANSFORM, mLayer.getOrientation());
624 }
625 }
626 }
627}
628
629void LayerBuffer::OverlaySource::serverDestroy()
630{
631 mLayer.clearSource();
632 destroyOverlay();
633}
634
635void LayerBuffer::OverlaySource::destroyOverlay()
636{
637 // we need a lock here to protect "onVisibilityResolved"
638 Mutex::Autolock _l(mLock);
639 if (mOverlay) {
640 overlay_control_device_t* overlay_dev = mOverlayDevice;
641 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
642 mOverlay = 0;
643 }
644}
645
646// ---------------------------------------------------------------------------
647}; // namespace android