blob: d871fc311f4dbd07f4ac25036723956d7fbf73fd [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
107 copybit_t* copybit = mFlinger->getBlitEngine();
108 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()
126 ->createHeap(NATIVE_MEMORY_TYPE_PMEM);
127 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{
233 status_t err = (memoryHeap!=0 && memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT;
234 if (err != NO_ERROR)
235 return err;
236
237 // TODO: validate format/parameters
238
239 Mutex::Autolock _l(mLock);
240 mHeap = memoryHeap;
241 mWidth = w;
242 mHeight = h;
243 mHStride = hstride;
244 mVStride = vstride;
245 mFormat = format;
246 PixelFormatInfo info;
247 getPixelFormatInfo(format, &info);
248 mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
249 return NO_ERROR;
250}
251
252void LayerBuffer::postBuffer(ssize_t offset)
253{
254 sp<IMemoryHeap> heap;
255 int w, h, hs, vs, f;
256 { // scope for the lock
257 Mutex::Autolock _l(mLock);
258 w = mWidth;
259 h = mHeight;
260 hs= mHStride;
261 vs= mVStride;
262 f = mFormat;
263 heap = mHeap;
264 }
265
266 sp<Buffer> buffer;
267 if (heap != 0) {
268 buffer = new Buffer(heap, offset, w, h, hs, vs, f);
269 if (buffer->getStatus() != NO_ERROR)
270 buffer.clear();
271 setBuffer(buffer);
272 invalidate();
273 }
274}
275
276void LayerBuffer::unregisterBuffers()
277{
278 Mutex::Autolock _l(mLock);
279 mHeap.clear();
280 mBuffer.clear();
281 invalidateLocked();
282}
283
284sp<LayerBuffer::Buffer> LayerBuffer::getBuffer() const
285{
286 Mutex::Autolock _l(mLock);
287 return mBuffer;
288}
289
290void LayerBuffer::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
291{
292 Mutex::Autolock _l(mLock);
293 mBuffer = buffer;
294}
295
296// ---------------------------------------------------------------------------
297
298LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
299 : LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
300{
301}
302
303LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
304{
305 unregisterBuffers();
306 mOwner = 0;
307}
308
309status_t LayerBuffer::SurfaceBuffer::registerBuffers(
310 int w, int h, int hs, int vs,
311 PixelFormat format, const sp<IMemoryHeap>& heap)
312{
313 LayerBuffer* owner(getOwner());
314 if (owner)
315 return owner->registerBuffers(w, h, hs, vs, format, heap);
316 return NO_INIT;
317}
318
319void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
320{
321 LayerBuffer* owner(getOwner());
322 if (owner)
323 owner->postBuffer(offset);
324}
325
326void LayerBuffer::SurfaceBuffer::unregisterBuffers()
327{
328 LayerBuffer* owner(getOwner());
329 if (owner)
330 owner->unregisterBuffers();
331}
332
333void LayerBuffer::SurfaceBuffer::disown()
334{
335 Mutex::Autolock _l(mLock);
336 mOwner = 0;
337}
338
339
340// ---------------------------------------------------------------------------
341
342LayerBuffer::Buffer::Buffer(const sp<IMemoryHeap>& heap, ssize_t offset,
343 int w, int h, int hs, int vs, int f)
344 : mCount(0), mHeap(heap)
345{
346 NativeBuffer& src(mNativeBuffer);
347 src.crop.l = 0;
348 src.crop.t = 0;
349 src.crop.r = w;
350 src.crop.b = h;
351 src.img.w = hs ?: w;
352 src.img.h = vs ?: h;
353 src.img.format = f;
354 src.img.offset = offset;
355 src.img.base = heap->base();
356 src.img.fd = heap->heapID();
357 // FIXME: make sure this buffer lies within the heap, in which case, set
358 // mHeap to null
359}
360
361LayerBuffer::Buffer::~Buffer()
362{
363}
364
365// ---------------------------------------------------------------------------
366}; // namespace android