aboutsummaryrefslogtreecommitdiff
path: root/sim/bfin/gui.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2011-03-06 00:20:21 +0000
committerMike Frysinger <vapier@gentoo.org>2011-03-06 00:20:21 +0000
commitef016f835f292f01f065412fcfd84c50bfff1fea (patch)
treefe72facf7bcdc58af74f3a37d30f0f25d501f6a0 /sim/bfin/gui.c
parent7dcf22fd41de725f3280c80a1274bcef309d6891 (diff)
downloadgdb-ef016f835f292f01f065412fcfd84c50bfff1fea.zip
gdb-ef016f835f292f01f065412fcfd84c50bfff1fea.tar.gz
gdb-ef016f835f292f01f065412fcfd84c50bfff1fea.tar.bz2
sim: bfin: new port
This can boot Das U-Boot and a Linux kernel. It also supports Linux userspace FLAT and FDPIC (dynamic and static) ELFs. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'sim/bfin/gui.c')
-rw-r--r--sim/bfin/gui.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/sim/bfin/gui.c b/sim/bfin/gui.c
new file mode 100644
index 0000000..65f3735
--- /dev/null
+++ b/sim/bfin/gui.c
@@ -0,0 +1,286 @@
+/* Blackfin GUI (SDL) helper code
+
+ Copyright (C) 2010-2011 Free Software Foundation, Inc.
+ Contributed by Analog Devices, Inc.
+
+ This file is part of simulators.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+
+#ifdef HAVE_SDL
+# include <SDL.h>
+#endif
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+
+#include "libiberty.h"
+#include "gui.h"
+
+#ifdef HAVE_SDL
+
+static struct {
+ void *handle;
+ int (*Init) (Uint32 flags);
+ void (*Quit) (void);
+ SDL_Surface *(*SetVideoMode) (int width, int height, int bpp, Uint32 flags);
+ void (*WM_SetCaption) (const char *title, const char *icon);
+ int (*ShowCursor) (int toggle);
+ int (*LockSurface) (SDL_Surface *surface);
+ void (*UnlockSurface) (SDL_Surface *surface);
+ void (*GetRGB) (Uint32 pixel, const SDL_PixelFormat * const fmt, Uint8 *r, Uint8 *g, Uint8 *b);
+ Uint32 (*MapRGB) (const SDL_PixelFormat * const format, const Uint8 r, const Uint8 g, const Uint8 b);
+ void (*UpdateRect) (SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h);
+} sdl;
+
+static const char * const sdl_syms[] = {
+ "SDL_Init",
+ "SDL_Quit",
+ "SDL_SetVideoMode",
+ "SDL_WM_SetCaption",
+ "SDL_ShowCursor",
+ "SDL_LockSurface",
+ "SDL_UnlockSurface",
+ "SDL_GetRGB",
+ "SDL_MapRGB",
+ "SDL_UpdateRect",
+};
+
+struct gui_state {
+ SDL_Surface *screen;
+ const SDL_PixelFormat *format;
+ int throttle, throttle_limit;
+ enum gui_color color;
+ int curr_line;
+};
+
+/* Load the SDL lib on the fly to avoid hard linking against it. */
+static int
+bfin_gui_sdl_setup (void)
+{
+ int i;
+ uintptr_t **funcs;
+
+ if (sdl.handle)
+ return 0;
+
+ sdl.handle = dlopen ("libSDL-1.2.so.0", RTLD_LAZY);
+ if (sdl.handle == NULL)
+ return -1;
+
+ funcs = (void *) &sdl.Init;
+ for (i = 0; i < ARRAY_SIZE (sdl_syms); ++i)
+ {
+ funcs[i] = dlsym (sdl.handle, sdl_syms[i]);
+ if (funcs[i] == NULL)
+ {
+ dlclose (sdl.handle);
+ sdl.handle = NULL;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static const SDL_PixelFormat *bfin_gui_color_format (enum gui_color color);
+
+void *
+bfin_gui_setup (void *state, int enabled, int width, int height,
+ enum gui_color color)
+{
+ if (bfin_gui_sdl_setup ())
+ return NULL;
+
+ /* Create an SDL window if enabled and we don't have one yet. */
+ if (enabled && !state)
+ {
+ struct gui_state *gui = xmalloc (sizeof (*gui));
+ if (!gui)
+ return NULL;
+
+ if (sdl.Init (SDL_INIT_VIDEO))
+ goto error;
+
+ gui->color = color;
+ gui->format = bfin_gui_color_format (gui->color);
+ gui->screen = sdl.SetVideoMode (width, height, 32,
+ SDL_ANYFORMAT|SDL_HWSURFACE);
+ if (!gui->screen)
+ {
+ sdl.Quit();
+ goto error;
+ }
+
+ sdl.WM_SetCaption ("GDB Blackfin Simulator", NULL);
+ sdl.ShowCursor (0);
+ gui->curr_line = 0;
+ gui->throttle = 0;
+ gui->throttle_limit = 0xf; /* XXX: let people control this ? */
+ return gui;
+
+ error:
+ free (gui);
+ return NULL;
+ }
+
+ /* Else break down a window if disabled and we had one. */
+ else if (!enabled && state)
+ {
+ sdl.Quit();
+ free (state);
+ return NULL;
+ }
+
+ /* Retain existing state, whatever that may be. */
+ return state;
+}
+
+static int
+SDL_ConvertBlitLineFrom (const Uint8 *src, const SDL_PixelFormat * const format,
+ SDL_Surface *dst, int dsty)
+{
+ Uint8 r, g, b;
+ Uint32 *pixels;
+ unsigned i, j;
+
+ if (SDL_MUSTLOCK (dst))
+ if (sdl.LockSurface (dst))
+ return 1;
+
+ pixels = dst->pixels;
+ pixels += (dsty * dst->pitch / 4);
+
+ for (i = 0; i < dst->w; ++i)
+ {
+ /* Exract the packed source pixel; RGB or BGR. */
+ Uint32 pix = 0;
+ for (j = 0; j < format->BytesPerPixel; ++j)
+ if (format->Rshift)
+ pix = (pix << 8) | src[j];
+ else
+ pix = pix | ((Uint32)src[j] << (j * 8));
+
+ /* Unpack the source pixel into its components. */
+ sdl.GetRGB (pix, format, &r, &g, &b);
+ /* Translate into the screen pixel format. */
+ *pixels++ = sdl.MapRGB (dst->format, r, g, b);
+
+ src += format->BytesPerPixel;
+ }
+
+ if (SDL_MUSTLOCK (dst))
+ sdl.UnlockSurface (dst);
+
+ sdl.UpdateRect (dst, 0, dsty, dst->w, 1);
+
+ return 0;
+}
+
+unsigned
+bfin_gui_update (void *state, const void *source, unsigned nr_bytes)
+{
+ struct gui_state *gui = state;
+ int ret;
+
+ if (!gui)
+ return 0;
+
+ /* XXX: Make this an option ? */
+ gui->throttle = (gui->throttle + 1) & gui->throttle_limit;
+ if (gui->throttle)
+ return 0;
+
+ ret = SDL_ConvertBlitLineFrom (source, gui->format, gui->screen,
+ gui->curr_line);
+ if (ret)
+ return 0;
+
+ gui->curr_line = (gui->curr_line + 1) % gui->screen->h;
+
+ return nr_bytes;
+}
+
+#define FMASK(cnt, shift) (((1 << (cnt)) - 1) << (shift))
+#define _FORMAT(bpp, rcnt, gcnt, bcnt, acnt, rsh, gsh, bsh, ash) \
+ NULL, bpp, (bpp)/8, 8-(rcnt), 8-(gcnt), 8-(bcnt), 8-(acnt), rsh, gsh, bsh, ash, \
+ FMASK (rcnt, rsh), FMASK (gcnt, gsh), FMASK (bcnt, bsh), FMASK (acnt, ash),
+#define FORMAT(rcnt, gcnt, bcnt, acnt, rsh, gsh, bsh, ash) \
+ _FORMAT(((((rcnt) + (gcnt) + (bcnt) + (acnt)) + 7) / 8) * 8, \
+ rcnt, gcnt, bcnt, acnt, rsh, gsh, bsh, ash)
+
+static const SDL_PixelFormat sdl_rgb_565 = {
+ FORMAT (5, 6, 5, 0, 11, 5, 0, 0)
+};
+static const SDL_PixelFormat sdl_bgr_565 = {
+ FORMAT (5, 6, 5, 0, 0, 5, 11, 0)
+};
+static const SDL_PixelFormat sdl_rgb_888 = {
+ FORMAT (8, 8, 8, 0, 16, 8, 0, 0)
+};
+static const SDL_PixelFormat sdl_bgr_888 = {
+ FORMAT (8, 8, 8, 0, 0, 8, 16, 0)
+};
+static const SDL_PixelFormat sdl_rgba_8888 = {
+ FORMAT (8, 8, 8, 8, 24, 16, 8, 0)
+};
+
+static const struct {
+ const char *name;
+ const SDL_PixelFormat *format;
+ enum gui_color color;
+} color_spaces[] = {
+ { "rgb565", &sdl_rgb_565, GUI_COLOR_RGB_565, },
+ { "bgr565", &sdl_bgr_565, GUI_COLOR_BGR_565, },
+ { "rgb888", &sdl_rgb_888, GUI_COLOR_RGB_888, },
+ { "bgr888", &sdl_bgr_888, GUI_COLOR_BGR_888, },
+ { "rgba8888", &sdl_rgba_8888, GUI_COLOR_RGBA_8888, },
+};
+
+enum gui_color bfin_gui_color (const char *color)
+{
+ int i;
+
+ if (!color)
+ goto def;
+
+ for (i = 0; i < ARRAY_SIZE (color_spaces); ++i)
+ if (!strcmp (color, color_spaces[i].name))
+ return color_spaces[i].color;
+
+ /* Pick a random default. */
+ def:
+ return GUI_COLOR_RGB_888;
+}
+
+static const SDL_PixelFormat *bfin_gui_color_format (enum gui_color color)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (color_spaces); ++i)
+ if (color == color_spaces[i].color)
+ return color_spaces[i].format;
+
+ return NULL;
+}
+
+int bfin_gui_color_depth (enum gui_color color)
+{
+ const SDL_PixelFormat *format = bfin_gui_color_format (color);
+ return format ? format->BitsPerPixel : 0;
+}
+
+#endif