Merge change I56c3504f into eclair
* changes: fix [2211532] improves sholes graphics performance
This commit is contained in:
@@ -130,91 +130,170 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t Layer::initializeEglImageLocked(
|
||||||
|
const sp<GraphicBuffer>& buffer, Texture* texture)
|
||||||
|
{
|
||||||
|
status_t err = NO_ERROR;
|
||||||
|
|
||||||
|
// we need to recreate the texture
|
||||||
|
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
|
||||||
|
|
||||||
|
// free the previous image
|
||||||
|
if (texture->image != EGL_NO_IMAGE_KHR) {
|
||||||
|
eglDestroyImageKHR(dpy, texture->image);
|
||||||
|
texture->image = EGL_NO_IMAGE_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct an EGL_NATIVE_BUFFER_ANDROID
|
||||||
|
android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
|
||||||
|
|
||||||
|
// create the new EGLImageKHR
|
||||||
|
const EGLint attrs[] = {
|
||||||
|
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
|
||||||
|
EGL_NONE, EGL_NONE
|
||||||
|
};
|
||||||
|
texture->image = eglCreateImageKHR(
|
||||||
|
dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
|
||||||
|
(EGLClientBuffer)clientBuf, attrs);
|
||||||
|
|
||||||
|
LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
|
||||||
|
"eglCreateImageKHR() failed. err=0x%4x",
|
||||||
|
eglGetError());
|
||||||
|
|
||||||
|
if (texture->image != EGL_NO_IMAGE_KHR) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->name);
|
||||||
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
|
||||||
|
(GLeglImageOES)texture->image);
|
||||||
|
GLint error = glGetError();
|
||||||
|
if (UNLIKELY(error != GL_NO_ERROR)) {
|
||||||
|
// this failed, for instance, because we don't support NPOT.
|
||||||
|
// FIXME: do something!
|
||||||
|
LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
|
||||||
|
"failed err=0x%04x",
|
||||||
|
this, texture->image, error);
|
||||||
|
mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
|
||||||
|
err = INVALID_OPERATION;
|
||||||
|
} else {
|
||||||
|
// Everything went okay!
|
||||||
|
texture->NPOTAdjust = false;
|
||||||
|
texture->dirty = false;
|
||||||
|
texture->width = clientBuf->width;
|
||||||
|
texture->height = clientBuf->height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
void Layer::reloadTexture(const Region& dirty)
|
void Layer::reloadTexture(const Region& dirty)
|
||||||
{
|
{
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
sp<GraphicBuffer> buffer(getFrontBufferLocked());
|
sp<GraphicBuffer> buffer(getFrontBufferLocked());
|
||||||
if (LIKELY((mFlags & DisplayHardware::DIRECT_TEXTURE) &&
|
int index = mFrontBufferIndex;
|
||||||
(buffer->usage & GRALLOC_USAGE_HW_TEXTURE))) {
|
|
||||||
int index = mFrontBufferIndex;
|
// create the new texture name if needed
|
||||||
if (LIKELY(!mTextures[index].dirty)) {
|
if (UNLIKELY(mTextures[index].name == -1U)) {
|
||||||
glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
|
mTextures[index].name = createTexture();
|
||||||
|
mTextures[index].width = 0;
|
||||||
|
mTextures[index].height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
|
||||||
|
if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
|
||||||
|
if (mTextures[index].dirty) {
|
||||||
|
initializeEglImageLocked(buffer, &mTextures[index]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// we need to recreate the texture
|
if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
|
||||||
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
|
mHybridBuffer->height != buffer->height)) {
|
||||||
|
mHybridBuffer.clear();
|
||||||
// create the new texture name if needed
|
mHybridBuffer = new GraphicBuffer(
|
||||||
if (UNLIKELY(mTextures[index].name == -1U)) {
|
buffer->width, buffer->height, buffer->format,
|
||||||
mTextures[index].name = createTexture();
|
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
|
||||||
} else {
|
GraphicBuffer::USAGE_HW_TEXTURE);
|
||||||
glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
|
initializeEglImageLocked(
|
||||||
|
mHybridBuffer, &mTextures[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// free the previous image
|
GGLSurface t;
|
||||||
if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
|
status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
|
||||||
eglDestroyImageKHR(dpy, mTextures[index].image);
|
LOGE_IF(res, "error %d (%s) locking buffer %p",
|
||||||
mTextures[index].image = EGL_NO_IMAGE_KHR;
|
res, strerror(res), buffer.get());
|
||||||
}
|
if (res == NO_ERROR) {
|
||||||
|
Texture* const texture(&mTextures[0]);
|
||||||
// construct an EGL_NATIVE_BUFFER_ANDROID
|
|
||||||
android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
|
|
||||||
|
|
||||||
// create the new EGLImageKHR
|
|
||||||
const EGLint attrs[] = {
|
|
||||||
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
|
|
||||||
EGL_NONE, EGL_NONE
|
|
||||||
};
|
|
||||||
mTextures[index].image = eglCreateImageKHR(
|
|
||||||
dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
|
|
||||||
(EGLClientBuffer)clientBuf, attrs);
|
|
||||||
|
|
||||||
LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR,
|
glBindTexture(GL_TEXTURE_2D, texture->name);
|
||||||
"eglCreateImageKHR() failed. err=0x%4x",
|
|
||||||
eglGetError());
|
sp<GraphicBuffer> buf(mHybridBuffer);
|
||||||
|
void* vaddr;
|
||||||
if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
|
res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
|
if (res == NO_ERROR) {
|
||||||
(GLeglImageOES)mTextures[index].image);
|
int bpp = 0;
|
||||||
GLint error = glGetError();
|
switch (t.format) {
|
||||||
if (UNLIKELY(error != GL_NO_ERROR)) {
|
case GGL_PIXEL_FORMAT_RGB_565:
|
||||||
// this failed, for instance, because we don't support
|
case GGL_PIXEL_FORMAT_RGBA_4444:
|
||||||
// NPOT.
|
bpp = 2;
|
||||||
// FIXME: do something!
|
break;
|
||||||
LOGD("layer=%p, glEGLImageTargetTexture2DOES(%p) "
|
case GGL_PIXEL_FORMAT_RGBA_8888:
|
||||||
"failed err=0x%04x",
|
case GGL_PIXEL_FORMAT_RGBX_8888:
|
||||||
this, mTextures[index].image, error);
|
bpp = 4;
|
||||||
mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
|
break;
|
||||||
} else {
|
case GGL_PIXEL_FORMAT_YCbCr_422_SP:
|
||||||
// Everything went okay!
|
case GGL_PIXEL_FORMAT_YCbCr_420_SP:
|
||||||
mTextures[index].NPOTAdjust = false;
|
// just show the Y plane of YUV buffers
|
||||||
mTextures[index].dirty = false;
|
bpp = 1;
|
||||||
mTextures[index].width = clientBuf->width;
|
break;
|
||||||
mTextures[index].height = clientBuf->height;
|
default:
|
||||||
|
// oops, we don't handle this format!
|
||||||
|
LOGE("layer %p, texture=%d, using format %d, which is not "
|
||||||
|
"supported by the GL", this, texture->name, t.format);
|
||||||
|
}
|
||||||
|
if (bpp) {
|
||||||
|
const Rect bounds(dirty.getBounds());
|
||||||
|
size_t src_stride = t.stride;
|
||||||
|
size_t dst_stride = buf->stride;
|
||||||
|
if (src_stride == dst_stride &&
|
||||||
|
bounds.width() == t.width &&
|
||||||
|
bounds.height() == t.height)
|
||||||
|
{
|
||||||
|
memcpy(vaddr, t.data, t.height * t.stride * bpp);
|
||||||
|
} else {
|
||||||
|
GLubyte const * src = t.data +
|
||||||
|
(bounds.left + bounds.top * src_stride) * bpp;
|
||||||
|
GLubyte * dst = (GLubyte *)vaddr +
|
||||||
|
(bounds.left + bounds.top * dst_stride) * bpp;
|
||||||
|
const size_t length = bounds.width() * bpp;
|
||||||
|
size_t h = bounds.height();
|
||||||
|
src_stride *= bpp;
|
||||||
|
dst_stride *= bpp;
|
||||||
|
while (h--) {
|
||||||
|
memcpy(dst, src, length);
|
||||||
|
dst += dst_stride;
|
||||||
|
src += src_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf->unlock();
|
||||||
}
|
}
|
||||||
}
|
buffer->unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (size_t i=0 ; i<NUM_BUFFERS ; i++)
|
for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
|
||||||
mTextures[i].image = EGL_NO_IMAGE_KHR;
|
mTextures[i].image = EGL_NO_IMAGE_KHR;
|
||||||
|
}
|
||||||
GGLSurface t;
|
GGLSurface t;
|
||||||
status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
|
status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
|
||||||
LOGE_IF(res, "error %d (%s) locking buffer %p",
|
LOGE_IF(res, "error %d (%s) locking buffer %p",
|
||||||
res, strerror(res), buffer.get());
|
res, strerror(res), buffer.get());
|
||||||
|
|
||||||
if (res == NO_ERROR) {
|
if (res == NO_ERROR) {
|
||||||
if (UNLIKELY(mTextures[0].name == -1U)) {
|
|
||||||
mTextures[0].name = createTexture();
|
|
||||||
mTextures[0].width = 0;
|
|
||||||
mTextures[0].height = 0;
|
|
||||||
}
|
|
||||||
loadTexture(&mTextures[0], dirty, t);
|
loadTexture(&mTextures[0], dirty, t);
|
||||||
buffer->unlock();
|
buffer->unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Layer::onDraw(const Region& clip) const
|
void Layer::onDraw(const Region& clip) const
|
||||||
{
|
{
|
||||||
int index = mFrontBufferIndex;
|
int index = mFrontBufferIndex;
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reloadTexture(const Region& dirty);
|
void reloadTexture(const Region& dirty);
|
||||||
|
status_t initializeEglImageLocked(
|
||||||
|
const sp<GraphicBuffer>& buffer, Texture* texture);
|
||||||
|
|
||||||
uint32_t getEffectiveUsage(uint32_t usage) const;
|
uint32_t getEffectiveUsage(uint32_t usage) const;
|
||||||
|
|
||||||
@@ -118,6 +120,7 @@ private:
|
|||||||
// protected by mLock
|
// protected by mLock
|
||||||
sp<GraphicBuffer> mBuffers[NUM_BUFFERS];
|
sp<GraphicBuffer> mBuffers[NUM_BUFFERS];
|
||||||
Texture mTextures[NUM_BUFFERS];
|
Texture mTextures[NUM_BUFFERS];
|
||||||
|
sp<GraphicBuffer> mHybridBuffer;
|
||||||
uint32_t mWidth;
|
uint32_t mWidth;
|
||||||
uint32_t mHeight;
|
uint32_t mHeight;
|
||||||
|
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ void LayerBase::loadTexture(Texture* texture,
|
|||||||
// uh?
|
// uh?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->name);
|
glBindTexture(GL_TEXTURE_2D, texture->name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user