diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-03-06 00:20:21 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-03-06 00:20:21 +0000 |
commit | ef016f835f292f01f065412fcfd84c50bfff1fea (patch) | |
tree | fe72facf7bcdc58af74f3a37d30f0f25d501f6a0 /sim/bfin/gui.c | |
parent | 7dcf22fd41de725f3280c80a1274bcef309d6891 (diff) | |
download | gdb-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.c | 286 |
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 |