Merge changes Id4222c9b,I3c1a9172

* changes:
  More clean-up. Get rid off the "blur" effect in SurfaceFlinger
  fix [3259708] Graphic Buffer Mapper does not support YV12
This commit is contained in:
Mathias Agopian 2010-12-08 17:15:54 -08:00 committed by Android (Google) Code Review
commit c5b4c45b58
10 changed files with 19 additions and 991 deletions

View File

@ -1,83 +0,0 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H
#define ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H
#include <stdint.h>
#include <limits.h>
#include <sys/cdefs.h>
#include <hardware/gralloc.h>
#include <errno.h>
#include <cutils/native_handle.h>
namespace android {
/*****************************************************************************/
struct sw_gralloc_handle_t : public native_handle
{
// file-descriptors
int fd;
// ints
int magic;
int size;
int base;
int prot;
int pid;
static const int sNumInts = 5;
static const int sNumFds = 1;
static const int sMagic = '_sgh';
sw_gralloc_handle_t() :
fd(-1), magic(sMagic), size(0), base(0), prot(0), pid(getpid())
{
version = sizeof(native_handle);
numInts = sNumInts;
numFds = sNumFds;
}
~sw_gralloc_handle_t() {
magic = 0;
}
static int validate(const native_handle* h) {
const sw_gralloc_handle_t* hnd = (const sw_gralloc_handle_t*)h;
if (!h || h->version != sizeof(native_handle) ||
h->numInts != sNumInts || h->numFds != sNumFds ||
hnd->magic != sMagic)
{
return -EINVAL;
}
return 0;
}
static status_t alloc(uint32_t w, uint32_t h, int format,
int usage, buffer_handle_t* handle, int32_t* stride);
static status_t free(sw_gralloc_handle_t* hnd);
static status_t registerBuffer(sw_gralloc_handle_t* hnd);
static status_t unregisterBuffer(sw_gralloc_handle_t* hnd);
static status_t lock(sw_gralloc_handle_t* hnd, int usage,
int l, int t, int w, int h, void** vaddr);
static status_t unlock(sw_gralloc_handle_t* hnd);
};
/*****************************************************************************/
}; // namespace android
#endif /* ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H */

View File

