blob: 8a55a3f277e4c9cf36c99d04401a81efb5bc2503 [file] [log] [blame]
The Android Open Source Project9066cfe2009-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 Project9066cfe2009-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 Project9066cfe2009-03-03 19:31:44 -080026#include <ui/PixelFormat.h>
Mathias Agopiancbc4c9f2009-06-23 21:11:43 -070027#include <ui/FramebufferNativeWindow.h>
28
29#include <hardware/copybit.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
Mathias Agopian5cec4742009-08-11 22:34:02 -070031#include "BufferAllocator.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032#include "LayerBuffer.h"
33#include "SurfaceFlinger.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034#include "DisplayHardware/DisplayHardware.h"
35
Mathias Agopian2eab9d82009-06-24 16:55:59 -070036#include "gralloc_priv.h" // needed for msm / copybit
The Android Open Source Project9066cfe2009-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 Agopian6edf5af2009-06-19 17:00:27 -070048 const sp<Client>& client, int32_t i)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 : LayerBaseClient(flinger, display, client, i),
50 mNeedsBlending(false)
51{
52}
53
54LayerBuffer::~LayerBuffer()
55{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056}
57
Mathias Agopian6cf0db22009-04-17 19:36:26 -070058void LayerBuffer::onFirstRef()
59{
Mathias Agopianc6603952009-06-23 20:06:46 -070060 LayerBaseClient::onFirstRef();
Mathias Agopian6cf0db22009-04-17 19:36:26 -070061 mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
62 const_cast<LayerBuffer *>(this));
63}
64
Mathias Agopian1473f462009-04-10 14:24:30 -070065sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066{
Mathias Agopian6cf0db22009-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 Project9066cfe2009-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 Agopian6cf0db22009-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 Project9066cfe2009-03-03 19:31:44 -0800190{
191}
192
193LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
194{
195 unregisterBuffers();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196}
197
Mathias Agopian1473f462009-04-10 14:24:30 -0700198status_t LayerBuffer::SurfaceBuffer::registerBuffers(
199 const ISurface::BufferHeap& buffers)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200{
Mathias Agopian1473f462009-04-10 14:24:30 -0700201 sp<LayerBuffer> owner(getOwner());
202 if (owner != 0)
The Android Open Source Project9066cfe2009-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 Agopian1473f462009-04-10 14:24:30 -0700209 sp<LayerBuffer> owner(getOwner());
210 if (owner != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 owner->postBuffer(offset);
212}
213
214void LayerBuffer::SurfaceBuffer::unregisterBuffers()
215{
Mathias Agopian1473f462009-04-10 14:24:30 -0700216 sp<LayerBuffer> owner(getOwner());
217 if (owner != 0)
The Android Open Source Project9066cfe2009-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 Agopian1473f462009-04-10 14:24:30 -0700224 sp<LayerBuffer> owner(getOwner());
225 if (owner != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 result = owner->createOverlay(w, h, format);
227 return result;
228}
229
The Android Open Source Project9066cfe2009-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 Agopian2eab9d82009-06-24 16:55:59 -0700238
The Android Open Source Project9066cfe2009-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 Agopian2eab9d82009-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 Agopian8f78faa2009-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 Agopian2eab9d82009-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 Project9066cfe2009-03-03 19:31:44 -0800255}
256
257LayerBuffer::Buffer::~Buffer()
258{
Mathias Agopian2eab9d82009-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 Project9066cfe2009-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 Agopian999543b2009-06-23 18:08:22 -0700295 : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
The Android Open Source Project9066cfe2009-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 Agopiancbc4c9f2009-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 Project9066cfe2009-03-03 19:31:44 -0800340}
341
342LayerBuffer::BufferSource::~BufferSource()
343{
Mathias Agopian999543b2009-06-23 18:08:22 -0700344 if (mTexture.name != -1U) {
345 glDeleteTextures(1, &mTexture.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 }
Mathias Agopian68eeb802009-06-25 15:39:25 -0700347 if (mBlitEngine) {
348 copybit_close(mBlitEngine);
349 }
The Android Open Source Project9066cfe2009-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 Agopian999543b2009-06-23 18:08:22 -0700406 sp<Buffer> ourBuffer(getBuffer());
407 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 // nothing to do, we don't have a buffer
409 mLayer.clearWithOpenGL(clip);
410 return;
411 }
412
Mathias Agopiancbc4c9f2009-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 Project9066cfe2009-03-03 19:31:44 -0800417
Mathias Agopiancbc4c9f2009-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 Agopian26c28b12009-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 Agopiancbc4c9f2009-06-23 21:11:43 -0700441
Mathias Agopian8f78faa2009-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 Agopian5cec4742009-08-11 22:34:02 -0700468 mTempBitmap = new android::Buffer(
469 tmp_w, tmp_h, src.img.format,
Mathias Agopian5cec4742009-08-11 22:34:02 -0700470 BufferAllocator::USAGE_HW_2D);
Mathias Agopian8f78faa2009-06-25 17:41:12 -0700471 err = mTempBitmap->initCheck();
472 }
473
474 if (LIKELY(err == NO_ERROR)) {
475 NativeBuffer tmp;
476 tmp.img.w = tmp_w;
477 tmp.img.h = tmp_h;
478 tmp.img.format = src.img.format;
479 tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle;
480 tmp.crop.l = 0;
481 tmp.crop.t = 0;
482 tmp.crop.r = tmp.img.w;
483 tmp.crop.b = tmp.img.h;
484
485 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
486 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
487 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
488 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
489 err = copybit->stretch(copybit,
490 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
491 src = tmp;
492 }
493 }
494
Mathias Agopian26c28b12009-06-24 22:39:26 -0700495 const Rect& transformedBounds = mLayer.getTransformedBounds();
Mathias Agopian8f78faa2009-06-25 17:41:12 -0700496 const copybit_rect_t& drect =
497 reinterpret_cast<const copybit_rect_t&>(transformedBounds);
Mathias Agopian26c28b12009-06-24 22:39:26 -0700498 const State& s(mLayer.drawingState());
499 region_iterator it(clip);
Mathias Agopiancbc4c9f2009-06-23 21:11:43 -0700500
Mathias Agopian26c28b12009-06-24 22:39:26 -0700501 // pick the right orientation for this buffer
502 int orientation = mLayer.getOrientation();
503 if (UNLIKELY(mBufferHeap.transform)) {
504 Transform rot90;
505 GraphicPlane::orientationToTransfrom(
506 ISurfaceComposer::eOrientation90, 0, 0, &rot90);
507 const Transform& planeTransform(mLayer.graphicPlane(0).transform());
508 const Layer::State& s(mLayer.drawingState());
509 Transform tr(planeTransform * s.transform * rot90);
510 orientation = tr.getOrientation();
511 }
Mathias Agopiancbc4c9f2009-06-23 21:11:43 -0700512
Mathias Agopian26c28b12009-06-24 22:39:26 -0700513 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
514 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
515 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
Mathias Agopiancbc4c9f2009-06-23 21:11:43 -0700516
Mathias Agopian26c28b12009-06-24 22:39:26 -0700517 err = copybit->stretch(copybit,
518 &dst, &src.img, &drect, &src.crop, &it);
519 if (err != NO_ERROR) {
520 LOGE("copybit failed (%s)", strerror(err));
521 }
Mathias Agopiancbc4c9f2009-06-23 21:11:43 -0700522 }
523 }
Mathias Agopian26c28b12009-06-24 22:39:26 -0700524#endif
525
Mathias Agopiancbc4c9f2009-06-23 21:11:43 -0700526 if (!copybit || err)
Mathias Agopian999543b2009-06-23 18:08:22 -0700527 {
528 // OpenGL fall-back
529 if (UNLIKELY(mTexture.name == -1LU)) {
530 mTexture.name = mLayer.createTexture();
531 }
Mathias Agopiandff8e582009-05-04 14:17:04 -0700532 GLuint w = 0;
533 GLuint h = 0;
Mathias Agopian999543b2009-06-23 18:08:22 -0700534 GGLSurface t;
535 t.version = sizeof(GGLSurface);
536 t.width = src.crop.r;
537 t.height = src.crop.b;
538 t.stride = src.img.w;
539 t.vstride= src.img.h;
540 t.format = src.img.format;
Mathias Agopian2eab9d82009-06-24 16:55:59 -0700541 t.data = (GGLubyte*)src.img.base;
Mathias Agopian999543b2009-06-23 18:08:22 -0700542 const Region dirty(Rect(t.width, t.height));
543 mLayer.loadTexture(&mTexture, mTexture.name, dirty, t);
544 mTexture.transform = mBufferHeap.transform;
545 mLayer.drawWithOpenGL(clip, mTexture);
Mathias Agopiandff8e582009-05-04 14:17:04 -0700546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547}
548
549
550// ---------------------------------------------------------------------------
551
552LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
553 sp<OverlayRef>* overlayRef,
554 uint32_t w, uint32_t h, int32_t format)
555 : Source(layer), mVisibilityChanged(false),
556 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
557{
558 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
559 if (overlay_dev == NULL) {
560 // overlays not supported
561 return;
562 }
563
564 mOverlayDevice = overlay_dev;
565 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
566 if (overlay == NULL) {
567 // couldn't create the overlay (no memory? no more overlays?)
568 return;
569 }
570
571 // enable dithering...
572 overlay_dev->setParameter(overlay_dev, overlay,
573 OVERLAY_DITHER, OVERLAY_ENABLE);
574
575 mOverlay = overlay;
576 mWidth = overlay->w;
577 mHeight = overlay->h;
578 mFormat = overlay->format;
579 mWidthStride = overlay->w_stride;
580 mHeightStride = overlay->h_stride;
Rebecca Schultz Zavin43ab7632009-07-21 16:17:59 -0700581 mInitialized = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582
583 mOverlayHandle = overlay->getHandleRef(overlay);
584
585 // NOTE: here it's okay to acquire a reference to "this"m as long as
586 // the reference is not released before we leave the ctor.
587 sp<OverlayChannel> channel = new OverlayChannel(this);
588
589 *overlayRef = new OverlayRef(mOverlayHandle, channel,
590 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
591}
592
593LayerBuffer::OverlaySource::~OverlaySource()
594{
595 if (mOverlay && mOverlayDevice) {
596 overlay_control_device_t* overlay_dev = mOverlayDevice;
597 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
598 }
599}
600
Rebecca Schultz Zavin7ac5e692009-07-20 21:18:04 -0700601void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
602{
Rebecca Schultz Zavinc8546782009-09-01 23:06:45 -0700603 GLclampx color = 0x000018; //dark blue
604 GLclampx red = 0;
605 GLclampx green = 0;
606 GLclampx blue = 0x1818;
607 mLayer.clearWithOpenGL(clip, red, green, blue, 0);
Rebecca Schultz Zavin7ac5e692009-07-20 21:18:04 -0700608}
609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
611{
612 const Layer::State& front(mLayer.drawingState());
613 const Layer::State& temp(mLayer.currentState());
614 if (temp.sequence != front.sequence) {
615 mVisibilityChanged = true;
616 }
617}
618
619void LayerBuffer::OverlaySource::onVisibilityResolved(
620 const Transform& planeTransform)
621{
622 // this code-path must be as tight as possible, it's called each time
623 // the screen is composited.
624 if (UNLIKELY(mOverlay != 0)) {
Rebecca Schultz Zavin43ab7632009-07-21 16:17:59 -0700625 if (mVisibilityChanged || !mInitialized) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 mVisibilityChanged = false;
Rebecca Schultz Zavin43ab7632009-07-21 16:17:59 -0700627 mInitialized = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 const Rect& bounds = mLayer.getTransformedBounds();
629 int x = bounds.left;
630 int y = bounds.top;
631 int w = bounds.width();
632 int h = bounds.height();
633
634 // we need a lock here to protect "destroy"
635 Mutex::Autolock _l(mLock);
636 if (mOverlay) {
637 overlay_control_device_t* overlay_dev = mOverlayDevice;
638 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
Rebecca Schultz Zavin43ab7632009-07-21 16:17:59 -0700639 overlay_dev->setParameter(overlay_dev, mOverlay,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 OVERLAY_TRANSFORM, mLayer.getOrientation());
Rebecca Schultz Zavin7ac5e692009-07-20 21:18:04 -0700641 overlay_dev->commit(overlay_dev, mOverlay);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800642 }
643 }
644 }
645}
646
647void LayerBuffer::OverlaySource::serverDestroy()
648{
649 mLayer.clearSource();
650 destroyOverlay();
651}
652
653void LayerBuffer::OverlaySource::destroyOverlay()
654{
655 // we need a lock here to protect "onVisibilityResolved"
656 Mutex::Autolock _l(mLock);
657 if (mOverlay) {
658 overlay_control_device_t* overlay_dev = mOverlayDevice;
659 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
660 mOverlay = 0;
661 }
662}
663
664// ---------------------------------------------------------------------------
665}; // namespace android