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