aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-01-16 01:42:37 +0100
committerDavid 'Digit' Turner <digit@android.com>2011-01-18 20:53:34 +0100
commit97d795c955f8d261a0a5294d49ea06d5a473ed03 (patch)
treec38306a988e9cbe8514827efd62e92cd7021c8fa
parent9cf288a4a03f6745a81b35e8022aab3d1d5f2247 (diff)
downloadexternal_qemu-97d795c955f8d261a0a5294d49ea06d5a473ed03.zip
external_qemu-97d795c955f8d261a0a5294d49ea06d5a473ed03.tar.gz
external_qemu-97d795c955f8d261a0a5294d49ea06d5a473ed03.tar.bz2
Add support for 32-bit framebuffers.
This modifies the emulator so support 32-bit framebuffers. You can create such a frame-buffer using one of these methods: - Add a "bpp 32" line to the "display" element of your skin - Use the new 'magic' skin option format: e.g. -skin 320x480x32 Note that the result will be hideous since the kernel driver still thinks the hardware is only 16-bits. This will be addressed in a later patch to hw/goldfish_fb.c and to the kernel driver ($KERNEL/drivers/video/goldfishfb.c) Change-Id: I0fc700c4a4cb8521076605324e15ed34e5d01136
-rw-r--r--android/display-core.c12
-rw-r--r--android/display.c2
-rw-r--r--android/main-ui.c9
-rw-r--r--android/main.c13
-rw-r--r--android/skin/file.c4
-rw-r--r--android/skin/file.h1
-rw-r--r--android/skin/window.c283
-rw-r--r--framebuffer.c14
-rw-r--r--framebuffer.h1
9 files changed, 238 insertions, 101 deletions
diff --git a/android/display-core.c b/android/display-core.c
index 1efb4a2..0b2a869 100644
--- a/android/display-core.c
+++ b/android/display-core.c
@@ -79,14 +79,24 @@ coredisplay_fb_done(void* opaque)
void
coredisplay_init(DisplayState* ds)
{
+ int format;
+
core_display.ds = ds;
/* Create and initialize framebuffer instance that will be used for core
* display.
*/
ANEW0(core_display.fb);
core_display.core_fb = NULL;
+
+ /* In the core, there is no skin to parse and the format of ds->surface
+ * is determined by the -android-gui option.
+ */
+ format = QFRAME_BUFFER_RGB565;
+ if (ds->surface->pf.bytes_per_pixel == 4)
+ format = QFRAME_BUFFER_RGBX_8888;
+
qframebuffer_init(core_display.fb, ds->surface->width, ds->surface->height,
- 0, QFRAME_BUFFER_RGB565 );
+ 0, format);
qframebuffer_fifo_add(core_display.fb);
/* Register core display as the client for the framebuffer, so we can start
* receiving framebuffer notifications. Note that until UI connects to the
diff --git a/android/display.c b/android/display.c
index d7c261a..8bad585 100644
--- a/android/display.c
+++ b/android/display.c
@@ -88,7 +88,7 @@ void android_display_init(DisplayState* ds, QFrameBuffer* qf)
ds->opaque = qf;
ds->surface = qemu_create_displaysurface_from(qf->width,
qf->height,
- 16,
+ qf->bits_per_pixel,
qf->pitch,
qf->pixels);
diff --git a/android/main-ui.c b/android/main-ui.c
index 927debb..a48c0fc 100644
--- a/android/main-ui.c
+++ b/android/main-ui.c
@@ -375,8 +375,13 @@ void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts)
if(x && isdigit(x[1])) {
int width = atoi(name);
int height = atoi(x + 1);
- sprintf(tmp,"display {\n width %d\n height %d\n}\n",
- width, height);
+ int bpp = 16;
+ char* y = strchr(x+1, 'x');
+ if (y && isdigit(y[1])) {
+ bpp = atoi(y+1);
+ }
+ sprintf(tmp,"display {\n width %d\n height %d\n bpp %d}\n",
+ width, height,bpp);
aconfig_load(root, strdup(tmp));
path = ":";
goto found_a_skin;
diff --git a/android/main.c b/android/main.c
index 840c764..00d54d1 100644
--- a/android/main.c
+++ b/android/main.c
@@ -359,14 +359,19 @@ void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts)
}
}
- /* Magically support skins like "320x240" */
+ /* Magically support skins like "320x240" or "320x240x16" */
if(isdigit(name[0])) {
char *x = strchr(name, 'x');
if(x && isdigit(x[1])) {
int width = atoi(name);
- int height = atoi(x + 1);
- sprintf(tmp,"display {\n width %d\n height %d\n}\n",
- width, height);
+ int height = atoi(x+1);
+ int bpp = 16;
+ char* y = strchr(x+1, 'x');
+ if (y && isdigit(y[1])) {
+ bpp = atoi(y+1);
+ }
+ sprintf(tmp,"display {\n width %d\n height %d\n bpp %d}\n",
+ width, height,bpp);
aconfig_load(root, strdup(tmp));
path = ":";
goto found_a_skin;
diff --git a/android/skin/file.c b/android/skin/file.c
index f7f0be9..5947ad9 100644
--- a/android/skin/file.c
+++ b/android/skin/file.c
@@ -91,6 +91,7 @@ skin_display_init_from( SkinDisplay* display, AConfig* node )
display->rect.size.w = aconfig_int(node, "width", 0);
display->rect.size.h = aconfig_int(node, "height", 0);
display->rotation = aconfig_unsigned(node, "rotation", SKIN_ROTATION_0);
+ display->bpp = aconfig_int(node, "bpp", 16);
display->valid = ( display->rect.size.w > 0 && display->rect.size.h > 0 );
@@ -101,7 +102,8 @@ skin_display_init_from( SkinDisplay* display, AConfig* node )
r.size.w,
r.size.h,
0,
- QFRAME_BUFFER_RGB565 );
+ display->bpp == 32 ? QFRAME_BUFFER_RGBX_8888
+ : QFRAME_BUFFER_RGB565 );
qframebuffer_fifo_add( display->qfbuff );
}
diff --git a/android/skin/file.h b/android/skin/file.h
index 9f188b9..6f88063 100644
--- a/android/skin/file.h
+++ b/android/skin/file.h
@@ -28,6 +28,7 @@ typedef struct SkinBackground {
typedef struct SkinDisplay {
SkinRect rect; /* display rectangle */
SkinRotation rotation; /* framebuffer rotation */
+ int bpp; /* bits per pixel, 32 or 16 */
char valid;
QFrameBuffer qfbuff[1];
} SkinDisplay;
diff --git a/android/skin/window.c b/android/skin/window.c
index edc9028..018c184 100644
--- a/android/skin/window.c
+++ b/android/skin/window.c
@@ -151,10 +151,18 @@ static __inline__ uint32_t rgb565_to_argb32( uint32_t pix )
uint32_t r = ((pix & 0xf800) << 8) | ((pix & 0xe000) << 3);
uint32_t g = ((pix & 0x07e0) << 5) | ((pix & 0x0600) >> 1);
uint32_t b = ((pix & 0x001f) << 3) | ((pix & 0x001c) >> 2);
-
return 0xff000000 | r | g | b;
}
+/* The framebuffer format is R,G,B,X in framebuffer memory, on a
+ * little-endian system, this translates to XBGR after a load.
+ */
+static __inline__ uint32_t xbgr_to_argb32( uint32_t pix )
+{
+ uint32_t g = (pix & 0x0000ff00);
+ uint32_t rb = (pix & 0xff00ff);
+ return 0xff000000 | (rb << 16) | g | (rb >> 16);
+}
static void
display_set_onion( ADisplay* disp, SkinImage* onion, SkinRotation rotation, int blend )
@@ -366,6 +374,184 @@ lcd_off_argb32( unsigned char* pixels, SkinRect* r, int pitch )
}
}
+static void
+display_redraw_rect16( ADisplay* disp, SkinRect* rect, SDL_Surface* surface)
+{
+ int x = rect->pos.x - disp->rect.pos.x;
+ int y = rect->pos.y - disp->rect.pos.y;
+ int w = rect->size.w;
+ int h = rect->size.h;
+ int disp_w = disp->rect.size.w;
+ int disp_h = disp->rect.size.h;
+ int dst_pitch = surface->pitch;
+ uint8_t* dst_line = (uint8_t*)surface->pixels + rect->pos.x*4 + rect->pos.y*dst_pitch;
+ int src_pitch = disp->datasize.w*2;
+ uint8_t* src_line = (uint8_t*)disp->data;
+ int yy, xx;
+
+ switch ( disp->rotation & 3 )
+ {
+ case ANDROID_ROTATION_0:
+ src_line += x*2 + y*src_pitch;
+
+ for (yy = h; yy > 0; yy--)
+ {
+ uint32_t* dst = (uint32_t*)dst_line;
+ uint16_t* src = (uint16_t*)src_line;
+
+ for (xx = 0; xx < w; xx++) {
+ dst[xx] = rgb565_to_argb32(src[xx]);
+ }
+ src_line += src_pitch;
+ dst_line += dst_pitch;
+ }
+ break;
+
+ case ANDROID_ROTATION_90:
+ src_line += y*2 + (disp_w - x - 1)*src_pitch;
+
+ for (yy = h; yy > 0; yy--)
+ {
+ uint32_t* dst = (uint32_t*)dst_line;
+ uint8_t* src = src_line;
+
+ for (xx = w; xx > 0; xx--)
+ {
+ dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
+ src -= src_pitch;
+ dst += 1;
+ }
+ src_line += 2;
+ dst_line += dst_pitch;
+ }
+ break;
+
+ case ANDROID_ROTATION_180:
+ src_line += (disp_w -1 - x)*2 + (disp_h-1-y)*src_pitch;
+
+ for (yy = h; yy > 0; yy--)
+ {
+ uint16_t* src = (uint16_t*)src_line;
+ uint32_t* dst = (uint32_t*)dst_line;
+
+ for (xx = w; xx > 0; xx--) {
+ dst[0] = rgb565_to_argb32(src[0]);
+ src -= 1;
+ dst += 1;
+ }
+
+ src_line -= src_pitch;
+ dst_line += dst_pitch;
+ }
+ break;
+
+ default: /* ANDROID_ROTATION_270 */
+ src_line += (disp_h-1-y)*2 + x*src_pitch;
+
+ for (yy = h; yy > 0; yy--)
+ {
+ uint32_t* dst = (uint32_t*)dst_line;
+ uint8_t* src = src_line;
+
+ for (xx = w; xx > 0; xx--) {
+ dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
+ dst += 1;
+ src += src_pitch;
+ }
+ src_line -= 2;
+ dst_line += dst_pitch;
+ }
+ }
+}
+
+static void
+display_redraw_rect32( ADisplay* disp, SkinRect* rect,SDL_Surface* surface)
+{
+ int x = rect->pos.x - disp->rect.pos.x;
+ int y = rect->pos.y - disp->rect.pos.y;
+ int w = rect->size.w;
+ int h = rect->size.h;
+ int disp_w = disp->rect.size.w;
+ int disp_h = disp->rect.size.h;
+ int dst_pitch = surface->pitch;
+ uint8_t* dst_line = (uint8_t*)surface->pixels + rect->pos.x*4 + rect->pos.y*dst_pitch;
+ int src_pitch = disp->datasize.w*4;
+ uint8_t* src_line = (uint8_t*)disp->data;
+ int yy, xx;
+
+ switch ( disp->rotation & 3 )
+ {
+ case ANDROID_ROTATION_0:
+ src_line += x*4 + y*src_pitch;
+
+ for (yy = h; yy > 0; yy--) {
+ uint32_t* src = (uint32_t*)src_line;
+ uint32_t* dst = (uint32_t*)dst_line;
+
+ for (xx = 0; xx < w; xx++) {
+ dst[xx] = xbgr_to_argb32(src[xx]);
+ }
+ src_line += src_pitch;
+ dst_line += dst_pitch;
+ }
+ break;
+
+ case ANDROID_ROTATION_90:
+ src_line += y*4 + (disp_w - x - 1)*src_pitch;
+
+ for (yy = h; yy > 0; yy--)
+ {
+ uint32_t* dst = (uint32_t*)dst_line;
+ uint8_t* src = src_line;
+
+ for (xx = w; xx > 0; xx--)
+ {
+ dst[0] = xbgr_to_argb32(*(uint32_t*)src);
+ src -= src_pitch;
+ dst += 1;
+ }
+ src_line += 4;
+ dst_line += dst_pitch;
+ }
+ break;
+
+ case ANDROID_ROTATION_180:
+ src_line += (disp_w -1 - x)*4 + (disp_h-1-y)*src_pitch;
+
+ for (yy = h; yy > 0; yy--)
+ {
+ uint32_t* src = (uint32_t*)src_line;
+ uint32_t* dst = (uint32_t*)dst_line;
+
+ for (xx = w; xx > 0; xx--) {
+ dst[0] = xbgr_to_argb32(src[0]);
+ src -= 1;
+ dst += 1;
+ }
+
+ src_line -= src_pitch;
+ dst_line += dst_pitch;
+ }
+ break;
+
+ default: /* ANDROID_ROTATION_270 */
+ src_line += (disp_h-1-y)*4 + x*src_pitch;
+
+ for (yy = h; yy > 0; yy--)
+ {
+ uint32_t* dst = (uint32_t*)dst_line;
+ uint8_t* src = src_line;
+
+ for (xx = w; xx > 0; xx--) {
+ dst[0] = xbgr_to_argb32(*(uint32_t*)src);
+ dst += 1;
+ src += src_pitch;
+ }
+ src_line -= 4;
+ dst_line += dst_pitch;
+ }
+ }
+}
static void
display_redraw( ADisplay* disp, SkinRect* rect, SDL_Surface* surface )
@@ -374,21 +560,11 @@ display_redraw( ADisplay* disp, SkinRect* rect, SDL_Surface* surface )
if (skin_rect_intersect( &r, rect, &disp->rect ))
{
- int x = r.pos.x - disp->rect.pos.x;
- int y = r.pos.y - disp->rect.pos.y;
- int w = r.size.w;
- int h = r.size.h;
- int disp_w = disp->rect.size.w;
- int disp_h = disp->rect.size.h;
- int dst_pitch = surface->pitch;
- uint8_t* dst_line = (uint8_t*)surface->pixels + r.pos.x*4 + r.pos.y*dst_pitch;
- int src_pitch = disp->datasize.w*2;
- uint8_t* src_line = (uint8_t*)disp->data;
- int yy, xx;
#if 0
fprintf(stderr, "--- display redraw r.pos(%d,%d) r.size(%d,%d) "
"disp.pos(%d,%d) disp.size(%d,%d) datasize(%d,%d) rect.pos(%d,%d) rect.size(%d,%d)\n",
- r.pos.x - disp->rect.pos.x, r.pos.y - disp->rect.pos.y, w, h, disp->rect.pos.x, disp->rect.pos.y,
+ r.pos.x - disp->rect.pos.x, r.pos.y - disp->rect.pos.y,
+ r.size.w, r.size.h, disp->rect.pos.x, disp->rect.pos.y,
disp->rect.size.w, disp->rect.size.h, disp->datasize.w, disp->datasize.h,
rect->pos.x, rect->pos.y, rect->size.w, rect->size.h );
#endif
@@ -396,83 +572,14 @@ display_redraw( ADisplay* disp, SkinRect* rect, SDL_Surface* surface )
if (disp->brightness == LCD_BRIGHTNESS_OFF)
{
- lcd_off_argb32( surface->pixels, &r, dst_pitch );
+ lcd_off_argb32( surface->pixels, &r, surface->pitch );
}
else
{
- switch ( disp->rotation & 3 )
- {
- case ANDROID_ROTATION_0:
- src_line += x*2 + y*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint32_t* dst = (uint32_t*)dst_line;
- uint16_t* src = (uint16_t*)src_line;
-
- for (xx = 0; xx < w; xx++) {
- dst[xx] = rgb565_to_argb32(src[xx]);
- }
- src_line += src_pitch;
- dst_line += dst_pitch;
- }
- break;
-
- case ANDROID_ROTATION_90:
- src_line += y*2 + (disp_w - x - 1)*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint32_t* dst = (uint32_t*)dst_line;
- uint8_t* src = src_line;
-
- for (xx = w; xx > 0; xx--)
- {
- dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
- src -= src_pitch;
- dst += 1;
- }
- src_line += 2;
- dst_line += dst_pitch;
- }
- break;
-
- case ANDROID_ROTATION_180:
- src_line += (disp_w -1 - x)*2 + (disp_h-1-y)*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint16_t* src = (uint16_t*)src_line;
- uint32_t* dst = (uint32_t*)dst_line;
-
- for (xx = w; xx > 0; xx--) {
- dst[0] = rgb565_to_argb32(src[0]);
- src -= 1;
- dst += 1;
- }
-
- src_line -= src_pitch;
- dst_line += dst_pitch;
- }
- break;
-
- default: /* ANDROID_ROTATION_270 */
- src_line += (disp_h-1-y)*2 + x*src_pitch;
-
- for (yy = h; yy > 0; yy--)
- {
- uint32_t* dst = (uint32_t*)dst_line;
- uint8_t* src = src_line;
-
- for (xx = w; xx > 0; xx--) {
- dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]);
- dst += 1;
- src += src_pitch;
- }
- src_line -= 2;
- dst_line += dst_pitch;
- }
- }
+ if (disp->qfbuff->bits_per_pixel == 32)
+ display_redraw_rect32(disp, &r, surface);
+ else
+ display_redraw_rect16(disp, &r, surface);
#if DOT_MATRIX
dotmatrix_dither_argb32( surface->pixels, r.pos.x, r.pos.y, r.size.w, r.size.h, surface->pitch );
#endif
@@ -502,7 +609,7 @@ display_redraw( ADisplay* disp, SkinRect* rect, SDL_Surface* surface )
}
}
- SDL_UpdateRect( surface, r.pos.x, r.pos.y, w, h );
+ SDL_UpdateRect( surface, r.pos.x, r.pos.y, r.size.w, r.size.h );
}
}
diff --git a/framebuffer.c b/framebuffer.c
index 225d60d..a90a1e8 100644
--- a/framebuffer.c
+++ b/framebuffer.c
@@ -37,6 +37,8 @@ _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;
}
@@ -49,6 +51,8 @@ _get_bits_per_pixel(QFrameBufferFormat format)
switch (format) {
case QFRAME_BUFFER_RGB565:
return 16;
+ case QFRAME_BUFFER_RGBX_8888:
+ return 32;
default:
return -1;
}
@@ -61,6 +65,8 @@ _get_bytes_per_pixel(QFrameBufferFormat format)
switch (format) {
case QFRAME_BUFFER_RGB565:
return 2;
+ case QFRAME_BUFFER_RGBX_8888:
+ return 4;
default:
return -1;
}
@@ -84,11 +90,11 @@ qframebuffer_init( QFrameBuffer* qfbuff,
if (pitch < 0)
return -1;
- bits_per_pixel = _get_bits_per_pixel(format);
- if (bits_per_pixel < 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);
+ bytes_per_pixel = _get_bytes_per_pixel(format);
if (bytes_per_pixel < 0)
return -1;
diff --git a/framebuffer.h b/framebuffer.h
index 0e502d1..7a69440 100644
--- a/framebuffer.h
+++ b/framebuffer.h
@@ -40,6 +40,7 @@ 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;