blob: e1f4bea228c54a925d7bfdc6267dd0c2f5e74926 [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
Mathias Agopian52212712009-08-11 22:34:02 -070031#include "BufferAllocator.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032#include "LayerBuffer.h"
33#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080034#include "DisplayHardware/DisplayHardware.h"
35
Mathias Agopian5911aa92009-06-24 16:55:59 -070036#include "gralloc_priv.h" // needed for msm / copybit
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037
38namespace android {
39
40// ---------------------------------------------------------------------------
41
42const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
43const char* const LayerBuffer::typeID = "LayerBuffer";
44
45// ---------------------------------------------------------------------------
46
47LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
Mathias Agopianf9d93272009-06-19 17:00:27 -070048 const sp<Client>& client, int32_t i)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049 : LayerBaseClient(flinger, display, client, i),
50 mNeedsBlending(false)
51{
52}
53
54LayerBuffer::~LayerBuffer()
55{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080056}
57
Mathias Agopian9a112062009-04-17 19:36:26 -070058void LayerBuffer::onFirstRef()
59{
Mathias Agopian2e123242009-06-23 20:06:46 -070060 LayerBaseClient::onFirstRef();
Mathias Agopian9a112062009-04-17 19:36:26 -070061 mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
62 const_cast<LayerBuffer *>(this));
63}
64
Mathias Agopian076b1cc2009-04-10 14:24:30 -070065sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080066{
Mathias Agopian9a112062009-04-17 19:36:26 -070067 return mSurface;
68}
69
70status_t LayerBuffer::ditch()
71{
72 mSurface.clear();
73 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080074}
75
76bool LayerBuffer::needsBlending() const {
77 return mNeedsBlending;
78}
79
80void LayerBuffer::setNeedsBlending(bool blending) {
81 mNeedsBlending = blending;
82}
83
84void LayerBuffer::postBuffer(ssize_t offset)
85{
86 sp<Source> source(getSource());
87 if (source != 0)
88 source->postBuffer(offset);
89}
90
91void LayerBuffer::unregisterBuffers()
92{
93 sp<Source> source(clearSource());
94 if (source != 0)
95 source->unregisterBuffers();
96}
97
98uint32_t LayerBuffer::doTransaction(uint32_t flags)
99{
100 sp<Source> source(getSource());
101 if (source != 0)
102 source->onTransaction(flags);
103 return LayerBase::doTransaction(flags);
104}
105
106void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
107 Region& outDirtyRegion)
108{
109 // this code-path must be as tight as possible, it's called each time
110 // the screen is composited.
111 sp<Source> source(getSource());
112 if (source != 0)
113 source->onVisibilityResolved(planeTransform);
114 LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
115}
116
117void LayerBuffer::onDraw(const Region& clip) const
118{
119 sp<Source> source(getSource());
120 if (LIKELY(source != 0)) {
121 source->onDraw(clip);
122 } else {
123 clearWithOpenGL(clip);
124 }
125}
126
127bool LayerBuffer::transformed() const
128{
129 sp<Source> source(getSource());
130 if (LIKELY(source != 0))
131 return source->transformed();
132 return false;
133}
134
135/**
136 * This creates a "buffer" source for this surface
137 */
138status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
139{
140 Mutex::Autolock _l(mLock);
141 if (mSource != 0)
142 return INVALID_OPERATION;
143
144 sp<BufferSource> source = new BufferSource(*this, buffers);
145
146 status_t result = source->getStatus();
147 if (result == NO_ERROR) {
148 mSource = source;
149 }
150 return result;
151}
152
153/**
154 * This creates an "overlay" source for this surface
155 */
156sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
157{
158 sp<OverlayRef> result;
159 Mutex::Autolock _l(mLock);
160 if (mSource != 0)
161 return result;
162
163 sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f);
164 if (result != 0) {
165 mSource = source;
166 }
167 return result;
168}
169
170sp<LayerBuffer::Source> LayerBuffer::getSource() const {
171 Mutex::Autolock _l(mLock);
172 return mSource;
173}
174
175sp<LayerBuffer::Source> LayerBuffer::clearSource() {
176 sp<Source> source;
177 Mutex::Autolock _l(mLock);
178 source = mSource;
179 mSource.clear();
180 return source;
181}
182
183// ============================================================================
184// LayerBuffer::SurfaceBuffer
185// ============================================================================
186
Mathias Agopian9a112062009-04-17 19:36:26 -0700187LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
188 SurfaceID id, const sp<LayerBuffer>& owner)
189 : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800190{
191}
192
193LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
194{
195 unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800196}
197
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700198status_t LayerBuffer::SurfaceBuffer::registerBuffers(
199 const ISurface::BufferHeap& buffers)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700201 sp<LayerBuffer> owner(getOwner());
202 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203 return owner->registerBuffers(buffers);
204 return NO_INIT;
205}
206
207void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
208{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700209 sp<LayerBuffer> owner(getOwner());
210 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800211 owner->postBuffer(offset);
212}
213
214void LayerBuffer::SurfaceBuffer::unregisterBuffers()
215{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700216 sp<LayerBuffer> owner(getOwner());
217 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800218 owner->unregisterBuffers();
219}
220
221sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
222 uint32_t w, uint32_t h, int32_t format) {
223 sp<OverlayRef> result;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700224 sp<LayerBuffer> owner(getOwner());
225 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800226 result = owner->createOverlay(w, h, format);
227 return result;
228}
229
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800230// ============================================================================
231// LayerBuffer::Buffer
232// ============================================================================
233
234LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
235 : mBufferHeap(buffers)
236{
237 NativeBuffer& src(mNativeBuffer);
Mathias Agopian5911aa92009-06-24 16:55:59 -0700238
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800239 src.crop.l = 0;
240 src.crop.t = 0;
241 src.crop.r = buffers.w;
242 src.crop.b = buffers.h;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700243
244 src.img.w = buffers.hor_stride ?: buffers.w;
245 src.img.h = buffers.ver_stride ?: buffers.h;
246 src.img.format = buffers.format;
247 src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset);
248
Mathias Agopiand512f232009-06-25 17:41:12 -0700249 // FIXME: gross hack, we should never access private_handle_t from here,
250 // but this is needed by msm drivers
Mathias Agopian5911aa92009-06-24 16:55:59 -0700251 private_handle_t* hnd = new private_handle_t(
252 buffers.heap->heapID(), buffers.heap->getSize(), 0);
253 hnd->offset = offset;
254 src.img.handle = hnd;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800255}
256
257LayerBuffer::Buffer::~Buffer()
258{
Mathias Agopian5911aa92009-06-24 16:55:59 -0700259 NativeBuffer& src(mNativeBuffer);
260 if (src.img.handle)
261 delete (private_handle_t*)src.img.handle;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800262}
263
264// ============================================================================
265// LayerBuffer::Source
266// LayerBuffer::BufferSource
267// LayerBuffer::OverlaySource
268// ============================================================================
269
270LayerBuffer::Source::Source(LayerBuffer& layer)
271 : mLayer(layer)
272{
273}
274LayerBuffer::Source::~Source() {
275}
276void LayerBuffer::Source::onDraw(const Region& clip) const {
277}
278void LayerBuffer::Source::onTransaction(uint32_t flags) {
279}
280void LayerBuffer::Source::onVisibilityResolved(
281 const Transform& planeTransform) {
282}
283void LayerBuffer::Source::postBuffer(ssize_t offset) {
284}
285void LayerBuffer::Source::unregisterBuffers() {
286}
287bool LayerBuffer::Source::transformed() const {
288 return mLayer.mTransformed;
289}
290
291// ---------------------------------------------------------------------------
292
293LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
294 const ISurface::BufferHeap& buffers)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700295 : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800296{
297 if (buffers.heap == NULL) {
298 // this is allowed, but in this case, it is illegal to receive
299 // postBuffer(). The surface just erases the framebuffer with
300 // fully transparent pixels.
301 mBufferHeap = buffers;
302 mLayer.setNeedsBlending(false);
303 return;
304 }
305
306 status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
307 if (err != NO_ERROR) {
308 LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
309 mStatus = err;
310 return;
311 }
312
313 PixelFormatInfo info;
314 err = getPixelFormatInfo(buffers.format, &info);
315 if (err != NO_ERROR) {
316 LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
317 buffers.format, strerror(err));
318 mStatus = err;
319 return;
320 }
321
322 if (buffers.hor_stride<0 || buffers.ver_stride<0) {
323 LOGE("LayerBuffer::BufferSource: invalid parameters "
324 "(w=%d, h=%d, xs=%d, ys=%d)",
325 buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
326 mStatus = BAD_VALUE;
327 return;
328 }
329
330 mBufferHeap = buffers;
331 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
332 mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
333 mLayer.forceVisibilityTransaction();
Mathias Agopian69029eb2009-06-23 21:11:43 -0700334
335 hw_module_t const* module;
336 mBlitEngine = NULL;
337 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
338 copybit_open(module, &mBlitEngine);
339 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800340}
341
342LayerBuffer::BufferSource::~BufferSource()
343{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700344 if (mTexture.name != -1U) {
345 glDeleteTextures(1, &mTexture.name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800346 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700347 if (mBlitEngine) {
348 copybit_close(mBlitEngine);
349 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800350}
351
352void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
353{
354 ISurface::BufferHeap buffers;
355 { // scope for the lock
356 Mutex::Autolock _l(mLock);
357 buffers = mBufferHeap;
358 if (buffers.heap != 0) {
359 const size_t memorySize = buffers.heap->getSize();
360 if ((size_t(offset) + mBufferSize) > memorySize) {
361 LOGE("LayerBuffer::BufferSource::postBuffer() "
362 "invalid buffer (offset=%d, size=%d, heap-size=%d",
363 int(offset), int(mBufferSize), int(memorySize));
364 return;
365 }
366 }
367 }
368
369 sp<Buffer> buffer;
370 if (buffers.heap != 0) {
371 buffer = new LayerBuffer::Buffer(buffers, offset);
372 if (buffer->getStatus() != NO_ERROR)
373 buffer.clear();
374 setBuffer(buffer);
375 mLayer.invalidate();
376 }
377}
378
379void LayerBuffer::BufferSource::unregisterBuffers()
380{
381 Mutex::Autolock _l(mLock);
382 mBufferHeap.heap.clear();
383 mBuffer.clear();
384 mLayer.invalidate();
385}
386
387sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
388{
389 Mutex::Autolock _l(mLock);
390 return mBuffer;
391}
392
393void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
394{
395 Mutex::Autolock _l(mLock);
396 mBuffer = buffer;
397}
398
399bool LayerBuffer::BufferSource::transformed() const
400{
401 return mBufferHeap.transform ? true : Source::transformed();
402}
403
404void LayerBuffer::BufferSource::onDraw(const Region& clip) const
405{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700406 sp<Buffer> ourBuffer(getBuffer());
407 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800408 // nothing to do, we don't have a buffer
409 mLayer.clearWithOpenGL(clip);
410 return;
411 }
412
Mathias Agopian69029eb2009-06-23 21:11:43 -0700413 status_t err = NO_ERROR;
414 NativeBuffer src(ourBuffer->getBuffer());
415 const Rect& transformedBounds = mLayer.getTransformedBounds();
416 copybit_device_t* copybit = mBlitEngine;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800417
Mathias Agopian69029eb2009-06-23 21:11:43 -0700418 if (copybit) {
419 const int src_width = src.crop.r - src.crop.l;
420 const int src_height = src.crop.b - src.crop.t;
421 int W = transformedBounds.width();
422 int H = transformedBounds.height();
423 if (mLayer.getOrientation() & Transform::ROT_90) {
424 int t(W); W=H; H=t;
425 }
426
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700427#ifdef EGL_ANDROID_get_render_buffer
428 EGLDisplay dpy = eglGetCurrentDisplay();
429 EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
430 EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
431 android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
432 if (nb == 0) {
433 err = BAD_VALUE;
434 } else {
435 copybit_image_t dst;
436 dst.w = nb->width;
437 dst.h = nb->height;
438 dst.format = nb->format;
439 dst.base = NULL; // unused by copybit on msm7k
440 dst.handle = (native_handle_t *)nb->handle;
Mathias Agopian69029eb2009-06-23 21:11:43 -0700441
Mathias Agopiand512f232009-06-25 17:41:12 -0700442 /* With LayerBuffer, it is likely that we'll have to rescale the
443 * surface, because this is often used for video playback or
444 * camera-preview. Since we want these operation as fast as possible
445 * we make sure we can use the 2D H/W even if it doesn't support
446 * the requested scale factor, in which case we perform the scaling
447 * in several passes. */
448
449 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
450 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
451
452 float xscale = 1.0f;
453 if (src_width > W*min) xscale = 1.0f / min;
454 else if (src_width*mag < W) xscale = mag;
455
456 float yscale = 1.0f;
457 if (src_height > H*min) yscale = 1.0f / min;
458 else if (src_height*mag < H) yscale = mag;
459
460 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
461 const int tmp_w = floorf(src_width * xscale);
462 const int tmp_h = floorf(src_height * yscale);
463
464 if (mTempBitmap==0 ||
465 mTempBitmap->getWidth() < tmp_w ||
466 mTempBitmap->getHeight() < tmp_h) {
467 mTempBitmap.clear();
Mathias Agopian52212712009-08-11 22:34:02 -0700468 mTempBitmap = new android::Buffer(
469 tmp_w, tmp_h, src.img.format,
470 BufferAllocator::USAGE_HW_TEXTURE |
471 BufferAllocator::USAGE_HW_2D);
Mathias Agopiand512f232009-06-25 17:41:12 -0700472 err = mTempBitmap->initCheck();
473 }
474
475 if (LIKELY(err == NO_ERROR)) {
476 NativeBuffer tmp;
477 tmp.img.w = tmp_w;
478 tmp.img.h = tmp_h;
479 tmp.img.format = src.img.format;
480 tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle;
481 tmp.crop.l = 0;
482 tmp.crop.t = 0;
483 tmp.crop.r = tmp.img.w;
484 tmp.crop.b = tmp.img.h;
485
486 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
487 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
488 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
489 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
490 err = copybit->stretch(copybit,
491 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
492 src = tmp;
493 }
494 }
495
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700496 const Rect& transformedBounds = mLayer.getTransformedBounds();
Mathias Agopiand512f232009-06-25 17:41:12 -0700497 const copybit_rect_t& drect =
498 reinterpret_cast<const copybit_rect_t&>(transformedBounds);
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700499 const State& s(mLayer.drawingState());
500 region_iterator it(clip);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700501
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700502 // pick the right orientation for this buffer
503 int orientation = mLayer.getOrientation();
504 if (UNLIKELY(mBufferHeap.transform)) {
505 Transform rot90;
506 GraphicPlane::orientationToTransfrom(
507 ISurfaceComposer::eOrientation90, 0, 0, &rot90);
508 const Transform& planeTransform(mLayer.graphicPlane(0).transform());
509 const Layer::State& s(mLayer.drawingState());
510 Transform tr(planeTransform * s.transform * rot90);
511 orientation = tr.getOrientation();
512 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700513
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700514 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
515 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
516 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
Mathias Agopian69029eb2009-06-23 21:11:43 -0700517
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700518 err = copybit->stretch(copybit,
519 &dst, &src.img, &drect, &src.crop, &it);
520 if (err != NO_ERROR) {
521 LOGE("copybit failed (%s)", strerror(err));
522 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700523 }
524 }
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700525#endif
526
Mathias Agopian69029eb2009-06-23 21:11:43 -0700527 if (!copybit || err)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700528 {
529 // OpenGL fall-back
530 if (UNLIKELY(mTexture.name == -1LU)) {
531 mTexture.name = mLayer.createTexture();
532 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700533 GLuint w = 0;
534 GLuint h = 0;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700535 GGLSurface t;
536 t.version = sizeof(GGLSurface);
537 t.width = src.crop.r;
538 t.height = src.crop.b;
539 t.stride = src.img.w;
540 t.vstride= src.img.h;
541 t.format = src.img.format;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700542 t.data = (GGLubyte*)src.img.base;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700543 const Region dirty(Rect(t.width, t.height));
544 mLayer.loadTexture(&mTexture, mTexture.name, dirty, t);
545 mTexture.transform = mBufferHeap.transform;
546 mLayer.drawWithOpenGL(clip, mTexture);
Mathias Agopian0926f502009-05-04 14:17:04 -0700547 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800548}
549
550
551// ---------------------------------------------------------------------------
552
553LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
554 sp<OverlayRef>* overlayRef,
555 uint32_t w, uint32_t h, int32_t format)
556 : Source(layer), mVisibilityChanged(false),
557 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
558{
559 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
560 if (overlay_dev == NULL) {
561 // overlays not supported
562 return;
563 }
564
565 mOverlayDevice = overlay_dev;
566 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
567 if (overlay == NULL) {
568 // couldn't create the overlay (no memory? no more overlays?)
569 return;
570 }
571
572 // enable dithering...
573 overlay_dev->setParameter(overlay_dev, overlay,
574 OVERLAY_DITHER, OVERLAY_ENABLE);
575
576 mOverlay = overlay;
577 mWidth = overlay->w;
578 mHeight = overlay->h;
579 mFormat = overlay->format;
580 mWidthStride = overlay->w_stride;
581 mHeightStride = overlay->h_stride;
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700582 mInitialized = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800583
584 mOverlayHandle = overlay->getHandleRef(overlay);
585
586 // NOTE: here it's okay to acquire a reference to "this"m as long as
587 // the reference is not released before we leave the ctor.
588 sp<OverlayChannel> channel = new OverlayChannel(this);
589
590 *overlayRef = new OverlayRef(mOverlayHandle, channel,
591 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
592}
593
594LayerBuffer::OverlaySource::~OverlaySource()
595{
596 if (mOverlay && mOverlayDevice) {
597 overlay_control_device_t* overlay_dev = mOverlayDevice;
598 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
599 }
600}
601
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700602void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
603{
604 mLayer.clearWithOpenGL(clip);
605}
606
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800607void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
608{
609 const Layer::State& front(mLayer.drawingState());
610 const Layer::State& temp(mLayer.currentState());
611 if (temp.sequence != front.sequence) {
612 mVisibilityChanged = true;
613 }
614}
615
616void LayerBuffer::OverlaySource::onVisibilityResolved(
617 const Transform& planeTransform)
618{
619 // this code-path must be as tight as possible, it's called each time
620 // the screen is composited.
621 if (UNLIKELY(mOverlay != 0)) {
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700622 if (mVisibilityChanged || !mInitialized) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800623 mVisibilityChanged = false;
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700624 mInitialized = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800625 const Rect& bounds = mLayer.getTransformedBounds();
626 int x = bounds.left;
627 int y = bounds.top;
628 int w = bounds.width();
629 int h = bounds.height();
630
631 // we need a lock here to protect "destroy"
632 Mutex::Autolock _l(mLock);
633 if (mOverlay) {
634 overlay_control_device_t* overlay_dev = mOverlayDevice;
635 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700636 overlay_dev->setParameter(overlay_dev, mOverlay,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800637 OVERLAY_TRANSFORM, mLayer.getOrientation());
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700638 overlay_dev->commit(overlay_dev, mOverlay);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800639 }
640 }
641 }
642}
643
644void LayerBuffer::OverlaySource::serverDestroy()
645{
646 mLayer.clearSource();
647 destroyOverlay();
648}
649
650void LayerBuffer::OverlaySource::destroyOverlay()
651{
652 // we need a lock here to protect "onVisibilityResolved"
653 Mutex::Autolock _l(mLock);
654 if (mOverlay) {
655 overlay_control_device_t* overlay_dev = mOverlayDevice;
656 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
657 mOverlay = 0;
658 }
659}
660
661// ---------------------------------------------------------------------------
662}; // namespace android