aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-02-02 14:43:23 +0100
committerDavid 'Digit' Turner <digit@android.com>2011-02-02 14:43:23 +0100
commite3fdd075ed97085b4201cb0c79609633b19bddcc (patch)
treed695bda577170403a9c2556d64ea99860523b349 /android
parente993126c6704029cb1c656922a66a32bd09b6089 (diff)
downloadexternal_qemu-e3fdd075ed97085b4201cb0c79609633b19bddcc.zip
external_qemu-e3fdd075ed97085b4201cb0c79609633b19bddcc.tar.gz
external_qemu-e3fdd075ed97085b4201cb0c79609633b19bddcc.tar.bz2
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
Diffstat (limited to 'android')
-rw-r--r--android/display-core.h2
-rw-r--r--android/display.h2
-rw-r--r--android/framebuffer.c294
-rw-r--r--android/framebuffer.h218
-rw-r--r--android/main-ui.c2
-rw-r--r--android/main.c2
-rw-r--r--android/protocol/fb-updates-impl.h2
-rw-r--r--android/protocol/fb-updates-proxy.c2
-rw-r--r--android/skin/file.h2
-rw-r--r--android/skin/window.c2
10 files changed, 520 insertions, 8 deletions
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