Move framebuffer.h to android/

The QFrameBuffer is no used by QEMU-specific code anymore so it's
more logical to move it here.

Change-Id: Id49ff53dd49648000e7543652d66f7c03881a8cb
diff --git a/android/display-core.h b/android/display-core.h
index 6204e56..edeccac 100644
--- a/android/display-core.h
+++ b/android/display-core.h
@@ -18,7 +18,7 @@
 #ifndef _ANDROID_DISPLAY_CORE_H
 #define _ANDROID_DISPLAY_CORE_H
 
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 #include "android/display.h"
 #include "android/protocol/fb-updates-proxy.h"
 
diff --git a/android/display.h b/android/display.h
index 111979c..4b9e908 100644
--- a/android/display.h
+++ b/android/display.h
@@ -13,7 +13,7 @@
 #define _ANDROID_DISPLAY_H
 
 #include "console.h"
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 
 extern void android_display_init(DisplayState* ds, QFrameBuffer* qfbuff);
 
diff --git a/android/framebuffer.c b/android/framebuffer.c
new file mode 100644
index 0000000..53c6a48
--- /dev/null
+++ b/android/framebuffer.c
@@ -0,0 +1,294 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#include "android/framebuffer.h"
+#include <memory.h>
+#include <stdlib.h>
+
+typedef struct {
+    /* client fields, these correspond to code that waits for updates before displaying them */
+    /* at the moment, only one client is supported */
+    void*                        fb_opaque;
+    QFrameBufferUpdateFunc       fb_update;
+    QFrameBufferRotateFunc       fb_rotate;
+    QFrameBufferPollFunc         fb_poll;
+    QFrameBufferDoneFunc         fb_done;
+
+    void*                        pr_opaque;
+    QFrameBufferCheckUpdateFunc  pr_check;
+    QFrameBufferInvalidateFunc   pr_invalidate;
+    QFrameBufferDetachFunc       pr_detach;
+
+} QFrameBufferExtra;
+
+
+static int
+_get_pitch( int  width, QFrameBufferFormat  format )
+{
+
+    switch (format) {
+        case QFRAME_BUFFER_RGB565:
+            return width*2;
+        case QFRAME_BUFFER_RGBX_8888:
+            return width*4;
+        default:
+            return -1;
+    }
+}
+
+static int
+_get_bits_per_pixel(QFrameBufferFormat  format)
+{
+
+    switch (format) {
+        case QFRAME_BUFFER_RGB565:
+            return 16;
+        case QFRAME_BUFFER_RGBX_8888:
+            return 32;
+        default:
+            return -1;
+    }
+}
+
+static int
+_get_bytes_per_pixel(QFrameBufferFormat  format)
+{
+
+    switch (format) {
+        case QFRAME_BUFFER_RGB565:
+            return 2;
+        case QFRAME_BUFFER_RGBX_8888:
+            return 4;
+        default:
+            return -1;
+    }
+}
+
+int
+qframebuffer_init( QFrameBuffer*       qfbuff,
+                   int                 width,
+                   int                 height,
+                   int                 rotation,
+                   QFrameBufferFormat  format )
+{
+    int   pitch, bytes_per_pixel, bits_per_pixel;
+
+    rotation &= 3;
+
+    if (!qfbuff || width < 0 || height < 0)
+        return -1;
+
+    pitch = _get_pitch( width, format );
+    if (pitch < 0)
+        return -1;
+
+    bits_per_pixel = _get_bits_per_pixel(format);
+    if (bits_per_pixel < 0)
+        return -1;
+
+    bytes_per_pixel = _get_bytes_per_pixel(format);
+    if (bytes_per_pixel < 0)
+        return -1;
+
+    memset( qfbuff, 0, sizeof(*qfbuff) );
+
+    qfbuff->extra = calloc( 1, sizeof(QFrameBufferExtra) );
+    if (qfbuff->extra == NULL)
+        return -1;
+
+    qfbuff->pixels = calloc( pitch, height );
+    if (qfbuff->pixels == NULL && (height > 0 && pitch > 0)) {
+        free( qfbuff->extra );
+        return -1;
+    }
+
+    qfbuff->width  = width;
+    qfbuff->height = height;
+    qfbuff->pitch  = pitch;
+    qfbuff->format = format;
+    qfbuff->bits_per_pixel = bits_per_pixel;
+    qfbuff->bytes_per_pixel = bytes_per_pixel;
+
+    qframebuffer_set_dpi( qfbuff, DEFAULT_FRAMEBUFFER_DPI, DEFAULT_FRAMEBUFFER_DPI );
+    return 0;
+}
+
+
+void
+qframebuffer_set_dpi( QFrameBuffer*   qfbuff,
+                      int             x_dpi,
+                      int             y_dpi )
+{
+    /* dpi = dots / inch
+    ** inch = dots / dpi
+    ** mm / 25.4 = dots / dpi
+    ** mm = (dots * 25.4)/dpi
+    */
+    qfbuff->phys_width_mm  = (int)(0.5 + 25.4 * qfbuff->width  / x_dpi);
+    qfbuff->phys_height_mm = (int)(0.5 + 25.4 * qfbuff->height / y_dpi);
+}
+
+/* alternative to qframebuffer_set_dpi where one can set the physical dimensions directly */
+/* in millimeters. for the record 1 inch = 25.4 mm */
+void
+qframebuffer_set_mm( QFrameBuffer*   qfbuff,
+                     int             width_mm,
+                     int             height_mm )
+{
+    qfbuff->phys_width_mm  = width_mm;
+    qfbuff->phys_height_mm = height_mm;
+}
+
+void
+qframebuffer_update( QFrameBuffer*  qfbuff, int  x, int  y, int  w, int  h )
+{
+    QFrameBufferExtra*  extra = qfbuff->extra;
+
+    if (extra->fb_update)
+        extra->fb_update( extra->fb_opaque, x, y, w, h );
+}
+
+
+void
+qframebuffer_add_client( QFrameBuffer*           qfbuff,
+                         void*                   fb_opaque,
+                         QFrameBufferUpdateFunc  fb_update,
+                         QFrameBufferRotateFunc  fb_rotate,
+                         QFrameBufferPollFunc    fb_poll,
+                         QFrameBufferDoneFunc    fb_done )
+{
+    QFrameBufferExtra*  extra = qfbuff->extra;
+
+    extra->fb_opaque = fb_opaque;
+    extra->fb_update = fb_update;
+    extra->fb_rotate = fb_rotate;
+    extra->fb_poll   = fb_poll;
+    extra->fb_done   = fb_done;
+}
+
+void
+qframebuffer_set_producer( QFrameBuffer*                qfbuff,
+                           void*                        opaque,
+                           QFrameBufferCheckUpdateFunc  pr_check,
+                           QFrameBufferInvalidateFunc   pr_invalidate,
+                           QFrameBufferDetachFunc       pr_detach )
+{
+    QFrameBufferExtra*  extra = qfbuff->extra;
+
+    extra->pr_opaque     = opaque;
+    extra->pr_check      = pr_check;
+    extra->pr_invalidate = pr_invalidate;
+    extra->pr_detach     = pr_detach;
+}
+
+
+void
+qframebuffer_rotate( QFrameBuffer*  qfbuff, int  rotation )
+{
+    QFrameBufferExtra*  extra = qfbuff->extra;
+
+    if ((rotation ^ qfbuff->rotation) & 1) {
+        /* swap width and height if new rotation requires it */
+        int  temp = qfbuff->width;
+        qfbuff->width  = qfbuff->height;
+        qfbuff->height = temp;
+        qfbuff->pitch  = _get_pitch( qfbuff->width, qfbuff->format );
+
+        temp = qfbuff->phys_width_mm;
+        qfbuff->phys_width_mm  = qfbuff->phys_height_mm;
+        qfbuff->phys_height_mm = temp;
+    }
+    qfbuff->rotation = rotation;
+
+    if (extra->fb_rotate)
+        extra->fb_rotate( extra->fb_opaque, rotation );
+}
+
+void
+qframebuffer_poll( QFrameBuffer* qfbuff )
+{
+    QFrameBufferExtra*  extra = qfbuff->extra;
+
+    if (extra && extra->fb_poll)
+        extra->fb_poll( extra->fb_opaque );
+}
+
+
+extern void
+qframebuffer_done( QFrameBuffer*   qfbuff )
+{
+    QFrameBufferExtra*  extra = qfbuff->extra;
+
+    if (extra) {
+        if (extra->pr_detach)
+            extra->pr_detach( extra->pr_opaque );
+
+        if (extra->fb_done)
+            extra->fb_done( extra->fb_opaque );
+    }
+
+    free( qfbuff->pixels );
+    free( qfbuff->extra );
+    memset( qfbuff, 0, sizeof(*qfbuff) );
+}
+
+
+#define  MAX_FRAME_BUFFERS  8
+
+static QFrameBuffer* framebuffer_fifo[ MAX_FRAME_BUFFERS ];
+static int           framebuffer_fifo_rpos;
+static int           framebuffer_fifo_count;
+
+void
+qframebuffer_fifo_add( QFrameBuffer*  qfbuff )
+{
+    if (framebuffer_fifo_count >= MAX_FRAME_BUFFERS)
+        return;
+
+    framebuffer_fifo[ framebuffer_fifo_count++ ] = qfbuff;
+}
+
+
+QFrameBuffer*
+qframebuffer_fifo_get( void )
+{
+    if (framebuffer_fifo_rpos >= framebuffer_fifo_count)
+        return NULL;
+
+    return framebuffer_fifo[ framebuffer_fifo_rpos++ ];
+}
+
+
+void
+qframebuffer_check_updates( void )
+{
+    int  nn;
+    for (nn = 0; nn < framebuffer_fifo_count; nn++) {
+        QFrameBuffer*       q     = framebuffer_fifo[nn];
+        QFrameBufferExtra*  extra = q->extra;
+
+        if (extra->pr_check)
+            extra->pr_check( extra->pr_opaque );
+    }
+}
+
+void
+qframebuffer_invalidate_all( void )
+{
+    int  nn;
+    for (nn = 0; nn < framebuffer_fifo_count; nn++) {
+        QFrameBuffer*       q     = framebuffer_fifo[nn];
+        QFrameBufferExtra*  extra = q->extra;
+
+        if (extra->pr_invalidate)
+            extra->pr_invalidate( extra->pr_opaque );
+    }
+}
diff --git a/android/framebuffer.h b/android/framebuffer.h
new file mode 100644
index 0000000..9d1f626
--- /dev/null
+++ b/android/framebuffer.h
@@ -0,0 +1,218 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#ifndef _ANDROID_FRAMEBUFFER_H_
+#define _ANDROID_FRAMEBUFFER_H_
+
+/* A simple abstract interface to framebuffer displays. this is used to
+ * de-couple hardware emulation from final display.
+ *
+ * Each QFrameBuffer object holds a pixel buffer that is shared between
+ * one 'Producer' and one or more 'Clients'
+ *
+ * The Producer is in charge of updating the pixel buffer from the state
+ * of the emulated VRAM. A Client listens to updates to the pixel buffer,
+ * sent from the producer through qframebuffer_update()/_rotate() and
+ * displays them.
+ *
+ * note the 'rotation' field: it can take values 0, 1, 2 or 3 and corresponds
+ * to a rotation that must be performed to the pixels stored in the framebuffer
+ * *before* displaying them a value of 1 corresponds to a rotation of
+ * 90 clockwise-degrees, when the framebuffer is rotated 90 or 270 degrees,
+ * its width/height are swapped automatically
+ *
+ * phys_width_mm and phys_height_mm are physical dimensions expressed
+ * in millimeters
+ *
+ * More about the client/producer relationships below.
+ */
+typedef struct QFrameBuffer   QFrameBuffer;
+
+
+typedef enum {
+    QFRAME_BUFFER_NONE   = 0,
+    QFRAME_BUFFER_RGB565 = 1,
+    QFRAME_BUFFER_RGBX_8888 = 2,
+    QFRAME_BUFFER_MAX          /* do not remove */
+} QFrameBufferFormat;
+
+struct QFrameBuffer {
+    int                 width;        /* width in pixels */
+    int                 height;       /* height in pixels */
+    int                 pitch;        /* bytes per line */
+    int                 bits_per_pixel; /* bits per pixel */
+    int                 bytes_per_pixel;    /* bytes per pixel */
+    int                 rotation;     /* rotation to be applied when displaying */
+    QFrameBufferFormat  format;
+    void*               pixels;       /* pixel buffer */
+
+    int                 phys_width_mm;
+    int                 phys_height_mm;
+
+    /* extra data that is handled by the framebuffer implementation */
+    void*               extra;
+
+};
+
+/* the default dpi resolution of a typical framebuffer. this is an average
+ * between various prototypes being used during the development of the
+ * Android system...
+ */
+#define  DEFAULT_FRAMEBUFFER_DPI   165
+
+
+/* initialize a framebuffer object and allocate its pixel buffer */
+/* this computes phys_width_mm and phys_height_mm assuming a 165 dpi screen */
+/* returns -1 in case of error, 0 otherwise */
+extern int
+qframebuffer_init( QFrameBuffer*       qfbuff,
+                   int                 width,
+                   int                 height,
+                   int                 rotation,
+                   QFrameBufferFormat  format );
+
+/* recompute phys_width_mm and phys_height_mm according to the emulated
+ * screen DPI settings */
+extern void
+qframebuffer_set_dpi( QFrameBuffer*   qfbuff,
+                      int             x_dpi,
+                      int             y_dpi );
+
+/* alternative to qframebuffer_set_dpi where one can set the physical
+ * dimensions directly in millimeters. for the record 1 inch = 25.4 mm */
+extern void
+qframebuffer_set_mm( QFrameBuffer*   qfbuff,
+                     int             width_mm,
+                     int             height_mm );
+
+/* the Client::Update method is called to instruct a client that a given
+ * rectangle of the framebuffer pixels was updated and needs to be
+ * redrawn.
+ */
+typedef void (*QFrameBufferUpdateFunc)( void*  opaque, int  x, int  y,
+                                                       int  w, int  h );
+
+/* the Client::Rotate method is called to instruct the client that a
+ * framebuffer's internal rotation has changed. This is the rotation
+ * that must be applied before displaying the pixels.
+ *
+ * Note that it is assumed that all framebuffer pixels have changed too
+ * so the client should call its Update method as well.
+ */
+typedef void (*QFrameBufferRotateFunc)( void*  opaque, int  rotation );
+
+/* the Client::Poll method is called periodically to poll for input
+ * events and act on them. Putting this here is not 100% pure but
+ * make things simpler due to QEMU's weird architecture where the
+ * GUI timer drivers event polling.
+ */
+typedef void (*QFrameBufferPollFunc)( void* opaque );
+
+/* the Client::Done func tells a client that a framebuffer object was freed.
+ * no more reference to its pixels should be done.
+ */
+typedef void (*QFrameBufferDoneFunc)  ( void*  opaque );
+
+/* add one client to a given framebuffer.
+ * the current implementation only allows one client per frame-buffer,
+ * but we could allow more for various reasons (e.g. displaying the
+ * framebuffer + dispatching it through VNC at the same time)
+ */
+extern void
+qframebuffer_add_client( QFrameBuffer*           qfbuff,
+                         void*                   fb_opaque,
+                         QFrameBufferUpdateFunc  fb_update,
+                         QFrameBufferRotateFunc  fb_rotate,
+                         QFrameBufferPollFunc    fb_poll,
+                         QFrameBufferDoneFunc    fb_done );
+
+/* Producer::CheckUpdate is called to let the producer check the
+ * VRAM state (e.g. VRAM dirty pages) to see if anything changed since the
+ * last call to the method. When true, the method should call either
+ * qframebuffer_update() or qframebuffer_rotate() with the appropriate values.
+ */
+typedef void (*QFrameBufferCheckUpdateFunc)( void*  opaque );
+
+/* Producer::Invalidate tells the producer that the next call to
+ * CheckUpdate should act as if the whole content of VRAM had changed.
+ * this is normally done to force client initialization/refreshes.
+ */
+typedef void (*QFrameBufferInvalidateFunc) ( void*  opaque );
+
+/* the Producer::Detach method is used to tell the producer that the
+ * underlying QFrameBuffer object is about to be de-allocated.
+ */
+typedef void (*QFrameBufferDetachFunc)     ( void*  opaque );
+
+/* set the producer of a given framebuffer */
+extern void
+qframebuffer_set_producer( QFrameBuffer*                qfbuff,
+                           void*                        opaque,
+                           QFrameBufferCheckUpdateFunc  fb_check,
+                           QFrameBufferInvalidateFunc   fb_invalidate,
+                           QFrameBufferDetachFunc       fb_detach );
+
+/* tell a client that a rectangle region has been updated in the framebuffer
+ * pixel buffer this is typically called from a Producer::CheckUpdate method
+ */
+extern void
+qframebuffer_update( QFrameBuffer*  qfbuff, int  x, int  y, int  w, int  h );
+
+/* rotate the framebuffer (may swap width/height), and tell all clients.
+ * Should be called from a Producer::CheckUpdate method
+ */
+extern void
+qframebuffer_rotate( QFrameBuffer*  qfbuff, int  rotation );
+
+extern void
+qframebuffer_poll( QFrameBuffer* qfbuff );
+
+/* finalize a framebuffer, release its pixel buffer. Should be called
+ * from the framebuffer object's owner
+ */
+extern void
+qframebuffer_done( QFrameBuffer*   qfbuff );
+
+
+/* this is called repeatedly by the emulator. for each registered framebuffer,
+ * call its producer's CheckUpdate method, if any.
+ */
+extern void
+qframebuffer_check_updates( void );
+
+/* this is called by the emulator. for each registered framebuffer, call
+ * its producer's Invalidate method, if any
+ */
+extern void
+qframebuffer_invalidate_all( void );
+
+/*
+ * to completely separate the implementation of clients, producers, and skins,
+ * we use a simple global FIFO list of QFrameBuffer objects.
+ *
+ * qframebuffer_fifo_add() is typically called by the emulator initialization
+ * depending on the emulated device's configuration
+ *
+ * qframebuffer_fifo_get() is typically called by a hardware framebuffer
+ * emulation.
+ */
+
+/* add a new constructed frame buffer object to our global list */
+extern void
+qframebuffer_fifo_add( QFrameBuffer*  qfbuff );
+
+/* retrieve a frame buffer object from the global FIFO list */
+extern QFrameBuffer*
+qframebuffer_fifo_get( void );
+
+/* */
+
+#endif /* _ANDROID_FRAMEBUFFER_H_ */
diff --git a/android/main-ui.c b/android/main-ui.c
index 051f3e8..9981b76 100644
--- a/android/main-ui.c
+++ b/android/main-ui.c
@@ -59,7 +59,7 @@
 #include "android/protocol/ui-commands-impl.h"
 #include "android/protocol/attach-ui-impl.h"
 
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 #include "iolooper.h"
 
 AndroidRotation  android_framebuffer_rotation;
