diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index 0539a1b68..04a2f5295 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -96,7 +96,9 @@ public: // allowSynchronousMode specifies whether or not synchronous mode can be // enabled. // bufferCount sets the minimum number of undequeued buffers for this queue - BufferQueue( bool allowSynchronousMode = true, int bufferCount = MIN_UNDEQUEUED_BUFFERS); + BufferQueue(bool allowSynchronousMode = true, + int bufferCount = MIN_UNDEQUEUED_BUFFERS, + const sp& allocator = NULL); virtual ~BufferQueue(); virtual int query(int what, int* value); diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index a0774cfe6..a2e08c036 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -81,7 +81,8 @@ static const char* scalingModeName(int scalingMode) { } } -BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) : +BufferQueue::BufferQueue(bool allowSynchronousMode, int bufferCount, + const sp& allocator) : mDefaultWidth(1), mDefaultHeight(1), mPixelFormat(PIXEL_FORMAT_RGBA_8888), @@ -105,10 +106,14 @@ BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) : mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); ST_LOGV("BufferQueue"); - sp composer(ComposerService::getComposerService()); - mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); - if (mGraphicBufferAlloc == 0) { - ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()"); + if (allocator == NULL) { + sp composer(ComposerService::getComposerService()); + mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); + if (mGraphicBufferAlloc == 0) { + ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()"); + } + } else { + mGraphicBufferAlloc = allocator; } } diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 6f7a7e1ff..7d2b75acc 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \ LayerScreenshot.cpp \ DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ + DisplayHardware/FramebufferSurface.cpp \ DisplayHardware/HWComposer.cpp \ DisplayHardware/PowerHAL.cpp \ GLExtensions.cpp \ diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index bb93215e0..e1c4f62fa 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -25,13 +25,13 @@ #include #include -#include #include #include #include #include "DisplayHardware/DisplayHardware.h" +#include "DisplayHardware/FramebufferSurface.h" #include @@ -148,7 +148,7 @@ static status_t selectConfigForPixelFormat( void DisplayHardware::init(uint32_t dpy) { - mNativeWindow = new FramebufferNativeWindow(); + mNativeWindow = new FramebufferSurface(); framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); if (!fbDev) { ALOGE("Display subsystem failed to initialize. check logs. exiting..."); diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h index 0604031fc..f029a0a13 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -35,7 +35,7 @@ namespace android { -class FramebufferNativeWindow; +class FramebufferSurface; class DisplayHardware : public DisplayHardwareBase, @@ -144,7 +144,7 @@ private: // protected by mLock wp mVSyncHandler; - sp mNativeWindow; + sp mNativeWindow; }; }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp new file mode 100644 index 000000000..02ec86ec4 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -0,0 +1,188 @@ +/* + ** + ** Copyright 2007 The Android Open Source Project + ** + ** Licensed under the Apache License Version 2.0(the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing software + ** distributed under the License is distributed on an "AS IS" BASIS + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include "DisplayHardware/FramebufferSurface.h" + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + + +/* + * This implements the (main) framebuffer management. This class is used + * mostly by SurfaceFlinger, but also by command line GL application. + * + */ + +FramebufferSurface::FramebufferSurface() + : SurfaceTextureClient(), + fbDev(0), mCurrentBufferIndex(-1), mUpdateOnDemand(false) +{ + hw_module_t const* module; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { + int stride; + int err; + int i; + err = framebuffer_open(module, &fbDev); + ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); + + // bail out if we can't initialize the modules + if (!fbDev) + return; + + mUpdateOnDemand = (fbDev->setUpdateRect != 0); + + const_cast(ANativeWindow::flags) = fbDev->flags; + const_cast(ANativeWindow::xdpi) = fbDev->xdpi; + const_cast(ANativeWindow::ydpi) = fbDev->ydpi; + const_cast(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; + const_cast(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval; + } else { + ALOGE("Couldn't get gralloc module"); + } + + class GraphicBufferAlloc : public BnGraphicBufferAlloc { + public: + GraphicBufferAlloc() { }; + virtual ~GraphicBufferAlloc() { }; + virtual sp createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage, status_t* error) { + sp graphicBuffer(new GraphicBuffer(w, h, format, usage)); + return graphicBuffer; + } + }; + + mBufferQueue = new BufferQueue(true, NUM_FRAME_BUFFERS, new GraphicBufferAlloc()); + mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB|GRALLOC_USAGE_HW_RENDER|GRALLOC_USAGE_HW_COMPOSER); + mBufferQueue->setDefaultBufferFormat(fbDev->format); + mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height); + mBufferQueue->setSynchronousMode(true); + mBufferQueue->setBufferCountServer(NUM_FRAME_BUFFERS); + setISurfaceTexture(mBufferQueue); +} + +void FramebufferSurface::onFirstRef() { + class Listener : public BufferQueue::ConsumerListener { + const wp that; + virtual ~Listener() { } + virtual void onBuffersReleased() { } + void onFrameAvailable() { + sp self = that.promote(); + if (self != NULL) { + BufferQueue::BufferItem item; + status_t err = self->mBufferQueue->acquireBuffer(&item); + if (err == 0) { + if (item.mGraphicBuffer != 0) { + self->mBuffers[item.mBuf] = item.mGraphicBuffer; + } + self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle); + if (self->mCurrentBufferIndex >= 0) { + self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); + } + self->mCurrentBufferIndex = item.mBuf; + } + } + } + public: + Listener(const sp& that) : that(that) { } + }; + + mBufferQueue->setConsumerName(String8("FramebufferSurface")); + mBufferQueue->consumerConnect(new Listener(this)); +} + +FramebufferSurface::~FramebufferSurface() { + if (fbDev) { + framebuffer_close(fbDev); + } +} + +status_t FramebufferSurface::setUpdateRectangle(const Rect& r) +{ + if (!mUpdateOnDemand) { + return INVALID_OPERATION; + } + return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height()); +} + +status_t FramebufferSurface::compositionComplete() +{ + if (fbDev->compositionComplete) { + return fbDev->compositionComplete(fbDev); + } + return INVALID_OPERATION; +} + +void FramebufferSurface::dump(String8& result) { + if (fbDev->common.version >= 1 && fbDev->dump) { + const size_t SIZE = 4096; + char buffer[SIZE]; + + fbDev->dump(fbDev, buffer, SIZE); + result.append(buffer); + } +} + +int FramebufferSurface::query(int what, int* value) const { + Mutex::Autolock _l(mLock); + framebuffer_device_t* fb = fbDev; + switch (what) { + case NATIVE_WINDOW_DEFAULT_WIDTH: + case NATIVE_WINDOW_WIDTH: + *value = fb->width; + return NO_ERROR; + case NATIVE_WINDOW_DEFAULT_HEIGHT: + case NATIVE_WINDOW_HEIGHT: + *value = fb->height; + return NO_ERROR; + case NATIVE_WINDOW_FORMAT: + *value = fb->format; + return NO_ERROR; + case NATIVE_WINDOW_CONCRETE_TYPE: + *value = NATIVE_WINDOW_FRAMEBUFFER; + return NO_ERROR; + case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: + *value = 0; + return NO_ERROR; + case NATIVE_WINDOW_TRANSFORM_HINT: + *value = 0; + return NO_ERROR; + } + return SurfaceTextureClient::query(what, value); +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h new file mode 100644 index 000000000..5b4fd01b0 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SF_FRAMEBUFFER_SURFACE_H +#define ANDROID_SF_FRAMEBUFFER_SURFACE_H + +#include +#include + +#include + +#include + +#define NUM_FRAME_BUFFERS 2 + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class Rect; +class String8; + +// --------------------------------------------------------------------------- + +class FramebufferSurface : public SurfaceTextureClient { +public: + FramebufferSurface(); + + virtual void onFirstRef(); + + framebuffer_device_t const * getDevice() const { return fbDev; } + + bool isUpdateOnDemand() const { return mUpdateOnDemand; } + status_t setUpdateRectangle(const Rect& updateRect); + status_t compositionComplete(); + + void dump(String8& result); + +private: + virtual ~FramebufferSurface(); // this class cannot be overloaded + virtual int query(int what, int* value) const; + + framebuffer_device_t* fbDev; + + sp mBufferQueue; + int mCurrentBufferIndex; + sp mBuffers[NUM_FRAME_BUFFERS]; + + mutable Mutex mLock; + bool mUpdateOnDemand; +}; + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_SF_FRAMEBUFFER_SURFACE_H +