blob: 3db5434564febff2093d001cff53b395d065e86d [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>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027
28#include "LayerBuffer.h"
29#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080030#include "DisplayHardware/DisplayHardware.h"
31
32
33namespace android {
34
35// ---------------------------------------------------------------------------
36
37const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
38const char* const LayerBuffer::typeID = "LayerBuffer";
39
40// ---------------------------------------------------------------------------
41
42LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
Mathias Agopianf9d93272009-06-19 17:00:27 -070043 const sp<Client>& client, int32_t i)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044 : LayerBaseClient(flinger, display, client, i),
45 mNeedsBlending(false)
46{
47}
48
49LayerBuffer::~LayerBuffer()
50{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080051}
52
Mathias Agopian9a112062009-04-17 19:36:26 -070053void LayerBuffer::onFirstRef()
54{
55 mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
56 const_cast<LayerBuffer *>(this));
57}
58
Mathias Agopian076b1cc2009-04-10 14:24:30 -070059sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080060{
Mathias Agopian9a112062009-04-17 19:36:26 -070061 return mSurface;
62}
63
64status_t LayerBuffer::ditch()
65{
66 mSurface.clear();
67 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080068}
69
70bool LayerBuffer::needsBlending() const {
71 return mNeedsBlending;
72}
73
74void LayerBuffer::setNeedsBlending(bool blending) {
75 mNeedsBlending = blending;
76}
77
78void LayerBuffer::postBuffer(ssize_t offset)
79{
80 sp<Source> source(getSource());
81 if (source != 0)
82 source->postBuffer(offset);
83}
84
85void LayerBuffer::unregisterBuffers()
86{
87 sp<Source> source(clearSource());
88 if (source != 0)
89 source->unregisterBuffers();
90}
91
92uint32_t LayerBuffer::doTransaction(uint32_t flags)
93{
94 sp<Source> source(getSource());
95 if (source != 0)
96 source->onTransaction(flags);
97 return LayerBase::doTransaction(flags);
98}
99
100void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
101 Region& outDirtyRegion)
102{
103 // this code-path must be as tight as possible, it's called each time
104 // the screen is composited.
105 sp<Source> source(getSource());
106 if (source != 0)
107 source->onVisibilityResolved(planeTransform);
108 LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
109}
110
111void LayerBuffer::onDraw(const Region& clip) const
112{
113 sp<Source> source(getSource());
114 if (LIKELY(source != 0)) {
115 source->onDraw(clip);
116 } else {
117 clearWithOpenGL(clip);
118 }
119}
120
121bool LayerBuffer::transformed() const
122{
123 sp<Source> source(getSource());
124 if (LIKELY(source != 0))
125 return source->transformed();
126 return false;
127}
128
129/**
130 * This creates a "buffer" source for this surface
131 */
132status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
133{
134 Mutex::Autolock _l(mLock);
135 if (mSource != 0)
136 return INVALID_OPERATION;
137
138 sp<BufferSource> source = new BufferSource(*this, buffers);
139
140 status_t result = source->getStatus();
141 if (result == NO_ERROR) {
142 mSource = source;
143 }
144 return result;
145}
146
147/**
148 * This creates an "overlay" source for this surface
149 */
150sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
151{
152 sp<OverlayRef> result;
153 Mutex::Autolock _l(mLock);
154 if (mSource != 0)
155 return result;
156
157 sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f);
158 if (result != 0) {
159 mSource = source;
160 }
161 return result;
162}
163
164sp<LayerBuffer::Source> LayerBuffer::getSource() const {
165 Mutex::Autolock _l(mLock);
166 return mSource;
167}
168
169sp<LayerBuffer::Source> LayerBuffer::clearSource() {
170 sp<Source> source;
171 Mutex::Autolock _l(mLock);
172 source = mSource;
173 mSource.clear();
174 return source;
175}
176
177// ============================================================================
178// LayerBuffer::SurfaceBuffer
179// ============================================================================
180
Mathias Agopian9a112062009-04-17 19:36:26 -0700181LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
182 SurfaceID id, const sp<LayerBuffer>& owner)
183 : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800184{
185}
186
187LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
188{
189 unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800190}
191
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700192status_t LayerBuffer::SurfaceBuffer::registerBuffers(
193 const ISurface::BufferHeap& buffers)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700195 sp<LayerBuffer> owner(getOwner());
196 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800197 return owner->registerBuffers(buffers);
198 return NO_INIT;
199}
200
201void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
202{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700203 sp<LayerBuffer> owner(getOwner());
204 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800205 owner->postBuffer(offset);
206}
207
208void LayerBuffer::SurfaceBuffer::unregisterBuffers()
209{
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->unregisterBuffers();
213}
214
215sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
216 uint32_t w, uint32_t h, int32_t format) {
217 sp<OverlayRef> result;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700218 sp<LayerBuffer> owner(getOwner());
219 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800220 result = owner->createOverlay(w, h, format);
221 return result;
222}
223
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224// ============================================================================
225// LayerBuffer::Buffer
226// ============================================================================
227
228LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
229 : mBufferHeap(buffers)
230{
231 NativeBuffer& src(mNativeBuffer);
232 src.crop.l = 0;
233 src.crop.t = 0;
234 src.crop.r = buffers.w;
235 src.crop.b = buffers.h;
236 src.img.w = buffers.hor_stride ?: buffers.w;
237 src.img.h = buffers.ver_stride ?: buffers.h;
238 src.img.format = buffers.format;
239 src.img.offset = offset;
240 src.img.base = buffers.heap->base();
241 src.img.fd = buffers.heap->heapID();
242}
243
244LayerBuffer::Buffer::~Buffer()
245{
246}
247
248// ============================================================================
249// LayerBuffer::Source
250// LayerBuffer::BufferSource
251// LayerBuffer::OverlaySource
252// ============================================================================
253
254LayerBuffer::Source::Source(LayerBuffer& layer)
255 : mLayer(layer)
256{
257}
258LayerBuffer::Source::~Source() {
259}
260void LayerBuffer::Source::onDraw(const Region& clip) const {
261}
262void LayerBuffer::Source::onTransaction(uint32_t flags) {
263}
264void LayerBuffer::Source::onVisibilityResolved(
265 const Transform& planeTransform) {
266}
267void LayerBuffer::Source::postBuffer(ssize_t offset) {
268}
269void LayerBuffer::Source::unregisterBuffers() {
270}
271bool LayerBuffer::Source::transformed() const {
272 return mLayer.mTransformed;
273}
274
275// ---------------------------------------------------------------------------
276
277LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
278 const ISurface::BufferHeap& buffers)
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700279 : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800280{
281 if (buffers.heap == NULL) {
282 // this is allowed, but in this case, it is illegal to receive
283 // postBuffer(). The surface just erases the framebuffer with
284 // fully transparent pixels.
285 mBufferHeap = buffers;
286 mLayer.setNeedsBlending(false);
287 return;
288 }
289
290 status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
291 if (err != NO_ERROR) {
292 LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
293 mStatus = err;
294 return;
295 }
296
297 PixelFormatInfo info;
298 err = getPixelFormatInfo(buffers.format, &info);
299 if (err != NO_ERROR) {
300 LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
301 buffers.format, strerror(err));
302 mStatus = err;
303 return;
304 }
305
306 if (buffers.hor_stride<0 || buffers.ver_stride<0) {
307 LOGE("LayerBuffer::BufferSource: invalid parameters "
308 "(w=%d, h=%d, xs=%d, ys=%d)",
309 buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
310 mStatus = BAD_VALUE;
311 return;
312 }
313
314 mBufferHeap = buffers;
315 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
316 mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
317 mLayer.forceVisibilityTransaction();
318
319}
320
321LayerBuffer::BufferSource::~BufferSource()
322{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700323 if (mTexture.name != -1U) {
324 glDeleteTextures(1, &mTexture.name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800325 }
326}
327
328void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
329{
330 ISurface::BufferHeap buffers;
331 { // scope for the lock
332 Mutex::Autolock _l(mLock);
333 buffers = mBufferHeap;
334 if (buffers.heap != 0) {
335 const size_t memorySize = buffers.heap->getSize();
336 if ((size_t(offset) + mBufferSize) > memorySize) {
337 LOGE("LayerBuffer::BufferSource::postBuffer() "
338 "invalid buffer (offset=%d, size=%d, heap-size=%d",
339 int(offset), int(mBufferSize), int(memorySize));
340 return;
341 }
342 }
343 }
344
345 sp<Buffer> buffer;
346 if (buffers.heap != 0) {
347 buffer = new LayerBuffer::Buffer(buffers, offset);
348 if (buffer->getStatus() != NO_ERROR)
349 buffer.clear();
350 setBuffer(buffer);
351 mLayer.invalidate();
352 }
353}
354
355void LayerBuffer::BufferSource::unregisterBuffers()
356{
357 Mutex::Autolock _l(mLock);
358 mBufferHeap.heap.clear();
359 mBuffer.clear();
360 mLayer.invalidate();
361}
362
363sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
364{
365 Mutex::Autolock _l(mLock);
366 return mBuffer;
367}
368
369void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
370{
371 Mutex::Autolock _l(mLock);
372 mBuffer = buffer;
373}
374
375bool LayerBuffer::BufferSource::transformed() const
376{
377 return mBufferHeap.transform ? true : Source::transformed();
378}
379
380void LayerBuffer::BufferSource::onDraw(const Region& clip) const
381{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700382 sp<Buffer> ourBuffer(getBuffer());
383 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800384 // nothing to do, we don't have a buffer
385 mLayer.clearWithOpenGL(clip);
386 return;
387 }
388
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700389 const NativeBuffer& src( ourBuffer->getBuffer() );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800390
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700391 //if (!can_use_copybit || err)
392 {
393 // OpenGL fall-back
394 if (UNLIKELY(mTexture.name == -1LU)) {
395 mTexture.name = mLayer.createTexture();
396 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700397 GLuint w = 0;
398 GLuint h = 0;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700399 GGLSurface t;
400 t.version = sizeof(GGLSurface);
401 t.width = src.crop.r;
402 t.height = src.crop.b;
403 t.stride = src.img.w;
404 t.vstride= src.img.h;
405 t.format = src.img.format;
406 t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
407 const Region dirty(Rect(t.width, t.height));
408 mLayer.loadTexture(&mTexture, mTexture.name, dirty, t);
409 mTexture.transform = mBufferHeap.transform;
410 mLayer.drawWithOpenGL(clip, mTexture);
Mathias Agopian0926f502009-05-04 14:17:04 -0700411 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800412}
413
414
415// ---------------------------------------------------------------------------
416
417LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
418 sp<OverlayRef>* overlayRef,
419 uint32_t w, uint32_t h, int32_t format)
420 : Source(layer), mVisibilityChanged(false),
421 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
422{
423 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
424 if (overlay_dev == NULL) {
425 // overlays not supported
426 return;
427 }
428
429 mOverlayDevice = overlay_dev;
430 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
431 if (overlay == NULL) {
432 // couldn't create the overlay (no memory? no more overlays?)
433 return;
434 }
435
436 // enable dithering...
437 overlay_dev->setParameter(overlay_dev, overlay,
438 OVERLAY_DITHER, OVERLAY_ENABLE);
439
440 mOverlay = overlay;
441 mWidth = overlay->w;
442 mHeight = overlay->h;
443 mFormat = overlay->format;
444 mWidthStride = overlay->w_stride;
445 mHeightStride = overlay->h_stride;
446
447 mOverlayHandle = overlay->getHandleRef(overlay);
448
449 // NOTE: here it's okay to acquire a reference to "this"m as long as
450 // the reference is not released before we leave the ctor.
451 sp<OverlayChannel> channel = new OverlayChannel(this);
452
453 *overlayRef = new OverlayRef(mOverlayHandle, channel,
454 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
455}
456
457LayerBuffer::OverlaySource::~OverlaySource()
458{
459 if (mOverlay && mOverlayDevice) {
460 overlay_control_device_t* overlay_dev = mOverlayDevice;
461 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
462 }
463}
464
465void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
466{
467 const Layer::State& front(mLayer.drawingState());
468 const Layer::State& temp(mLayer.currentState());
469 if (temp.sequence != front.sequence) {
470 mVisibilityChanged = true;
471 }
472}
473
474void LayerBuffer::OverlaySource::onVisibilityResolved(
475 const Transform& planeTransform)
476{
477 // this code-path must be as tight as possible, it's called each time
478 // the screen is composited.
479 if (UNLIKELY(mOverlay != 0)) {
480 if (mVisibilityChanged) {
481 mVisibilityChanged = false;
482 const Rect& bounds = mLayer.getTransformedBounds();
483 int x = bounds.left;
484 int y = bounds.top;
485 int w = bounds.width();
486 int h = bounds.height();
487
488 // we need a lock here to protect "destroy"
489 Mutex::Autolock _l(mLock);
490 if (mOverlay) {
491 overlay_control_device_t* overlay_dev = mOverlayDevice;
492 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
493 overlay_dev->setParameter(overlay_dev, mOverlay,
494 OVERLAY_TRANSFORM, mLayer.getOrientation());
495 }
496 }
497 }
498}
499
500void LayerBuffer::OverlaySource::serverDestroy()
501{
502 mLayer.clearSource();
503 destroyOverlay();
504}
505
506void LayerBuffer::OverlaySource::destroyOverlay()
507{
508 // we need a lock here to protect "onVisibilityResolved"
509 Mutex::Autolock _l(mLock);
510 if (mOverlay) {
511 overlay_control_device_t* overlay_dev = mOverlayDevice;
512 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
513 mOverlay = 0;
514 }
515}
516
517// ---------------------------------------------------------------------------
518}; // namespace android