Merge change I56c3504f into eclair

* changes:
  fix [2211532] improves sholes graphics performance
This commit is contained in:
Android (Google) Code Review
2009-10-23 19:02:12 -04:00
3 changed files with 145 additions and 63 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
/* /*