diff options
-rw-r--r-- | include/ui/FramebufferNativeWindow.h | 8 | ||||
-rw-r--r-- | libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 7 | ||||
-rw-r--r-- | libs/surfaceflinger/DisplayHardware/DisplayHardware.h | 6 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBuffer.cpp | 124 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBuffer.h | 3 | ||||
-rw-r--r-- | libs/ui/FramebufferNativeWindow.cpp | 6 |
6 files changed, 142 insertions, 12 deletions
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h index a780472..03d064c 100644 --- a/include/ui/FramebufferNativeWindow.h +++ b/include/ui/FramebufferNativeWindow.h @@ -55,6 +55,9 @@ public: bool isUpdateOnDemand() const { return mUpdateOnDemand; } status_t setUpdateRectangle(const Rect& updateRect); + // FIXME: needed for copybit hack in LayerBuffer + android_native_buffer_t const* getBackbuffer() const; + private: friend class LightRefBase<FramebufferNativeWindow>; ~FramebufferNativeWindow(); // this class cannot be overloaded @@ -75,8 +78,11 @@ private: int32_t mNumFreeBuffers; int32_t mBufferHead; bool mUpdateOnDemand; -}; + // FIXME: for getBackbuffer + int32_t mLastDequeued; +}; + // --------------------------------------------------------------------------- }; // namespace android // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 784dfa5..925f5cc 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -349,10 +349,7 @@ void DisplayHardware::makeCurrent() const eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); } -void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { - // FIXME: we need to get rid of this +sp<FramebufferNativeWindow> DisplayHardware::getFb() const { + return mNativeWindow; } -void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { - // FIXME: we need to get rid of this -} diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index c3dbff1..240c5d1 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -80,13 +80,13 @@ public: EGLDisplay getEGLDisplay() const { return mDisplay; } overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } - void copyFrontToImage(const copybit_image_t& front) const; - void copyBackToImage(const copybit_image_t& front) const; - Rect bounds() const { return Rect(mWidth, mHeight); } + // FIXME: needed in LayerBuffer for msm7k/copybit hack + sp<FramebufferNativeWindow> getFb() const; + private: void init(uint32_t displayIndex) __attribute__((noinline)); void fini() __attribute__((noinline)); diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 22fd499..1baf720 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -24,6 +24,9 @@ #include <utils/StopWatch.h> #include <ui/PixelFormat.h> +#include <ui/FramebufferNativeWindow.h> + +#include <hardware/copybit.h> #include "LayerBuffer.h" #include "SurfaceFlinger.h" @@ -316,7 +319,12 @@ 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() @@ -387,9 +395,119 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const return; } - const NativeBuffer& src( ourBuffer->getBuffer() ); + 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; + } + +#if 0 + /* 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)) { + if (UNLIKELY(mTemporaryDealer == 0)) { + // allocate a memory-dealer for this the first time + mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager() + ->createHeap(ISurfaceComposer::eHardware); + mTempBitmap.init(mTemporaryDealer); + } + + const int tmp_w = floorf(src_width * xscale); + const int tmp_h = floorf(src_height * yscale); + err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format); + + if (LIKELY(err == NO_ERROR)) { + NativeBuffer tmp; + mTempBitmap.getBitmapSurface(&tmp.img); + 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; + } + } +#endif + + copybit_image_t dst; + const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware()); + sp<FramebufferNativeWindow> fbw = hw.getFb(); + android_native_buffer_t const* nb = fbw->getBackbuffer(); + native_handle_t const* hnd = nb->handle; + + if (hnd->data[1] != 0x3141592) { + LOGE("buffer not compatible with copybit"); + err = -1; + } else { + + dst.w = 320; + dst.h = 480; + dst.format = 4; + dst.offset = hnd->data[4]; + dst.base = 0; + dst.fd = hnd->data[0]; + + 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(); + } + + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + + err = copybit->stretch(copybit, + &dst, &src.img, &drect, &src.crop, &it); + if (err != NO_ERROR) { + LOGE("copybit failed (%s)", strerror(err)); + } + } + } - //if (!can_use_copybit || err) + if (!copybit || err) { // OpenGL fall-back if (UNLIKELY(mTexture.name == -1LU)) { diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index e1b3cf8..cd541a5 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -26,6 +26,8 @@ #include "LayerBase.h" #include "LayerBitmap.h" +struct copybit_device_t; + namespace android { // --------------------------------------------------------------------------- @@ -128,6 +130,7 @@ private: size_t mBufferSize; mutable sp<android::Buffer> mTempBitmap; mutable LayerBase::Texture mTexture; + copybit_device_t* mBlitEngine; }; class OverlaySource : public Source { diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 8c8fd6b..406c072 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -63,6 +63,11 @@ private: }; +android_native_buffer_t const* FramebufferNativeWindow::getBackbuffer() const { + return static_cast<android_native_buffer_t const*>(buffers[mLastDequeued].get()); +} + + /* * This implements the (main) framebuffer management. This class is used * mostly by SurfaceFlinger, but also by command line GL application. @@ -165,6 +170,7 @@ int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, if (self->mBufferHead >= self->mNumBuffers) self->mBufferHead = 0; + self->mLastDequeued = index; *buffer = self->buffers[index].get(); return 0; |