blob: 90e7f5048067789b07b1a88e6254ba105d5ed2e8 [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
Mathias Agopiand512f232009-06-25 17:41:12 -0700248 // FIXME: gross hack, we should never access private_handle_t from here,
249 // but this is needed by msm drivers
Mathias Agopian5911aa92009-06-24 16:55:59 -0700250 private_handle_t* hnd = new private_handle_t(
251 buffers.heap->heapID(), buffers.heap->getSize(), 0);
252 hnd->offset = offset;
253 src.img.handle = hnd;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800254}
255
256LayerBuffer::Buffer::~Buffer()
257{
Mathias Agopian5911aa92009-06-24 16:55:59 -0700258 NativeBuffer& src(mNativeBuffer);
259 if (src.img.handle)
260 delete (private_handle_t*)src.img.handle;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800261}
262
263// ============================================================================
264// LayerBuffer::Source
265// LayerBuffer::BufferSource
266// LayerBuffer::OverlaySource
267// ============================================================================
268
269LayerBuffer::Source::Source(LayerBuffer& layer)
270 : mLayer(layer)
271{
272}
273LayerBuffer::Source::~Source() {
274}
275void LayerBuffer::Source::onDraw(const Region& clip) const {
276}
277void LayerBuffer::Source::onTransaction(uint32_t flags) {
278}
279void LayerBuffer::Source::onVisibilityResolved(
280 const Transform& planeTransform) {
281}
282void LayerBuffer::Source::postBuffer(ssize_t offset) {
283}
284void LayerBuffer::Source::unregisterBuffers() {
285}
286bool LayerBuffer::Source::transformed() const {
287 return mLayer.mTransformed;
288}
289
290// ---------------------------------------------------------------------------
291
292LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
293 const ISurface::BufferHeap& buffers)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700294 : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800295{
296 if (buffers.heap == NULL) {
297 // this is allowed, but in this case, it is illegal to receive
298 // postBuffer(). The surface just erases the framebuffer with
299 // fully transparent pixels.
300 mBufferHeap = buffers;
301 mLayer.setNeedsBlending(false);
302 return;
303 }
304
305 status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
306 if (err != NO_ERROR) {
307 LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
308 mStatus = err;
309 return;
310 }
311
312 PixelFormatInfo info;
313 err = getPixelFormatInfo(buffers.format, &info);
314 if (err != NO_ERROR) {
315 LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
316 buffers.format, strerror(err));
317 mStatus = err;
318 return;
319 }
320
321 if (buffers.hor_stride<0 || buffers.ver_stride<0) {
322 LOGE("LayerBuffer::BufferSource: invalid parameters "
323 "(w=%d, h=%d, xs=%d, ys=%d)",
324 buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
325 mStatus = BAD_VALUE;
326 return;
327 }
328
329 mBufferHeap = buffers;
330 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
331 mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
332 mLayer.forceVisibilityTransaction();
Mathias Agopian69029eb2009-06-23 21:11:43 -0700333
334 hw_module_t const* module;
335 mBlitEngine = NULL;
336 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
337 copybit_open(module, &mBlitEngine);
338 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800339}
340
341LayerBuffer::BufferSource::~BufferSource()
342{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700343 if (mTexture.name != -1U) {
344 glDeleteTextures(1, &mTexture.name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800345 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700346 if (mBlitEngine) {
347 copybit_close(mBlitEngine);
348 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800349}
350
351void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
352{
353 ISurface::BufferHeap buffers;
354 { // scope for the lock
355 Mutex::Autolock _l(mLock);
356 buffers = mBufferHeap;
357 if (buffers.heap != 0) {
358 const size_t memorySize = buffers.heap->getSize();
359 if ((size_t(offset) + mBufferSize) > memorySize) {
360 LOGE("LayerBuffer::BufferSource::postBuffer() "
361 "invalid buffer (offset=%d, size=%d, heap-size=%d",
362 int(offset), int(mBufferSize), int(memorySize));
363 return;
364 }
365 }
366 }
367
368 sp<Buffer> buffer;
369 if (buffers.heap != 0) {
370 buffer = new LayerBuffer::Buffer(buffers, offset);
371 if (buffer->getStatus() != NO_ERROR)
372 buffer.clear();
373 setBuffer(buffer);
374 mLayer.invalidate();
375 }
376}
377
378void LayerBuffer::BufferSource::unregisterBuffers()
379{
380 Mutex::Autolock _l(mLock);
381 mBufferHeap.heap.clear();
382 mBuffer.clear();
383 mLayer.invalidate();
384}
385
386sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
387{
388 Mutex::Autolock _l(mLock);
389 return mBuffer;
390}
391
392void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
393{
394 Mutex::Autolock _l(mLock);
395 mBuffer = buffer;
396}
397
398bool LayerBuffer::BufferSource::transformed() const
399{
400 return mBufferHeap.transform ? true : Source::transformed();
401}
402
403void LayerBuffer::BufferSource::onDraw(const Region& clip) const
404{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700405 sp<Buffer> ourBuffer(getBuffer());
406 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800407 // nothing to do, we don't have a buffer
408 mLayer.clearWithOpenGL(clip);
409 return;
410 }
411
Mathias Agopian69029eb2009-06-23 21:11:43 -0700412 status_t err = NO_ERROR;
413 NativeBuffer src(ourBuffer->getBuffer());
414 const Rect& transformedBounds = mLayer.getTransformedBounds();
415 copybit_device_t* copybit = mBlitEngine;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800416
Mathias Agopian69029eb2009-06-23 21:11:43 -0700417 if (copybit) {
418 const int src_width = src.crop.r - src.crop.l;
419 const int src_height = src.crop.b - src.crop.t;
420 int W = transformedBounds.width();
421 int H = transformedBounds.height();
422 if (mLayer.getOrientation() & Transform::ROT_90) {
423 int t(W); W=H; H=t;
424 }
425
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700426#ifdef EGL_ANDROID_get_render_buffer
427 EGLDisplay dpy = eglGetCurrentDisplay();
428 EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
429 EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
430 android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
431 if (nb == 0) {
432 err = BAD_VALUE;
433 } else {
434 copybit_image_t dst;
435 dst.w = nb->width;
436 dst.h = nb->height;
437 dst.format = nb->format;
438 dst.base = NULL; // unused by copybit on msm7k
439 dst.handle = (native_handle_t *)nb->handle;
Mathias Agopian69029eb2009-06-23 21:11:43 -0700440
Mathias Agopiand512f232009-06-25 17:41:12 -0700441 /* With LayerBuffer, it is likely that we'll have to rescale the
442 * surface, because this is often used for video playback or
443 * camera-preview. Since we want these operation as fast as possible
444 * we make sure we can use the 2D H/W even if it doesn't support
445 * the requested scale factor, in which case we perform the scaling
446 * in several passes. */
447
448 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
449 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
450
451 float xscale = 1.0f;
452 if (src_width > W*min) xscale = 1.0f / min;
453 else if (src_width*mag < W) xscale = mag;
454
455 float yscale = 1.0f;
456 if (src_height > H*min) yscale = 1.0f / min;
457 else if (src_height*mag < H) yscale = mag;
458
459 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
460 const int tmp_w = floorf(src_width * xscale);
461 const int tmp_h = floorf(src_height * yscale);
462
463 if (mTempBitmap==0 ||
464 mTempBitmap->getWidth() < tmp_w ||
465 mTempBitmap->getHeight() < tmp_h) {
466 mTempBitmap.clear();
Fred Quintanab2fd4662009-08-11 20:49:35 -0700467 mTempBitmap = new android::Buffer(tmp_w, tmp_h, src.img.format);
Mathias Agopiand512f232009-06-25 17:41:12 -0700468 err = mTempBitmap->initCheck();
469 }
470
471 if (LIKELY(err == NO_ERROR)) {
472 NativeBuffer tmp;
473 tmp.img.w = tmp_w;
474 tmp.img.h = tmp_h;
475 tmp.img.format = src.img.format;
476 tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle;
477 tmp.crop.l = 0;
478 tmp.crop.t = 0;
479 tmp.crop.r = tmp.img.w;
480 tmp.crop.b = tmp.img.h;
481
482 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
483 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
484 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
485 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
486 err = copybit->stretch(copybit,
487 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
488 src = tmp;
489 }
490 }
491
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700492 const Rect& transformedBounds = mLayer.getTransformedBounds();
Mathias Agopiand512f232009-06-25 17:41:12 -0700493 const copybit_rect_t& drect =
494 reinterpret_cast<const copybit_rect_t&>(transformedBounds);
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700495 const State& s(mLayer.drawingState());
496 region_iterator it(clip);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700497
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700498 // pick the right orientation for this buffer
499 int orientation = mLayer.getOrientation();
500 if (UNLIKELY(mBufferHeap.transform)) {
501 Transform rot90;
502 GraphicPlane::orientationToTransfrom(
503 ISurfaceComposer::eOrientation90, 0, 0, &rot90);
504 const Transform& planeTransform(mLayer.graphicPlane(0).transform());
505 const Layer::State& s(mLayer.drawingState());
506 Transform tr(planeTransform * s.transform * rot90);
507 orientation = tr.getOrientation();
508 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700509
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700510 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
511 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
512 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700513
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700514 err = copybit->stretch(copybit,
515 &dst, &src.img, &drect, &src.crop, &it);
516 if (err != NO_ERROR) {
517 LOGE("copybit failed (%s)", strerror(err));
518 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700519 }
520 }
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700521#endif
522
Mathias Agopian69029eb2009-06-23 21:11:43 -0700523 if (!copybit || err)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700524 {
525 // OpenGL fall-back
526 if (UNLIKELY(mTexture.name == -1LU)) {
527 mTexture.name = mLayer.createTexture();
528 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700529 GLuint w = 0;
530 GLuint h = 0;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700531 GGLSurface t;
532 t.version = sizeof(GGLSurface);
533 t.width = src.crop.r;
534 t.height = src.crop.b;
535 t.stride = src.img.w;
536 t.vstride= src.img.h;
537 t.format = src.img.format;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700538 t.data = (GGLubyte*)src.img.base;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700539 const Region dirty(Rect(t.width, t.height));
540 mLayer.loadTexture(&mTexture, mTexture.name, dirty, t);
541 mTexture.transform = mBufferHeap.transform;
542 mLayer.drawWithOpenGL(clip, mTexture);
Mathias Agopian0926f502009-05-04 14:17:04 -0700543 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800544}
545
546
547// ---------------------------------------------------------------------------
548
549LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
550 sp<OverlayRef>* overlayRef,
551 uint32_t w, uint32_t h, int32_t format)
552 : Source(layer), mVisibilityChanged(false),
553 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
554{
555 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
556 if (overlay_dev == NULL) {
557 // overlays not supported
558 return;
559 }
560
561 mOverlayDevice = overlay_dev;
562 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
563 if (overlay == NULL) {
564 // couldn't create the overlay (no memory? no more overlays?)
565 return;
566 }
567
568 // enable dithering...
569 overlay_dev->setParameter(overlay_dev, overlay,
570 OVERLAY_DITHER, OVERLAY_ENABLE);
571
572 mOverlay = overlay;
573 mWidth = overlay->w;
574 mHeight = overlay->h;
575 mFormat = overlay->format;
576 mWidthStride = overlay->w_stride;
577 mHeightStride = overlay->h_stride;
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700578 mInitialized = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800579
580 mOverlayHandle = overlay->getHandleRef(overlay);
581
582 // NOTE: here it's okay to acquire a reference to "this"m as long as
583 // the reference is not released before we leave the ctor.
584 sp<OverlayChannel> channel = new OverlayChannel(this);
585
586 *overlayRef = new OverlayRef(mOverlayHandle, channel,
587 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
588}
589
590LayerBuffer::OverlaySource::~OverlaySource()
591{
592 if (mOverlay && mOverlayDevice) {
593 overlay_control_device_t* overlay_dev = mOverlayDevice;
594 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
595 }
596}
597
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700598void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
599{
600 mLayer.clearWithOpenGL(clip);
601}
602
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800603void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
604{
605 const Layer::State& front(mLayer.drawingState());
606 const Layer::State& temp(mLayer.currentState());
607 if (temp.sequence != front.sequence) {
608 mVisibilityChanged = true;
609 }
610}
611
612void LayerBuffer::OverlaySource::onVisibilityResolved(
613 const Transform& planeTransform)
614{
615 // this code-path must be as tight as possible, it's called each time
616 // the screen is composited.
617 if (UNLIKELY(mOverlay != 0)) {
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700618 if (mVisibilityChanged || !mInitialized) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800619 mVisibilityChanged = false;
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700620 mInitialized = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800621 const Rect& bounds = mLayer.getTransformedBounds();
622 int x = bounds.left;
623 int y = bounds.top;
624 int w = bounds.width();
625 int h = bounds.height();
626
627 // we need a lock here to protect "destroy"
628 Mutex::Autolock _l(mLock);
629 if (mOverlay) {
630 overlay_control_device_t* overlay_dev = mOverlayDevice;
631 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700632 overlay_dev->setParameter(overlay_dev, mOverlay,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800633 OVERLAY_TRANSFORM, mLayer.getOrientation());
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700634 overlay_dev->commit(overlay_dev, mOverlay);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800635 }
636 }
637 }
638}
639
640void LayerBuffer::OverlaySource::serverDestroy()
641{
642 mLayer.clearSource();
643 destroyOverlay();
644}
645
646void LayerBuffer::OverlaySource::destroyOverlay()
647{
648 // we need a lock here to protect "onVisibilityResolved"
649 Mutex::Autolock _l(mLock);
650 if (mOverlay) {
651 overlay_control_device_t* overlay_dev = mOverlayDevice;
652 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
653 mOverlay = 0;
654 }
655}
656
657// ---------------------------------------------------------------------------
658}; // namespace android