blob: 3861e68198e545358747613f2757fe8a6f62c733 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
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
17#define LOG_TAG "SurfaceFlinger"
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <math.h>
22#include <sys/types.h>
23
24#include <utils/Errors.h>
25#include <utils/Log.h>
26#include <utils/StopWatch.h>
27
28#include <ui/PixelFormat.h>
29#include <ui/EGLDisplaySurface.h>
30
31#include "LayerBuffer.h"
32#include "SurfaceFlinger.h"
33#include "VRamHeap.h"
34#include "DisplayHardware/DisplayHardware.h"
35
36
37namespace android {
38
39// ---------------------------------------------------------------------------
40
41const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
42const char* const LayerBuffer::typeID = "LayerBuffer";
43
44// ---------------------------------------------------------------------------
45
46LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
47 Client* client, int32_t i)
48 : LayerBaseClient(flinger, display, client, i),
49 mBuffer(0), mTextureName(-1U), mInvalidate(false), mNeedsBlending(false)
50{
51}
52
53LayerBuffer::~LayerBuffer()
54{
55 sp<SurfaceBuffer> s(getClientSurface());
56 if (s != 0) {
57 s->disown();
58 mClientSurface.clear();
59 }
60
61 // this should always be called from the OpenGL thread
62 if (mTextureName != -1U) {
63 //glDeleteTextures(1, &mTextureName);
64 deletedTextures.add(mTextureName);
65 }
66 // to help debugging we set those to zero
67 mWidth = mHeight = 0;
68}
69
70bool LayerBuffer::needsBlending() const
71{
72 Mutex::Autolock _l(mLock);
73 return mNeedsBlending;
74}
75
76void LayerBuffer::onDraw(const Region& clip) const
77{
78 sp<Buffer> buffer(getBuffer());
79 if (UNLIKELY(buffer == 0)) {
80 // nothing to do, we don't have a buffer
81 clearWithOpenGL(clip);
82 return;
83 }
84
85 status_t err = NO_ERROR;
86 NativeBuffer src(buffer->getBuffer());
87 const int can_use_copybit = canUseCopybit();
88
89 if (can_use_copybit) {
90 //StopWatch watch("MDP");
91
92 const int src_width = src.crop.r - src.crop.l;
93 const int src_height = src.crop.b - src.crop.t;
94 int W = mTransformedBounds.width();
95 int H = mTransformedBounds.height();
96 if (getOrientation() & Transform::ROT_90) {
97 int t(W); W=H; H=t;
98 }
99
100 /* With LayerBuffer, it is likely that we'll have to rescale the
101 * surface, because this is often used for video playback or
102 * camera-preview. Since we want these operation as fast as possible
103 * we make sure we can use the 2D H/W even if it doesn't support
104 * the requested scale factor, in which case we perform the scaling
105 * in several passes. */
106
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800107 copybit_device_t* copybit = mFlinger->getBlitEngine();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700108 const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
109 const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
110
111 float xscale = 1.0f;
112 if (src_width > W*min) xscale = 1.0f / min;
113 else if (src_width*mag < W) xscale = mag;
114
115 float yscale = 1.0f;
116 if (src_height > H*min) yscale = 1.0f / min;
117 else if (src_height*mag < H) yscale = mag;
118
119 if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
120 //LOGD("MDP scaling hack w=%d, h=%d, ww=%d, wh=%d, xs=%f, ys=%f",
121 // src_width, src_height, W, H, xscale, yscale);
122
123 if (UNLIKELY(mTemporaryDealer == 0)) {
124 // allocate a memory-dealer for this the first time
125 mTemporaryDealer = mFlinger->getSurfaceHeapManager()
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800126 ->createHeap(ISurfaceComposer::eHardware);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700127 mTempBitmap.init(mTemporaryDealer);
128 }
129
130 const int tmp_w = floorf(src_width * xscale);
131 const int tmp_h = floorf(src_height * yscale);
132 err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
133
134 if (LIKELY(err == NO_ERROR)) {
135 NativeBuffer tmp;
136 mTempBitmap.getBitmapSurface(&tmp.img);
137 tmp.crop.l = 0;
138 tmp.crop.t = 0;
139 tmp.crop.r = tmp.img.w;
140 tmp.crop.b = tmp.img.h;
141
142 region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
143 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
144 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
145 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
146 err = copybit->stretch(copybit,
147 &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
148 src = tmp;
149 }
150 }
151
152 const DisplayHardware& hw(graphicPlane(0).displayHardware());
153 copybit_image_t dst;
154 hw.getDisplaySurface(&dst);
155 const copybit_rect_t& drect
156 = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
157 const State& s(drawingState());
158 region_iterator it(clip);
159 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
160 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
161 copybit->set_parameter(copybit, COPYBIT_DITHER,
162 s.flags & ISurfaceComposer::eLayerDither ?
163 COPYBIT_ENABLE : COPYBIT_DISABLE);
164 err = copybit->stretch(copybit,
165 &dst, &src.img, &drect, &src.crop, &it);
166 }
167
168 if (!can_use_copybit || err) {
169 if (UNLIKELY(mTextureName == -1LU)) {
170 mTextureName = createTexture();
171 }
172 GLuint w = 0;
173 GLuint h = 0;
174 GGLSurface t;
175 t.version = sizeof(GGLSurface);
176 t.width = src.crop.r;
177 t.height = src.crop.b;
178 t.stride = src.img.w;
179 t.vstride= src.img.h;
180 t.format = src.img.format;
181 t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
182 const Region dirty(Rect(t.width, t.height));
183 loadTexture(dirty, mTextureName, t, w, h);
184 drawWithOpenGL(clip, mTextureName, t);
185 }
186}
187
188void LayerBuffer::invalidateLocked()
189{
190 mInvalidate = true;
191 mFlinger->signalEvent();
192}
193
194void LayerBuffer::invalidate()
195{
196 Mutex::Autolock _l(mLock);
197 invalidateLocked();
198}
199
200void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
201 Region& outDirtyRegion)
202{
203 Mutex::Autolock _l(mLock);
204 if (mInvalidate) {
205 mInvalidate = false;
206 outDirtyRegion.orSelf(visibleRegionScreen);
207 }
208}
209
210sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
211{
212 Mutex::Autolock _l(mLock);
213 return mClientSurface.promote();
214}
215
216sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const
217{
218 sp<SurfaceBuffer> s;
219 Mutex::Autolock _l(mLock);
220 s = mClientSurface.promote();
221 if (s == 0) {
222 s = new SurfaceBuffer(clientIndex(),
223 const_cast<LayerBuffer *>(this));
224 mClientSurface = s;
225 }
226 return s;
227}
228
229
230status_t LayerBuffer::registerBuffers(int w, int h, int hstride, int vstride,
231 PixelFormat format, const sp<IMemoryHeap>& memoryHeap)
232{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800233 if (memoryHeap == NULL) {
234 // this is allowed, but in this case, it is illegal to receive
235 // postBuffer(). The surface just erases the framebuffer with
236 // fully transparent pixels.
237 mHeap.clear();
238 mWidth = w;
239 mHeight = h;
240 mNeedsBlending = false;
241 return NO_ERROR;
242 }
243
244 status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700245 if (err != NO_ERROR)
246 return err;
247
248 // TODO: validate format/parameters
249
250 Mutex::Autolock _l(mLock);
251 mHeap = memoryHeap;
252 mWidth = w;
253 mHeight = h;
254 mHStride = hstride;
255 mVStride = vstride;
256 mFormat = format;
257 PixelFormatInfo info;
258 getPixelFormatInfo(format, &info);
259 mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
260 return NO_ERROR;
261}
262
263void LayerBuffer::postBuffer(ssize_t offset)
264{
265 sp<IMemoryHeap> heap;
266 int w, h, hs, vs, f;
267 { // scope for the lock
268 Mutex::Autolock _l(mLock);
269 w = mWidth;
270 h = mHeight;
271 hs= mHStride;
272 vs= mVStride;
273 f = mFormat;
274 heap = mHeap;
275 }
276
277 sp<Buffer> buffer;
278 if (heap != 0) {
279 buffer = new Buffer(heap, offset, w, h, hs, vs, f);
280 if (buffer->getStatus() != NO_ERROR)
281 buffer.clear();
282 setBuffer(buffer);
283 invalidate();
284 }
285}
286
287void LayerBuffer::unregisterBuffers()
288{
289 Mutex::Autolock _l(mLock);
290 mHeap.clear();
291 mBuffer.clear();
292 invalidateLocked();
293}
294
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800295sp<Overlay> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t format)
296{
297 sp<Overlay> result;
298 Mutex::Autolock _l(mLock);
299 if (mHeap != 0 || mBuffer != 0) {
300 // we're a push surface. error.
301 return result;
302 }
303
304 overlay_device_t* overlay_dev = mFlinger->getOverlayEngine();
305 if (overlay_dev == NULL) {
306 // overlays not supported
307 return result;
308 }
309
310 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
311 if (overlay == NULL) {
312 // couldn't create the overlay (no memory? no more overlays?)
313 return result;
314 }
315
316 /* TODO: implement the real stuff here */
317
318 return result;
319}
320
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700321sp<LayerBuffer::Buffer> LayerBuffer::getBuffer() const
322{
323 Mutex::Autolock _l(mLock);
324 return mBuffer;
325}
326
327void LayerBuffer::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
328{
329 Mutex::Autolock _l(mLock);
330 mBuffer = buffer;
331}
332
333// ---------------------------------------------------------------------------
334
335LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
336 : LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
337{
338}
339
340LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
341{
342 unregisterBuffers();
343 mOwner = 0;
344}
345
346status_t LayerBuffer::SurfaceBuffer::registerBuffers(
347 int w, int h, int hs, int vs,
348 PixelFormat format, const sp<IMemoryHeap>& heap)
349{
350 LayerBuffer* owner(getOwner());
351 if (owner)
352 return owner->registerBuffers(w, h, hs, vs, format, heap);
353 return NO_INIT;
354}
355
356void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
357{
358 LayerBuffer* owner(getOwner());
359 if (owner)
360 owner->postBuffer(offset);
361}
362
363void LayerBuffer::SurfaceBuffer::unregisterBuffers()
364{
365 LayerBuffer* owner(getOwner());
366 if (owner)
367 owner->unregisterBuffers();
368}
369
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800370sp<Overlay> LayerBuffer::SurfaceBuffer::createOverlay(
371 uint32_t w, uint32_t h, int32_t format) {
372 sp<Overlay> result;
373 LayerBuffer* owner(getOwner());
374 if (owner)
375 result = owner->createOverlay(w, h, format);
376 return result;
377}
378
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700379void LayerBuffer::SurfaceBuffer::disown()
380{
381 Mutex::Autolock _l(mLock);
382 mOwner = 0;
383}
384
385
386// ---------------------------------------------------------------------------
387
388LayerBuffer::Buffer::Buffer(const sp<IMemoryHeap>& heap, ssize_t offset,
389 int w, int h, int hs, int vs, int f)
390 : mCount(0), mHeap(heap)
391{
392 NativeBuffer& src(mNativeBuffer);
393 src.crop.l = 0;
394 src.crop.t = 0;
395 src.crop.r = w;
396 src.crop.b = h;
397 src.img.w = hs ?: w;
398 src.img.h = vs ?: h;
399 src.img.format = f;
400 src.img.offset = offset;
401 src.img.base = heap->base();
402 src.img.fd = heap->heapID();
403 // FIXME: make sure this buffer lies within the heap, in which case, set
404 // mHeap to null
405}
406
407LayerBuffer::Buffer::~Buffer()
408{
409}
410
411// ---------------------------------------------------------------------------
412}; // namespace android