Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / video_common.c
diff --git a/qemu/roms/openbios/libopenbios/video_common.c b/qemu/roms/openbios/libopenbios/video_common.c
new file mode 100644 (file)
index 0000000..9bbc18c
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ *   Creation Date: <2002/10/23 20:26:40 samuel>
+ *   Time-stamp: <2004/01/07 19:39:15 samuel>
+ *
+ *     <video_common.c>
+ *
+ *     Shared video routines
+ *
+ *   Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ *   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
+ *
+ */
+
+#include "config.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/fontdata.h"
+#include "libopenbios/ofmem.h"
+#include "libopenbios/video.h"
+#include "packages/video.h"
+#include "drivers/vga.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+
+struct video_info video;
+
+unsigned long
+video_get_color( int col_ind )
+{
+       unsigned long col;
+       if( !VIDEO_DICT_VALUE(video.ih) || col_ind < 0 || col_ind > 255 )
+               return 0;
+       if( VIDEO_DICT_VALUE(video.depth) == 8 )
+               return col_ind;
+       col = video.pal[col_ind];
+       if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 )
+               return col;
+       if( VIDEO_DICT_VALUE(video.depth) == 15 )
+               return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
+       return 0;
+}
+
+/* ( fbaddr maskaddr width height fgcolor bgcolor -- ) */
+
+void
+video_mask_blit(void)
+{
+       ucell bgcolor = POP();
+       ucell fgcolor = POP();
+       ucell height = POP();
+       ucell width = POP();
+       unsigned char *mask = (unsigned char *)POP();
+       unsigned char *fbaddr = (unsigned char *)POP();
+
+       ucell color;
+       unsigned char *dst, *rowdst;
+       int x, y, m, b, d, depthbytes;
+
+       fgcolor = video_get_color(fgcolor);
+       bgcolor = video_get_color(bgcolor);
+       d = VIDEO_DICT_VALUE(video.depth);
+       depthbytes = (d + 1) >> 3;
+
+       dst = fbaddr;
+       for( y = 0; y < height; y++) {
+               rowdst = dst;
+               for( x = 0; x < (width + 1) >> 3; x++ ) {
+                       for (b = 0; b < 8; b++) {
+                               m = (1 << (7 - b));
+
+                               if (*mask & m) {
+                                       color = fgcolor;
+                               } else {
+                                       color = bgcolor;
+                               }
+
+                               if( d >= 24 )
+                                       *((uint32_t*)dst) = color;
+                               else if( d >= 15 )
+                                       *((uint16_t*)dst) = color;
+                               else
+                                       *dst = color;
+
+                               dst += depthbytes;
+                       }
+                       mask++;
+               }
+               dst = rowdst;
+               dst += VIDEO_DICT_VALUE(video.rb);
+       }
+}
+
+/* ( x y w h fgcolor bgcolor -- ) */
+
+void
+video_invert_rect( void )
+{
+       ucell bgcolor = POP();
+       ucell fgcolor = POP();
+       int h = POP();
+       int w = POP();
+       int y = POP();
+       int x = POP();
+       char *pp;
+
+       bgcolor = video_get_color(bgcolor);
+       fgcolor = video_get_color(fgcolor);
+
+       if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
+               x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
+               return;
+
+       pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
+       for( ; h--; pp += *(video.rb) ) {
+               int ww = w;
+               if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
+                       uint32_t *p = (uint32_t*)pp + x;
+                       while( ww-- ) {
+                               if (*p == fgcolor) {
+                                       *p++ = bgcolor;
+                               } else if (*p == bgcolor) {
+                                       *p++ = fgcolor;
+                               }
+                       }
+               } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
+                       uint16_t *p = (uint16_t*)pp + x;
+                       while( ww-- ) {
+                               if (*p == (uint16_t)fgcolor) {
+                                       *p++ = bgcolor;
+                               } else if (*p == (uint16_t)bgcolor) {
+                                       *p++ = fgcolor;
+                               }
+                       }
+               } else {
+                       char *p = (char *)(pp + x);
+
+                       while( ww-- ) {
+                               if (*p == (char)fgcolor) {
+                                       *p++ = bgcolor;
+                               } else if (*p == (char)bgcolor) {
+                                       *p++ = fgcolor;
+                               }
+                       }
+               }
+       }
+}
+
+/* ( color_ind x y width height -- ) (?) */
+void
+video_fill_rect(void)
+{
+       int h = POP();
+       int w = POP();
+       int y = POP();
+       int x = POP();
+       int col_ind = POP();
+
+       char *pp;
+       unsigned long col = video_get_color(col_ind);
+
+        if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
+            x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
+               return;
+
+       pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
+       for( ; h--; pp += VIDEO_DICT_VALUE(video.rb) ) {
+               int ww = w;
+               if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
+                       uint32_t *p = (uint32_t*)pp + x;
+                       while( ww-- )
+                               *p++ = col;
+               } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
+                       uint16_t *p = (uint16_t*)pp + x;
+                       while( ww-- )
+                               *p++ = col;
+               } else {
+                        char *p = (char *)(pp + x);
+
+                       while( ww-- )
+                               *p++ = col;
+               }
+       }
+}
+
+void setup_video()
+{
+       /* Make everything inside the video_info structure point to the
+          values in the Forth dictionary. Hence everything is always in
+          sync. */
+       phandle_t options;
+       char buf[6];
+
+       feval("['] display-ih cell+");
+       video.ih = cell2pointer(POP());
+
+       feval("['] frame-buffer-adr cell+");
+       video.mvirt = cell2pointer(POP());
+       feval("['] openbios-video-width cell+");
+       video.w = cell2pointer(POP());
+       feval("['] openbios-video-height cell+");
+       video.h = cell2pointer(POP());
+       feval("['] depth-bits cell+");
+       video.depth = cell2pointer(POP());
+       feval("['] line-bytes cell+");
+       video.rb = cell2pointer(POP());
+       feval("['] color-palette cell+");
+       video.pal = cell2pointer(POP());
+
+       /* Set global variables ready for fb8-install */
+       PUSH( pointer2cell(video_mask_blit) );
+       fword("is-noname-cfunc");
+       feval("to fb8-blitmask");
+       PUSH( pointer2cell(video_fill_rect) );
+       fword("is-noname-cfunc");
+       feval("to fb8-fillrect");
+       PUSH( pointer2cell(video_invert_rect) );
+       fword("is-noname-cfunc");
+       feval("to fb8-invertrect");
+
+       /* Static information */
+       PUSH((ucell)fontdata);
+       feval("to (romfont)");
+       PUSH(FONT_HEIGHT);
+       feval("to (romfont-height)");
+       PUSH(FONT_WIDTH);
+       feval("to (romfont-width)");
+
+       /* Initialise the structure */
+       VIDEO_DICT_VALUE(video.w) = VGA_DEFAULT_WIDTH;
+       VIDEO_DICT_VALUE(video.h) = VGA_DEFAULT_HEIGHT;
+       VIDEO_DICT_VALUE(video.depth) = VGA_DEFAULT_DEPTH;
+       VIDEO_DICT_VALUE(video.rb) = VGA_DEFAULT_LINEBYTES;
+
+#if defined(CONFIG_QEMU) && (defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64))
+       /* If running from QEMU, grab the parameters from the firmware interface */
+       int w, h, d;
+
+       w = fw_cfg_read_i16(FW_CFG_ARCH_WIDTH);
+        h = fw_cfg_read_i16(FW_CFG_ARCH_HEIGHT);
+        d = fw_cfg_read_i16(FW_CFG_ARCH_DEPTH);
+       if (w && h && d) {
+               VIDEO_DICT_VALUE(video.w) = w;
+               VIDEO_DICT_VALUE(video.h) = h;
+               VIDEO_DICT_VALUE(video.depth) = d;
+               VIDEO_DICT_VALUE(video.rb) = (w * ((d + 7) / 8));
+       }
+#endif
+
+       /* Setup screen-#rows/screen-#columns */
+       options = find_dev("/options");
+       snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.w) / FONT_WIDTH);
+       set_property(options, "screen-#columns", buf, strlen(buf) + 1);
+       snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.h) / FONT_HEIGHT);
+       set_property(options, "screen-#rows", buf, strlen(buf) + 1);
+}