diff options
author | Mathias Agopian <mathias@google.com> | 2009-10-26 20:12:37 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-10-27 13:13:29 -0700 |
commit | 9042b4564de5477b18e680c7dce13b587a681dd9 (patch) | |
tree | 04872061371527ef76dbfff6ee0d6c8fdadb99bc /libs | |
parent | 678cdbe55e0de71436f8aad5f139eafc2ab6f937 (diff) | |
download | frameworks_base-9042b4564de5477b18e680c7dce13b587a681dd9.zip frameworks_base-9042b4564de5477b18e680c7dce13b587a681dd9.tar.gz frameworks_base-9042b4564de5477b18e680c7dce13b587a681dd9.tar.bz2 |
fix [2143798] Need to figure out how to do video
Use EGLImageKHR instead of copybit directly.
We now have the basis to use streaming YUV textures (well, in fact
we already are). When/if we use the GPU instead of the MDP we'll
need to make sure it supports the appropriate YUV format.
Also make sure we compile if EGL_ANDROID_image_native_buffer is not supported
Diffstat (limited to 'libs')
-rw-r--r-- | libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 4 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 65 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.h | 2 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.cpp | 57 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.h | 2 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBuffer.cpp | 143 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBuffer.h | 1 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerDim.cpp | 7 | ||||
-rw-r--r-- | libs/ui/GraphicBuffer.cpp | 28 |
9 files changed, 117 insertions, 192 deletions
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f84933e..1abfd68 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -256,12 +256,16 @@ void DisplayHardware::init(uint32_t dpy) if (strstr(gl_extensions, "GL_OES_draw_texture")) { mFlags |= DRAW_TEXTURE_EXTENSION; } +#ifdef EGL_ANDROID_image_native_buffer if (strstr( gl_extensions, "GL_OES_EGL_image") && (strstr(egl_extensions, "EGL_KHR_image_base") || strstr(egl_extensions, "EGL_KHR_image")) && strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) { mFlags |= DIRECT_TEXTURE; } +#else +#warning "EGL_ANDROID_image_native_buffer not supported" +#endif // Unbind the context from this thread eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 2bb1e12..f5a5a0b 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -130,62 +130,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, 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) { Mutex::Autolock _l(mLock); @@ -199,10 +143,11 @@ void Layer::reloadTexture(const Region& dirty) mTextures[index].height = 0; } +#ifdef EGL_ANDROID_image_native_buffer if (mFlags & DisplayHardware::DIRECT_TEXTURE) { if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) { if (mTextures[index].dirty) { - initializeEglImageLocked(buffer, &mTextures[index]); + initializeEglImage(buffer, &mTextures[index]); } } else { if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width || @@ -212,7 +157,7 @@ void Layer::reloadTexture(const Region& dirty) buffer->width, buffer->height, buffer->format, GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE); - initializeEglImageLocked( + initializeEglImage( mHybridBuffer, &mTextures[0]); } @@ -279,7 +224,9 @@ void Layer::reloadTexture(const Region& dirty) buffer->unlock(); } } - } else { + } else +#endif + { for (size_t i=0 ; i<NUM_BUFFERS ; i++) { mTextures[i].image = EGL_NO_IMAGE_KHR; } diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 57b3dfa..1310ecc 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -85,8 +85,6 @@ private: } void reloadTexture(const Region& dirty); - status_t initializeEglImageLocked( - const sp<GraphicBuffer>& buffer, Texture* texture); uint32_t getEffectiveUsage(uint32_t usage) const; diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index ecc7894..8003d22 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -617,6 +617,63 @@ void LayerBase::loadTexture(Texture* texture, } } +status_t LayerBase::initializeEglImage( + 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; +} + + // --------------------------------------------------------------------------- int32_t LayerBaseClient::sIdentity = 0; diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index efa4f8c..ed07b3f 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -261,6 +261,8 @@ protected: void drawWithOpenGL(const Region& clip, const Texture& texture) const; void loadTexture(Texture* texture, const Region& dirty, const GGLSurface& t) const; + status_t initializeEglImage( + const sp<GraphicBuffer>& buffer, Texture* texture); sp<SurfaceFlinger> mFlinger; diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 7e27a02..6590503 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -339,12 +339,6 @@ LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer, mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0); mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride; mLayer.forceVisibilityTransaction(); - - hw_module_t const* module; - mBlitEngine = NULL; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } } LayerBuffer::BufferSource::~BufferSource() @@ -352,8 +346,9 @@ LayerBuffer::BufferSource::~BufferSource() if (mTexture.name != -1U) { glDeleteTextures(1, &mTexture.name); } - if (mBlitEngine) { - copybit_close(mBlitEngine); + if (mTexture.image != EGL_NO_IMAGE_KHR) { + EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay()); + eglDestroyImageKHR(dpy, mTexture.image); } } @@ -421,122 +416,28 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const status_t err = NO_ERROR; NativeBuffer src(ourBuffer->getBuffer()); const Rect transformedBounds(mLayer.getTransformedBounds()); - copybit_device_t* copybit = mBlitEngine; - - if (copybit) { - const int src_width = src.crop.r - src.crop.l; - const int src_height = src.crop.b - src.crop.t; - int W = transformedBounds.width(); - int H = transformedBounds.height(); - if (mLayer.getOrientation() & Transform::ROT_90) { - int t(W); W=H; H=t; - } - -#ifdef EGL_ANDROID_get_render_buffer - EGLDisplay dpy = eglGetCurrentDisplay(); - EGLSurface draw = eglGetCurrentSurface(EGL_DRAW); - EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw); - android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf; - if (nb == 0) { - err = BAD_VALUE; - } else { - copybit_image_t dst; - dst.w = nb->width; - dst.h = nb->height; - dst.format = nb->format; - dst.base = NULL; // unused by copybit on msm7k - dst.handle = (native_handle_t *)nb->handle; - - /* With LayerBuffer, it is likely that we'll have to rescale the - * surface, because this is often used for video playback or - * camera-preview. Since we want these operation as fast as possible - * we make sure we can use the 2D H/W even if it doesn't support - * the requested scale factor, in which case we perform the scaling - * in several passes. */ - - const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT); - const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT); - - float xscale = 1.0f; - if (src_width > W*min) xscale = 1.0f / min; - else if (src_width*mag < W) xscale = mag; - - float yscale = 1.0f; - if (src_height > H*min) yscale = 1.0f / min; - else if (src_height*mag < H) yscale = mag; - - if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) { - const int tmp_w = floorf(src_width * xscale); - const int tmp_h = floorf(src_height * yscale); - - if (mTempBitmap==0 || - mTempBitmap->getWidth() < size_t(tmp_w) || - mTempBitmap->getHeight() < size_t(tmp_h)) { - mTempBitmap.clear(); - mTempBitmap = new GraphicBuffer( - tmp_w, tmp_h, src.img.format, - GraphicBuffer::USAGE_HW_2D); - err = mTempBitmap->initCheck(); - } - - if (LIKELY(err == NO_ERROR)) { - NativeBuffer tmp; - tmp.img.w = tmp_w; - tmp.img.h = tmp_h; - tmp.img.format = src.img.format; - tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle; - tmp.crop.l = 0; - tmp.crop.t = 0; - tmp.crop.r = tmp.img.w; - tmp.crop.b = tmp.img.h; - - region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - err = copybit->stretch(copybit, - &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it); - src = tmp; - } - } - const Rect transformedBounds(mLayer.getTransformedBounds()); - const copybit_rect_t& drect = - reinterpret_cast<const copybit_rect_t&>(transformedBounds); - const State& s(mLayer.drawingState()); - region_iterator it(clip); - - // pick the right orientation for this buffer - int orientation = mLayer.getOrientation(); - if (UNLIKELY(mBufferHeap.transform)) { - Transform rot90; - GraphicPlane::orientationToTransfrom( - ISurfaceComposer::eOrientation90, 0, 0, &rot90); - const Transform& planeTransform(mLayer.graphicPlane(0).transform()); - const Layer::State& s(mLayer.drawingState()); - Transform tr(planeTransform * s.transform * rot90); - orientation = tr.getOrientation(); - } + if (UNLIKELY(mTexture.name == -1LU)) { + mTexture.name = mLayer.createTexture(); + } - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); +#if defined(EGL_ANDROID_image_native_buffer) + if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) { + // NOTE: Assume the buffer is allocated with the proper USAGE flags + sp<GraphicBuffer> graphicBuffer = new GraphicBuffer( + src.crop.r, src.crop.b, src.img.format, + GraphicBuffer::USAGE_HW_TEXTURE, + src.img.w, src.img.handle, false); - err = copybit->stretch(copybit, - &dst, &src.img, &drect, &src.crop, &it); - if (err != NO_ERROR) { - LOGE("copybit failed (%s)", strerror(err)); - } - } + err = mLayer.initializeEglImage(graphicBuffer, &mTexture); } #endif - - if (!copybit || err) - { + else { + err = INVALID_OPERATION; + } + + if (err != NO_ERROR) { // OpenGL fall-back - if (UNLIKELY(mTexture.name == -1LU)) { - mTexture.name = mLayer.createTexture(); - } GLuint w = 0; GLuint h = 0; GGLSurface t; @@ -549,11 +450,11 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const t.data = (GGLubyte*)src.img.base; const Region dirty(Rect(t.width, t.height)); mLayer.loadTexture(&mTexture, dirty, t); - mTexture.transform = mBufferHeap.transform; - mLayer.drawWithOpenGL(clip, mTexture); } -} + mTexture.transform = mBufferHeap.transform; + mLayer.drawWithOpenGL(clip, mTexture); +} // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 5eb472c..438b711 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -132,7 +132,6 @@ private: size_t mBufferSize; mutable sp<GraphicBuffer> mTempBitmap; mutable LayerBase::Texture mTexture; - copybit_device_t* mBlitEngine; }; class OverlaySource : public Source { diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index 538dc77..fd61e30 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -55,8 +55,8 @@ void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) sHeight = h; sUseTexture = false; -#ifdef DIM_WITH_TEXTURE - +#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer) + #warning "using a texture to implement LayerDim" /* On some h/w like msm7K, it is faster to use a texture because the @@ -69,7 +69,6 @@ void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) uint32_t flags = hw.getFlags(); if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) { - // TODO: api to pass the usage flags sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565, GraphicBuffer::USAGE_SW_WRITE_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE); @@ -123,7 +122,7 @@ void LayerDim::onDraw(const Region& clip) const glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColor4x(0, 0, 0, alpha); -#ifdef DIM_WITH_TEXTURE +#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer) if (sUseTexture) { glBindTexture(GL_TEXTURE_2D, sTexId); glEnable(GL_TEXTURE_2D); diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 1cf20d7..efe2d78 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -37,7 +37,7 @@ namespace android { // =========================================================================== GraphicBuffer::GraphicBuffer() - : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()), + : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mVStride(0), mIndex(-1) { width = @@ -50,7 +50,7 @@ GraphicBuffer::GraphicBuffer() GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, PixelFormat reqFormat, uint32_t reqUsage) - : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()), + : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mVStride(0), mIndex(-1) { width = @@ -62,8 +62,23 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, mInitCheck = initSize(w, h, reqFormat, reqUsage); } +GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, + PixelFormat inFormat, uint32_t inUsage, + uint32_t inStride, native_handle_t* inHandle, bool keepOwnership) + : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), + mBufferMapper(GraphicBufferMapper::get()), + mInitCheck(NO_ERROR), mVStride(0), mIndex(-1) +{ + width = w; + height = h; + stride = inStride; + format = inFormat; + usage = inUsage; + handle = inHandle; +} + GraphicBuffer::GraphicBuffer(const Parcel& data) - : BASE(), mOwner(true), mBufferMapper(GraphicBufferMapper::get()), + : BASE(), mOwner(ownHandle), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mVStride(0), mIndex(-1) { // we own the handle in this case @@ -83,10 +98,10 @@ GraphicBuffer::GraphicBuffer(const Parcel& data) GraphicBuffer::~GraphicBuffer() { if (handle) { - if (mOwner) { + if (mOwner == ownHandle) { native_handle_close(handle); native_handle_delete(const_cast<native_handle*>(handle)); - } else { + } else if (mOwner == ownData) { GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); allocator.free(handle); } @@ -106,6 +121,9 @@ android_native_buffer_t* GraphicBuffer::getNativeBuffer() const status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f, uint32_t reqUsage) { + if (mOwner != ownData) + return INVALID_OPERATION; + if (handle) { GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); allocator.free(handle); |