@ -24,8 +24,6 @@
#include <ui/GraphicBufferAllocator.h>
#include <private/ui/sw_gralloc_handle.h>
namespace android {
// ---------------------------------------------------------------------------
@ -95,11 +93,7 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma
// we have a h/w allocator and h/w buffer is requested
status_t err;
if (usage & GRALLOC_USAGE_HW_MASK) {
err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
} else {
err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride);
}
err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
w, h, format, usage, err, strerror(-err));
@ -123,11 +117,8 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma
status_t GraphicBufferAllocator::free(buffer_handle_t handle)
{
status_t err;
if (sw_gralloc_handle_t::validate(handle) < 0) {
err = mAllocDev->free(mAllocDev, handle);
} else {
err = sw_gralloc_handle_t::free((sw_gralloc_handle_t*)handle);
}
err = mAllocDev->free(mAllocDev, handle);
LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
if (err == NO_ERROR) {

View File

@ -17,15 +17,7 @@
#define LOG_TAG "GraphicBufferMapper"
#include <stdint.h>
#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define
# include <asm/page.h>
#else
# include <sys/user.h>
#endif
#include <errno.h>
#include <sys/mman.h>
#include <cutils/ashmem.h>
#include <utils/Errors.h>
#include <utils/Log.h>
@ -35,8 +27,6 @@
#include <hardware/gralloc.h>
#include <private/ui/sw_gralloc_handle.h>
namespace android {
// ---------------------------------------------------------------------------
@ -57,11 +47,9 @@ GraphicBufferMapper::GraphicBufferMapper()
status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
{
status_t err;
if (sw_gralloc_handle_t::validate(handle) < 0) {
err = mAllocMod->registerBuffer(mAllocMod, handle);
} else {
err = sw_gralloc_handle_t::registerBuffer((sw_gralloc_handle_t*)handle);
}
err = mAllocMod->registerBuffer(mAllocMod, handle);
LOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
handle, err, strerror(-err));
return err;
@ -70,11 +58,9 @@ status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
{
status_t err;
if (sw_gralloc_handle_t::validate(handle) < 0) {
err = mAllocMod->unregisterBuffer(mAllocMod, handle);
} else {
err = sw_gralloc_handle_t::unregisterBuffer((sw_gralloc_handle_t*)handle);
}
err = mAllocMod->unregisterBuffer(mAllocMod, handle);
LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",
handle, err, strerror(-err));
return err;
@ -84,15 +70,11 @@ status_t GraphicBufferMapper::lock(buffer_handle_t handle,
int usage, const Rect& bounds, void** vaddr)
{
status_t err;
if (sw_gralloc_handle_t::validate(handle) < 0) {
err = mAllocMod->lock(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),
vaddr);
} else {
err = sw_gralloc_handle_t::lock((sw_gralloc_handle_t*)handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),
vaddr);
}
err = mAllocMod->lock(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),
vaddr);
LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
return err;
}
@ -100,129 +82,12 @@ status_t GraphicBufferMapper::lock(buffer_handle_t handle,
status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
{
status_t err;
if (sw_gralloc_handle_t::validate(handle) < 0) {
err = mAllocMod->unlock(mAllocMod, handle);
} else {
err = sw_gralloc_handle_t::unlock((sw_gralloc_handle_t*)handle);
}
err = mAllocMod->unlock(mAllocMod, handle);
LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
return err;
}
// ---------------------------------------------------------------------------
status_t sw_gralloc_handle_t::alloc(uint32_t w, uint32_t h, int format,
int usage, buffer_handle_t* pHandle, int32_t* pStride)
{
int align = 4;
int bpp = 0;
switch (format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
bpp = 4;
break;
case HAL_PIXEL_FORMAT_RGB_888:
bpp = 3;
break;
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_RGBA_5551:
case HAL_PIXEL_FORMAT_RGBA_4444:
bpp = 2;
break;
default:
return -EINVAL;
}
size_t bpr = (w*bpp + (align-1)) & ~(align-1);
size_t size = bpr * h;
size_t stride = bpr / bpp;
size = (size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
int fd = ashmem_create_region("sw-gralloc-buffer", size);
if (fd < 0) {
LOGE("ashmem_create_region(size=%d) failed (%s)",
size, strerror(-errno));
return -errno;
}
int prot = PROT_READ;
if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
prot |= PROT_WRITE;
if (ashmem_set_prot_region(fd, prot) < 0) {
LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
fd, prot, strerror(-errno));
close(fd);
return -errno;
}
void* base = mmap(0, size, prot, MAP_SHARED, fd, 0);
if (base == MAP_FAILED) {
LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
fd, size, prot, strerror(-errno));
close(fd);
return -errno;
}
sw_gralloc_handle_t* hnd = new sw_gralloc_handle_t();
hnd->fd = fd;
hnd->size = size;
hnd->base = intptr_t(base);
hnd->prot = prot;
*pStride = stride;
*pHandle = hnd;
return NO_ERROR;
}
status_t sw_gralloc_handle_t::free(sw_gralloc_handle_t* hnd)
{
if (hnd->base) {
munmap((void*)hnd->base, hnd->size);
}
if (hnd->fd >= 0) {
close(hnd->fd);
}
delete hnd;
return NO_ERROR;
}
status_t sw_gralloc_handle_t::registerBuffer(sw_gralloc_handle_t* hnd)
{
if (hnd->pid != getpid()) {
void* base = mmap(0, hnd->size, hnd->prot, MAP_SHARED, hnd->fd, 0);
if (base == MAP_FAILED) {
LOGE("registerBuffer mmap(fd=%d, size=%d, prot=%x) failed (%s)",
hnd->fd, hnd->size, hnd->prot, strerror(-errno));
return -errno;
}
hnd->base = intptr_t(base);
}
return NO_ERROR;
}
status_t sw_gralloc_handle_t::unregisterBuffer(sw_gralloc_handle_t* hnd)
{
if (hnd->pid != getpid()) {
if (hnd->base) {
munmap((void*)hnd->base, hnd->size);
}
hnd->base = 0;
}
return NO_ERROR;
}
status_t sw_gralloc_handle_t::lock(sw_gralloc_handle_t* hnd, int usage,
int l, int t, int w, int h, void** vaddr)
{
*vaddr = (void*)hnd->base;
return NO_ERROR;
}
status_t sw_gralloc_handle_t::unlock(sw_gralloc_handle_t* hnd)
{
return NO_ERROR;
}
// ---------------------------------------------------------------------------
}; // namespace android

