OSDN Git Service

Android FrameBuffer implementation.
authorGreg Hartman <ghartman@google.com>
Fri, 20 Mar 2015 20:05:34 +0000 (13:05 -0700)
committerGreg Hartman <ghartman@google.com>
Wed, 25 Mar 2015 16:53:25 +0000 (16:53 +0000)
Change-Id: I95356056e7785e2dcfeffa95d4a38cc4e113ec62
Reviewed-on: https://swiftshader-review.googlesource.com/2661
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Greg Hartman <ghartman@google.com>
src/Main/FrameBufferAndroid.cpp [new file with mode: 0644]
src/Main/FrameBufferAndroid.hpp [new file with mode: 0644]

diff --git a/src/Main/FrameBufferAndroid.cpp b/src/Main/FrameBufferAndroid.cpp
new file mode 100644 (file)
index 0000000..8e69d2e
--- /dev/null
@@ -0,0 +1,95 @@
+#include "FrameBufferAndroid.hpp"
+
+#include <cutils/log.h>
+#include <ui/Fence.h>
+
+namespace sw
+{
+    FrameBufferAndroid::FrameBufferAndroid(ANativeWindow* window, int width, int height)
+        : FrameBuffer(width, height, false, false),
+        nativeWindow(window), buffer(0), gralloc(0), bits(NULL)
+    {
+        hw_module_t const* pModule;
+        hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
+        gralloc = reinterpret_cast<gralloc_module_t const*>(pModule);
+
+        nativeWindow->common.incRef(&nativeWindow->common);
+        native_window_set_usage(nativeWindow, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+    }
+
+    FrameBufferAndroid::~FrameBufferAndroid()
+    {
+        if (buffer)
+        {
+            // Probably doesn't have to cancel assuming a success queueing earlier
+            nativeWindow->cancelBuffer(nativeWindow, buffer, -1);
+            buffer = 0;
+        }
+        nativeWindow->common.decRef(&nativeWindow->common);
+    }
+
+    void FrameBufferAndroid::blit(void *source, const Rect *sourceRect, const Rect *destRect, Format format)
+    {
+        copy(source, format);
+        nativeWindow->queueBuffer(nativeWindow, buffer, -1);
+
+        if (buffer && bits)
+        {
+            bits = 0;
+            unlock(buffer);
+        }
+
+        buffer->common.decRef(&buffer->common);
+    }
+
+    void* FrameBufferAndroid::lock()
+    {
+        int fenceFd = -1;
+        if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &fenceFd) != android::NO_ERROR)
+        {
+            return NULL;
+        }
+
+        android::sp<android::Fence> fence(new android::Fence(fenceFd));
+        if (fence->wait(android::Fence::TIMEOUT_NEVER) != android::NO_ERROR)
+        {
+            nativeWindow->cancelBuffer(nativeWindow, buffer, fenceFd);
+            return NULL;
+        }
+
+        buffer->common.incRef(&buffer->common);
+
+        if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != android::NO_ERROR)
+        {
+            ALOGE("connect() failed to lock buffer %p", buffer);
+            return NULL;
+        }
+
+        locked = bits;
+        return locked;
+    }
+
+    void FrameBufferAndroid::unlock()
+    {
+        locked = 0;
+    }
+
+    int FrameBufferAndroid::lock(ANativeWindowBuffer* buf, int usage, void** vaddr)
+    {
+        return gralloc->lock(gralloc, buf->handle, usage, 0, 0, buf->width, buf->height, vaddr);
+    }
+
+    int FrameBufferAndroid::unlock(ANativeWindowBuffer* buf)
+    {
+        if (!buf) return -1;
+        return gralloc->unlock(gralloc, buf->handle);
+    }
+}
+
+extern "C"
+{
+    sw::FrameBuffer *createFrameBuffer(void *display, void* window, int width, int height)
+    {
+        return new sw::FrameBufferAndroid((ANativeWindow*)window, width, height);
+    }
+}
diff --git a/src/Main/FrameBufferAndroid.hpp b/src/Main/FrameBufferAndroid.hpp
new file mode 100644 (file)
index 0000000..e8a9c0c
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef sw_FrameBufferAndroid_hpp
+#define sw_FrameBufferAndroid_hpp
+
+#include "Main/FrameBuffer.hpp"
+#include "Common/Debug.hpp"
+
+#include <hardware/gralloc.h>
+#include <system/window.h>
+
+namespace sw
+{
+    class FrameBufferAndroid : public FrameBuffer
+    {
+    public:
+        FrameBufferAndroid(ANativeWindow* window, int width, int height);
+
+        ~FrameBufferAndroid();
+
+        virtual void flip(void *source, Format format) {blit(source, 0, 0, format);};
+        virtual void blit(void *source, const Rect *sourceRect, const Rect *destRect, Format format);
+
+        virtual void *lock();
+        virtual void unlock();
+
+        bool setSwapRectangle(int l, int t, int w, int h);
+
+    private:
+        int lock(ANativeWindowBuffer* buf, int usage, void** vaddr);
+        int unlock(ANativeWindowBuffer* buf);
+
+        ANativeWindow* nativeWindow;
+        ANativeWindowBuffer* buffer;
+        gralloc_module_t const* gralloc;
+        void* bits;
+    };
+}
+
+#endif   // sw_FrameBufferAndroid