diff --git a/android/main.c b/android/main.c
index 64fe617..e38c0e3 100644
--- a/android/main.c
+++ b/android/main.c
@@ -53,7 +53,7 @@
 
 #include "android/snapshot.h"
 
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 #include "iolooper.h"
 
 AndroidRotation  android_framebuffer_rotation;
diff --git a/android/protocol/fb-updates-impl.h b/android/protocol/fb-updates-impl.h
index 2572b5e..c4dd2e0 100644
--- a/android/protocol/fb-updates-impl.h
+++ b/android/protocol/fb-updates-impl.h
@@ -19,7 +19,7 @@
 #define _ANDROID_FRAMEBUFFER_UI_H
 
 #include "console.h"
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 #include "android/looper.h"
 #include "android/async-utils.h"
 
diff --git a/android/protocol/fb-updates-proxy.c b/android/protocol/fb-updates-proxy.c
index fee1195..359c942 100644
--- a/android/protocol/fb-updates-proxy.c
+++ b/android/protocol/fb-updates-proxy.c
@@ -16,7 +16,7 @@
  */
 
 #include "console.h"
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 #include "android/looper.h"
 #include "android/display-core.h"
 #include "android/async-utils.h"
diff --git a/android/skin/file.h b/android/skin/file.h
index 6f88063..4e3a8fc 100644
--- a/android/skin/file.h
+++ b/android/skin/file.h
@@ -14,7 +14,7 @@
 
 #include "android/skin/image.h"
 #include "android/config.h"
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 
 /**  Layout
  **/
diff --git a/android/skin/window.c b/android/skin/window.c
index c2d0bf4..2755763 100644
--- a/android/skin/window.c
+++ b/android/skin/window.c
@@ -21,7 +21,7 @@
 #include "user-events.h"
 #include <math.h>
 
-#include "framebuffer.h"
+#include "android/framebuffer.h"
 
 /* when shrinking, we reduce the pixel ratio by this fixed amount */
 #define  SHRINK_SCALE  0.6