blob: 433b48e1001fe1fcc47c1eb2b16394bc01924bdd [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 Agopiancbb288b2009-09-07 16:32:45 -070031#include "Buffer.h"
Mathias Agopian52212712009-08-11 22:34:02 -070032#include "BufferAllocator.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080033#include "LayerBuffer.h"
34#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080035#include "DisplayHardware/DisplayHardware.h"
36
Mathias Agopian5911aa92009-06-24 16:55:59 -070037#include "gralloc_priv.h" // needed for msm / copybit
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080038
39namespace android {
40
41// ---------------------------------------------------------------------------
42
43const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
44const char* const LayerBuffer::typeID = "LayerBuffer";
45
46// ---------------------------------------------------------------------------
47
48LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
Mathias Agopianf9d93272009-06-19 17:00:27 -070049 const sp<Client>& client, int32_t i)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050 : LayerBaseClient(flinger, display, client, i),
51 mNeedsBlending(false)
52{
53}
54
55LayerBuffer::~LayerBuffer()
56{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080057}
58
Mathias Agopian9a112062009-04-17 19:36:26 -070059void LayerBuffer::onFirstRef()
60{
Mathias Agopian2e123242009-06-23 20:06:46 -070061 LayerBaseClient::onFirstRef();
Mathias Agopiancbb288b2009-09-07 16:32:45 -070062 mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
Mathias Agopian9a112062009-04-17 19:36:26 -070063 const_cast<LayerBuffer *>(this));
64}
65
Mathias Agopian076b1cc2009-04-10 14:24:30 -070066sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080067{
Mathias Agopian9a112062009-04-17 19:36:26 -070068 return mSurface;
69}
70
71status_t LayerBuffer::ditch()
72{
73 mSurface.clear();
74 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080075}
76
77bool LayerBuffer::needsBlending() const {
78 return mNeedsBlending;
79}
80
81void LayerBuffer::setNeedsBlending(bool blending) {
82 mNeedsBlending = blending;
83}
84
85void LayerBuffer::postBuffer(ssize_t offset)
86{
87 sp<Source> source(getSource());
88 if (source != 0)
89 source->postBuffer(offset);
90}
91
92void LayerBuffer::unregisterBuffers()
93{
94 sp<Source> source(clearSource());
95 if (source != 0)
96 source->unregisterBuffers();
97}
98
99uint32_t LayerBuffer::doTransaction(uint32_t flags)
100{
101 sp<Source> source(getSource());
102 if (source != 0)
103 source->onTransaction(flags);
104 return LayerBase::doTransaction(flags);
105}
106
107void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
108 Region& outDirtyRegion)
109{
110 // this code-path must be as tight as possible, it's called each time
111 // the screen is composited.
112 sp<Source> source(getSource());
113 if (source != 0)
114 source->onVisibilityResolved(planeTransform);
115 LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
116}
117
118void LayerBuffer::onDraw(const Region& clip) const
119{
120 sp<Source> source(getSource());
121 if (LIKELY(source != 0)) {
122 source->onDraw(clip);
123 } else {
124 clearWithOpenGL(clip);
125 }
126}
127
128bool LayerBuffer::transformed() const
129{
130 sp<Source> source(getSource());
131 if (LIKELY(source != 0))
132 return source->transformed();
133 return false;
134}
135
136/**
137 * This creates a "buffer" source for this surface
138 */
139status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
140{
141 Mutex::Autolock _l(mLock);
142 if (mSource != 0)
143 return INVALID_OPERATION;
144
145 sp<BufferSource> source = new BufferSource(*this, buffers);
146
147 status_t result = source->getStatus();
148 if (result == NO_ERROR) {
149 mSource = source;
150 }
151 return result;
152}
153
154/**
155 * This creates an "overlay" source for this surface
156 */
157sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
158{
159 sp<OverlayRef> result;
160 Mutex::Autolock _l(mLock);
161 if (mSource != 0)
162 return result;
163
164 sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f);
165 if (result != 0) {
166 mSource = source;
167 }
168 return result;
169}
170
171sp<LayerBuffer::Source> LayerBuffer::getSource() const {
172 Mutex::Autolock _l(mLock);
173 return mSource;
174}
175
176sp<LayerBuffer::Source> LayerBuffer::clearSource() {
177 sp<Source> source;
178 Mutex::Autolock _l(mLock);
179 source = mSource;
180 mSource.clear();
181 return source;
182}
183
184// ============================================================================
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700185// LayerBuffer::SurfaceLayerBuffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800186// ============================================================================
187
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700188LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
Mathias Agopian9a112062009-04-17 19:36:26 -0700189 SurfaceID id, const sp<LayerBuffer>& owner)
190 : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800191{
192}
193
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700194LayerBuffer::SurfaceLayerBuffer::~SurfaceLayerBuffer()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800195{
196 unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800197}
198
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700199status_t LayerBuffer::SurfaceLayerBuffer::registerBuffers(
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700200 const ISurface::BufferHeap& buffers)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700202 sp<LayerBuffer> owner(getOwner());
203 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800204 return owner->registerBuffers(buffers);
205 return NO_INIT;
206}
207
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700208void LayerBuffer::SurfaceLayerBuffer::postBuffer(ssize_t offset)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700210 sp<LayerBuffer> owner(getOwner());
211 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800212 owner->postBuffer(offset);
213}
214
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700215void LayerBuffer::SurfaceLayerBuffer::unregisterBuffers()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700217 sp<LayerBuffer> owner(getOwner());
218 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800219 owner->unregisterBuffers();
220}
221
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700222sp<OverlayRef> LayerBuffer::SurfaceLayerBuffer::createOverlay(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800223 uint32_t w, uint32_t h, int32_t format) {
224 sp<OverlayRef> result;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700225 sp<LayerBuffer> owner(getOwner());
226 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800227 result = owner->createOverlay(w, h, format);
228 return result;
229}
230
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800231// ============================================================================
232// LayerBuffer::Buffer
233// ============================================================================
234
235LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
236 : mBufferHeap(buffers)
237{
238 NativeBuffer& src(mNativeBuffer);
Mathias Agopian5911aa92009-06-24 16:55:59 -0700239
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800240 src.crop.l = 0;
241 src.crop.t = 0;
242 src.crop.r = buffers.w;
243 src.crop.b = buffers.h;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700244
245 src.img.w = buffers.hor_stride ?: buffers.w;
246 src.img.h = buffers.ver_stride ?: buffers.h;
247 src.img.format = buffers.format;
248 src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset);
249
Mathias Agopiand512f232009-06-25 17:41:12 -0700250 // FIXME: gross hack, we should never access private_handle_t from here,
251 // but this is needed by msm drivers
Mathias Agopian5911aa92009-06-24 16:55:59 -0700252 private_handle_t* hnd = new private_handle_t(
253 buffers.heap->heapID(), buffers.heap->getSize(), 0);
254 hnd->offset = offset;
255 src.img.handle = hnd;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800256}
257
258LayerBuffer::Buffer::~Buffer()
259{
Mathias Agopian5911aa92009-06-24 16:55:59 -0700260 NativeBuffer& src(mNativeBuffer);
261 if (src.img.handle)
262 delete (private_handle_t*)src.img.handle;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800263}
264
265// ============================================================================
266// LayerBuffer::Source
267// LayerBuffer::BufferSource
268// LayerBuffer::OverlaySource
269// ============================================================================
270
271LayerBuffer::Source::Source(LayerBuffer& layer)
272 : mLayer(layer)
273{
274}
275LayerBuffer::Source::~Source() {
276}
277void LayerBuffer::Source::onDraw(const Region& clip) const {
278}
279void LayerBuffer::Source::onTransaction(uint32_t flags) {
280}
281void LayerBuffer::Source::onVisibilityResolved(
282 const Transform& planeTransform) {
283}
284void LayerBuffer::Source::postBuffer(ssize_t offset) {
285}
286void LayerBuffer::Source::unregisterBuffers() {
287}
288bool LayerBuffer::Source::transformed() const {
289 return mLayer.mTransformed;
290}
291
292// ---------------------------------------------------------------------------
293
294LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
295 const ISurface::BufferHeap& buffers)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700296 : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800297{
298 if (buffers.heap == NULL) {
299 // this is allowed, but in this case, it is illegal to receive
300 // postBuffer(). The surface just erases the framebuffer with
301 // fully transparent pixels.
302 mBufferHeap = buffers;
303 mLayer.setNeedsBlending(false);
304 return;
305 }
306
307 status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
308 if (err != NO_ERROR) {
309 LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
310 mStatus = err;
311 return;
312 }
313
314 PixelFormatInfo info;
315 err = getPixelFormatInfo(buffers.format, &info);
316 if (err != NO_ERROR) {
317 LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
318 buffers.format, strerror(err));
319 mStatus = err;
320 return;
321 }
322
323 if (buffers.hor_stride<0 || buffers.ver_stride<0) {
324 LOGE("LayerBuffer::BufferSource: invalid parameters "
325 "(w=%d, h=%d, xs=%d, ys=%d)",
326 buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
327 mStatus = BAD_VALUE;
328 return;
329 }
330
331 mBufferHeap = buffers;
332 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
333 mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
334 mLayer.forceVisibilityTransaction();
Mathias Agopian69029eb2009-06-23 21:11:43 -0700335
336 hw_module_t const* module;
337 mBlitEngine = NULL;
338 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
339 copybit_open(module, &mBlitEngine);
340 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800341}
342
343LayerBuffer::BufferSource::~BufferSource()
344{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700345 if (mTexture.name != -1U) {
346 glDeleteTextures(1, &mTexture.name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800347 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700348 if (mBlitEngine) {
349 copybit_close(mBlitEngine);
350 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351}
352
353void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
354{
355 ISurface::BufferHeap buffers;
356 { // scope for the lock
357 Mutex::Autolock _l(mLock);
358 buffers = mBufferHeap;
359 if (buffers.heap != 0) {
360 const size_t memorySize = buffers.heap->getSize();
361 if ((size_t(offset) + mBufferSize) > memorySize) {
362 LOGE("LayerBuffer::BufferSource::postBuffer() "
363 "invalid buffer (offset=%d, size=%d, heap-size=%d",
364 int(offset), int(mBufferSize), int(memorySize));
365 return;
366 }
367 }
368 }
369
370 sp<Buffer> buffer;
371 if (buffers.heap != 0) {
372 buffer = new LayerBuffer::Buffer(buffers, offset);
373 if (buffer->getStatus() != NO_ERROR)
374 buffer.clear();
375 setBuffer(buffer);
376 mLayer.invalidate();
377 }
378}
379
380void LayerBuffer::BufferSource::unregisterBuffers()
381{
382 Mutex::Autolock _l(mLock);
383 mBufferHeap.heap.clear();
384 mBuffer.clear();
385 mLayer.invalidate();
386}
387
388sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
389{
390 Mutex::Autolock _l(mLock);
391 return mBuffer;
392}
393
394void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
395{
396 Mutex::Autolock _l(mLock);
397 mBuffer = buffer;
398}
399
400bool LayerBuffer::BufferSource::transformed() const
401{
402 return mBufferHeap.transform ? true : Source::transformed();
403}
404
405void LayerBuffer::BufferSource::onDraw(const Region& clip) const
406{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700407 sp<Buffer> ourBuffer(getBuffer());
408 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800409 // nothing to do, we don't have a buffer
410 mLayer.clearWithOpenGL(clip);
411 return;
412 }
413
Mathias Agopian69029eb2009-06-23 21:11:43 -0700414 status_t err = NO_ERROR;
415 NativeBuffer src(ourBuffer->getBuffer());
416 const Rect& transformedBounds = mLayer.getTransformedBounds();
417 copybit_device_t* copybit = mBlitEngine;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800418
Mathias Agopian69029eb2009-06-23 21:11:43 -0700419 if (copybit) {
420 const int src_width = src.crop.r - src.crop.l;
421 const int src_height = src.crop.b - src.crop.t;
422 int W = transformedBounds.width();
423 int H = transformedBounds.height();
424 if (mLayer.getOrientation() & Transform::ROT_90) {
425 int t(W); W=H; H=t;
426 }
427
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700428#ifdef EGL_ANDROID_get_render_buffer
429 EGLDisplay dpy = eglGetCurrentDisplay();
430 EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
431 EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
432 android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
433 if (nb == 0) {
434 err = BAD_VALUE;
435 } else {
436 copybit_image_t dst;
437 dst.w = nb->width;
438 dst.h = nb->height;
439 dst.format = nb->format;
440 dst.base = NULL; // unused by copybit on msm7k
441 dst.handle = (native_handle_t *)nb->handle;
Mathias Agopian69029eb2009-06-23 21:11:43 -0700442
Mathias Agopiand512f232009-06-25 17:41:12 -0700443 /* With LayerBuffer, it is likely that we'll have to rescale the
444 * surface, because this is often used for video playback or
445 * camera-preview. Since we want these operation as fast as possible
446 * we make sure we can use the 2D H/W even if it doesn't support
447 * the requested scale factor, in which case we perform the scaling
448 * in several passes. */
449
450 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
451 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
452
453 float xscale = 1.0f;
454 if (src_width > W*min) xscale = 1.0f / min;
455 else if (src_width*mag < W) xscale = mag;
456
457 float yscale = 1.0f;
458 if (src_height > H*min) yscale = 1.0f / min;
459 else if (src_height*mag < H) yscale = mag;
460
461 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
462 const int tmp_w = floorf(src_width * xscale);
463 const int tmp_h = floorf(src_height * yscale);
464
465 if (mTempBitmap==0 ||
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700466 mTempBitmap->getWidth() < size_t(tmp_w) ||
467 mTempBitmap->getHeight() < size_t(tmp_h)) {
Mathias Agopiand512f232009-06-25 17:41:12 -0700468 mTempBitmap.clear();
Mathias Agopian52212712009-08-11 22:34:02 -0700469 mTempBitmap = new android::Buffer(
470 tmp_w, tmp_h, src.img.format,
Mathias Agopian52212712009-08-11 22:34:02 -0700471 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{
Rebecca Schultz Zavin29aa74c2009-09-01 23:06:45 -0700604 GLclampx color = 0x000018; //dark blue
605 GLclampx red = 0;
606 GLclampx green = 0;
607 GLclampx blue = 0x1818;
608 mLayer.clearWithOpenGL(clip, red, green, blue, 0);
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700609}
610
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800611void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
612{
613 const Layer::State& front(mLayer.drawingState());
614 const Layer::State& temp(mLayer.currentState());
615 if (temp.sequence != front.sequence) {
616 mVisibilityChanged = true;
617 }
618}
619
620void LayerBuffer::OverlaySource::onVisibilityResolved(
621 const Transform& planeTransform)
622{
623 // this code-path must be as tight as possible, it's called each time
624 // the screen is composited.
625 if (UNLIKELY(mOverlay != 0)) {
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700626 if (mVisibilityChanged || !mInitialized) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800627 mVisibilityChanged = false;
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700628 mInitialized = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800629 const Rect& bounds = mLayer.getTransformedBounds();
630 int x = bounds.left;
631 int y = bounds.top;
632 int w = bounds.width();
633 int h = bounds.height();
634
635 // we need a lock here to protect "destroy"
636 Mutex::Autolock _l(mLock);
637 if (mOverlay) {
638 overlay_control_device_t* overlay_dev = mOverlayDevice;
639 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700640 overlay_dev->setParameter(overlay_dev, mOverlay,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800641 OVERLAY_TRANSFORM, mLayer.getOrientation());
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700642 overlay_dev->commit(overlay_dev, mOverlay);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800643 }
644 }
645 }
646}
647
648void LayerBuffer::OverlaySource::serverDestroy()
649{
650 mLayer.clearSource();
651 destroyOverlay();
652}
653
654void LayerBuffer::OverlaySource::destroyOverlay()
655{
656 // we need a lock here to protect "onVisibilityResolved"
657 Mutex::Autolock _l(mLock);
658 if (mOverlay) {
659 overlay_control_device_t* overlay_dev = mOverlayDevice;
660 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
661 mOverlay = 0;
662 }
663}
664
665// ---------------------------------------------------------------------------
666}; // namespace android