display: Use single thread for FB post.
To support swapinterval zero a separate thread
was added to do the framebuffer post. Since we
are going to support the WAITFORVSYNC ioctl in HWC,
we can handle the zero swapinterval case there.
Change-Id: I39f960825ca4173f99a9895e0c132b70a7adccab
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index b9eb9e4..e3ca6f9 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -26,8 +26,7 @@
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" \
- -DDEBUG_CALC_FPS \
- -Wno-missing-field-initializers
+ -DDEBUG_CALC_FPS -Wno-missing-field-initializers
LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
ifeq ($(TARGET_USES_POST_PROCESSING),true)
diff --git a/libgralloc/fb_priv.h b/libgralloc/fb_priv.h
index 46b119f..628a961 100644
--- a/libgralloc/fb_priv.h
+++ b/libgralloc/fb_priv.h
@@ -25,84 +25,6 @@
#define NO_SURFACEFLINGER_SWAPINTERVAL
#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
-#ifdef __cplusplus
-template <class T>
-struct Node
-{
- T data;
- Node<T> *next;
-};
-
-template <class T>
-class Queue
-{
- public:
- Queue(): front(NULL), back(NULL), len(0) {dummy = new T;}
- ~Queue()
- {
- clear();
- delete dummy;
- }
- void push(const T& item) //add an item to the back of the queue
- {
- if(len != 0) { //if the queue is not empty
- back->next = new Node<T>; //create a new node
- back = back->next; //set the new node as the back node
- back->data = item;
- back->next = NULL;
- } else {
- back = new Node<T>;
- back->data = item;
- back->next = NULL;
- front = back;
- }
- len++;
- }
- void pop() //remove the first item from the queue
- {
- if (isEmpty())
- return; //if the queue is empty, no node to dequeue
- T item = front->data;
- Node<T> *tmp = front;
- front = front->next;
- delete tmp;
- if(front == NULL) //if the queue is empty, update the back pointer
- back = NULL;
- len--;
- return;
- }
- T& getHeadValue() const //return the value of the first item in the queue
- { //without modification to the structure
- if (isEmpty()) {
- ALOGE("Error can't get head of empty queue");
- return *dummy;
- }
- return front->data;
- }
-
- bool isEmpty() const //returns true if no elements are in the queue
- {
- return (front == NULL);
- }
-
- size_t size() const //returns the amount of elements in the queue
- {
- return len;
- }
-
- private:
- Node<T> *front;
- Node<T> *back;
- size_t len;
- void clear()
- {
- while (!isEmpty())
- pop();
- }
- T *dummy;
-};
-#endif
-
enum hdmi_mirroring_state {
HDMI_NO_MIRRORING,
HDMI_UI_MIRRORING,
@@ -110,17 +32,6 @@
struct private_handle_t;
-struct qbuf_t {
- buffer_handle_t buf;
- int idx;
-};
-
-enum buf_state {
- SUB,
- REF,
- AVL
-};
-
enum {
// flag to indicate we'll post this buffer
PRIV_USAGE_LOCKED_FOR_POST = 0x80000000,
@@ -128,17 +39,8 @@
PRIV_MAX_SWAP_INTERVAL = 1,
};
-
-struct avail_t {
- pthread_mutex_t lock;
- pthread_cond_t cond;
- bool is_avail;
- buf_state state;
-};
-
struct private_module_t {
gralloc_module_t base;
-
struct private_handle_t* framebuffer;
uint32_t fbFormat;
uint32_t flags;
@@ -146,18 +48,12 @@
uint32_t bufferMask;
pthread_mutex_t lock;
buffer_handle_t currentBuffer;
-
struct fb_var_screeninfo info;
struct fb_fix_screeninfo finfo;
float xdpi;
float ydpi;
float fps;
uint32_t swapInterval;
- Queue<struct qbuf_t> disp; // non-empty when buffer is ready for display
- int currentIdx;
- struct avail_t avail[NUM_FRAMEBUFFERS_MAX];
- pthread_mutex_t qlock;
- pthread_cond_t qpost;
#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
int orientation;
int videoOverlay; // VIDEO_OVERLAY - 2D or 3D
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index bd9ca9c..c3a6b93 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -55,8 +55,6 @@
return (a>b) ? a : b;
}
-char framebufferStateName[] = {'S', 'R', 'A'};
-
enum {
PAGE_FLIP = 0x00000001,
LOCKED = 0x00000002
@@ -70,6 +68,8 @@
static int fb_setSwapInterval(struct framebuffer_device_t* dev,
int interval)
{
+ //XXX: Get the value here and implement along with
+ //single vsync in HWC
char pval[PROPERTY_VALUE_MAX];
property_get("debug.egl.swapinterval", pval, "-1");
int property_interval = atoi(pval);
@@ -100,81 +100,6 @@
return 0;
}
-static void *disp_loop(void *ptr)
-{
- struct qbuf_t nxtBuf;
- static int cur_buf=-1;
- private_module_t *m = reinterpret_cast<private_module_t*>(ptr);
-
- while (1) {
- pthread_mutex_lock(&(m->qlock));
-
- // wait (sleep) while display queue is empty;
- if (m->disp.isEmpty()) {
- pthread_cond_wait(&(m->qpost),&(m->qlock));
- }
-
- // dequeue next buff to display and lock it
- nxtBuf = m->disp.getHeadValue();
- m->disp.pop();
- pthread_mutex_unlock(&(m->qlock));
-
- // post buf out to display synchronously
- private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>
- (nxtBuf.buf);
- const size_t offset = hnd->base - m->framebuffer->base;
- m->info.activate = FB_ACTIVATE_VBL;
- m->info.yoffset = offset / m->finfo.line_length;
-
-#if defined(HDMI_DUAL_DISPLAY)
- pthread_mutex_lock(&m->overlayLock);
- m->orientation = neworientation;
- m->currentOffset = offset;
- m->hdmiStateChanged = true;
- pthread_cond_signal(&(m->overlayPost));
- pthread_mutex_unlock(&m->overlayLock);
-#endif
- if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
- ALOGE("ERROR FBIOPUT_VSCREENINFO failed; frame not displayed");
- }
-
- CALC_FPS();
-
- if (cur_buf == -1) {
- int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers);
- pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
- m->avail[nxtBuf.idx].is_avail = true;
- m->avail[nxtBuf.idx].state = SUB;
- pthread_cond_signal(&(m->avail[nxtBuf.idx].cond));
- pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
- } else {
-#if 0 //XXX: Triple FB
- pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
- if (m->avail[nxtBuf.idx].state != SUB) {
- ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", nxtBuf.idx,
- framebufferStateName[m->avail[nxtBuf.idx].state],
- framebufferStateName[SUB]);
- }
-
- m->avail[nxtBuf.idx].state = REF;
- pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
- if (m->avail[cur_buf].state != REF) {
- ALOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", cur_buf,
- framebufferStateName[m->avail[cur_buf].state],
- framebufferStateName[SUB]);
- }
- m->avail[cur_buf].state = AVL;
-#endif
- pthread_mutex_lock(&(m->avail[cur_buf].lock));
- m->avail[cur_buf].is_avail = true;
- pthread_cond_signal(&(m->avail[cur_buf].cond));
- pthread_mutex_unlock(&(m->avail[cur_buf].lock));
- }
- cur_buf = nxtBuf.idx;
- }
- return NULL;
-}
-
#if defined(HDMI_DUAL_DISPLAY)
static int closeHDMIChannel(private_module_t* m)
{
@@ -577,9 +502,6 @@
if (private_handle_t::validate(buffer) < 0)
return -EINVAL;
- int nxtIdx;//, futureIdx = -1;
- bool reuse;
- struct qbuf_t qb;
fb_context_t* ctx = (fb_context_t*)dev;
private_handle_t const* hnd =
@@ -588,67 +510,25 @@
reinterpret_cast<private_module_t*>(dev->common.module);
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+ m->base.lock(&m->base, buffer,
+ PRIV_USAGE_LOCKED_FOR_POST,
+ 0, 0, m->info.xres, m->info.yres, NULL);
- reuse = false;
- nxtIdx = (m->currentIdx + 1) % m->numBuffers;
- //futureIdx = (nxtIdx + 1) % m->numBuffers;
- if (m->swapInterval == 0) {
- // if SwapInterval = 0 and no buffers available then reuse
- // current buf for next rendering so don't post new buffer
- if (pthread_mutex_trylock(&(m->avail[nxtIdx].lock))) {
- reuse = true;
- } else {
- if (! m->avail[nxtIdx].is_avail)
- reuse = true;
- pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
- }
+ if (m->currentBuffer) {
+ m->base.unlock(&m->base, m->currentBuffer);
+ m->currentBuffer = 0;
}
- if(!reuse){
- // unlock previous ("current") Buffer and lock the new buffer
- m->base.lock(&m->base, buffer,
- PRIV_USAGE_LOCKED_FOR_POST,
- 0,0, m->info.xres, m->info.yres, NULL);
-
- // post/queue the new buffer
- pthread_mutex_lock(&(m->avail[nxtIdx].lock));
- m->avail[nxtIdx].is_avail = false;
-#if 0 //XXX: Triple FB
- if (m->avail[nxtIdx].is_avail != true) {
- ALOGE_IF(m->swapInterval != 0, "Found %d buf to be not avail", nxtIdx);
- }
-
- if (m->avail[nxtIdx].state != AVL) {
- ALOGD("[%d] state %c, expected %c", nxtIdx,
- framebufferStateName[m->avail[nxtIdx].state],
- framebufferStateName[AVL]);
- }
-
- m->avail[nxtIdx].state = SUB;
-#endif
- pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
-
- qb.idx = nxtIdx;
- qb.buf = buffer;
- pthread_mutex_lock(&(m->qlock));
- m->disp.push(qb);
- pthread_cond_signal(&(m->qpost));
- pthread_mutex_unlock(&(m->qlock));
-
- if (m->currentBuffer)
- m->base.unlock(&m->base, m->currentBuffer);
-
- m->currentBuffer = buffer;
- m->currentIdx = nxtIdx;
- } else {
- if (m->currentBuffer)
- m->base.unlock(&m->base, m->currentBuffer);
- m->base.lock(&m->base, buffer,
- PRIV_USAGE_LOCKED_FOR_POST,
- 0,0, m->info.xres, m->info.yres, NULL);
- m->currentBuffer = buffer;
+ const size_t offset = hnd->base - m->framebuffer->base;
+ m->info.activate = FB_ACTIVATE_VBL;
+ m->info.yoffset = offset / m->finfo.line_length;
+ if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
+ ALOGE("FBIOPUT_VSCREENINFO failed");
+ m->base.unlock(&m->base, buffer);
+ return -errno;
}
-
+ CALC_FPS();
+ m->currentBuffer = buffer;
}
return 0;
}
@@ -661,25 +541,6 @@
return 0;
}
-static int fb_lockBuffer(struct framebuffer_device_t* dev, int index)
-{
- private_module_t* m = reinterpret_cast<private_module_t*>(
- dev->common.module);
-
- // Return immediately if the buffer is available
- if ((m->avail[index].state == AVL) || (m->swapInterval == 0))
- return 0;
-
- pthread_mutex_lock(&(m->avail[index].lock));
- while (m->avail[index].state != AVL) {
- pthread_cond_wait(&(m->avail[index].cond),
- &(m->avail[index].lock));
- }
- pthread_mutex_unlock(&(m->avail[index].lock));
-
- return 0;
-}
-
int mapFrameBufferLocked(struct private_module_t* module)
{
// already initialized...
@@ -863,42 +724,10 @@
module->xdpi = xdpi;
module->ydpi = ydpi;
module->fps = fps;
-
-#ifdef NO_SURFACEFLINGER_SWAPINTERVAL
- char pval[PROPERTY_VALUE_MAX];
- property_get("debug.gr.swapinterval", pval, "1");
- module->swapInterval = atoi(pval);
- if (module->swapInterval < PRIV_MIN_SWAP_INTERVAL ||
- module->swapInterval > PRIV_MAX_SWAP_INTERVAL) {
- module->swapInterval = 1;
- ALOGW("Out of range (%d to %d) value for debug.gr.swapinterval, using 1",
- PRIV_MIN_SWAP_INTERVAL,
- PRIV_MAX_SWAP_INTERVAL);
- }
-
-#else
- /* when surfaceflinger supports swapInterval then can just do this */
module->swapInterval = 1;
-#endif
CALC_INIT();
- module->currentIdx = -1;
- pthread_cond_init(&(module->qpost), NULL);
- pthread_mutex_init(&(module->qlock), NULL);
- for (i = 0; i < NUM_FRAMEBUFFERS_MAX; i++) {
- pthread_mutex_init(&(module->avail[i].lock), NULL);
- pthread_cond_init(&(module->avail[i].cond), NULL);
- module->avail[i].is_avail = true;
- module->avail[i].state = AVL;
- }
-
- /* create display update thread */
- pthread_t disp_thread;
- if (pthread_create(&disp_thread, NULL, &disp_loop, (void *) module)) {
- return -errno;
- }
-
/*
* map the framebuffer
*/