blob: d70a71f4568c5735c44f044d21bf97842b1a0cf6 [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 }
344}
345
346void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
347{
348 ISurface::BufferHeap buffers;
349 { // scope for the lock
350 Mutex::Autolock _l(mLock);
351 buffers = mBufferHeap;
352 if (buffers.heap != 0) {
353 const size_t memorySize = buffers.heap->getSize();
354 if ((size_t(offset) + mBufferSize) > memorySize) {
355 LOGE("LayerBuffer::BufferSource::postBuffer() "
356 "invalid buffer (offset=%d, size=%d, heap-size=%d",
357 int(offset), int(mBufferSize), int(memorySize));
358 return;
359 }
360 }
361 }
362
363 sp<Buffer> buffer;
364 if (buffers.heap != 0) {
365 buffer = new LayerBuffer::Buffer(buffers, offset);
366 if (buffer->getStatus() != NO_ERROR)
367 buffer.clear();
368 setBuffer(buffer);
369 mLayer.invalidate();
370 }
371}
372
373void LayerBuffer::BufferSource::unregisterBuffers()
374{
375 Mutex::Autolock _l(mLock);
376 mBufferHeap.heap.clear();
377 mBuffer.clear();
378 mLayer.invalidate();
379}
380
381sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
382{
383 Mutex::Autolock _l(mLock);
384 return mBuffer;
385}
386
387void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
388{
389 Mutex::Autolock _l(mLock);
390 mBuffer = buffer;
391}
392
393bool LayerBuffer::BufferSource::transformed() const
394{
395 return mBufferHeap.transform ? true : Source::transformed();
396}
397
398void LayerBuffer::BufferSource::onDraw(const Region& clip) const
399{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700400 sp<Buffer> ourBuffer(getBuffer());
401 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800402 // nothing to do, we don't have a buffer
403 mLayer.clearWithOpenGL(clip);
404 return;
405 }
406
Mathias Agopian69029eb2009-06-23 21:11:43 -0700407 status_t err = NO_ERROR;
408 NativeBuffer src(ourBuffer->getBuffer());
409 const Rect& transformedBounds = mLayer.getTransformedBounds();
410 copybit_device_t* copybit = mBlitEngine;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411
Mathias Agopian69029eb2009-06-23 21:11:43 -0700412 if (copybit) {
413 const int src_width = src.crop.r - src.crop.l;
414 const int src_height = src.crop.b - src.crop.t;
415 int W = transformedBounds.width();
416 int H = transformedBounds.height();
417 if (mLayer.getOrientation() & Transform::ROT_90) {
418 int t(W); W=H; H=t;
419 }
420
421#if 0
422 /* With LayerBuffer, it is likely that we'll have to rescale the
423 * surface, because this is often used for video playback or
424 * camera-preview. Since we want these operation as fast as possible
425 * we make sure we can use the 2D H/W even if it doesn't support
426 * the requested scale factor, in which case we perform the scaling
427 * in several passes. */
428
429 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
430 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
431
432 float xscale = 1.0f;
433 if (src_width > W*min) xscale = 1.0f / min;
434 else if (src_width*mag < W) xscale = mag;
435
436 float yscale = 1.0f;
437 if (src_height > H*min) yscale = 1.0f / min;
438 else if (src_height*mag < H) yscale = mag;
439
440 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
441 if (UNLIKELY(mTemporaryDealer == 0)) {
442 // allocate a memory-dealer for this the first time
443 mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
444 ->createHeap(ISurfaceComposer::eHardware);
445 mTempBitmap.init(mTemporaryDealer);
446 }
447
448 const int tmp_w = floorf(src_width * xscale);
449 const int tmp_h = floorf(src_height * yscale);
450 err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
451
452 if (LIKELY(err == NO_ERROR)) {
453 NativeBuffer tmp;
454 mTempBitmap.getBitmapSurface(&tmp.img);
455 tmp.crop.l = 0;
456 tmp.crop.t = 0;
457 tmp.crop.r = tmp.img.w;
458 tmp.crop.b = tmp.img.h;
459
460 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
461 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
462 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
463 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
464 err = copybit->stretch(copybit,
465 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
466 src = tmp;
467 }
468 }
469#endif
470
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700471#ifdef EGL_ANDROID_get_render_buffer
472 EGLDisplay dpy = eglGetCurrentDisplay();
473 EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
474 EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
475 android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
476 if (nb == 0) {
477 err = BAD_VALUE;
478 } else {
479 copybit_image_t dst;
480 dst.w = nb->width;
481 dst.h = nb->height;
482 dst.format = nb->format;
483 dst.base = NULL; // unused by copybit on msm7k
484 dst.handle = (native_handle_t *)nb->handle;
Mathias Agopian69029eb2009-06-23 21:11:43 -0700485
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700486 const Rect& transformedBounds = mLayer.getTransformedBounds();
487 const copybit_rect_t& drect
488 = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
489 const State& s(mLayer.drawingState());
490 region_iterator it(clip);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700491
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700492 // pick the right orientation for this buffer
493 int orientation = mLayer.getOrientation();
494 if (UNLIKELY(mBufferHeap.transform)) {
495 Transform rot90;
496 GraphicPlane::orientationToTransfrom(
497 ISurfaceComposer::eOrientation90, 0, 0, &rot90);
498 const Transform& planeTransform(mLayer.graphicPlane(0).transform());
499 const Layer::State& s(mLayer.drawingState());
500 Transform tr(planeTransform * s.transform * rot90);
501 orientation = tr.getOrientation();
502 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700503
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700504 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
505 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
506 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700507
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700508 err = copybit->stretch(copybit,
509 &dst, &src.img, &drect, &src.crop, &it);
510 if (err != NO_ERROR) {
511 LOGE("copybit failed (%s)", strerror(err));
512 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700513 }
514 }
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700515#endif
516
Mathias Agopian69029eb2009-06-23 21:11:43 -0700517 if (!copybit || err)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700518 {
519 // OpenGL fall-back
520 if (UNLIKELY(mTexture.name == -1LU)) {
521 mTexture.name = mLayer.createTexture();
522 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700523 GLuint w = 0;
524 GLuint h = 0;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700525 GGLSurface t;
526 t.version = sizeof(GGLSurface);
527 t.width = src.crop.r;
528 t.height = src.crop.b;
529 t.stride = src.img.w;
530 t.vstride= src.img.h;
531 t.format = src.img.format;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700532 t.data = (GGLubyte*)src.img.base;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700533 const Region dirty(Rect(t.width, t.height));
534 mLayer.loadTexture(&mTexture, mTexture.name, dirty, t);
535 mTexture.transform = mBufferHeap.transform;
536 mLayer.drawWithOpenGL(clip, mTexture);
Mathias Agopian0926f502009-05-04 14:17:04 -0700537 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538}
539
540
541// ---------------------------------------------------------------------------
542
543LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
544 sp<OverlayRef>* overlayRef,
545 uint32_t w, uint32_t h, int32_t format)
546 : Source(layer), mVisibilityChanged(false),
547 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
548{
549 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
550 if (overlay_dev == NULL) {
551 // overlays not supported
552 return;
553 }
554
555 mOverlayDevice = overlay_dev;
556 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
557 if (overlay == NULL) {
558 // couldn't create the overlay (no memory? no more overlays?)
559 return;
560 }
561
562 // enable dithering...
563 overlay_dev->setParameter(overlay_dev, overlay,
564 OVERLAY_DITHER, OVERLAY_ENABLE);
565
566 mOverlay = overlay;
567 mWidth = overlay->w;
568 mHeight = overlay->h;
569 mFormat = overlay->format;
570 mWidthStride = overlay->w_stride;
571 mHeightStride = overlay->h_stride;
572
573 mOverlayHandle = overlay->getHandleRef(overlay);
574
575 // NOTE: here it's okay to acquire a reference to "this"m as long as
576 // the reference is not released before we leave the ctor.
577 sp<OverlayChannel> channel = new OverlayChannel(this);
578
579 *overlayRef = new OverlayRef(mOverlayHandle, channel,
580 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
581}
582
583LayerBuffer::OverlaySource::~OverlaySource()
584{
585 if (mOverlay && mOverlayDevice) {
586 overlay_control_device_t* overlay_dev = mOverlayDevice;
587 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
588 }
589}
590
591void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
592{
593 const Layer::State& front(mLayer.drawingState());
594 const Layer::State& temp(mLayer.currentState());
595 if (temp.sequence != front.sequence) {
596 mVisibilityChanged = true;
597 }
598}
599
600void LayerBuffer::OverlaySource::onVisibilityResolved(
601 const Transform& planeTransform)
602{
603 // this code-path must be as tight as possible, it's called each time
604 // the screen is composited.
605 if (UNLIKELY(mOverlay != 0)) {
606 if (mVisibilityChanged) {
607 mVisibilityChanged = false;
608 const Rect& bounds = mLayer.getTransformedBounds();
609 int x = bounds.left;
610 int y = bounds.top;
611 int w = bounds.width();
612 int h = bounds.height();
613
614 // we need a lock here to protect "destroy"
615 Mutex::Autolock _l(mLock);
616 if (mOverlay) {
617 overlay_control_device_t* overlay_dev = mOverlayDevice;
618 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
619 overlay_dev->setParameter(overlay_dev, mOverlay,
620 OVERLAY_TRANSFORM, mLayer.getOrientation());
621 }
622 }
623 }
624}
625
626void LayerBuffer::OverlaySource::serverDestroy()
627{
628 mLayer.clearSource();
629 destroyOverlay();
630}
631
632void LayerBuffer::OverlaySource::destroyOverlay()
633{
634 // we need a lock here to protect "onVisibilityResolved"
635 Mutex::Autolock _l(mLock);
636 if (mOverlay) {
637 overlay_control_device_t* overlay_dev = mOverlayDevice;
638 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
639 mOverlay = 0;
640 }
641}
642
643// ---------------------------------------------------------------------------
644}; // namespace android