diff options
author | 2009-10-26 20:12:37 -0700 | |
---|---|---|
committer | 2009-10-27 13:13:29 -0700 | |
commit | 9042b4564de5477b18e680c7dce13b587a681dd9 (patch) | |
tree | 04872061371527ef76dbfff6ee0d6c8fdadb99bc | |
parent | 678cdbe55e0de71436f8aad5f139eafc2ab6f937 (diff) |
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
-rw-r--r-- | include/ui/GraphicBuffer.h | 14 | ||||
-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 | ||||
-rw-r--r-- | opengl/libagl/Android.mk | 15 | ||||
-rw-r--r-- | opengl/libagl/copybit.cpp | 100 |
12 files changed, 220 insertions, 218 deletions
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index 8897f0314b7d..21725360d1d9 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -66,7 +66,11 @@ public: GraphicBuffer(); // creates w * h buffer - GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t ssage); + GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage); + + // create a buffer from an existing handle + GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage, + uint32_t stride, native_handle_t* handle, bool keepOwnership); // return status status_t initCheck() const; @@ -94,9 +98,15 @@ protected: GraphicBuffer(const Parcel& reply); virtual ~GraphicBuffer(); + enum { + ownNone = 0, + ownHandle = 1, + ownData = 2, + }; + inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } - bool mOwner; + uint8_t mOwner; private: friend class Surface; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f84933ee77e9..1abfd68c7654 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 2bb1e1252ebf..f5a5a0bf2d2e 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 57b3dfa41ee2..1310ecc9c19f 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 ecc78946bb93..8003d22daa8b 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 efa4f8c2109a..ed07b3f93360 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 7e27a02be819..6590503d31f1 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 5eb472cc96a9..438b711be9c3 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 538dc777c0f0..fd61e30d8f5a 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 1cf20d783a26..efe2d786cf1f 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); diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index 2522656f2213..983784554d30 100644 --- a/opengl/libagl/Android.mk +++ b/opengl/libagl/Android.mk @@ -25,6 +25,13 @@ LOCAL_SRC_FILES:= \ primitives.cpp.arm \ vertex.cpp.arm +LOCAL_CFLAGS += -DLOG_TAG=\"libagl\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES +LOCAL_CFLAGS += -fvisibility=hidden + +LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger +LOCAL_LDLIBS := -lpthread -ldl + ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += fixed_asm.S iterators.S LOCAL_CFLAGS += -fstrict-aliasing @@ -38,15 +45,9 @@ endif ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1) LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS LOCAL_SRC_FILES += copybit.cpp + LOCAL_SHARED_LIBRARIES += libui endif -LOCAL_CFLAGS += -DLOG_TAG=\"libagl\" -LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES - -LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger -LOCAL_CFLAGS += -fvisibility=hidden - -LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl LOCAL_MODULE:= libGLES_android diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index 73b2355aa8ec..0c3d0eef5cdc 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -33,6 +33,10 @@ #include <hardware/copybit.h> #include <private/ui/android_natives_priv.h> +#include <ui/GraphicBuffer.h> +#include <ui/Region.h> +#include <ui/Rect.h> + #define DEBUG_COPYBIT true @@ -175,16 +179,6 @@ static bool copybit(GLint x, GLint y, dtdy /= screen_h; } dtdy = -dtdy; // see equation of dtdy above - if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale - || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) { - // The requested scale is out of the range the hardware - // can support. - LOGD_IF(DEBUG_COPYBIT, - "scale out of range dsdx=%08x (Wcr=%d / w=%d), " - "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d", - dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr); - return false; - } // copybit doesn't say anything about filtering, so we can't // discriminate. On msm7k, copybit will always filter. @@ -278,21 +272,93 @@ static bool copybit(GLint x, GLint y, return false; } + copybit_device_t* copybit = c->copybits.blitEngine; + copybit_image_t src; + buffer_handle_t source_hnd = textureObject->buffer->handle; + textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src); + copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr }; + + /* + * Below we perform extra passes needed to emulate things the h/w + * cannot do. + */ - // LOGW("calling copybits"); + const GLfixed minScaleInv = gglDivQ(0x10000, c->copybits.minScale, 16); + const GLfixed maxScaleInv = gglDivQ(0x10000, c->copybits.maxScale, 16); - copybit_device_t* copybit = c->copybits.blitEngine; + sp<GraphicBuffer> tempBitmap; + + if (dsdx < maxScaleInv || dsdx > minScaleInv || + dtdy < maxScaleInv || dtdy > minScaleInv) + { + // The requested scale is out of the range the hardware + // can support. + LOGD_IF(DEBUG_COPYBIT, + "scale out of range dsdx=%08x (Wcr=%d / w=%d), " + "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d", + dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr); + + int32_t xscale=0x10000, yscale=0x10000; + if (dsdx > minScaleInv) xscale = c->copybits.minScale; + else if (dsdx < maxScaleInv) xscale = c->copybits.maxScale; + if (dtdy > minScaleInv) yscale = c->copybits.minScale; + else if (dtdy < maxScaleInv) yscale = c->copybits.maxScale; + dsdx = gglMulx(dsdx, xscale); + dtdy = gglMulx(dtdy, yscale); + + /* we handle only one step of resizing below. Handling an arbitrary + * number is relatively easy (replace "if" above by "while"), but requires + * two intermediate buffers and so far we never had the need. + */ + + if (dsdx < maxScaleInv || dsdx > minScaleInv || + dtdy < maxScaleInv || dtdy > minScaleInv) { + LOGD_IF(DEBUG_COPYBIT, + "scale out of range dsdx=%08x (Wcr=%d / w=%d), " + "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d", + dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr); + return false; + } + + const int tmp_w = gglMulx(srect.r - srect.l, xscale, 16); + const int tmp_h = gglMulx(srect.b - srect.t, yscale, 16); + + LOGD_IF(DEBUG_COPYBIT, + "xscale=%08x, yscale=%08x, dsdx=%08x, dtdy=%08x, tmp_w=%d, tmp_h=%d", + xscale, yscale, dsdx, dtdy, tmp_w, tmp_h); + + tempBitmap = new GraphicBuffer( + tmp_w, tmp_h, src.format, + GraphicBuffer::USAGE_HW_2D); + + status_t err = tempBitmap->initCheck(); + if (err == NO_ERROR) { + copybit_image_t tmp_dst; + copybit_rect_t tmp_rect; + tmp_dst.w = tmp_w; + tmp_dst.h = tmp_h; + tmp_dst.format = src.format; + tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle; + tmp_rect.l = 0; + tmp_rect.t = 0; + tmp_rect.r = tmp_dst.w; + tmp_rect.b = tmp_dst.h; + region_iterator tmp_it(Region(Rect(tmp_rect.r, tmp_rect.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_dst, &src, &tmp_rect, &srect, &tmp_it); + src = tmp_dst; + srect = tmp_rect; + } + } copybit_image_t dst; buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer; textureToCopyBitImage(&cbSurface, cbSurface.format, target_hnd, &dst); copybit_rect_t drect = {x, y, x+w, y+h}; - copybit_image_t src; - buffer_handle_t source_hnd = textureObject->buffer->handle; - textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src); - copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr }; - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha); copybit->set_parameter(copybit, COPYBIT_DITHER, |