Loading libs/surfaceflinger/Layer.cpp +142 −63 Original line number Diff line number Diff line Loading @@ -130,30 +130,18 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, return NO_ERROR; } void Layer::reloadTexture(const Region& dirty) status_t Layer::initializeEglImageLocked( const sp<GraphicBuffer>& buffer, Texture* texture) { Mutex::Autolock _l(mLock); sp<GraphicBuffer> buffer(getFrontBufferLocked()); if (LIKELY((mFlags & DisplayHardware::DIRECT_TEXTURE) && (buffer->usage & GRALLOC_USAGE_HW_TEXTURE))) { int index = mFrontBufferIndex; if (LIKELY(!mTextures[index].dirty)) { glBindTexture(GL_TEXTURE_2D, mTextures[index].name); } else { status_t err = NO_ERROR; // we need to recreate the texture EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); // create the new texture name if needed if (UNLIKELY(mTextures[index].name == -1U)) { mTextures[index].name = createTexture(); } else { glBindTexture(GL_TEXTURE_2D, mTextures[index].name); } // free the previous image if (mTextures[index].image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, mTextures[index].image); mTextures[index].image = EGL_NO_IMAGE_KHR; if (texture->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, texture->image); texture->image = EGL_NO_IMAGE_KHR; } // construct an EGL_NATIVE_BUFFER_ANDROID Loading @@ -164,57 +152,148 @@ void Layer::reloadTexture(const Region& dirty) EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE }; mTextures[index].image = eglCreateImageKHR( texture->image = eglCreateImageKHR( dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, attrs); LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR, LOGE_IF(texture->image == EGL_NO_IMAGE_KHR, "eglCreateImageKHR() failed. err=0x%4x", eglGetError()); if (mTextures[index].image != EGL_NO_IMAGE_KHR) { if (texture->image != EGL_NO_IMAGE_KHR) { glBindTexture(GL_TEXTURE_2D, texture->name); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)mTextures[index].image); (GLeglImageOES)texture->image); GLint error = glGetError(); if (UNLIKELY(error != GL_NO_ERROR)) { // this failed, for instance, because we don't support // NPOT. // this failed, for instance, because we don't support NPOT. // FIXME: do something! LOGD("layer=%p, glEGLImageTargetTexture2DOES(%p) " LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) " "failed err=0x%04x", this, mTextures[index].image, error); this, texture->image, error); mFlags &= ~DisplayHardware::DIRECT_TEXTURE; err = INVALID_OPERATION; } else { // Everything went okay! mTextures[index].NPOTAdjust = false; mTextures[index].dirty = false; mTextures[index].width = clientBuf->width; mTextures[index].height = clientBuf->height; 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) { Mutex::Autolock _l(mLock); sp<GraphicBuffer> buffer(getFrontBufferLocked()); int index = mFrontBufferIndex; // create the new texture name if needed if (UNLIKELY(mTextures[index].name == -1U)) { 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 { for (size_t i=0 ; i<NUM_BUFFERS ; i++) mTextures[i].image = EGL_NO_IMAGE_KHR; if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width || mHybridBuffer->height != buffer->height)) { mHybridBuffer.clear(); mHybridBuffer = new GraphicBuffer( buffer->width, buffer->height, buffer->format, GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE); initializeEglImageLocked( mHybridBuffer, &mTextures[0]); } GGLSurface t; status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); if (res == NO_ERROR) { Texture* const texture(&mTextures[0]); glBindTexture(GL_TEXTURE_2D, texture->name); sp<GraphicBuffer> buf(mHybridBuffer); void* vaddr; res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr); if (res == NO_ERROR) { if (UNLIKELY(mTextures[0].name == -1U)) { mTextures[0].name = createTexture(); mTextures[0].width = 0; mTextures[0].height = 0; int bpp = 0; switch (t.format) { case GGL_PIXEL_FORMAT_RGB_565: case GGL_PIXEL_FORMAT_RGBA_4444: bpp = 2; break; case GGL_PIXEL_FORMAT_RGBA_8888: case GGL_PIXEL_FORMAT_RGBX_8888: bpp = 4; break; case GGL_PIXEL_FORMAT_YCbCr_422_SP: case GGL_PIXEL_FORMAT_YCbCr_420_SP: // just show the Y plane of YUV buffers bpp = 1; break; 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 { for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mTextures[i].image = EGL_NO_IMAGE_KHR; } GGLSurface t; status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); if (res == NO_ERROR) { loadTexture(&mTextures[0], dirty, t); buffer->unlock(); } } } void Layer::onDraw(const Region& clip) const { int index = mFrontBufferIndex; Loading libs/surfaceflinger/Layer.h +3 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,8 @@ private: } void reloadTexture(const Region& dirty); status_t initializeEglImageLocked( const sp<GraphicBuffer>& buffer, Texture* texture); uint32_t getEffectiveUsage(uint32_t usage) const; Loading Loading @@ -118,6 +120,7 @@ private: // protected by mLock sp<GraphicBuffer> mBuffers[NUM_BUFFERS]; Texture mTextures[NUM_BUFFERS]; sp<GraphicBuffer> mHybridBuffer; uint32_t mWidth; uint32_t mHeight; Loading libs/surfaceflinger/LayerBase.cpp +1 −1 File changed.Contains only whitespace changes. Show changes Loading
libs/surfaceflinger/Layer.cpp +142 −63 Original line number Diff line number Diff line Loading @@ -130,30 +130,18 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, return NO_ERROR; } void Layer::reloadTexture(const Region& dirty) status_t Layer::initializeEglImageLocked( const sp<GraphicBuffer>& buffer, Texture* texture) { Mutex::Autolock _l(mLock); sp<GraphicBuffer> buffer(getFrontBufferLocked()); if (LIKELY((mFlags & DisplayHardware::DIRECT_TEXTURE) && (buffer->usage & GRALLOC_USAGE_HW_TEXTURE))) { int index = mFrontBufferIndex; if (LIKELY(!mTextures[index].dirty)) { glBindTexture(GL_TEXTURE_2D, mTextures[index].name); } else { status_t err = NO_ERROR; // we need to recreate the texture EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); // create the new texture name if needed if (UNLIKELY(mTextures[index].name == -1U)) { mTextures[index].name = createTexture(); } else { glBindTexture(GL_TEXTURE_2D, mTextures[index].name); } // free the previous image if (mTextures[index].image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, mTextures[index].image); mTextures[index].image = EGL_NO_IMAGE_KHR; if (texture->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, texture->image); texture->image = EGL_NO_IMAGE_KHR; } // construct an EGL_NATIVE_BUFFER_ANDROID Loading @@ -164,57 +152,148 @@ void Layer::reloadTexture(const Region& dirty) EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE }; mTextures[index].image = eglCreateImageKHR( texture->image = eglCreateImageKHR( dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, attrs); LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR, LOGE_IF(texture->image == EGL_NO_IMAGE_KHR, "eglCreateImageKHR() failed. err=0x%4x", eglGetError()); if (mTextures[index].image != EGL_NO_IMAGE_KHR) { if (texture->image != EGL_NO_IMAGE_KHR) { glBindTexture(GL_TEXTURE_2D, texture->name); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)mTextures[index].image); (GLeglImageOES)texture->image); GLint error = glGetError(); if (UNLIKELY(error != GL_NO_ERROR)) { // this failed, for instance, because we don't support // NPOT. // this failed, for instance, because we don't support NPOT. // FIXME: do something! LOGD("layer=%p, glEGLImageTargetTexture2DOES(%p) " LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) " "failed err=0x%04x", this, mTextures[index].image, error); this, texture->image, error); mFlags &= ~DisplayHardware::DIRECT_TEXTURE; err = INVALID_OPERATION; } else { // Everything went okay! mTextures[index].NPOTAdjust = false; mTextures[index].dirty = false; mTextures[index].width = clientBuf->width; mTextures[index].height = clientBuf->height; 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) { Mutex::Autolock _l(mLock); sp<GraphicBuffer> buffer(getFrontBufferLocked()); int index = mFrontBufferIndex; // create the new texture name if needed if (UNLIKELY(mTextures[index].name == -1U)) { 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 { for (size_t i=0 ; i<NUM_BUFFERS ; i++) mTextures[i].image = EGL_NO_IMAGE_KHR; if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width || mHybridBuffer->height != buffer->height)) { mHybridBuffer.clear(); mHybridBuffer = new GraphicBuffer( buffer->width, buffer->height, buffer->format, GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE); initializeEglImageLocked( mHybridBuffer, &mTextures[0]); } GGLSurface t; status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); if (res == NO_ERROR) { Texture* const texture(&mTextures[0]); glBindTexture(GL_TEXTURE_2D, texture->name); sp<GraphicBuffer> buf(mHybridBuffer); void* vaddr; res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr); if (res == NO_ERROR) { if (UNLIKELY(mTextures[0].name == -1U)) { mTextures[0].name = createTexture(); mTextures[0].width = 0; mTextures[0].height = 0; int bpp = 0; switch (t.format) { case GGL_PIXEL_FORMAT_RGB_565: case GGL_PIXEL_FORMAT_RGBA_4444: bpp = 2; break; case GGL_PIXEL_FORMAT_RGBA_8888: case GGL_PIXEL_FORMAT_RGBX_8888: bpp = 4; break; case GGL_PIXEL_FORMAT_YCbCr_422_SP: case GGL_PIXEL_FORMAT_YCbCr_420_SP: // just show the Y plane of YUV buffers bpp = 1; break; 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 { for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mTextures[i].image = EGL_NO_IMAGE_KHR; } GGLSurface t; status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); if (res == NO_ERROR) { loadTexture(&mTextures[0], dirty, t); buffer->unlock(); } } } void Layer::onDraw(const Region& clip) const { int index = mFrontBufferIndex; Loading
libs/surfaceflinger/Layer.h +3 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,8 @@ private: } void reloadTexture(const Region& dirty); status_t initializeEglImageLocked( const sp<GraphicBuffer>& buffer, Texture* texture); uint32_t getEffectiveUsage(uint32_t usage) const; Loading Loading @@ -118,6 +120,7 @@ private: // protected by mLock sp<GraphicBuffer> mBuffers[NUM_BUFFERS]; Texture mTextures[NUM_BUFFERS]; sp<GraphicBuffer> mHybridBuffer; uint32_t mWidth; uint32_t mHeight; Loading