View File

@ -6,11 +6,9 @@ LOCAL_SRC_FILES:= \
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
DisplayHardware/HWComposer.cpp \
BlurFilter.cpp.arm \
GLExtensions.cpp \
Layer.cpp \
LayerBase.cpp \
LayerBlur.cpp \
LayerDim.cpp \
MessageQueue.cpp \
SurfaceFlinger.cpp \

View File

@ -1,376 +0,0 @@
/*
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <utils/Errors.h>
#include <pixelflinger/pixelflinger.h>
#include "clz.h"
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
namespace android {
#if BYTE_ORDER == LITTLE_ENDIAN
inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) {
return v;
}
inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) {
return v;
}
#else
inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) {
return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
}
inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) {
return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
}
#endif
const int BLUR_DITHER_BITS = 6; // dither weights stored on 6 bits
const int BLUR_DITHER_ORDER_SHIFT= 3;
const int BLUR_DITHER_ORDER = (1<<BLUR_DITHER_ORDER_SHIFT);
const int BLUR_DITHER_SIZE = BLUR_DITHER_ORDER * BLUR_DITHER_ORDER;
const int BLUR_DITHER_MASK = BLUR_DITHER_ORDER-1;
static const uint8_t gDitherMatrix[BLUR_DITHER_SIZE] = {
0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21
};
template <int FACTOR = 0>
struct BlurColor565
{
typedef uint16_t type;
int r, g, b;
inline BlurColor565() { }
inline BlurColor565(uint16_t v) {
r = v >> 11;
g = (v >> 5) & 0x3E;
b = v & 0x1F;
}
inline void clear() { r=g=b=0; }
inline uint16_t to(int shift, int last, int dither) const {
int R = r;
int G = g;
int B = b;
if (UNLIKELY(last)) {
if (FACTOR>0) {
int L = (R+G+B)>>1;
R += (((L>>1) - R) * FACTOR) >> 8;
G += (((L ) - G) * FACTOR) >> 8;
B += (((L>>1) - B) * FACTOR) >> 8;
}
R += (dither << shift) >> BLUR_DITHER_BITS;
G += (dither << shift) >> BLUR_DITHER_BITS;
B += (dither << shift) >> BLUR_DITHER_BITS;
}
R >>= shift;
G >>= shift;
B >>= shift;
return (R<<11) | (G<<5) | B;
}
inline BlurColor565& operator += (const BlurColor565& rhs) {
r += rhs.r;
g += rhs.g;
b += rhs.b;
return *this;
}
inline BlurColor565& operator -= (const BlurColor565& rhs) {
r -= rhs.r;
g -= rhs.g;
b -= rhs.b;
return *this;
}
};
template <int FACTOR = 0>
struct BlurColor888X
{
typedef uint32_t type;
int r, g, b;
inline BlurColor888X() { }
inline BlurColor888X(uint32_t v) {
v = BLUR_RGBA_TO_HOST(v);
r = v & 0xFF;
g = (v >> 8) & 0xFF;
b = (v >> 16) & 0xFF;
}
inline void clear() { r=g=b=0; }
inline uint32_t to(int shift, int last, int dither) const {
int R = r;
int G = g;
int B = b;
if (UNLIKELY(last)) {
if (FACTOR>0) {
int L = (R+G+G+B)>>2;
R += ((L - R) * FACTOR) >> 8;
G += ((L - G) * FACTOR) >> 8;
B += ((L - B) * FACTOR) >> 8;
}
}
R >>= shift;
G >>= shift;
B >>= shift;
return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R);
}
inline BlurColor888X& operator += (const BlurColor888X& rhs) {
r += rhs.r;
g += rhs.g;
b += rhs.b;
return *this;
}
inline BlurColor888X& operator -= (const BlurColor888X& rhs) {
r -= rhs.r;
g -= rhs.g;
b -= rhs.b;
return *this;
}
};
struct BlurGray565
{
typedef uint16_t type;
int l;
inline BlurGray565() { }
inline BlurGray565(uint16_t v) {
int r = v >> 11;
int g = (v >> 5) & 0x3F;
int b = v & 0x1F;
l = (r + g + b + 1)>>1;
}
inline void clear() { l=0; }
inline uint16_t to(int shift, int last, int dither) const {
int L = l;
if (UNLIKELY(last)) {
L += (dither << shift) >> BLUR_DITHER_BITS;
}
L >>= shift;
return ((L>>1)<<11) | (L<<5) | (L>>1);
}
inline BlurGray565& operator += (const BlurGray565& rhs) {
l += rhs.l;
return *this;
}
inline BlurGray565& operator -= (const BlurGray565& rhs) {
l -= rhs.l;
return *this;
}
};
struct BlurGray8888
{
typedef uint32_t type;
int l, a;
inline BlurGray8888() { }
inline BlurGray8888(uint32_t v) {
v = BLUR_RGBA_TO_HOST(v);
int r = v & 0xFF;
int g = (v >> 8) & 0xFF;
int b = (v >> 16) & 0xFF;
a = v >> 24;
l = r + g + g + b;
}
inline void clear() { l=a=0; }
inline uint32_t to(int shift, int last, int dither) const {
int L = l;
int A = a;
if (UNLIKELY(last)) {
L += (dither << (shift+2)) >> BLUR_DITHER_BITS;
A += (dither << shift) >> BLUR_DITHER_BITS;
}
L >>= (shift+2);
A >>= shift;
return BLUR_HOST_TO_RGBA((A<<24) | (L<<16) | (L<<8) | L);
}
inline BlurGray8888& operator += (const BlurGray8888& rhs) {
l += rhs.l;
a += rhs.a;
return *this;
}
inline BlurGray8888& operator -= (const BlurGray8888& rhs) {
l -= rhs.l;
a -= rhs.a;
return *this;
}
};
template<typename PIXEL>
static status_t blurFilter(
GGLSurface const* dst,
GGLSurface const* src,
int kernelSizeUser,
int repeat)
{
typedef typename PIXEL::type TYPE;
const int shift = 31 - clz(kernelSizeUser);
const int areaShift = shift*2;
const int kernelSize = 1<<shift;
const int kernelHalfSize = kernelSize/2;
const int mask = kernelSize-1;
const int w = src->width;
const int h = src->height;
const uint8_t* ditherMatrix = gDitherMatrix;
// we need a temporary buffer to store one line of blurred columns
// as well as kernelSize lines of source pixels organized as a ring buffer.
void* const temporary_buffer = malloc(
(w + kernelSize) * sizeof(PIXEL) +
(src->stride * kernelSize) * sizeof(TYPE));
if (!temporary_buffer)
return NO_MEMORY;
PIXEL* const sums = (PIXEL*)temporary_buffer;
TYPE* const scratch = (TYPE*)(sums + w + kernelSize);
// Apply the blur 'repeat' times, this is used to approximate
// gaussian blurs. 3 times gives good results.
for (int k=0 ; k<repeat ; k++) {
// Clear the columns sums for this round
memset(sums, 0, (w + kernelSize) * sizeof(PIXEL));
TYPE* head;
TYPE pixel;
PIXEL current;
// Since we're going to override the source data we need
// to copy it in a temporary buffer. Only kernelSize lines are
// required. But since we start in the center of the kernel,
// we only copy half of the data, and fill the rest with zeros
// (assuming black/transparent pixels).
memcpy( scratch + src->stride*kernelHalfSize,
src->data,
src->stride*kernelHalfSize*sizeof(TYPE));
// sum half of each column, because we assume the first half is
// zeros (black/transparent).
for (int y=0 ; y<kernelHalfSize ; y++) {
head = (TYPE*)src->data + y*src->stride;
for (int x=0 ; x<w ; x++)
sums[x] += PIXEL( *head++ );
}
for (int y=0 ; y<h ; y++) {
TYPE* fb = (TYPE*)dst->data + y*dst->stride;
// compute the dither matrix line
uint8_t const * ditherY = ditherMatrix
+ (y & BLUR_DITHER_MASK)*BLUR_DITHER_ORDER;
// Horizontal blur pass on the columns sums
int count, dither, x=0;
PIXEL const * out= sums;
PIXEL const * in = sums;
current.clear();
count = kernelHalfSize;
do {
current += *in;
in++;
} while (--count);
count = kernelHalfSize;
do {
current += *in;
dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
*fb++ = current.to(areaShift, k==repeat-1, dither);
in++;
} while (--count);
count = w-kernelSize;
do {
current += *in;
current -= *out;
dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
*fb++ = current.to(areaShift, k==repeat-1, dither);
in++, out++;
} while (--count);
count = kernelHalfSize;
do {
current -= *out;
dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
*fb++ = current.to(areaShift, k==repeat-1, dither);
out++;
} while (--count);
// vertical blur pass, subtract the oldest line from each columns
// and add a new line. Subtract or add zeros at the top
// and bottom edges.
TYPE* const tail = scratch + (y & mask) * src->stride;
if (y >= kernelHalfSize) {
for (int x=0 ; x<w ; x++)
sums[x] -= PIXEL( tail[x] );
}
if (y < h-kernelSize) {
memcpy( tail,
(TYPE*)src->data + (y+kernelHalfSize)*src->stride,
src->stride*sizeof(TYPE));
for (int x=0 ; x<w ; x++)
sums[x] += PIXEL( tail[x] );
}
}
// The subsequent passes are always done in-place.
src = dst;
}
free(temporary_buffer);
return NO_ERROR;
}
template status_t blurFilter< BlurColor565<0x80> >(
GGLSurface const* dst,
GGLSurface const* src,
int kernelSizeUser,
int repeat);
status_t blurFilter(
GGLSurface const* image,
int kernelSizeUser,
int repeat)
{
status_t err = BAD_VALUE;
if (image->format == GGL_PIXEL_FORMAT_RGB_565) {
err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
} else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) {
err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat);
}
return err;
}
} // namespace android
//err = blur< BlurColor565<0x80> >(dst, src, kernelSizeUser, repeat);
//err = blur<BlurGray565>(dst, src, kernelSizeUser, repeat);
//err = blur<BlurGray8888>(dst, src, kernelSizeUser, repeat);

View File

@ -1,35 +0,0 @@
/*
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef ANDROID_BLUR_FILTER_H
#define ANDROID_BLUR_FILTER_H
#include <stdint.h>
#include <utils/Errors.h>
#include <pixelflinger/pixelflinger.h>
namespace android {
status_t blurFilter(
GGLSurface const* image,
int kernelSizeUser,
int repeat);
} // namespace android
#endif // ANDROID_BLUR_FILTER_H

View File

@ -1,251 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include "clz.h"
#include "BlurFilter.h"
#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
namespace android {
// ---------------------------------------------------------------------------
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client)
: LayerBaseClient(flinger, display, client), mCacheDirty(true),
mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
mWidthScale(1.0f), mHeightScale(1.0f),
mBlurFormat(GGL_PIXEL_FORMAT_RGB_565)
{
}
LayerBlur::~LayerBlur()
{
if (mTextureName != -1U) {
glDeleteTextures(1, &mTextureName);
}
}
void LayerBlur::setVisibleRegion(const Region& visibleRegion)
{
LayerBaseClient::setVisibleRegion(visibleRegion);
if (visibleRegionScreen.isEmpty()) {
if (mTextureName != -1U) {
// We're not visible, free the texture up.
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &mTextureName);
mTextureName = -1U;
}
}
}
uint32_t LayerBlur::doTransaction(uint32_t flags)
{
// we're doing a transaction, refresh the cache!
if (!mFlinger->isFrozen()) {
mRefreshCache = true;
mCacheDirty = true;
flags |= eVisibleRegion;
this->contentDirty = true;
}
return LayerBase::doTransaction(flags);
}
void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion)
{
// this code-path must be as tight as possible, it's called each time
// the screen is composited.
if (UNLIKELY(!visibleRegionScreen.isEmpty())) {
// if anything visible below us is invalidated, the cache becomes dirty
if (!mCacheDirty &&
!visibleRegionScreen.intersect(outDirtyRegion).isEmpty()) {
mCacheDirty = true;
}
if (mCacheDirty) {
if (!mFlinger->isFrozen()) {
// update everything below us that is visible
outDirtyRegion.orSelf(visibleRegionScreen);
nsecs_t now = systemTime();
if ((now - mCacheAge) >= ms2ns(500)) {
mCacheAge = now;
mRefreshCache = true;
mCacheDirty = false;
} else {
if (!mAutoRefreshPending) {
mFlinger->postMessageAsync(
new MessageBase(MessageQueue::INVALIDATE),
ms2ns(500));
mAutoRefreshPending = true;
}
}
}
}
}
LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
}
void LayerBlur::onDraw(const Region& clip) const
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t fbHeight = hw.getHeight();
int x = mTransformedBounds.left;
int y = mTransformedBounds.top;
int w = mTransformedBounds.width();
int h = mTransformedBounds.height();
GLint X = x;
GLint Y = fbHeight - (y + h);
if (X < 0) {
w += X;
X = 0;
}
if (Y < 0) {
h += Y;
Y = 0;
}
if (w<0 || h<0) {
// we're outside of the framebuffer
return;
}
if (mTextureName == -1U) {
// create the texture name the first time
// can't do that in the ctor, because it runs in another thread.
glGenTextures(1, &mTextureName);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
mReadFormat = GL_RGBA;
mReadType = GL_UNSIGNED_BYTE;
mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
}
}
Region::const_iterator it = clip.begin();
Region::const_iterator const end = clip.end();
if (it != end) {
#if defined(GL_OES_EGL_image_external)
if (GLExtensions::getInstance().haveTextureExternal()) {
glDisable(GL_TEXTURE_EXTERNAL_OES);
}
#endif
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mTextureName);
if (mRefreshCache) {
mRefreshCache = false;
mAutoRefreshPending = false;
int32_t pixelSize = 4;
int32_t s = w;
if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
// allocate enough memory for 4-bytes (2 pixels) aligned data
s = (w + 1) & ~1;
pixelSize = 2;
}
uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);
// This reads the frame-buffer, so a h/w GL would have to
// finish() its rendering first. we don't want to do that
// too often. Read data is 4-bytes aligned.
glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
// blur that texture.
GGLSurface bl;
bl.version = sizeof(GGLSurface);
bl.width = w;
bl.height = h;
bl.stride = s;
bl.format = mBlurFormat;
bl.data = (GGLubyte*)pixels;
blurFilter(&bl, 8, 2);
if (GLExtensions::getInstance().haveNpot()) {
glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
mReadFormat, mReadType, pixels);
mWidthScale = 1.0f / w;
mHeightScale =-1.0f / h;
mYOffset = 0;
} else {
GLuint tw = 1 << (31 - clz(w));
GLuint th = 1 << (31 - clz(h));
if (tw < GLuint(w)) tw <<= 1;
if (th < GLuint(h)) th <<= 1;
glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
mReadFormat, mReadType, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
mReadFormat, mReadType, pixels);
mWidthScale = 1.0f / tw;
mHeightScale =-1.0f / th;
mYOffset = th-h;
}
free((void*)pixels);
}
const State& s = drawingState();
if (UNLIKELY(s.alpha < 0xFF)) {
const GLfloat alpha = s.alpha * (1.0f/255.0f);
glColor4f(0, 0, 0, alpha);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
} else {
glDisable(GL_BLEND);
}
if (mFlags & DisplayHardware::SLOW_CONFIG) {
glDisable(GL_DITHER);
} else {
glEnable(GL_DITHER);
}
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(mWidthScale, mHeightScale, 1);
glTranslatef(-x, mYOffset - y, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, mVertices);
glTexCoordPointer(2, GL_FLOAT, 0, mVertices);
while (it != end) {
const Rect& r = *it++;
const GLint sy = fbHeight - (r.top + r.height());
glScissor(r.left, sy, r.width(), r.height());
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
}
// ---------------------------------------------------------------------------
}; // namespace android

View File

@ -1,65 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_LAYER_BLUR_H
#define ANDROID_LAYER_BLUR_H
#include <stdint.h>
#include <sys/types.h>
#include <ui/Region.h>
#include "LayerBase.h"
namespace android {
// ---------------------------------------------------------------------------
class LayerBlur : public LayerBaseClient
{
public:
LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client);
virtual ~LayerBlur();
virtual void onDraw(const Region& clip) const;
virtual bool needsBlending() const { return true; }
virtual bool isSecure() const { return false; }
virtual const char* getTypeId() const { return "LayerBlur"; }
virtual uint32_t doTransaction(uint32_t flags);
virtual void setVisibleRegion(const Region& visibleRegion);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
private:
bool mCacheDirty;
mutable bool mRefreshCache;
mutable bool mAutoRefreshPending;
nsecs_t mCacheAge;
mutable GLuint mTextureName;
mutable GLfloat mWidthScale;
mutable GLfloat mHeightScale;
mutable GLfloat mYOffset;
mutable GLint mReadFormat;
mutable GLint mReadType;
mutable uint32_t mBlurFormat;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_LAYER_BLUR_H

View File

@ -47,7 +47,6 @@
#include "clz.h"
#include "GLExtensions.h"
#include "Layer.h"
#include "LayerBlur.h"
#include "LayerDim.h"
#include "SurfaceFlinger.h"
@ -1226,8 +1225,8 @@ sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid,
layer = normalLayer;
break;
case eFXSurfaceBlur:
layer = createBlurSurface(client, d, w, h, flags);
break;
// for now we treat Blur as Dim, until we can implement it
// efficiently.
case eFXSurfaceDim:
layer = createDimSurface(client, d, w, h, flags);
break;
@ -1291,15 +1290,6 @@ sp<Layer> SurfaceFlinger::createNormalSurface(
return layer;
}
sp<LayerBlur> SurfaceFlinger::createBlurSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags)
{
sp<LayerBlur> layer = new LayerBlur(this, display, client);
layer->initStates(w, h, flags);
return layer;
}
sp<LayerDim> SurfaceFlinger::createDimSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags)

View File

@ -48,7 +48,6 @@ class Client;
class DisplayHardware;
class FreezeLock;
class Layer;
class LayerBlur;
class LayerDim;
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
@ -218,7 +217,6 @@ private:
friend class LayerBaseClient;
friend class LayerBaseClient::Surface;
friend class Layer;
friend class LayerBlur;
friend class LayerDim;
sp<ISurface> createSurface(const sp<Client>& client,
@ -232,10 +230,6 @@ private:
uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format);
sp<LayerBlur> createBlurSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags);
sp<LayerDim> createDimSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags);