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 | |
| 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
| -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 8897f03..2172536 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 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); diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index 2522656..9837845 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 73b2355..0c3d0ee 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, |
