blob: 8a582daa7c4fd989c9ceabbba8c975c54cc653b9 [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
Mathias Agopian3330b202009-10-05 17:07:12 -070026#include <ui/GraphicBuffer.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027#include <ui/PixelFormat.h>
Mathias Agopian69029eb2009-06-23 21:11:43 -070028#include <ui/FramebufferNativeWindow.h>
Mathias Agopianbbc21b02009-11-05 23:08:00 -080029#include <ui/Rect.h>
30#include <ui/Region.h>
Mathias Agopian69029eb2009-06-23 21:11:43 -070031
32#include <hardware/copybit.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080033
34#include "LayerBuffer.h"
35#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036#include "DisplayHardware/DisplayHardware.h"
37
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080038namespace android {
39
40// ---------------------------------------------------------------------------
41
Mathias Agopian863e5fd2009-10-29 18:29:30 -070042gralloc_module_t const* LayerBuffer::sGrallocModule = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080043
44// ---------------------------------------------------------------------------
45
46LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
Mathias Agopianf9d93272009-06-19 17:00:27 -070047 const sp<Client>& client, int32_t i)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048 : LayerBaseClient(flinger, display, client, i),
Mathias Agopianbbc21b02009-11-05 23:08:00 -080049 mNeedsBlending(false), mBlitEngine(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050{
51}
52
53LayerBuffer::~LayerBuffer()
54{
Mathias Agopianbbc21b02009-11-05 23:08:00 -080055 if (mBlitEngine) {
56 copybit_close(mBlitEngine);
57 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080058}
59
Mathias Agopian9a112062009-04-17 19:36:26 -070060void LayerBuffer::onFirstRef()
61{
Mathias Agopian2e123242009-06-23 20:06:46 -070062 LayerBaseClient::onFirstRef();
Mathias Agopiancbb288b2009-09-07 16:32:45 -070063 mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
Mathias Agopian9a112062009-04-17 19:36:26 -070064 const_cast<LayerBuffer *>(this));
Mathias Agopian863e5fd2009-10-29 18:29:30 -070065
66 hw_module_t const* module = (hw_module_t const*)sGrallocModule;
67 if (!module) {
68 // NOTE: technically there is a race here, but it shouldn't
69 // cause any problem since hw_get_module() always returns
70 // the same value.
71 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
72 sGrallocModule = (gralloc_module_t const *)module;
73 }
74 }
Mathias Agopianbbc21b02009-11-05 23:08:00 -080075
76 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
77 copybit_open(module, &mBlitEngine);
78 }
Mathias Agopian9a112062009-04-17 19:36:26 -070079}
80
Mathias Agopian076b1cc2009-04-10 14:24:30 -070081sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080082{
Mathias Agopian9a112062009-04-17 19:36:26 -070083 return mSurface;
84}
85
86status_t LayerBuffer::ditch()
87{
88 mSurface.clear();
89 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080090}
91
92bool LayerBuffer::needsBlending() const {
93 return mNeedsBlending;
94}
95
96void LayerBuffer::setNeedsBlending(bool blending) {
97 mNeedsBlending = blending;
98}
99
100void LayerBuffer::postBuffer(ssize_t offset)
101{
102 sp<Source> source(getSource());
103 if (source != 0)
104 source->postBuffer(offset);
105}
106
107void LayerBuffer::unregisterBuffers()
108{
109 sp<Source> source(clearSource());
110 if (source != 0)
111 source->unregisterBuffers();
112}
113
114uint32_t LayerBuffer::doTransaction(uint32_t flags)
115{
116 sp<Source> source(getSource());
117 if (source != 0)
118 source->onTransaction(flags);
Mathias Agopian713795a2009-11-19 14:46:26 -0800119 uint32_t res = LayerBase::doTransaction(flags);
120 // we always want filtering for these surfaces
Mathias Agopiana7f66922010-05-26 22:08:52 -0700121 mNeedsFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG);
Mathias Agopian713795a2009-11-19 14:46:26 -0800122 return res;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800123}
124
125void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
126 Region& outDirtyRegion)
127{
128 // this code-path must be as tight as possible, it's called each time
129 // the screen is composited.
130 sp<Source> source(getSource());
131 if (source != 0)
132 source->onVisibilityResolved(planeTransform);
133 LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
134}
135
136void LayerBuffer::onDraw(const Region& clip) const
137{
138 sp<Source> source(getSource());
139 if (LIKELY(source != 0)) {
140 source->onDraw(clip);
141 } else {
142 clearWithOpenGL(clip);
143 }
144}
145
Mathias Agopian454ea682009-09-08 23:52:08 -0700146void LayerBuffer::serverDestroy()
147{
148 sp<Source> source(clearSource());
149 if (source != 0) {
150 source->destroy();
151 }
152}
153
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800154/**
155 * This creates a "buffer" source for this surface
156 */
157status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
158{
159 Mutex::Autolock _l(mLock);
160 if (mSource != 0)
161 return INVALID_OPERATION;
162
163 sp<BufferSource> source = new BufferSource(*this, buffers);
164
165 status_t result = source->getStatus();
166 if (result == NO_ERROR) {
167 mSource = source;
168 }
169 return result;
170}
171
172/**
173 * This creates an "overlay" source for this surface
174 */
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800175sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f,
176 int32_t orientation)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800177{
178 sp<OverlayRef> result;
179 Mutex::Autolock _l(mLock);
180 if (mSource != 0)
181 return result;
182
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800183 sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f, orientation);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800184 if (result != 0) {
185 mSource = source;
186 }
187 return result;
188}
189
190sp<LayerBuffer::Source> LayerBuffer::getSource() const {
191 Mutex::Autolock _l(mLock);
192 return mSource;
193}
194
195sp<LayerBuffer::Source> LayerBuffer::clearSource() {
196 sp<Source> source;
197 Mutex::Autolock _l(mLock);
198 source = mSource;
199 mSource.clear();
200 return source;
201}
202
203// ============================================================================
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700204// LayerBuffer::SurfaceLayerBuffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800205// ============================================================================
206
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700207LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
Mathias Agopian9a112062009-04-17 19:36:26 -0700208 SurfaceID id, const sp<LayerBuffer>& owner)
209 : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210{
211}
212
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700213LayerBuffer::SurfaceLayerBuffer::~SurfaceLayerBuffer()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800214{
215 unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216}
217
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700218status_t LayerBuffer::SurfaceLayerBuffer::registerBuffers(
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700219 const ISurface::BufferHeap& buffers)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800220{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700221 sp<LayerBuffer> owner(getOwner());
222 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800223 return owner->registerBuffers(buffers);
224 return NO_INIT;
225}
226
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700227void LayerBuffer::SurfaceLayerBuffer::postBuffer(ssize_t offset)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800228{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700229 sp<LayerBuffer> owner(getOwner());
230 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800231 owner->postBuffer(offset);
232}
233
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700234void LayerBuffer::SurfaceLayerBuffer::unregisterBuffers()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800235{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700236 sp<LayerBuffer> owner(getOwner());
237 if (owner != 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238 owner->unregisterBuffers();
239}
240
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700241sp<OverlayRef> LayerBuffer::SurfaceLayerBuffer::createOverlay(
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800242 uint32_t w, uint32_t h, int32_t format, int32_t orientation) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800243 sp<OverlayRef> result;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700244 sp<LayerBuffer> owner(getOwner());
245 if (owner != 0)
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800246 result = owner->createOverlay(w, h, format, orientation);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800247 return result;
248}
249
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800250// ============================================================================
251// LayerBuffer::Buffer
252// ============================================================================
253
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800254LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers,
255 ssize_t offset, size_t bufferSize)
Mathias Agopian1faed662010-01-20 13:24:14 -0800256 : mBufferHeap(buffers), mSupportsCopybit(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800257{
258 NativeBuffer& src(mNativeBuffer);
Mathias Agopian3e8a81e2009-12-02 16:23:11 -0800259 src.crop.l = 0;
260 src.crop.t = 0;
261 src.crop.r = buffers.w;
262 src.crop.b = buffers.h;
263
264 src.img.w = buffers.hor_stride ?: buffers.w;
265 src.img.h = buffers.ver_stride ?: buffers.h;
266 src.img.format = buffers.format;
267 src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset);
268 src.img.handle = 0;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700269
Mathias Agopian863e5fd2009-10-29 18:29:30 -0700270 gralloc_module_t const * module = LayerBuffer::getGrallocModule();
271 if (module && module->perform) {
272 int err = module->perform(module,
273 GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800274 buffers.heap->heapID(), bufferSize,
Mathias Agopian863e5fd2009-10-29 18:29:30 -0700275 offset, buffers.heap->base(),
276 &src.img.handle);
277
Mathias Agopian1faed662010-01-20 13:24:14 -0800278 // we can fail here is the passed buffer is purely software
279 mSupportsCopybit = (err == NO_ERROR);
Mathias Agopian863e5fd2009-10-29 18:29:30 -0700280 }
Mathias Agopian3e8a81e2009-12-02 16:23:11 -0800281 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800282
283LayerBuffer::Buffer::~Buffer()
284{
Mathias Agopian5911aa92009-06-24 16:55:59 -0700285 NativeBuffer& src(mNativeBuffer);
Mathias Agopian863e5fd2009-10-29 18:29:30 -0700286 if (src.img.handle) {
287 native_handle_delete(src.img.handle);
288 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800289}
290
291// ============================================================================
292// LayerBuffer::Source
293// LayerBuffer::BufferSource
294// LayerBuffer::OverlaySource
295// ============================================================================
296
297LayerBuffer::Source::Source(LayerBuffer& layer)
298 : mLayer(layer)
299{
300}
301LayerBuffer::Source::~Source() {
302}
303void LayerBuffer::Source::onDraw(const Region& clip) const {
304}
305void LayerBuffer::Source::onTransaction(uint32_t flags) {
306}
307void LayerBuffer::Source::onVisibilityResolved(
308 const Transform& planeTransform) {
309}
310void LayerBuffer::Source::postBuffer(ssize_t offset) {
311}
312void LayerBuffer::Source::unregisterBuffers() {
313}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800314
315// ---------------------------------------------------------------------------
316
317LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
318 const ISurface::BufferHeap& buffers)
Mathias Agopiana7e38032010-02-04 17:13:06 -0800319 : Source(layer), mStatus(NO_ERROR), mBufferSize(0),
Mathias Agopiand606de62010-05-10 20:06:11 -0700320 mTextureManager(layer.mFlags)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800321{
322 if (buffers.heap == NULL) {
323 // this is allowed, but in this case, it is illegal to receive
324 // postBuffer(). The surface just erases the framebuffer with
325 // fully transparent pixels.
326 mBufferHeap = buffers;
327 mLayer.setNeedsBlending(false);
328 return;
329 }
330
331 status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
332 if (err != NO_ERROR) {
333 LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
334 mStatus = err;
335 return;
336 }
337
338 PixelFormatInfo info;
339 err = getPixelFormatInfo(buffers.format, &info);
340 if (err != NO_ERROR) {
341 LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
342 buffers.format, strerror(err));
343 mStatus = err;
344 return;
345 }
346
347 if (buffers.hor_stride<0 || buffers.ver_stride<0) {
348 LOGE("LayerBuffer::BufferSource: invalid parameters "
349 "(w=%d, h=%d, xs=%d, ys=%d)",
350 buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
351 mStatus = BAD_VALUE;
352 return;
353 }
354
355 mBufferHeap = buffers;
356 mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
357 mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
358 mLayer.forceVisibilityTransaction();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800359}
360
361LayerBuffer::BufferSource::~BufferSource()
362{
Mathias Agopianedfd97c2010-01-21 16:04:56 -0800363 class MessageDestroyTexture : public MessageBase {
364 SurfaceFlinger* flinger;
365 GLuint name;
366 public:
367 MessageDestroyTexture(
368 SurfaceFlinger* flinger, GLuint name)
369 : flinger(flinger), name(name) { }
370 virtual bool handler() {
371 glDeleteTextures(1, &name);
372 return true;
373 }
374 };
375
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700376 if (mTexture.name != -1U) {
Mathias Agopianedfd97c2010-01-21 16:04:56 -0800377 // GL textures can only be destroyed from the GL thread
378 mLayer.mFlinger->mEventQueue.postMessage(
379 new MessageDestroyTexture(mLayer.mFlinger.get(), mTexture.name) );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800380 }
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700381 if (mTexture.image != EGL_NO_IMAGE_KHR) {
382 EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
383 eglDestroyImageKHR(dpy, mTexture.image);
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700384 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800385}
386
387void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
388{
389 ISurface::BufferHeap buffers;
390 { // scope for the lock
Mathias Agopian4d2de2c2009-09-08 20:02:47 -0700391 Mutex::Autolock _l(mBufferSourceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800392 buffers = mBufferHeap;
393 if (buffers.heap != 0) {
394 const size_t memorySize = buffers.heap->getSize();
395 if ((size_t(offset) + mBufferSize) > memorySize) {
396 LOGE("LayerBuffer::BufferSource::postBuffer() "
397 "invalid buffer (offset=%d, size=%d, heap-size=%d",
398 int(offset), int(mBufferSize), int(memorySize));
399 return;
400 }
401 }
402 }
403
404 sp<Buffer> buffer;
405 if (buffers.heap != 0) {
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800406 buffer = new LayerBuffer::Buffer(buffers, offset, mBufferSize);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800407 if (buffer->getStatus() != NO_ERROR)
408 buffer.clear();
409 setBuffer(buffer);
410 mLayer.invalidate();
411 }
412}
413
414void LayerBuffer::BufferSource::unregisterBuffers()
415{
Mathias Agopian4d2de2c2009-09-08 20:02:47 -0700416 Mutex::Autolock _l(mBufferSourceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800417 mBufferHeap.heap.clear();
418 mBuffer.clear();
419 mLayer.invalidate();
420}
421
422sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
423{
Mathias Agopian4d2de2c2009-09-08 20:02:47 -0700424 Mutex::Autolock _l(mBufferSourceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800425 return mBuffer;
426}
427
428void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
429{
Mathias Agopian4d2de2c2009-09-08 20:02:47 -0700430 Mutex::Autolock _l(mBufferSourceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800431 mBuffer = buffer;
432}
433
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800434void LayerBuffer::BufferSource::onDraw(const Region& clip) const
435{
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700436 sp<Buffer> ourBuffer(getBuffer());
437 if (UNLIKELY(ourBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800438 // nothing to do, we don't have a buffer
439 mLayer.clearWithOpenGL(clip);
440 return;
441 }
442
Mathias Agopian69029eb2009-06-23 21:11:43 -0700443 status_t err = NO_ERROR;
444 NativeBuffer src(ourBuffer->getBuffer());
Mathias Agopian454ea682009-09-08 23:52:08 -0700445 const Rect transformedBounds(mLayer.getTransformedBounds());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800446
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700447#if defined(EGL_ANDROID_image_native_buffer)
448 if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
Mathias Agopiana7e38032010-02-04 17:13:06 -0800449 err = INVALID_OPERATION;
450 if (ourBuffer->supportsCopybit()) {
Mathias Agopiana7e38032010-02-04 17:13:06 -0800451 copybit_device_t* copybit = mLayer.mBlitEngine;
452 if (copybit && err != NO_ERROR) {
453 // create our EGLImageKHR the first time
454 err = initTempBuffer();
455 if (err == NO_ERROR) {
456 // NOTE: Assume the buffer is allocated with the proper USAGE flags
457 const NativeBuffer& dst(mTempBuffer);
458 region_iterator clip(Region(Rect(dst.crop.r, dst.crop.b)));
459 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
460 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
461 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
462 err = copybit->stretch(copybit, &dst.img, &src.img,
463 &dst.crop, &src.crop, &clip);
464 if (err != NO_ERROR) {
465 clearTempBufferImage();
466 }
467 }
468 }
Mathias Agopianbbc21b02009-11-05 23:08:00 -0800469 }
Mathias Agopian69029eb2009-06-23 21:11:43 -0700470 }
Mathias Agopian2ab55a42009-06-24 22:39:26 -0700471#endif
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700472 else {
473 err = INVALID_OPERATION;
474 }
475
476 if (err != NO_ERROR) {
Mathias Agopiandf2d9292009-10-28 21:00:29 -0700477 // slower fallback
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700478 GGLSurface t;
479 t.version = sizeof(GGLSurface);
480 t.width = src.crop.r;
481 t.height = src.crop.b;
482 t.stride = src.img.w;
483 t.vstride= src.img.h;
484 t.format = src.img.format;
Mathias Agopian5911aa92009-06-24 16:55:59 -0700485 t.data = (GGLubyte*)src.img.base;
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700486 const Region dirty(Rect(t.width, t.height));
Mathias Agopiand606de62010-05-10 20:06:11 -0700487 mTextureManager.loadTexture(&mTexture, dirty, t);
Mathias Agopian0926f502009-05-04 14:17:04 -0700488 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800489
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700490 mTexture.transform = mBufferHeap.transform;
491 mLayer.drawWithOpenGL(clip, mTexture);
492}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800494status_t LayerBuffer::BufferSource::initTempBuffer() const
495{
496 // figure out the size we need now
497 const ISurface::BufferHeap& buffers(mBufferHeap);
498 uint32_t w = mLayer.mTransformedBounds.width();
499 uint32_t h = mLayer.mTransformedBounds.height();
500 if (buffers.w * h != buffers.h * w) {
501 int t = w; w = h; h = t;
502 }
503
Mathias Agopian5fdea8d2010-01-20 14:31:53 -0800504 // we're in the copybit case, so make sure we can handle this blit
505 // we don't have to keep the aspect ratio here
506 copybit_device_t* copybit = mLayer.mBlitEngine;
507 const int down = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
508 const int up = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
509 if (buffers.w > w*down) w = buffers.w / down;
510 else if (w > buffers.w*up) w = buffers.w*up;
511 if (buffers.h > h*down) h = buffers.h / down;
512 else if (h > buffers.h*up) h = buffers.h*up;
513
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800514 if (mTexture.image != EGL_NO_IMAGE_KHR) {
515 // we have an EGLImage, make sure the needed size didn't change
516 if (w!=mTexture.width || h!= mTexture.height) {
517 // delete the EGLImage and texture
Mathias Agopianecc99c02010-01-20 13:56:07 -0800518 clearTempBufferImage();
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800519 } else {
520 // we're good, we have an EGLImageKHR and it's (still) the
521 // right size
522 return NO_ERROR;
523 }
524 }
525
526 // figure out if we need linear filtering
527 if (buffers.w * h == buffers.h * w) {
528 // same pixel area, don't use filtering
Mathias Agopiana7f66922010-05-26 22:08:52 -0700529 mLayer.mNeedsFiltering = false;
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800530 }
531
532 // Allocate a temporary buffer and create the corresponding EGLImageKHR
Mathias Agopianc9e4a122010-02-12 18:50:28 -0800533 // once the EGLImage has been created we don't need the
534 // graphic buffer reference anymore.
535 sp<GraphicBuffer> buffer = new GraphicBuffer(
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800536 w, h, HAL_PIXEL_FORMAT_RGB_565,
537 GraphicBuffer::USAGE_HW_TEXTURE |
538 GraphicBuffer::USAGE_HW_2D);
539
Mathias Agopianc9e4a122010-02-12 18:50:28 -0800540 status_t err = buffer->initCheck();
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800541 if (err == NO_ERROR) {
542 NativeBuffer& dst(mTempBuffer);
Mathias Agopianc9e4a122010-02-12 18:50:28 -0800543 dst.img.w = buffer->getStride();
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800544 dst.img.h = h;
Mathias Agopianc9e4a122010-02-12 18:50:28 -0800545 dst.img.format = buffer->getPixelFormat();
546 dst.img.handle = (native_handle_t *)buffer->handle;
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800547 dst.img.base = 0;
548 dst.crop.l = 0;
549 dst.crop.t = 0;
550 dst.crop.r = w;
551 dst.crop.b = h;
552
Mathias Agopiand606de62010-05-10 20:06:11 -0700553 EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
554 err = mTextureManager.initEglImage(&mTexture, dpy, buffer);
Mathias Agopianc5e181f2009-12-09 14:32:56 -0800555 }
556
557 return err;
558}
559
Mathias Agopianecc99c02010-01-20 13:56:07 -0800560void LayerBuffer::BufferSource::clearTempBufferImage() const
561{
Mathias Agopian8c3b5972010-01-21 16:27:30 -0800562 // delete the image
Mathias Agopianecc99c02010-01-20 13:56:07 -0800563 EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
Mathias Agopianecc99c02010-01-20 13:56:07 -0800564 eglDestroyImageKHR(dpy, mTexture.image);
Mathias Agopian8c3b5972010-01-21 16:27:30 -0800565
566 // and the associated texture (recreate a name)
567 glDeleteTextures(1, &mTexture.name);
Mathias Agopianecc99c02010-01-20 13:56:07 -0800568 Texture defaultTexture;
569 mTexture = defaultTexture;
Mathias Agopianecc99c02010-01-20 13:56:07 -0800570}
571
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800572// ---------------------------------------------------------------------------
573
574LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
575 sp<OverlayRef>* overlayRef,
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800576 uint32_t w, uint32_t h, int32_t format, int32_t orientation)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800577 : Source(layer), mVisibilityChanged(false),
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800578 mOverlay(0), mOverlayHandle(0), mOverlayDevice(0), mOrientation(orientation)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800579{
580 overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
581 if (overlay_dev == NULL) {
582 // overlays not supported
583 return;
584 }
585
586 mOverlayDevice = overlay_dev;
587 overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
588 if (overlay == NULL) {
589 // couldn't create the overlay (no memory? no more overlays?)
590 return;
591 }
592
593 // enable dithering...
594 overlay_dev->setParameter(overlay_dev, overlay,
595 OVERLAY_DITHER, OVERLAY_ENABLE);
596
597 mOverlay = overlay;
598 mWidth = overlay->w;
599 mHeight = overlay->h;
600 mFormat = overlay->format;
601 mWidthStride = overlay->w_stride;
602 mHeightStride = overlay->h_stride;
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700603 mInitialized = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800604
605 mOverlayHandle = overlay->getHandleRef(overlay);
606
Mathias Agopian454ea682009-09-08 23:52:08 -0700607 sp<OverlayChannel> channel = new OverlayChannel( &layer );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800608
609 *overlayRef = new OverlayRef(mOverlayHandle, channel,
610 mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
Benny Wong56432612009-09-16 14:48:52 -0500611 mLayer.mFlinger->signalEvent();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800612}
613
614LayerBuffer::OverlaySource::~OverlaySource()
615{
616 if (mOverlay && mOverlayDevice) {
617 overlay_control_device_t* overlay_dev = mOverlayDevice;
618 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
619 }
620}
621
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700622void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
623{
Mathias Agopianb8cfc0f2009-09-15 19:31:28 -0700624 // this would be where the color-key would be set, should we need it.
Mathias Agopian010fccb2010-05-26 22:26:12 -0700625 GLclampf red = 0;
626 GLclampf green = 0;
627 GLclampf blue = 0;
Rebecca Schultz Zavin29aa74c2009-09-01 23:06:45 -0700628 mLayer.clearWithOpenGL(clip, red, green, blue, 0);
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700629}
630
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800631void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
632{
633 const Layer::State& front(mLayer.drawingState());
634 const Layer::State& temp(mLayer.currentState());
635 if (temp.sequence != front.sequence) {
636 mVisibilityChanged = true;
637 }
638}
639
640void LayerBuffer::OverlaySource::onVisibilityResolved(
641 const Transform& planeTransform)
642{
643 // this code-path must be as tight as possible, it's called each time
644 // the screen is composited.
645 if (UNLIKELY(mOverlay != 0)) {
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700646 if (mVisibilityChanged || !mInitialized) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800647 mVisibilityChanged = false;
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700648 mInitialized = true;
Mathias Agopian454ea682009-09-08 23:52:08 -0700649 const Rect bounds(mLayer.getTransformedBounds());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800650 int x = bounds.left;
651 int y = bounds.top;
652 int w = bounds.width();
653 int h = bounds.height();
654
655 // we need a lock here to protect "destroy"
Mathias Agopian4d2de2c2009-09-08 20:02:47 -0700656 Mutex::Autolock _l(mOverlaySourceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800657 if (mOverlay) {
658 overlay_control_device_t* overlay_dev = mOverlayDevice;
659 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800660 // we need to combine the layer orientation and the
661 // user-requested orientation.
662 Transform finalTransform = Transform(mOrientation) *
663 Transform(mLayer.getOrientation());
Rebecca Schultz Zavin10001702009-07-21 16:17:59 -0700664 overlay_dev->setParameter(overlay_dev, mOverlay,
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800665 OVERLAY_TRANSFORM, finalTransform.getOrientation());
Rebecca Schultz Zavin96df49b2009-07-20 21:18:04 -0700666 overlay_dev->commit(overlay_dev, mOverlay);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667 }
668 }
669 }
670}
671
Mathias Agopian454ea682009-09-08 23:52:08 -0700672void LayerBuffer::OverlaySource::destroy()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800673{
674 // we need a lock here to protect "onVisibilityResolved"
Mathias Agopian4d2de2c2009-09-08 20:02:47 -0700675 Mutex::Autolock _l(mOverlaySourceLock);
Mathias Agopian454ea682009-09-08 23:52:08 -0700676 if (mOverlay && mOverlayDevice) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800677 overlay_control_device_t* overlay_dev = mOverlayDevice;
678 overlay_dev->destroyOverlay(overlay_dev, mOverlay);
679 mOverlay = 0;
680 }
681}
682
683// ---------------------------------------------------------------------------
684}; // namespace android