aboutsummaryrefslogtreecommitdiffstats
path: root/android/framebuffer.c
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/framebuffer.c
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/framebuffer.c')
-rw-r--r--android/framebuffer.c294
1 files changed, 294 insertions, 0 deletions
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 );
+ }
+}