This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
synthetic target framebuffer driver
- From: Bart Veer <bartv at ecoscentric dot com>
- To: ecos-patches at sourceware dot org
- Date: Tue, 07 Oct 2008 22:07:11 +0100
- Subject: synthetic target framebuffer driver
This patch contributes eCosCentric's synthetic target framebuffer
device driver. It should allow people to experiment with the
framebuffer support, as well as act as a reference (albeit not
entirely typical) device driver.
Bart
Index: ChangeLog
===================================================================
RCS file: ChangeLog
diff -N ChangeLog
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ChangeLog 7 Oct 2008 21:00:17 -0000
@@ -0,0 +1,35 @@
+2008-10-06 Bart Veer <bartv@ecoscentric.com>
+
+ * synthetic target framebuffer driver imported into anoncvs
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
Index: cdl/framebuf_synth.cdl
===================================================================
RCS file: cdl/framebuf_synth.cdl
diff -N cdl/framebuf_synth.cdl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cdl/framebuf_synth.cdl 7 Oct 2008 21:00:17 -0000
@@ -0,0 +1,256 @@
+# ====================================================================
+#
+# framebuf_synth.cdl
+#
+# Framebuffer device driver for the synthetic target.
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+# -------------------------------------------
+# This file is part of eCos, the Embedded Configurable Operating System.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# eCos 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 2 or (at your option) any later version.
+#
+# eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# As a special exception, if other files instantiate templates or use macros
+# or inline functions from this file, or you compile this file and link it
+# with other works to produce a work based on this file, this file does not
+# by itself cause the resulting work to be covered by the GNU General Public
+# License. However the source code for this file must still be made available
+# in accordance with section (3) of the GNU General Public License.
+#
+# This exception does not invalidate any other reasons why a work based on
+# this file might be covered by the GNU General Public License.
+# -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): bartv
+# Date: 2005-10-24
+#
+#####DESCRIPTIONEND####
+#========================================================================
+
+cdl_package CYGPKG_DEVS_FRAMEBUF_SYNTH {
+ display "Synthetic Target Framebuffer device driver"
+ parent CYGPKG_IO_FRAMEBUF
+ active_if CYGPKG_IO_FRAMEBUF
+ hardware
+ include_files
+
+ description "
+ This package provides a framebuffer device driver for the
+ synthetic target."
+
+ for { set _fb 0 } { $_fb < 4 } { incr _fb } {
+ cdl_component CYGPKG_DEVS_FRAMEBUF_SYNTH_FB$_fb {
+ display "Provide framebuffer device fb$_fb"
+ description "
+ The synthetic target framebuffer driver can provide up to
+ four framebuffer devices, named fb0 to fb3. Each device's
+ width, height, depth, and colour format can be controlled.
+ This option enables device fb$_fb"
+
+ flavor bool
+ default_value [expr $_fb ? 0 : 1]
+ implements CYGINT_IO_FRAMEBUF_DEVICES
+ implements CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER
+ requires is_substr(CYGDAT_IO_FRAMEBUF_DEVICES, \" fb[set _fb] \")
+
+ cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_WIDTH {
+ display "fb$_fb width"
+ flavor data
+ default_value 320
+ legal_values 16 to 4096
+ }
+
+ cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_HEIGHT {
+ display "fb$_fb height"
+ flavor data
+ default_value 240
+ legal_values 16 to 4096
+ }
+
+ cdl_option CYGDAT_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_FORMAT {
+ display "fb$_fb format"
+ flavor data
+ if { 0 } {
+ legal_values { "1BPP_BE_PAL888" "1BPP_LE_PAL888"
+ "2BPP_BE_PAL888" "2BPP_LE_PAL888"
+ "4BPP_BE_PAL888" "4BPP_LE_PAL888"
+ "8BPP_PAL888" "8BPP_TRUE_332"
+ "16BPP_TRUE_565" "16BPP_TRUE_555"
+ "32BPP_TRUE_0888"
+ }
+ } else {
+ legal_values {
+ "8BPP_PAL888" "8BPP_TRUE_332"
+ "16BPP_TRUE_565" "16BPP_TRUE_555"
+ "32BPP_TRUE_0888"
+ }
+ }
+ default_value { "8BPP_PAL888" }
+ if { 0 } {
+ description "
+ Each synthetic target framebuffer device can be configured
+ to emulate a particular format. This consists of three fields:
+ depth, endianness, and colour. The depth is in bits per pixel
+ and can be 1bpp, 2bpp, 4bpp, 8bpp, 16bpp or 32bpp. The endianness
+ is only relevant for 1bpp, 2bpp and 4bpp devices and affects how
+ pixels are organized within each byte. Colour can be either
+ paletted or true colour. 1bpp, 2bpp and 4bpp implies paletted, and
+ 16bpp and 32bpp implies true colour. 8bpp can be either paletted
+ or true colour. For 1bpp the default palette is monochrome with
+ colour 0 == black. For 2bpp the default palette is greyscale with
+ colour 0 == black. For 4bpp the default palette is EGA. For 8bpp
+ the default palette is VGA. The application can change these
+ default palettes as required to match the hardware being emulated."
+ } else {
+ description "
+ Each synthetic target framebuffer device can be configured
+ to emulate a particular format. This consists of two fields:
+ depth and colour. The depth is in bits per pixel and can be
+ 8bpp, 16bpp or 32bpp. Colour can be either paletted or true colour.
+ 16bpp and 32bpp implies true colour. 8bpp can be either paletted
+ or true colour. For 8bpp the default palette is VGA. The application
+ can change these default palettes as required to match the hardware being emulated."
+ }
+ }
+
+ cdl_component CYGIMP_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_VIEWPORT {
+ display "fb$_fb provides viewport support"
+ default_value 0
+ implements CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+ description "
+ Optionally framebuffer device $_fb can support a viewport.
+ In other words only a subset of the framebuffer, the viewport,
+ is actually visible on the display and application code can
+ move this viewport."
+
+ cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_VIEWPORT_WIDTH {
+ display "fb$_fb viewport width"
+ flavor data
+ default_value CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_WIDTH
+ legal_values 16 to CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_WIDTH
+ }
+
+ cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_VIEWPORT_HEIGHT {
+ display "fb$_fb viewport height"
+ flavor data
+ default_value CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_HEIGHT
+ legal_values 16 to CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_HEIGHT
+ }
+ }
+
+ cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set _fb]_PAGE_FLIPPING {
+ display "fb$_fb supports page flipping"
+ flavor booldata
+ default_value 0
+ legal_values 2 3 4
+ description "
+ Optionally framebuffer device $_fb can support page flipping.
+ The device supports between two and four pages, only one
+ of which is visible on the display. This allows code to
+ update one page without disturbing what is currently visible."
+ }
+ }
+
+ # Eliminate any framebuffer devices that are no longer enabled.
+ requires (CYGPKG_DEVS_FRAMEBUF_SYNTH_FB$_fb || !is_substr(CYGDAT_IO_FRAMEBUF_DEVICES, \" fb[set _fb] \"))
+ }
+
+ cdl_component CYGPKG_DEVS_FRAMEBUF_SYNTH_FUNCTIONALITY {
+ display "Functionality supported by the enabled framebuffer(s)"
+ flavor none
+ description "
+ The generic framebuffer code needs configure-time information about
+ functionality of the enabled framebuffer or framebuffers. Usually
+ all this information is fixed by the hardware, but the synthetic
+ target framebuffer support is more flexible than real hardware. To
+ cope with this some dummy options are needed."
+
+ active_if { CYGPKG_DEVS_FRAMEBUF_SYNTH_FB0 ||
+ CYGPKG_DEVS_FRAMEBUF_SYNTH_FB1 ||
+ CYGPKG_DEVS_FRAMEBUF_SYNTH_FB2 ||
+ CYGPKG_DEVS_FRAMEBUF_SYNTH_FB3 }
+ make -priority=1 {
+ $(PREFIX)/include/cyg/io/framebufs/synth_fb.h : \
+ $(REPOSITORY)/$(PACKAGE)/src/gen_synthfb.tcl \
+ $(PREFIX)/include/pkgconf/devs_framebuf_synth.h
+ sh $< $(PREFIX)
+ }
+ compile synthfb.c
+ compile -library=libextras.a synthfb_init.cxx
+
+ cdl_option CYGHWR_DEVS_FRAMEBUF_SYNTH_FUNCTIONALITY_32BPP {
+ display "One or more of the enabled framebuffer devices has a depth of 32bpp"
+ calculated { is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB0_FORMAT, "32BPP") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB1_FORMAT, "32BPP") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB2_FORMAT, "32BPP") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB3_FORMAT, "32BPP") }
+ implements CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_32BPP
+ }
+
+ cdl_option CYGHWR_DEVS_FRAMEBUF_SYNTH_FUNCTIONALITY_PALETTED {
+ display "One or more of the enabled framebuffer devices uses a paletted display"
+ calculated { is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB0_FORMAT, "PAL") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB1_FORMAT, "PAL") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB2_FORMAT, "PAL") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB3_FORMAT, "PAL") }
+ implements CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+ implements CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+ }
+
+ cdl_option CYGHWR_DEVS_FRAMEBUF_SYNTH_TRUE_COLOUR {
+ display "One or more of the enabled framebuffer devices uses a true colour display"
+ calculated { is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB0_FORMAT, "TRUE") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB1_FORMAT, "TRUE") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB2_FORMAT, "TRUE") ||
+ is_substr(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB3_FORMAT, "TRUE") }
+ implements CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+ }
+ }
+
+ cdl_component CYGPKG_DEVS_FRAMEBUF_SYNTH_OPTIONS {
+ display "Framebuffer build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building the synthetic
+ target framebuffer device driver."
+
+ cdl_option CYGPKG_DEVS_FRAMEBUF_SYNTH_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for building
+ the synthetic target framebuffer device driver. These flags
+ are used in addition to the set of global flags."
+ }
+
+ cdl_option CYGPKG_DEVS_FRAMEBUF_SYNTH_CFLAGS_REMOVE {
+ display "Suppressed compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for building
+ the synthetic target framebuffer device driver. These flags
+ are removed from the set of global flags if present."
+ }
+ }
+}
Index: doc/synth_framebuf.sgml
===================================================================
RCS file: doc/synth_framebuf.sgml
diff -N doc/synth_framebuf.sgml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ doc/synth_framebuf.sgml 7 Oct 2008 21:00:18 -0000
@@ -0,0 +1,239 @@
+<!-- DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V3.1//EN" -->
+
+<!-- =============================================================== -->
+<!-- -->
+<!-- synth_framebuf.sgml -->
+<!-- -->
+<!-- Synthetic target frame buffer device -->
+<!-- -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN#### -->
+<!-- -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 2008 Free Software Foundation, Inc. -->
+<!-- This material may be distributed only subject to the terms -->
+<!-- and conditions set forth in the Open Publication License, v1.0 -->
+<!-- or later (the latest version is presently available at -->
+<!-- http://www.opencontent.org/openpub/) -->
+<!-- Distribution of the work or derivative of the work in any -->
+<!-- standard (paper) book form is prohibited unless prior -->
+<!-- permission obtained from the copyright holder -->
+<!-- =============================================================== -->
+<!-- -->
+<!-- ####COPYRIGHTEND#### -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN#### -->
+<!-- -->
+<!-- Author(s): bartv -->
+<!-- Contact(s): bartv -->
+<!-- Date: 2008/10/07 -->
+<!-- Version: 0.01 -->
+<!-- -->
+<!-- ####DESCRIPTIONEND#### -->
+<!-- =============================================================== -->
+
+<part id="devs-framebuf-synth-ref">
+ <title>Synthetic Target Framebuffer Device</title>
+
+<refentry id="devs-framebuf-synth">
+ <refmeta>
+ <refentrytitle>Synthetic Target Framebuffer Device</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Synthetic Target Framebuffer Device</refname>
+ <refpurpose>Emulate framebuffer hardware in the synthetic target</refpurpose>
+ </refnamediv>
+
+ <refsect1 id="devs-framebuf-synth-overview"><title>Overview</title>
+ <para>
+This package <varname>CYGPKG_DEVS_FRAMEBUF_SYNTH</varname> provides a
+framebuffer device driver for the eCos synthetic target.
+ </para>
+ <informalfigure PgWide=1>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="synthfb.png" Scalefit=1 Align="Center">
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+The driver supports up to four framebuffer devices
+<varname>fb0</varname>, <varname>fb1</varname>, <varname>fb2</varname>
+and <varname>fb3</varname>. The width, height, depth, and display
+format of each framebuffer can be controlled via configuration
+options. It is also possible to set a viewport for each device and to
+enable page flipping.
+ </para>
+ <para>
+To use the framebuffer support the eCos application must run inside an
+X session, not from the console, and it must be started with
+<parameter>--io</parameter> to enable the I/O auxiliary. The I/O
+auxiliary will start a separate instance of a host-side utility
+<application>framebuf</application> for each target-side framebuffer
+device. The <application>framebuf</application> utility can access the
+eCos framebuffer data via a shared memory region and draw it to the
+screen using X library calls. It needs the X server to run with a
+TrueColor visual and a display of depth of 24 or 32 bits per pixel.
+ </para>
+ </refsect1>
+
+ <refsect1 id="devs-framebuf-synth-install"><title>Installation</title>
+ <para>
+The synthetic target framebuffer driver depends on host-side support
+which must be built and installed. The relevant code resides in the
+<filename class="directory">host</filename> subdirectory of the
+synthetic target framebuffer package, and building it involves the
+standard <command>configure</command>, <command>make</command> and
+<command>make install</command> steps. This will build and install a
+utility program <application>framebuf</application> that does the
+actual drawing of the eCos framebuffer contents to the host-side X
+display. It will also install a Tcl script and some support files.
+<application>framebuf</application> is an X11 application so can only
+be built on Linux systems with the appropriate X11 development package
+or packages.
+ </para>
+ <para>
+There are two main ways of building the host-side software. It is
+possible to build both the generic host-side software and all
+package-specific host-side software, including the framebuffer
+support, in a single build tree. This involves using the
+<command>configure</command> script at the toplevel of the eCos
+repository. For more information on this, see the
+<filename>README.host</filename> file at the top of the repository.
+Note that if you have an existing build tree which does not include
+the synthetic target framebuffer support then it will be necessary to
+rerun the toplevel configure script: the search for appropriate
+packages happens at configure time.
+ </para>
+ <para>
+The alternative is to build just the host-side for this package.
+This requires a separate build directory, building directly in the
+source tree is disallowed. The <command>configure</command> options
+are much the same as for a build from the toplevel, and the
+<filename>README.host</filename> file can be consulted for more
+details. It is essential that the framebuffer support be configured with
+the same <option>--prefix</option> option as other eCos host-side
+software, especially the I/O auxiliary provided by the architectural
+synthetic target HAL package, otherwise the I/O auxiliary will be
+unable to locate the framebuffer support.
+ </para>
+ </refsect1>
+
+ <refsect1 id="devs-framebuf-synth-config"><title>Configuration</title>
+ <para>
+The package is loaded automatically when creating a configuration for
+the synthetic target. However it is inactive unless the generic
+framebuffer support <varname>CYGPKG_IO_FRAMEBUF</varname> is also
+added to the configuration, for example by <computeroutput>ecosconfig
+add framebuf</computeroutput>.
+ </para>
+ <para>
+By default the package enables a single framebuffer device
+<varname>fb0</varname> with a corresponding
+<structname>cyg_fb</structname> data structure
+<varname>cyg_synth_fb0</varname>. The default settings for this device
+are 320 by 240 pixels, a depth of 8 bits per pixel, a paletted
+display, no viewport support, and no page flipping. All of these
+settings can be changed by configuration options inside the CDL
+component <varname>CYGPKG_DEVS_FRAMEBUF_SYNTH_FB0</varname>. The
+supported display formats are: 8 bpp paletted; 8bpp true colour 332;
+16bpp true 565; 16bpp true 555; and 32bpp 0888. This allows the
+synthetic target to match the actual display capabilities of the
+hardware that is being emulated. If the actual hardware has more than
+one framebuffer device then this can be emulated by enabling
+additional components
+<varname>CYGPKG_DEVS_FRAMEBUF_SYNTH_FB1</varname> …, and
+setting the appropriate options.
+ </para>
+ </refsect1>
+
+ <refsect1 id="devs-framebuf-synth-customization"><title>Customization</title>
+ <para>
+In addition to the target-side configurability it is possible to
+customize the host-side behaviour. For example, the default behaviour
+is for <varname>fb0</varname> to be drawn inside the I/O auxiliary's
+main window, if it is not too large. <varname>fb1</varname>,
+<varname>fb2</varname> and <varname>fb3</varname> will be drawn inside
+separate toplevel windows, as will <varname>fb0</varname> if that has
+been configured too large for embedding in the main window. This
+behaviour can be changed by providing a custom Tcl/Tk procedure that
+creates the containing frame for the framebuffer device.
+ </para>
+ <para>
+Customization involves adding a <structname>synth_device</structname>
+<varname>framebuf</varname> section to the <filename>.tdf</filename>
+target definition file, usually <filename>default.tdf</filename> or
+<filename>~/.ecos/synth/default.tdf</filename>.
+ </para>
+ <programlisting width=72>
+proc my_framebuf_create_frame { &hellip } {
+ …
+}
+
+synth_device framebuf {
+ fb2_magnification 2
+ create_frame_proc my_framebuf_create_frame
+}
+ </programlisting>
+ <para>
+The pixel size on the host display may be rather smaller than on the
+final hardware, causing a serious mismatch between the application's
+appearance when using synthetic target emulation and when using real
+hardware. To reduce this problem the host-side can magnify the
+target-side framebuffer devices. In the example above each target-side
+pixel in device <varname>fb2</varname> will be drawn using 2*2 pixels
+on the host side. Valid magnifications are 1, 2, 3 and 4. With a
+magnification of 4 an eCos framebuffer device of 320*240 pixels will
+be drawn in an X window of 1280*960 pixels.
+ </para>
+ <para>
+The <parameter>create_frame_proc</parameter> entry can be used to
+specify a custom Tcl/Tk procedure that will create the containing Tk
+frames for the host-side displays. This procedure can be written for a
+specific configuration, but it is supplied with all the parameters
+associated with the framebuffer device so can be more generic. An
+example is supplied in the package's <filename
+class="directory">misc</filename> subdirectory:
+ </para>
+ <orderedlist>
+ <listitem><para>
+Create a configuration for the synthetic target with the default
+template.
+ </para></listitem>
+ <listitem><para>
+Import the <filename>example.ecm</filename> configuration fragment
+from the <filename class="directory">misc</filename> subdirectory.
+This will add the generic framebuffer support package, enable all four
+framebuffer devices, and configure each device. Build the resulting
+configuration.
+ </para></listitem>
+ <listitem><para>
+Compile the <filename>example.c</filename> program and link it against
+the eCos configuration.
+ </para></listitem>
+ <listitem><para>
+Incorporate the <filename>example.tdf</filename> fragment into the
+appropriate target definition file, typically
+<filename>default.tdf</filename> or
+<filename>~/.ecos/synth/default.tdf</filename>.
+ </para></listitem>
+ <listitem><para>
+Run the example executable. The four framebuffer devices should get
+instantiated in a separate window in a single column.
+<varname>FB0</varname> just contains a static display.
+<varname>FB1</varname> supports two pages, one with vertical stripes
+and one with horizontal stripes, and the two pages are flipped at
+regular intervals. <varname>FB2</varname> has a static display similar
+to <varname>FB0</varname>, but is drawn in a viewport of only 160x120
+pixels. However <filename>example.tdf</filename> magnifies this by 2
+so it appears the same size as the other devices. The application
+moves the viewport around the underlying framebuffer device.
+<varname>FB3</varname> is also a static display, a simple set of
+vertical stripes. However this framebuffer is paletted and the palette
+is changed at regular intervals, causing apparent movement.
+ </para></listitem>
+ </orderedlist>
+ </refsect1>
+
+</refentry>
+</part>
\ No newline at end of file
Index: doc/synthfb.png
===================================================================
RCS file: doc/synthfb.png
diff -N doc/synthfb.png
Binary files /dev/null and synthfb.png differ
Index: host/Makefile.am
===================================================================
RCS file: host/Makefile.am
diff -N host/Makefile.am
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/Makefile.am 7 Oct 2008 21:00:19 -0000
@@ -0,0 +1,84 @@
+## Process this file with automake to produce Makefile.in
+## =====================================================================
+##
+## Makefile.am
+##
+## Build support for the host-side synthetic target support,
+## the ethernetpackage.
+##
+## =====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+# -------------------------------------------
+# This file is part of eCos, the Embedded Configurable Operating System.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# eCos 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 2 or (at your option) any later version.
+#
+# eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# As a special exception, if other files instantiate templates or use macros
+# or inline functions from this file, or you compile this file and link it
+# with other works to produce a work based on this file, this file does not
+# by itself cause the resulting work to be covered by the GNU General Public
+# License. However the source code for this file must still be made available
+# in accordance with section (3) of the GNU General Public License.
+#
+# This exception does not invalidate any other reasons why a work based on
+# this file might be covered by the GNU General Public License.
+# -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+## =====================================================================
+#######DESCRIPTIONBEGIN####
+##
+## Author(s): bartv
+## Contact(s): bartv
+## Date: 2005/10/28
+## Version: 0.01
+##
+######DESCRIPTIONEND####
+## =====================================================================
+
+AUTOMAKE_OPTIONS = 1.10 foreign
+
+## The synthetic target support consists of a single program framebuf,
+## a Tcl script, and some additional data files. These are
+## all installed in a single directory $(libexec)/ecos/<package>_<version>/
+## Neither the framebuf executable nor any of the scripts are directly
+## executable, instead framebuf gets fork()'d/execve()'d by the Tcl
+## script so $(libexec) is appropriate. Strictly speaking the
+## Tcl scripts and data files are architecture-independent so should
+## probably be installed in an analogous directory below $(datadir),
+## but that would add more directories for little real gain. The scripts
+## are treated as data files since they should not be executed directly,
+## i.e. they should not be installed with the execute bit set.
+
+AM_CFLAGS = @ecos_CFLAGS@ -DECOSYNTH_VERSION=\"@VERSION@\" \
+ -DECOS_REPOSITORY=\"@ECOS_REPOSITORY@\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DPKG_DIR=\"@PACKAGE_DIR@\" \
+ -DPKG_VERSION=\"@PACKAGE_VERSION@\" \
+ -DPKG_INSTALL=\"@PACKAGE_INSTALL@\"
+AM_CXXFLAGS = @ecos_CXXFLAGS@
+INCLUDES = @ecos_INCLUDES@
+LIBS = @ecos_LIBS@ @ecos_LDADD@
+
+if SUPPORTED
+framebufdir = $(libexecdir)/ecos/@PACKAGE_INSTALL@
+framebuf_PROGRAMS = framebuf
+framebuf_DATA = framebuf.tcl framebuf.tdf framebuf_icon.xbm framebuf_iconmask.xbm
+framebuf_SOURCES = framebuf.c
+framebuf_LDADD = -L/usr/X11R6/lib -lX11
+
+## Manual dependencies
+framebuf.$(OBJEXT) : Makefile ../src/protocol.h
+
+endif
Index: host/acinclude.m4
===================================================================
RCS file: host/acinclude.m4
diff -N host/acinclude.m4
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/acinclude.m4 7 Oct 2008 21:00:19 -0000
@@ -0,0 +1,45 @@
+dnl Process this file with aclocal to get an aclocal.m4 file. Then
+dnl process that with autoconf.
+dnl ====================================================================
+dnl
+dnl acinclude.m4
+dnl
+dnl ====================================================================
+dnl####COPYRIGHTBEGIN####
+dnl
+dnl ----------------------------------------------------------------------------
+dnl Copyright (C) 2005 Bart Veer
+dnl
+dnl This file is part of the eCos host tools.
+dnl
+dnl This program is free software; you can redistribute it and/or modify it
+dnl under the terms of the GNU General Public License as published by the Free
+dnl Software Foundation; either version 2 of the License, or (at your option)
+dnl any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but WITHOUT
+dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+dnl more details.
+dnl
+dnl You should have received a copy of the GNU General Public License along with
+dnl this program; if not, write to the Free Software Foundation, Inc.,
+dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl ----------------------------------------------------------------------------
+dnl
+dnl####COPYRIGHTEND####
+dnl ====================================================================
+dnl#####DESCRIPTIONBEGIN####
+dnl
+dnl Author(s): bartv
+dnl Contact(s): bartv
+dnl Date: 2005/10/28
+dnl Version: 0.01
+dnl
+dnl####DESCRIPTIONEND####
+dnl ====================================================================
+
+dnl Access shared macros.
+dnl AM_CONDITIONAL needs to be mentioned here or else aclocal does not
+dnl incorporate the macro into aclocal.m4
+sinclude(../../../../../../acsupport/acinclude.m4)
Index: host/configure.in
===================================================================
RCS file: host/configure.in
diff -N host/configure.in
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/configure.in 7 Oct 2008 21:00:31 -0000
@@ -0,0 +1,91 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl ====================================================================
+dnl
+dnl configure.in
+dnl
+dnl configure script for eCos synthetic target framebuffer
+dnl host-side support
+dnl
+dnl ====================================================================
+dnl####ECOSGPLCOPYRIGHTBEGIN####
+dnl -------------------------------------------
+dnl This file is part of eCos, the Embedded Configurable Operating System.
+dnl Copyright (C) 2008 Free Software Foundation, Inc.
+dnl
+dnl eCos is free software; you can redistribute it and/or modify it under
+dnl the terms of the GNU General Public License as published by the Free
+dnl Software Foundation; either version 2 or (at your option) any later version.
+dnl
+dnl eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
+dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+dnl for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License along
+dnl with eCos; if not, write to the Free Software Foundation, Inc.,
+dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+dnl
+dnl As a special exception, if other files instantiate templates or use macros
+dnl or inline functions from this file, or you compile this file and link it
+dnl with other works to produce a work based on this file, this file does not
+dnl by itself cause the resulting work to be covered by the GNU General Public
+dnl License. However the source code for this file must still be made available
+dnl in accordance with section (3) of the GNU General Public License.
+dnl
+dnl This exception does not invalidate any other reasons why a work based on
+dnl this file might be covered by the GNU General Public License.
+dnl -------------------------------------------
+dnl####ECOSGPLCOPYRIGHTEND####
+dnl ====================================================================
+dnl#####DESCRIPTIONBEGIN####
+dnl
+dnl Author(s): bartv
+dnl Contact(s): bartv
+dnl Date: 2005/10/28
+dnl Version: 0.01
+dnl
+dnl####DESCRIPTIONEND####
+dnl ====================================================================
+
+
+AC_INIT(framebuf.c)
+
+dnl Pick up the support files from the top-level acsupport directory.
+AC_CONFIG_AUX_DIR(../../../../../../acsupport)
+
+dnl The current version of the synthetic target is implemented only for
+dnl x86 Linux platforms, so a test is appropriate here. However
+dnl it is not a good idea for the configure script to report an error:
+dnl that would prevent any top-level configury working for other
+dnl platforms. Instead an automake conditional is used to suppress adding
+dnl targets to the build. Unfortunately it is still necessary to
+dnl perform most of the tests or you run into problems with e.g.
+dnl automake's dependency handling.
+
+ECOS_CHECK_BUILD_ne_SRC
+AC_CANONICAL_HOST
+AM_INIT_AUTOMAKE(eCos_synthetic_target_framebuf,0.1,0)
+AM_MAINTAINER_MODE
+AC_PROG_CC
+AC_PROG_CXX
+AC_OBJEXT
+AC_EXEEXT
+ECOS_PROG_MSVC
+ECOS_PROG_STANDARD_COMPILER_FLAGS
+ECOS_PACKAGE_DIRS
+
+case "${host}" in
+ i[[34567]]86-*-linux-gnu* ) SUPPORTED="yes";;
+ * ) SUPPORTED="no"
+esac
+if test "${SUPPORTED}" = "no" ; then
+ AC_MSG_WARN([Synthetic target framebuffer support is only available on x86 Linux hosts])
+fi
+
+AM_CONDITIONAL(SUPPORTED, test "${SUPPORTED}" = "yes")
+
+dnl There is no real need for a config.h file at this time, since the code
+dnl is specific to x86 Linux. This may change in future.
+dnl AM_CONFIG_HEADER(config.h:config.h.in)
+
+AC_OUTPUT(Makefile:Makefile.in)
Index: host/framebuf.c
===================================================================
RCS file: host/framebuf.c
diff -N host/framebuf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/framebuf.c 7 Oct 2008 21:00:31 -0000
@@ -0,0 +1,1484 @@
+//============================================================================
+//
+// framebuf.c
+//
+// A utility program to perform low-level ethernet operations
+//
+//============================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): bartv
+// Contact(s): bartv
+// Date: 2005/10/28
+// Version: 0.01
+// Description:
+// Implementation of a framebuffer device. This script should only ever
+// be run from inside the ecosynth auxiliary.
+//
+// This program is fork'ed by the framebuf.tcl script running inside
+// the synthetic target auxiliary. It is responsible for performing the
+// low-level framebuffer accesses.
+//
+//####DESCRIPTIONEND####
+//============================================================================
+
+// We want to instantiate multiple conversion routines for the different
+// graphics formats, with extensive use of macros for efficiences. Multiple
+// C #include's are used for this.
+#ifndef RENDERFN
+# include <stdio.h>
+# include <stdarg.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include <signal.h>
+# include <limits.h>
+# include <unistd.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <sys/param.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/socket.h>
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <X11/Xlib.h>
+
+// The protocol between host and target is defined by a private
+// target-side header.
+# include "../src/protocol.h"
+
+// ----------------------------------------------------------------------------
+// Globals
+// First the variables needed for X operations. The window is created by
+// Tcl/Tk code and its id is supplied as an argument.
+static Display* host_display;
+static Window host_win = 0;
+static GC host_gc;
+static XImage* host_image;
+
+// R, G & B shifts for the host-side. Used for palette conversion.
+static int host_r_shift;
+static int host_g_shift;
+static int host_b_shift;
+
+// The image data. Only 32bpp is supported.
+// NOTE: this is not 64-bit clean.
+static unsigned int* img_fb;
+
+// This is used for display depths up to and including 16bpp -
+// 256K of static data is irrelevant for a Linux host-side app.
+// 32bpp will have to be handled differently.
+static unsigned int host_palette[65536];
+
+// The current function for rendering target-side data
+static void (*render_fn)(int, int, int, int);
+
+// And palette init and update functions.
+static void (*palette_init_fn)(void);
+static void (*palette_update_fn)(void);
+
+// Positions. With target-side viewports, magnification, and the
+// possibility of windows being resized, this can
+// get very messy.
+//
+// The target-side framebuffer consists of n pages, each of
+// width*height pixels, plus possibly padding at the end of each
+// scanline.
+//
+// img_fb consists of viewport_width*viewport_height pixels.
+// At magnification 1 each pixel is a 32-bit unsigned int, but
+// at higher magnification each pixel takes up mag^2 unsigned
+// ints.
+//
+// win_width and win_height determine the current window dimensions in
+// target pixel units, i.e. ignoring magnification. x_win_width
+// and x_win_height are the same dimensions in X pixels, so
+// mag*win_width. These dimensions are provided by X configure events.
+// They may be smaller, the same size, or larger than the viewport.
+//
+// A coordinate (target_x,target_y) within the current page
+// corresponds to (target_x - viewport_x, target_y - viewport_y).
+// within host_image and within the window.
+//
+// For an X expose event we get X windows coordinates.
+
+// The actually visible window dimensions. If the Tk window gets
+// resized then only part of the image data may be visible. These
+// variables change in response to X configure events.
+static int win_width;
+static int win_height;
+static int x_win_width;
+static int x_win_height;
+
+// Target-side framebuffer.
+//
+// The synth_fb_data structure at the start of the shared memory region.
+static synth_fb_data* shared_fb_data;
+
+// The target-side framebuffer starts at shared_fb_data->framebuf[0].
+// However that is not necessarily where the visible data starts
+// because of page flipping and viewport support. This always points
+// at the top-left corner of visible data.
+static void* target_fb;
+
+// Parameters supplied by the target.
+static int target_id;
+static int target_depth;
+static int target_le;
+static int target_width;
+static int target_height;
+static int target_viewport_width;
+static int target_viewport_height;
+static int target_stride;
+static int target_number_pages;
+static char* target_format;
+
+// Parameters supplied by a host-side configuration file
+static int config_magnification;
+
+// Communication between host and target happens partially through the
+// shared memory region and partially through a fifo, the latter
+// allowing for select(). shared_fb_data already points at the shared
+// memory region.
+static char shm_name[L_tmpnam];
+static int shm_created;
+static int shm_fd;
+static char fifo_t2h_name[L_tmpnam];
+static int fifo_t2h_created;
+static int fifo_t2h_fd;
+static char fifo_h2t_name[L_tmpnam];
+static int fifo_h2t_created;
+static int fifo_h2t_fd;
+
+// An atexit() handler for cleaning up the fifos and shared memory.
+static void
+atexit_handler(void)
+{
+ if (shm_created) {
+ unlink(shm_name);
+ }
+ if (fifo_t2h_created) {
+ unlink(fifo_t2h_name);
+ }
+ if (fifo_h2t_created) {
+ unlink(fifo_h2t_name);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Diagnostics. Warnings and errors are sent up to the I/O auxiliary for
+// display there. Debug output goes straight to stderr
+
+// Set the DEBUG_LEVEL to 0 for no debugging, 3 for maximum debugging.
+#define DEBUG_LEVEL 0
+#define DEBUG(_level_, _str_, ...) \
+ if (_level_ <= DEBUG_LEVEL) { \
+ fprintf(stderr, "%d: " _str_, target_id, ## __VA_ARGS__); \
+ }
+
+#if 0
+static void
+warn(char* fmt, ...)
+{
+ char buf[512];
+ va_list args;
+ va_start(args, fmt);
+
+ sprintf(buf, "Warning (fb%d) : ", target_id);
+ vsnprintf(buf + strlen(buf), 512 - strlen(buf), fmt, args);
+ buf[511] = '\0';
+
+ (void) write(1, buf, strlen(buf));
+}
+#endif
+
+static void
+error(char* fmt, ...)
+{
+ char buf[512];
+ va_list args;
+ va_start(args, fmt);
+
+ sprintf(buf, "Error (fb%d) : ", target_id);
+ vsnprintf(buf + strlen(buf), 512 - strlen(buf), fmt, args);
+ buf[511] = '\0';
+
+ (void) write(1, buf, strlen(buf));
+ exit(1);
+}
+
+// ----------------------------------------------------------------------------
+// Host-side.
+//
+// The main redraw routines. schedule_redraw() can get called as a result of:
+//
+// 1) an X expose event.
+// 2) a message from the Tk code affecting the on/off setting of
+// the framebuffer.
+// 3) a message from the target-side code indicating some of the
+// target-side data has changed, or some other event such as
+// viewport repositioning or page flipping.
+//
+// It just maintains a bounding box. do_redraw() does the real work and
+// is called from inside the main loop.
+
+static int redraw_pending = 0;
+static int x_redraw_x, x_redraw_y, x_redraw_width, x_redraw_height;
+
+static void
+do_redraw(void)
+{
+ while (redraw_pending) {
+ redraw_pending = 0;
+ DEBUG(3, "do_redraw: win_x %d, win_y %d, width %d, height %d\n", x_redraw_x, x_redraw_y, x_redraw_width, x_redraw_height);
+ XPutImage(host_display, host_win, host_gc, host_image, x_redraw_x, x_redraw_y, x_redraw_x, x_redraw_y, x_redraw_width, x_redraw_height);
+ XFlush(host_display);
+ }
+}
+
+static void
+schedule_redraw(int x_new_x, int x_new_y, int x_new_width, int x_new_height)
+{
+ if (! redraw_pending) {
+ redraw_pending = 1;
+ x_redraw_x = x_new_x;
+ x_redraw_y = x_new_y;
+ x_redraw_width = x_new_width;
+ x_redraw_height = x_new_height;
+ } else {
+ if (x_redraw_x > x_new_x) {
+ x_redraw_x = x_new_x;
+ } else {
+ x_new_width += (x_new_x - x_redraw_x);
+ }
+ if (x_redraw_y > x_new_y) {
+ x_redraw_y = x_new_y;
+ } else {
+ x_new_height += (x_new_y - x_redraw_y);
+ }
+ if (x_new_width > x_redraw_width) {
+ x_redraw_width = x_new_width;
+ }
+ if (x_new_height > x_redraw_height) {
+ x_redraw_height = x_new_height;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Utility for blanking the screen
+static void
+blackout(void)
+{
+ memset(img_fb, 0, target_viewport_width * target_viewport_height * sizeof(int) * config_magnification * config_magnification);
+ if (0 != host_win) {
+ schedule_redraw(0, 0, x_win_width, x_win_height);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// This function gets called when the main select() indicates the
+// X server is trying to send some data.
+static void
+handle_X_event(void)
+{
+ XEvent event;
+
+ XNextEvent(host_display, &event);
+ switch(event.type) {
+ case Expose:
+ {
+ // In theory this code should be able to do partial redraws for every
+ // expose event, but that does not seem to work reliably. Instead do a
+ // full redraw, but only for the final event in a sequence.
+ if (0 == event.xexpose.count) {
+ DEBUG(3, "X expose event, x %d, y %d, width %d, height %d\n",
+ event.xexpose.x, event.xexpose.y, event.xexpose.width, event.xexpose.height);
+ schedule_redraw(0, 0, x_win_width, x_win_height);
+ }
+ break;
+ }
+
+ case ConfigureNotify:
+ {
+ DEBUG(2, "X configure notify event, width %d, height %d\n", event.xconfigure.width, event.xconfigure.height);
+ x_win_width = event.xconfigure.width;
+ x_win_height = event.xconfigure.height;
+ win_width = (x_win_width + config_magnification - 1) / config_magnification;
+ win_height = (x_win_height + config_magnification - 1) / config_magnification;
+
+ if (shared_fb_data->display_on && shared_fb_data->blank_on) {
+ (*render_fn)(0 + shared_fb_data->viewport_x, 0 + shared_fb_data->viewport_y, win_width, win_height);
+ } else {
+ blackout();
+ }
+ break;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Conversion routines
+
+// This dummy function is installed to handle draw requests before the
+// window is mapped - until that time the exact render function is unknown.
+static void
+dummy_render_fn(int target_x, int target_y, int width, int height)
+{
+ DEBUG(2, "rendering: target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ DEBUG(2, " : window has not been mapped on to the display yet\n");
+}
+#else // RENDERFN
+
+// These functions get instantiated N times for the N different
+// graphics formats. We need to take the target-side region defined by
+// x/y/width/height, render it into the image data, and then redraw
+// the relevant part of the image data. There is no point rendering more
+// data than is visible.
+
+static void
+RENDERFN(1, TARGET_FORMAT)(int target_x, int target_y, int width, int height)
+{
+ int x, y;
+ int win_x, win_y;
+ unsigned int* img_data;
+ unsigned int colour;
+ TARGET_DATA;
+
+ DEBUG(2, "rendering: target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ if ((0 == host_win) || !shared_fb_data->display_on || !shared_fb_data->blank_on) {
+ DEBUG(2, " : no-op, host_win %d, display_on %d, blank_on %d\n", (int)host_win, shared_fb_data->display_on, shared_fb_data->blank_on);
+ return;
+ }
+ DEBUG(2, " : current viewport x %d, y %d\n", shared_fb_data->viewport_x, shared_fb_data->viewport_y);
+
+ win_x = target_x - shared_fb_data->viewport_x;
+ win_y = target_y - shared_fb_data->viewport_y;
+ if (win_x < 0) {
+ width += win_x;
+ win_x = 0;
+ }
+ if (win_y < 0) {
+ height += win_y;
+ win_y = 0;
+ }
+ if ((win_x + width) > win_width) {
+ width = win_width - win_x;
+ }
+ if ((win_y + height) > win_height) {
+ height = win_height - win_y;
+ }
+ DEBUG(2, " : after clipping, win_x %d, win_y %d, width %d, height %d\n", win_x, win_y, width, height);
+ if ((width < 0) || (height < 0)) {
+ return;
+ }
+
+ img_data = img_fb + (win_y * target_viewport_width) + win_x;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ colour = TARGET_NEXT_COLOUR();
+ *img_data++ = colour;
+ }
+ img_data += (target_viewport_width - width);
+ TARGET_NEXT_LINE();
+ }
+ schedule_redraw(win_x, win_y, width, height);
+}
+
+static void
+RENDERFN(2, TARGET_FORMAT)(int target_x, int target_y, int width, int height)
+{
+ int x, y;
+ int win_x, win_y;
+ unsigned int* img_data0;
+ unsigned int* img_data1;
+ unsigned int colour;
+ TARGET_DATA;
+
+ DEBUG(2, "rendering: target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ if ((0 == host_win) || !shared_fb_data->display_on || !shared_fb_data->blank_on) {
+ DEBUG(2, " : no-op, host_win %d, display_on %d, blank_on %d\n", (int)host_win, shared_fb_data->display_on, shared_fb_data->blank_on);
+ return;
+ }
+ DEBUG(2, " : current viewport x %d, y %d\n", shared_fb_data->viewport_x, shared_fb_data->viewport_y);
+ win_x = target_x - shared_fb_data->viewport_x;
+ win_y = target_y - shared_fb_data->viewport_y;
+ if (win_x < 0) {
+ width += win_x;
+ win_x = 0;
+ }
+ if (win_y < 0) {
+ height += win_y;
+ win_y = 0;
+ }
+ if ((win_x + width) > win_width) {
+ width = win_width - win_x;
+ }
+ if ((win_y + height) > win_height) {
+ height = win_height - win_y;
+ }
+ DEBUG(2, " : after clipping, target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ if ((width < 0) || (height < 0)) {
+ return;
+ }
+
+
+ for (y = 0; y < height; y++) {
+ img_data0 = img_fb + (2 * (win_y + y) * (2 * target_viewport_width)) + (2 * win_x);
+ img_data1 = img_data0 + (2 * target_viewport_width);
+ for (x = 0; x < width; x++) {
+ colour = TARGET_NEXT_COLOUR();
+ *img_data0++ = colour;
+ *img_data0++ = colour;
+ *img_data1++ = colour;
+ *img_data1++ = colour;
+ }
+ TARGET_NEXT_LINE();
+ }
+ schedule_redraw(2 * win_x, 2 * win_y, 2 * width, 2 * height);
+}
+
+static void
+RENDERFN(3, TARGET_FORMAT)(int target_x, int target_y, int width, int height)
+{
+ int x, y;
+ int win_x, win_y;
+ unsigned int* img_data0;
+ unsigned int* img_data1;
+ unsigned int* img_data2;
+ unsigned int colour;
+ TARGET_DATA;
+
+ DEBUG(2, "rendering: target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ if ((0 == host_win) || !shared_fb_data->display_on || !shared_fb_data->blank_on) {
+ DEBUG(2, " : no-op, host_win %d, display_on %d, blank_on %d\n", (int)host_win, shared_fb_data->display_on, shared_fb_data->blank_on);
+ return;
+ }
+ DEBUG(2, " : current viewport x %d, y %d\n", shared_fb_data->viewport_x, shared_fb_data->viewport_y);
+ win_x = target_x - shared_fb_data->viewport_x;
+ win_y = target_y - shared_fb_data->viewport_y;
+ if (win_x < 0) {
+ width += win_x;
+ win_x = 0;
+ }
+ if (win_y < 0) {
+ height += win_y;
+ win_y = 0;
+ }
+ if ((win_x + width) > win_width) {
+ width = win_width - win_x;
+ }
+ if ((win_y + height) > win_height) {
+ height = win_height - win_y;
+ }
+ DEBUG(2, " : after clipping, target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ if ((width < 0) || (height < 0)) {
+ return;
+ }
+
+ for (y = 0; y < height; y++) {
+ img_data0 = img_fb + (3 * (win_y + y) * (3 * target_viewport_width)) + (3 * win_x);
+ img_data1 = img_data0 + (3 * target_viewport_width);
+ img_data2 = img_data1 + (3 * target_viewport_width);
+
+ for (x = 0; x < width; x++) {
+ colour = TARGET_NEXT_COLOUR();
+ *img_data0++ = colour;
+ *img_data0++ = colour;
+ *img_data0++ = colour;
+ *img_data1++ = colour;
+ *img_data1++ = colour;
+ *img_data1++ = colour;
+ *img_data2++ = colour;
+ *img_data2++ = colour;
+ *img_data2++ = colour;
+ }
+ TARGET_NEXT_LINE();
+ }
+ schedule_redraw(3 * win_x, 3 * win_y, 3 * width, 3 * height);
+}
+
+static void
+RENDERFN(4, TARGET_FORMAT)(int target_x, int target_y, int width, int height)
+{
+ int x, y;
+ int win_x, win_y;
+ unsigned int* img_data0;
+ unsigned int* img_data1;
+ unsigned int* img_data2;
+ unsigned int* img_data3;
+ unsigned int colour;
+ TARGET_DATA;
+
+ DEBUG(2, "rendering: target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ if ((0 == host_win) || !shared_fb_data->display_on || !shared_fb_data->blank_on) {
+ DEBUG(2, " : no-op, host_win %d, display_on %d, blank_on %d\n", (int)host_win, shared_fb_data->display_on, shared_fb_data->blank_on);
+ return;
+ }
+ DEBUG(2, " : current viewport x %d, y %d\n", shared_fb_data->viewport_x, shared_fb_data->viewport_y);
+ win_x = target_x - shared_fb_data->viewport_x;
+ win_y = target_y - shared_fb_data->viewport_y;
+ if (win_x < 0) {
+ width += win_x;
+ win_x = 0;
+ }
+ if (win_y < 0) {
+ height += win_y;
+ win_y = 0;
+ }
+ if ((win_x + width) > win_width) {
+ width = win_width - win_x;
+ }
+ if ((win_y + height) > win_height) {
+ height = win_height - win_y;
+ }
+ DEBUG(2, " : after clipping, target_x %d, target_y %d, width %d, height %d\n", target_x, target_y, width, height);
+ if ((width < 0) || (height < 0)) {
+ return;
+ }
+
+ for (y = 0; y < height; y++) {
+ img_data0 = img_fb + (4 * (win_y + y) * (4 * target_viewport_width)) + (4 * win_x);
+ img_data1 = img_data0 + (4 * target_viewport_width);
+ img_data2 = img_data1 + (4 * target_viewport_width);
+ img_data3 = img_data2 + (4 * target_viewport_width);
+
+ for (x = 0; x < width; x++) {
+ colour = TARGET_NEXT_COLOUR();
+ *img_data0++ = colour;
+ *img_data0++ = colour;
+ *img_data0++ = colour;
+ *img_data0++ = colour;
+ *img_data1++ = colour;
+ *img_data1++ = colour;
+ *img_data1++ = colour;
+ *img_data1++ = colour;
+ *img_data2++ = colour;
+ *img_data2++ = colour;
+ *img_data2++ = colour;
+ *img_data2++ = colour;
+ *img_data3++ = colour;
+ *img_data3++ = colour;
+ *img_data3++ = colour;
+ *img_data3++ = colour;
+ }
+ TARGET_NEXT_LINE();
+ }
+ schedule_redraw(4 * win_x, 4 * win_y, 4 * width, 4 * height);
+}
+
+#endif
+#ifndef RENDERFN
+
+# define RENDERFN_AUX(_magnification_, _format_) render_ ## _magnification_ ## _ ## _format_
+# define RENDERFN(_magnification_, _format_) RENDERFN_AUX(_magnification_, _format_)
+
+// ----------------------------------------------------------------------------
+// 1bpp, BE. It is convenient to always render in byte-multiples
+# define TARGET_FORMAT 1BPP_BE
+
+# define TARGET_DATA \
+ unsigned char* target_fb_current; \
+ unsigned int mask; \
+ width += target_x & 0x07; \
+ target_x &= ~0x07; \
+ width = (width + 7) & ~0x07; \
+ target_fb_current = ((unsigned char*)target_fb) + \
+ (target_y * target_stride) + (target_x >> 3); \
+ mask = 0x0080
+
+# define TARGET_NEXT_COLOUR() \
+ ({ \
+ unsigned int next_colour; \
+ next_colour = host_palette[*target_fb_current & mask]; \
+ mask >>= 1; \
+ if (0 == mask) { \
+ target_fb_current += 1; \
+ mask = 0x0080; \
+ } \
+ next_colour; \
+ })
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += target_stride - (width >> 3)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 1bpp, LE
+# define TARGET_FORMAT 1BPP_LE
+
+# define TARGET_DATA \
+ unsigned char* target_fb_current; \
+ unsigned int mask; \
+ width += target_x & 0x07; \
+ target_x &= ~0x07; \
+ width = (width + 7) & ~0x07; \
+ target_fb_current = ((unsigned char*)target_fb) + \
+ (target_y * target_stride) + (target_x >> 3); \
+ mask = 0x0001
+
+# define TARGET_NEXT_COLOUR() \
+ ({ \
+ unsigned int next_colour; \
+ next_colour = host_palette[*target_fb_current & mask]; \
+ mask <<= 1; \
+ if (0x0100 == mask) { \
+ target_fb_current += 1; \
+ mask = 0x0001; \
+ } \
+ next_colour; \
+ })
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += target_stride - (width >> 3)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 2bpp, BE
+# define TARGET_FORMAT 2BPP_BE
+
+# define TARGET_DATA \
+ unsigned char* target_fb_current; \
+ unsigned int mask; \
+ width += target_x & 0x03; \
+ target_x &= ~0x03; \
+ width = (width + 3) & ~0x03; \
+ target_fb_current = ((unsigned char*)target_fb) + \
+ (target_y * target_stride) + (target_x >> 2); \
+ mask = 0x00C0
+
+# define TARGET_NEXT_COLOUR() \
+ ({ \
+ unsigned int next_colour; \
+ next_colour = host_palette[*target_fb_current & mask]; \
+ mask >>= 2; \
+ if (0x00 == mask) { \
+ target_fb_current += 1; \
+ mask = 0x00C0; \
+ } \
+ next_colour; \
+ })
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += target_stride - (width >> 2)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 2bpp, LE
+# define TARGET_FORMAT 2BPP_LE
+
+# define TARGET_DATA \
+ unsigned char* target_fb_current; \
+ unsigned int mask; \
+ width += target_x & 0x03; \
+ target_x &= ~0x03; \
+ width = (width + 3) & ~0x03; \
+ target_fb_current = ((unsigned char*)target_fb) + \
+ (target_y * target_stride) + (target_x >> 2); \
+ mask = 0x0003
+
+# define TARGET_NEXT_COLOUR() \
+ ({ \
+ unsigned int next_colour; \
+ next_colour = host_palette[*target_fb_current & mask]; \
+ mask <<= 2; \
+ if (0x0300 == mask) { \
+ target_fb_current += 1; \
+ mask = 0x0003; \
+ } \
+ next_colour; \
+ })
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += target_stride - (width >> 2)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 4bpp, BE
+# define TARGET_FORMAT 4BPP_BE
+
+# define TARGET_DATA \
+ unsigned char* target_fb_current; \
+ unsigned int mask; \
+ width += target_x & 0x01; \
+ target_x &= ~0x01; \
+ width = (width + 1) & ~0x01; \
+ target_fb_current = ((unsigned char*)target_fb) + \
+ (target_y * target_stride) + (target_x >> 1); \
+ mask = 0x00F0
+
+# define TARGET_NEXT_COLOUR() \
+ ({ \
+ unsigned int next_colour; \
+ next_colour = host_palette[*target_fb_current & mask]; \
+ mask >>= 4; \
+ if (0 == mask) { \
+ target_fb_current += 1; \
+ mask = 0x00F0; \
+ } \
+ next_colour; \
+ })
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += target_stride - (width >> 1)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 4bpp, LE
+# define TARGET_FORMAT 4BPP_LE
+
+# define TARGET_DATA \
+ unsigned char* target_fb_current; \
+ unsigned int mask; \
+ width += target_x & 0x01; \
+ target_x &= ~0x01; \
+ width = (width + 1) & ~0x01; \
+ target_fb_current = ((unsigned char*)target_fb) + \
+ (target_y * target_stride) + (target_x >> 1); \
+ mask = 0x000F
+
+# define TARGET_NEXT_COLOUR() \
+ ({ \
+ unsigned int next_colour; \
+ next_colour = host_palette[*target_fb_current & mask]; \
+ mask <<= 4; \
+ if (0x0F00 == mask) { \
+ target_fb_current += 1; \
+ mask = 0x000F; \
+ } \
+ next_colour; \
+ })
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += target_stride - (width >> 2)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 8bpp, paletted or true colour. In the case of a true colour display the
+// host_palette array will have been filled in appropriately for 332 so
+// conversion to 32-bit true colour again just involves indirecting through
+// the palette, rather than the more expensive bit masking and shifting.
+# define TARGET_FORMAT 8BPP
+
+# define TARGET_DATA \
+ unsigned char* target_fb_current; \
+ target_fb_current = ((unsigned char*)target_fb) + \
+ (target_y * target_stride) + target_x
+
+# define TARGET_NEXT_COLOUR() host_palette[*target_fb_current++]
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += (target_stride - width)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 16bpp. Again this is handled via the host_palette array, suitably
+// initialized for either 555 or 565
+# define TARGET_FORMAT 16BPP
+
+# define TARGET_DATA \
+ unsigned short* target_fb_current; \
+ target_fb_current = ((unsigned short*)target_fb) + \
+ (target_y * (target_stride >> 1)) + target_x
+
+# define TARGET_NEXT_COLOUR() host_palette[*target_fb_current++]
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += ((target_stride >> 1) - width)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 32bpp, 0888, no swapping
+
+# define TARGET_FORMAT 32BPP
+
+# define TARGET_DATA \
+ unsigned int* target_fb_current; \
+ target_fb_current = ((unsigned int*)target_fb) + \
+ (target_y * (target_stride >> 2)) + target_x
+
+# define TARGET_NEXT_COLOUR() *target_fb_current++ & 0x00FFFFFF
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += ((target_stride >> 2) - width)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// 32bpp, 0888, but the host uses 8880.
+# define TARGET_FORMAT 32BPP_SWAPPED
+
+# define TARGET_DATA \
+ unsigned int* target_fb_current; \
+ target_fb_current = ((unsigned int*)target_fb) + \
+ (target_y * (target_stride >> 2)) + target_x
+
+# define TARGET_NEXT_COLOUR() \
+ ({ \
+ unsigned int _colour_ = *target_fb_current++; \
+ _colour_ = \
+ ((_colour_ & 0x000000FF) << 24) | \
+ ((_colour_ & 0x0000FF00) << 16) | \
+ ((_colour_ & 0x00FF0000) << 8); \
+ _colour_; \
+ })
+
+# define TARGET_NEXT_LINE() \
+ target_fb_current += ((target_stride >> 2) - width)
+
+# include "framebuf.c"
+# undef TARGET_FORMAT
+# undef TARGET_DATA
+# undef TARGET_NEXT_COLOUR
+# undef TARGET_NEXT_LINE
+
+// ----------------------------------------------------------------------------
+// Palette management. 8bpp and 16bpp true colour can be initialized
+// statically. 32bpp does not involve the host_palette array at all.
+// Other formats involve dynamic palette updating.
+
+static void
+palette_initialize_8bpp_332(void)
+{
+ static const unsigned char expand2[4] = { 0x00, 0x55, 0xAA, 0xFF };
+ static const unsigned char expand3[8] = { 0x00, 0x20 + 4, 0x40 + 9, 0x60 + 13, 0x80 + 18, 0xA0 + 22, 0xC0 + 27, 0xE0 + 31 };
+ int i;
+ for (i = 0; i < 256; i++) {
+ int r = (i & 0x00E0) >> 5;
+ int g = (i & 0x001C) >> 2;
+ int b = (i & 0x0003) >> 0;
+ host_palette[i] = (expand3[r] << host_r_shift) | (expand3[g] << host_g_shift) | (expand2[b] << host_b_shift);
+ }
+}
+
+static void
+palette_initialize_16bpp_555(void)
+{
+ static const unsigned char expand5[32] = {
+ 0x00 + 0, 0x08 + 0, 0x10 + 0, 0x18 + 0, 0x20 + 1, 0x28 + 1, 0x30 + 1, 0x38 + 1,
+ 0x40 + 2, 0x48 + 2, 0x50 + 2, 0x58 + 2, 0x60 + 3, 0x68 + 3, 0x70 + 3, 0x78 + 3,
+ 0x80 + 4, 0x88 + 4, 0x90 + 4, 0x98 + 4, 0xA0 + 5, 0xA8 + 5, 0xB0 + 5, 0xB8 + 5,
+ 0xC0 + 6, 0xC8 + 6, 0xD0 + 6, 0xD8 + 6, 0xE0 + 7, 0xE8 + 7, 0xF0 + 7, 0xF8 + 7,
+ };
+ int i;
+ for (i = 0; i < 65536; i++) {
+ int r = (i & 0x00007C00) >> 10;
+ int g = (i & 0x000003E0) >> 5;
+ int b = (i & 0x0000001F) >> 0;
+ host_palette[i] = (expand5[r] << host_r_shift) | (expand5[g] << host_g_shift) | (expand5[b] << host_b_shift);
+ }
+}
+
+static void
+palette_initialize_16bpp_565(void)
+{
+ static const unsigned char expand5[32] = {
+ 0x00 + 0, 0x08 + 0, 0x10 + 0, 0x18 + 0, 0x20 + 1, 0x28 + 1, 0x30 + 1, 0x38 + 1,
+ 0x40 + 2, 0x48 + 2, 0x50 + 2, 0x58 + 2, 0x60 + 3, 0x68 + 3, 0x70 + 3, 0x78 + 3,
+ 0x80 + 4, 0x88 + 4, 0x90 + 4, 0x98 + 4, 0xA0 + 5, 0xA8 + 5, 0xB0 + 5, 0xB8 + 5,
+ 0xC0 + 6, 0xC8 + 6, 0xD0 + 6, 0xD8 + 6, 0xE0 + 7, 0xE8 + 7, 0xF0 + 7, 0xF8 + 7,
+ };
+ static const unsigned char expand6[64] = {
+ 0x00 + 0, 0x04 + 0, 0x08 + 0, 0x0C + 0, 0x10 + 0, 0x14 + 0, 0x18 + 0, 0x1C + 0,
+ 0x20 + 0, 0x24 + 0, 0x28 + 0, 0x2C + 0, 0x30 + 0, 0x34 + 0, 0x38 + 0, 0x3C + 0,
+ 0x40 + 1, 0x44 + 1, 0x48 + 1, 0x4C + 1, 0x50 + 1, 0x54 + 1, 0x58 + 1, 0x5C + 1,
+ 0x60 + 1, 0x64 + 1, 0x68 + 1, 0x6C + 1, 0x70 + 1, 0x74 + 1, 0x78 + 1, 0x7C + 1,
+ 0x80 + 2, 0x84 + 2, 0x88 + 2, 0x8C + 2, 0x90 + 2, 0x94 + 2, 0x98 + 2, 0x9C + 2,
+ 0xA0 + 2, 0xA4 + 2, 0xA8 + 2, 0xAC + 2, 0xB0 + 2, 0xB4 + 2, 0xB8 + 2, 0xBC + 2,
+ 0xC0 + 3, 0xC4 + 3, 0xC8 + 3, 0xCC + 3, 0xD0 + 3, 0xD4 + 3, 0xD8 + 3, 0xDC + 3,
+ 0xE0 + 3, 0xE4 + 3, 0xE8 + 3, 0xEC + 3, 0xF0 + 3, 0xF4 + 3, 0xF8 + 3, 0xFC + 3,
+ };
+ int i;
+ for (i = 0; i < 65536; i++) {
+ int r = (i & 0x0000F800) >> 11;
+ int g = (i & 0x000007E0) >> 5;
+ int b = (i & 0x0000001F) >> 0;
+ host_palette[i] = (expand5[r] << host_r_shift) | (expand6[g] << host_g_shift) | (expand5[b] << host_b_shift);
+ }
+}
+
+static void
+palette_update(void)
+{
+ int i, j;
+ unsigned char* target_palette;
+ int r, g, b;
+
+ target_palette = shared_fb_data->palette;
+ for (i = 0; i < (0x01 << target_depth); i++) {
+ r = *target_palette++;
+ g = *target_palette++;
+ b = *target_palette++;
+ host_palette[i] = (r << host_r_shift) | (g << host_g_shift) | (b << host_b_shift);
+ }
+
+ // Make sure the palette is replicated throughout the first 256
+ // entries. That way when rendering <8bpp data we can just mask
+ // the target-side bytes without having to shift.
+ for (j = 0; i < 256; i++, j++) {
+ host_palette[i] = host_palette[j];
+ }
+}
+
+// ----------------------------------------------------------------------------
+// This array is used to map the various display formats etc. on to
+// render functions.
+static struct _render_details {
+ char* rd_format;
+ unsigned int rd_endianness_matters;
+ unsigned int rd_le;
+ void (*rd_palette_init)(void);
+ void (*rd_palette_update)(void);
+ void (*rd_render_fns[4])(int, int, int, int);
+} render_array[] = {
+ // 32BPP must come first
+ { "32BPP_TRUE_0888", 0, 0, NULL, NULL,
+ { &render_1_32BPP, &render_2_32BPP, &render_3_32BPP, &render_4_32BPP }
+ },
+ { "16BPP_TRUE_555", 0, 0, &palette_initialize_16bpp_555, NULL,
+ { &render_1_16BPP, &render_2_16BPP, &render_3_16BPP, &render_4_16BPP }
+ },
+ { "16BPP_TRUE_565", 0, 0, &palette_initialize_16bpp_565, NULL,
+ { &render_1_16BPP, &render_2_16BPP, &render_3_16BPP, &render_4_16BPP }
+ },
+ { "8BPP_TRUE_332", 0, 0, &palette_initialize_8bpp_332, NULL,
+ { &render_1_8BPP, &render_2_8BPP, &render_3_8BPP, &render_4_8BPP }
+ },
+ { "8BPP_PAL888", 0, 0, NULL, &palette_update,
+ { &render_1_8BPP, &render_2_8BPP, &render_3_8BPP, &render_4_8BPP }
+ },
+ { "4BPP_PAL888", 1, 1, NULL, &palette_update,
+ { &render_1_4BPP_LE, &render_2_4BPP_LE, &render_3_4BPP_LE, &render_4_4BPP_LE }
+ },
+ { "4BPP_PAL888", 1, 0, NULL, &palette_update,
+ { &render_1_4BPP_BE, &render_2_4BPP_BE, &render_3_4BPP_BE, &render_4_4BPP_BE }
+ },
+ { "2BPP_PAL888", 1, 1, NULL, &palette_update,
+ { &render_1_2BPP_LE, &render_2_2BPP_LE, &render_3_2BPP_LE, &render_4_2BPP_LE }
+ },
+ { "2BPP_PAL888", 1, 0, NULL, &palette_update,
+ { &render_1_2BPP_BE, &render_2_2BPP_BE, &render_3_2BPP_BE, &render_4_2BPP_BE }
+ },
+ { "1BPP_PAL888", 1, 1, NULL, &palette_update,
+ { &render_1_1BPP_LE, &render_2_1BPP_LE, &render_3_1BPP_LE, &render_4_1BPP_LE }
+ },
+ { "1BPP_PAL888", 1, 0, NULL, &palette_update,
+ { &render_1_1BPP_BE, &render_2_1BPP_BE, &render_3_1BPP_BE, &render_4_1BPP_BE }
+ },
+ { NULL }
+};
+
+
+// ----------------------------------------------------------------------------
+// Communication between host and target
+//
+// When the target wants to wake up the host it sends a single byte down
+// a fifo, typically after having filled in appropriate fields in the
+// shared memory region.
+static void
+handle_target_request(void)
+{
+ unsigned char buf[1];
+ int result;
+
+ result = read(fifo_t2h_fd, buf, 1);
+ if (-1 == result) {
+ if (EINTR == errno) {
+ return;
+ }
+ error("unexpected error %d (%s) reading fifo command from target-side code", errno, strerror(errno));
+ }
+ if (0 == result) {
+ // The target-side must have exited. Do not follow suit yet. Instead
+ // exit only when the I/O auxiliary exits.
+ DEBUG(1, "eCos application has exited\n");
+ close(fifo_t2h_fd);
+ fifo_t2h_fd = -1;
+ return;
+ }
+
+ switch(buf[0]) {
+ case SYNTH_FB_OK:
+ {
+ // The target has finished initializing. This may have
+ // involved filling in the palette
+ DEBUG(1, "target request SYNTH_FB_OK, eCos application has connected.\n");
+ if (palette_update_fn) {
+ (*palette_update_fn)();
+ }
+ break;
+ }
+
+ case SYNTH_FB_SYNC:
+ {
+ // The target has updated part of the display.
+ DEBUG(2, "target request SYNC, x0 %d, y0 %d, x1 %d, y1 %d\n",
+ shared_fb_data->sync_x0, shared_fb_data->sync_y0, shared_fb_data->sync_x1, shared_fb_data->sync_y1);
+ (*render_fn)(shared_fb_data->sync_x0, shared_fb_data->sync_y0,
+ (shared_fb_data->sync_x1 - shared_fb_data->sync_x0),
+ (shared_fb_data->sync_y1 - shared_fb_data->sync_y0));
+ break;
+ }
+
+ case SYNTH_FB_WRITE_PALETTE:
+ {
+ // The target-side palette has been updated. Adjust the
+ // host-side palette and then render the whole window with
+ // the curent colours (unless blanked).
+ DEBUG(1, "target request WRITE_PALETTE\n");
+ if (palette_update_fn) {
+ (*palette_update_fn)();
+ }
+ (*render_fn)(shared_fb_data->viewport_x, shared_fb_data->viewport_y, win_width, win_height);
+ }
+
+ case SYNTH_FB_BLANK:
+ {
+ DEBUG(1, "target request blank, display should be %s\n", shared_fb_data->blank_on ? "on" : "off");
+ if (shared_fb_data->blank_on) {
+ (*render_fn)(shared_fb_data->viewport_x, shared_fb_data->viewport_y, win_width, win_height);
+ } else {
+ blackout();
+ }
+ break;
+ }
+
+ case SYNTH_FB_VIEWPORT:
+ {
+ // Just rerender the whole display as per the new viewport position.
+ DEBUG(1, "target request move viewport to x %d, y %d\n", shared_fb_data->viewport_x, shared_fb_data->viewport_y);
+ (*render_fn)(shared_fb_data->viewport_x, shared_fb_data->viewport_y, win_width, win_height);
+ break;
+ }
+
+ case SYNTH_FB_PAGE_FLIP:
+ {
+ int page_size = target_height * target_stride;
+ DEBUG(1, "target request page flip to page %d\n", shared_fb_data->page_visible);
+ target_fb = (void*)(((char*)&(shared_fb_data->framebuf[0])) + (page_size * shared_fb_data->page_visible));
+ (*render_fn)(shared_fb_data->viewport_x, shared_fb_data->viewport_y, win_width, win_height);
+ break;
+ }
+ }
+
+ // Send a single-byte response back to the target
+ DEBUG(2, "target request handled\n");
+ buf[0] = SYNTH_FB_OK;
+ do {
+ result = write(fifo_h2t_fd, buf, 1);
+ } while ((result < 0) && (errno == EINTR));
+ if (result < 0) {
+ error("unexpected error %d (%s) writing fifo status to target-side code", errno, strerror(errno));
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Communication from the Tcl/Tk script
+static void
+handle_mapped(int winid)
+{
+ Status result;
+ XWindowAttributes attr;
+ XGCValues gc_values;
+ Visual* visual;
+ int i;
+
+ DEBUG(1, "X window %d has been mapped\n", winid);
+ if (0 != (int)host_win) {
+ error(" window has already been mapped.\n");
+ }
+
+ host_win = (Window)winid;
+ result = XGetWindowAttributes(host_display, host_win, &attr);
+ if (0 == result) {
+ error("failed to get window attributes.");
+ }
+ gc_values.graphics_exposures = False;
+ host_gc = XCreateGC(host_display, host_win, GCGraphicsExposures, &gc_values);
+ result = XSelectInput(host_display, host_win, ExposureMask | StructureNotifyMask);
+
+ // The Tcl script has already checked that we are on a 24/32 bit display.
+ // We need to know the colour shifts and possibly adjust the render array.
+ visual = attr.visual;
+ DEBUG(1, " red_mask 0x%08lx, green_mask 0x%08lx, blue_mask 0x%08lx\n", visual->red_mask, visual->green_mask, visual->blue_mask);
+ if ((0x00FF0000 == visual->red_mask) && (0x0000FF00 == visual->green_mask) && (0x000000FF == visual->blue_mask)) {
+ // 0888, nothing special needed
+ host_r_shift = 16;
+ host_g_shift = 8;
+ host_b_shift = 0;
+ } else if ((0x0000FF00 == visual->red_mask) && (0x00FF0000 == visual->green_mask) && (0xFF000000 == visual->blue_mask)) {
+ // 8880
+ host_r_shift = 8;
+ host_g_shift = 16;
+ host_b_shift = 24;
+ render_array[0].rd_render_fns[0] = &render_1_32BPP_SWAPPED;
+ render_array[0].rd_render_fns[1] = &render_2_32BPP_SWAPPED;
+ render_array[0].rd_render_fns[2] = &render_3_32BPP_SWAPPED;
+ render_array[0].rd_render_fns[3] = &render_4_32BPP_SWAPPED;
+ }
+
+ // Time to figure out which render function etc. to use.
+ render_fn = (void (*)(int, int, int, int)) NULL;
+ for (i = 0; render_array[i].rd_format; i++) {
+ if ((0 == strcmp(render_array[i].rd_format, target_format)) &&
+ (!render_array[i].rd_endianness_matters || (render_array[i].rd_le == target_le))) {
+
+ render_fn = render_array[i].rd_render_fns[config_magnification - 1];
+ palette_init_fn = render_array[i].rd_palette_init;
+ palette_update_fn = render_array[i].rd_palette_update;
+ break;
+ }
+ }
+ if (NULL == render_fn) {
+ error("Target format not supported.");
+ }
+
+ // Now it is possible to create the XImage structure, the fifos,
+ // and the shared memory region for interaction with the target.
+ // The XImage needs to be large enough for the viewport. That may
+ // be larger than the actually visible window, but the window may
+ // get resized.
+ host_image = XCreateImage(host_display, visual,
+ 24, // image depth. 24 bits of colour info.
+ ZPixmap,
+ 0, // offset
+ NULL, // data, filled in later
+ target_viewport_width * config_magnification,
+ target_viewport_height * config_magnification,
+ 32, // bitmap_pad
+ 0 // bytes_per_line, calculated by X
+ );
+ if (NULL == host_image) {
+ error("Failed to allocate XImage structure.");
+ }
+ host_image->data = (void*)img_fb;
+
+ x_win_width = attr.width;
+ x_win_height = attr.height;
+ win_width = (x_win_width + config_magnification - 1) / config_magnification;
+ win_height = (x_win_height + config_magnification - 1) / config_magnification;
+ DEBUG(1, " mapped window, X width %d, X height %d, win width %d, win height %d, blank on %d, display on %d\n",
+ x_win_width, x_win_height, win_width, win_height, shared_fb_data->blank_on, shared_fb_data->display_on);
+
+ // The palette may get initialized locally or by the target, depending
+ // on the mode.
+ if (palette_init_fn) {
+ (*palette_init_fn)();
+ }
+ if (palette_update_fn) {
+ (*palette_update_fn)();
+ }
+ if (shared_fb_data->display_on && shared_fb_data->blank_on) {
+ (*render_fn)(shared_fb_data->viewport_x, shared_fb_data->viewport_y, win_width, win_height);
+ } else {
+ // Just draw the initial blank screen.
+ blackout();
+ }
+}
+
+static void
+handle_auxiliary_request(void)
+{
+ synth_fb_auxiliary_request req;
+ int result;
+
+ result = read(0, &req, sizeof(synth_fb_auxiliary_request));
+ if (result <= 0) {
+ // The I/O auxiliary has terminated, so assume the window has gone as well.
+ exit(0);
+ }
+ DEBUG(2, "handle_auxiliary request %d\n", req.command);
+ switch (req.command) {
+ case SYNTH_FB_AUX_MAPPED:
+ {
+ handle_mapped(req.arg1);
+ break;
+ }
+ case SYNTH_FB_AUX_ON:
+ {
+ // This is used when the target-side switches the display
+ // off and back on, rather than just blanking it. Treat it
+ // the same as blanking.
+ DEBUG(1, "Target has switched the display on\n");
+ shared_fb_data->display_on = 1;
+ (*render_fn)(shared_fb_data->viewport_x, shared_fb_data->viewport_y, win_width, win_height);
+ break;
+ }
+ case SYNTH_FB_AUX_OFF:
+ {
+ DEBUG(1, "Target has switched the display off\n");
+ shared_fb_data->display_on = 0;
+ blackout();
+ break;
+ }
+ case SYNTH_FB_AUX_REDRAW:
+ {
+ DEBUG(1, "Auxiliary has requested a redraw\n");
+ schedule_redraw(0, 0, x_win_width, x_win_height);
+ }
+ }
+ DEBUG(2, "handle_auxiliary request done\n");
+}
+
+// Report an error to ecosynth during initialization. This means a
+// single byte 0, followed by a string.
+static void
+report_init_error(char* msg)
+{
+ write(1, "0", 1);
+ write(1, msg, strlen(msg));
+ close(1);
+ exit(0);
+}
+
+// ----------------------------------------------------------------------------
+int
+main(int argc, char** argv)
+{
+ int size;
+ fd_set read_fds;
+ int max_fd;
+
+ atexit(&atexit_handler);
+ signal(SIGPIPE, SIG_IGN);
+
+ if (12 != argc) {
+ report_init_error("Incorrect number of arguments.");
+ }
+ target_id = (int) strtoul(argv[1], NULL, 0);
+ target_depth = (int) strtoul(argv[2], NULL, 0);
+ target_le = (int) strtoul(argv[3], NULL, 0);
+ target_width = (int) strtoul(argv[4], NULL, 0);
+ target_height = (int) strtoul(argv[5], NULL, 0);
+ target_viewport_width = (int) strtoul(argv[6], NULL, 0);
+ target_viewport_height = (int) strtoul(argv[7], NULL, 0);
+ target_stride = (int) strtoul(argv[8], NULL, 0);
+ target_number_pages = (int) strtoul(argv[9], NULL, 0);
+ target_format = argv[10];
+ config_magnification = (int) strtoul(argv[11], NULL, 0);
+
+ if ((target_depth != 1) && (target_depth != 2) && (target_depth != 4) && (target_depth != 8) && (target_depth != 16) && (target_depth != 32)) {
+ report_init_error("Invalid target depth.");
+ }
+ if ((target_width < 16) || (target_width > 4096)) {
+ report_init_error("Invalid target width.");
+ }
+ if ((target_height < 16) || (target_height > 4096)) {
+ report_init_error("Invalid target height.");
+ }
+ if ((target_viewport_width < 16) || (target_viewport_width > target_width)) {
+ report_init_error("Invalid target viewport width.");
+ }
+ if ((target_viewport_height < 16) || (target_viewport_height > target_height)) {
+ report_init_error("Invalid target viewport height.");
+ }
+ if ((target_number_pages < 1) || (target_number_pages > 4)) {
+ report_init_error("Invalid target number of pages.");
+ }
+ if ((config_magnification < 1) || (config_magnification > 4)) {
+ report_init_error("Invalid config magnification.");
+ }
+
+ host_display = XOpenDisplay(NULL);
+ if (NULL == host_display) {
+ report_init_error("Failed to open X display.");
+ }
+ img_fb = (unsigned int*) malloc(target_viewport_width * target_viewport_height * sizeof(int) * config_magnification * config_magnification);
+ if (NULL == img_fb) {
+ report_init_error("Failed to allocate XImage data.");
+ }
+ blackout();
+
+ // Use of tmpnam() is generally discouraged and generates a linker
+ // warning, but only three temporary file names are needed and
+ // there are no root privileges involved so security is not a big
+ // issue. mkstemp() cannot easily be used with fifos.
+ if (NULL == tmpnam(fifo_t2h_name)) {
+ report_init_error("Failed to create unique file name for target->host fifo.");
+ }
+ if (0 != mkfifo(fifo_t2h_name, S_IRUSR | S_IWUSR)) {
+ report_init_error("Failed to create target->host fifo.");
+ }
+ // Opening O_RDONLY or O_WRONLY will result in blocking until the
+ // other end is open as well, which is not what is wanted here.
+ // Instead we use the Linux feature of opening with O_RDWR which
+ // gives non-blocking behaviour.
+ fifo_t2h_created = 1;
+ fifo_t2h_fd = open(fifo_t2h_name, O_RDWR);
+ if (-1 == fifo_t2h_fd) {
+ report_init_error("Failed to open target->host fifo.");
+ }
+ if (NULL == tmpnam(fifo_h2t_name)) {
+ report_init_error("Failed to create unique file name for host->target fifo.");
+ }
+ if (0 != mkfifo(fifo_h2t_name, S_IRUSR | S_IWUSR)) {
+ report_init_error("Failed to create host->target fifo.");
+ }
+ fifo_h2t_created = 1;
+ fifo_h2t_fd = open(fifo_h2t_name, O_RDWR);
+ if (-1 == fifo_h2t_fd) {
+ report_init_error("Failed to open target->host fifo.");
+ }
+
+ size = sizeof(synth_fb_data) + (target_height * target_stride * target_number_pages);
+ if (NULL == tmpnam(shm_name)) {
+ report_init_error("Failed to create unique file name for shared memory.");
+ }
+ shm_fd = open(shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ if (shm_fd < 0) {
+ report_init_error("Failed to open file for shared memory region.");
+ }
+ shm_created = 1;
+ if (ftruncate(shm_fd, size) < 0) {
+ report_init_error("Failed to set shared memory file size.");
+ }
+
+ shared_fb_data = (synth_fb_data*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
+ if (shared_fb_data == (synth_fb_data*)MAP_FAILED) {
+ report_init_error("Failed to mmap shared memory file.");
+ }
+ target_fb = &(shared_fb_data->framebuf[0]);
+
+ shared_fb_data->connected = 0;
+ shared_fb_data->fifo_to_framebuf = -1;
+ shared_fb_data->fifo_from_framebuf = -1;
+ shared_fb_data->devid = target_id;
+ shared_fb_data->sync_x0 = 0;
+ shared_fb_data->sync_y0 = 0;
+ shared_fb_data->sync_x1 = target_viewport_width;
+ shared_fb_data->sync_y1 = target_viewport_height;
+ shared_fb_data->display_on = 0;
+ shared_fb_data->blank_on = 1;
+ shared_fb_data->viewport_x = 0;
+ shared_fb_data->viewport_y = 0;
+ shared_fb_data->page_visible = 0;
+
+ render_fn = &dummy_render_fn;
+ msync(shared_fb_data, size, MS_SYNC);
+
+ // Everything seems to be in order. Report back to the auxiliary.
+ {
+ char buf[513];
+ if ((strlen(shm_name) + strlen(fifo_t2h_name) + strlen(fifo_h2t_name) + 3) > 512) {
+ report_init_error("Temporary path names too long.");
+ }
+ buf[0] = '1';
+ strcpy(&(buf[1]), shm_name);
+ strcat(&(buf[1]), ";");
+ strcat(&(buf[1]), fifo_t2h_name);
+ strcat(&(buf[1]), ";");
+ strcat(&(buf[1]), fifo_h2t_name);
+ strcat(&(buf[1]), ";");
+ write(1, buf, 2 + strlen(&(buf[1])));
+ }
+
+ // Now we just loop, processing events. We want to select on file descriptor
+ // 0 from the auxiliary, the X file descriptor, and the fifo t2h descriptor.
+ // The latter may go away. X should never go away, and if the auxiliary goes
+ // away we exit immediately.
+ max_fd = MAX(ConnectionNumber(host_display), fifo_t2h_fd);
+ while ( 1 ) {
+ while (XPending(host_display) > 0) {
+ handle_X_event();
+ }
+ FD_ZERO(&read_fds);
+ FD_SET(0, &read_fds);
+ FD_SET(ConnectionNumber(host_display), &read_fds);
+ if (-1 != fifo_t2h_fd) {
+ FD_SET(fifo_t2h_fd, &read_fds);
+ }
+ DEBUG(3, "framebuf main loop: selecting on 0x%08x\n", *(int*)&read_fds);
+ do_redraw();
+ if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) >= 0) {
+ if (FD_ISSET(0, &read_fds)) {
+ DEBUG(2, "framebuf main loop: auxiliary request\n");
+ handle_auxiliary_request();
+ }
+ if ((-1 != fifo_t2h_fd) && FD_ISSET(fifo_t2h_fd, &read_fds)) {
+ DEBUG(2, "framebuf main loop: target request\n");
+ handle_target_request();
+ }
+ if (FD_ISSET(ConnectionNumber(host_display), &read_fds)) {
+ DEBUG(3, "framebuf main loop: X request\n");
+ (void)XEventsQueued(host_display, QueuedAfterReading);
+ }
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+}
+#endif // INSTANTIATE_CONVERTER
Index: host/framebuf.tcl
===================================================================
RCS file: host/framebuf.tcl
diff -N host/framebuf.tcl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/framebuf.tcl 7 Oct 2008 21:00:31 -0000
@@ -0,0 +1,373 @@
+# {{{ Banner
+
+# ============================================================================
+#
+# framebuf.tcl
+#
+# Framebuffer support for the eCos synthetic target I/O auxiliary
+#
+# ============================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+# -------------------------------------------
+# This file is part of eCos, the Embedded Configurable Operating System.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# eCos 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 2 or (at your option) any later version.
+#
+# eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# As a special exception, if other files instantiate templates or use macros
+# or inline functions from this file, or you compile this file and link it
+# with other works to produce a work based on this file, this file does not
+# by itself cause the resulting work to be covered by the GNU General Public
+# License. However the source code for this file must still be made available
+# in accordance with section (3) of the GNU General Public License.
+#
+# This exception does not invalidate any other reasons why a work based on
+# this file might be covered by the GNU General Public License.
+# -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ============================================================================
+# #####DESCRIPTIONBEGIN####
+#
+# Author(s): bartv
+# Contact(s): bartv
+# Date: 2005/10/28
+# Version: 0.01
+# Description:
+# Implementation of a framebuffer device. This script should only ever
+# be run from inside the ecosynth auxiliary.
+#
+# ####DESCRIPTIONEND####
+# ============================================================================
+
+# }}}
+
+# Overview
+#
+# The synthetic framebuffer package supports up to four framebuffer
+# devices. The eCos framebuffers are displayed by a separate C program
+# framebuf which gets spawned by this script. framebuf operates using
+# low-level X library calls. Doing the drawing inside Tcl/Tk would be
+# far too slow, and trying to draw directly to an X display from inside
+# an eCos application would be complicated.
+#
+# When an eCos framebuffer is switched on for the first time it will
+# result in a device instantiation in this script. A suitable frame
+# is created, and once it is mapped the framebuf program is started.
+# The device data string from the target includes a protocol version
+# number, target display depth, width and height, display format, etc.
+
+namespace eval framebuf {
+
+ # Protocol between the target-side and the auxiliary, as per protocol.h
+ variable SYNTH_FB_INIT 0x01
+ variable SYNTH_FB_ABORT 0x02
+ variable SYNTH_FB_ON 0x03
+ variable SYNTH_FB_OFF 0x04
+
+ # Protocol between the auxiliary and the framebuf program
+ variable SYNTH_FB_AUX_MAPPED 0x01
+ variable SYNTH_FB_AUX_ON 0x02
+ variable SYNTH_FB_AUX_OFF 0x03
+ variable SYNTH_FB_AUX_REDRAW 0x04
+
+ variable init_ok 1
+ array set settings []
+
+ # Set DEBUG_LEVEL to between 0 for no debug output, 2 for maximum
+ variable DEBUG_LEVEL 0
+ proc DEBUG { level devid msg } {
+ if { $level < $framebuf::DEBUG_LEVEL } {
+ if { [info exists framebuf::settings($devid,fbid)] } {
+ set fbid $framebuf::settings($devid,fbid)
+ } else {
+ set fbid "<unknown>"
+ }
+ puts -nonewline stderr "framebuf.tcl (fb$fbid): $msg"; flush stderr
+ }
+ }
+
+ # One-off initialization.
+ variable install_dir $synth::device_install_dir
+ variable framebuf_executable [file join $framebuf::install_dir "framebuf"]
+ if { ! [file exists $framebuf_executable] } {
+ synth::report_error "Framebuffer device, framebuf executable has not been installed in $framebuf::install_dir.\n"
+ set init_ok 0
+ } elseif { ! [file executable $framebuf_executable] } {
+ synth::report_error "Framebuffer device, installed program $framebuf_executable is not executable.\n"
+ set init_ok 0
+ }
+
+ if { ! [file exists [file join $framebuf::install_dir "framebuf_icon.xbm"]] ||
+ ! [file exists [file join $framebuf::install_dir "framebuf_iconmask.xbm"]] } {
+ synth::report_error "Framebuffer device, bitmap support files have not been installed.\n"
+ set init_ok =
+ }
+
+ # A default function for creating the Tk frame for an eCos
+ # framebuffer device. Framebuffer 0 is usually part of the
+ # main window, unless it would take up too much space.
+ # Unfortunately at this stage of initialization there is no
+ # easy way to work out how big . is going to be so some
+ # hard-wired numbers are used instead.
+ proc default_create_frame { fbid magnification depth little_endian width height viewport_width viewport_height stride number_pages format } {
+
+ puts "default_create_frame $fbid mag $magnification width $viewport_width height $viewport_height"
+ set viewport_width [expr $viewport_width * $magnification]
+ set viewport_height [expr $viewport_height * $magnification]
+ puts "default_create_frame $fbid mag $magnification width $viewport_width height $viewport_height"
+
+ if { (0 == $fbid) && ($viewport_height <= 240) && ($viewport_width <= 640) } {
+ frame .fb$fbid -container 1 -height $viewport_height -width $viewport_width
+ pack .fb$fbid -in .main.n -expand 0 -anchor nw
+ return .fb$fbid
+ } else {
+ toplevel .fb$fbid
+ frame .fb$fbid.frame -container 1 -height $viewport_height -width $viewport_width
+ pack .fb$fbid.frame -side top -expand 0 -anchor nw
+ wm title .fb$fbid "Synth FB[set fbid] [set width]*[set height]*[set depth]bpp"
+ wm iconbitmap .fb$fbid "@[file join $framebuf::install_dir framebuf_icon.xbm]"
+ wm iconmask .fb$fbid "@[file join $framebuf::install_dir framebuf_iconmask.xbm]"
+ wm iconname .fb$fbid "Synth FB[set fbid]"
+ wm protocol .fb$fbid WM_DELETE_WINDOW { }
+ return .fb$fbid.frame
+ }
+ }
+
+ variable create_frame_proc default_create_frame
+
+ if { [synth::tdf_has_option "framebuf" "create_frame_proc"] } {
+ set framebuf::create_frame_proc [synth::tdf_get_option "framebuf" "create_frame_proc"]
+ }
+
+ # Optional magnification
+ for { set i 0 } { $i < 4 } { incr i } {
+ set framebuf::settings(fb$i,magnification) 1
+ if { [synth::tdf_has_option "framebuf" "fb[set i]_magnification"] } {
+ set magnification [synth::tdf_get_option "framebuf" "fb[set i]_magnification"]
+ if { ! [string is integer -strict $magnification] } {
+ synth::report_error [concat
+ "Framebuf device, invalid value in target definition file $synth::target_definition\n"
+ " fb[set i]_magnification should be a simple integer, not $magnification\n"]
+ set init_ok 0
+ } elseif { ($magnification < 1) || ($magnification > 4) } {
+ synth::report_error [concat
+ "Framebuf device, invalid value in target definition file $synth::target_definition\n"
+ " fb[set i]_magnification should be 1, 2, 3 or 4.\n"]
+ set init_ok 0
+ } else {
+ set framebuf::settings(fb$i,magnification) $magnification
+ }
+ }
+ }
+
+ proc handle_framebuf_reply { devid } {
+ DEBUG 1 $devid "reading reply from framebuf program\n"
+ if { ! $framebuf::settings($devid,got_reply) } {
+ # The first message from the framebuf program indicates success+pathnames or failure+message
+ # This will wake up a vwait in the instantiate proc
+ set framebuf::settings($devid,reply) [read $framebuf::settings($devid,fd)]
+ set framebuf::settings($devid,got_reply) 1
+ } else {
+ # The framebuf program sends back no other data, but may issue warnings or failures
+ synth::report [read $framebuf::settings($devid,fd)]
+ }
+ }
+
+ proc send_framebuf_request { devid code arg1 arg2 } {
+ # FIXME handle endianness
+ set auxiliary_request [binary format iii $code $arg1 $arg2]
+ puts -nonewline $framebuf::settings($devid,fd) $auxiliary_request
+ flush $framebuf::settings($devid,fd)
+ }
+
+ proc handle_ecos_request { devid reqcode arg1 arg2 reqdata reqlen reply_len } {
+ DEBUG 1 $devid "got request $reqcode from eCos application\n"
+ if { $framebuf::SYNTH_FB_INIT == $reqcode } {
+ # This request is used after instantiation to get hold of the connectivity information
+ synth::send_reply 1 [string length $framebuf::settings($devid,connectivity)] $framebuf::settings($devid,connectivity)
+ } elseif { $framebuf::SYNTH_FB_ABORT == $reqcode } {
+ # FIXME: kill off the framebuf program? Destroy the window/frame?
+ synth::report_error "framebuf: eCos application has failed to connect to host-side framebuf program"
+ synth::report_error " : graphical display is not operational"
+ } elseif { $framebuf::SYNTH_FB_ON == $reqcode } {
+ send_framebuf_request $devid $framebuf::SYNTH_FB_AUX_ON 0 0
+ } elseif { $framebuf::SYNTH_FB_OFF == $reqcode } {
+ send_framebuf_request $devid $framebuf::SYNTH_FB_AUX_OFF 0 0
+ } else {
+ synth::report_error "framebuf: got invalid request $reqcode from eCos application"
+ }
+ }
+
+ proc mapped { devid } {
+ DEBUG 1 $devid "frame has been mapped\n"
+ bind $framebuf::settings($devid,frame) <Map> ""
+ send_framebuf_request $devid $framebuf::SYNTH_FB_AUX_MAPPED [winfo id $framebuf::settings($devid,frame)] 0
+ # This should not be necessary, but sometimes there are problems
+ # with an initial XPutImage() not actually drawing anything.
+ after 250 framebuf::send_framebuf_request $devid $framebuf::SYNTH_FB_AUX_REDRAW 0 0
+ }
+
+ proc instantiate { devid name data } {
+
+ DEBUG 1 $devid "instantiate devid $devid, name $name, data $data\n"
+
+ if { ! $synth::flag_gui } {
+ # If we are not running under a windowing system we cannot
+ # show the framebuffer data. Just stuck to the default
+ # memory framebuffer.
+ return ""
+ }
+
+ if { [info exists framebuf::settings($name,id)] } {
+ synth::report_error "Framebuf device: attempt to create several $name instances\n"
+ return ""
+ }
+
+ # Check that the framebuf program can actually handle this display.
+ set depth [winfo depth .]
+ if { (24 != $depth) && (32 != $depth) } {
+ synth::report_error "Framebuf device: requires 24bpp or 32bpp X display\n"
+ return ""
+ }
+ set visual [winfo visual .]
+ if { ![string equal "truecolor" $visual] && ![string equal "directcolor" $visual] } {
+ synth::report_error "Framebuf device: requires a truecolor or directcolor X display\n"
+ return ""
+ }
+
+ # Data is a set of comma-separated parameters, mostly numeric,
+ # describing the desired framebuffer device. The first number
+ # is a protocol number as per ../src/protocol.h
+ set junk ""
+ set protocol 0
+ if { ! [regexp -- {^(\d*),.*} $data junk protocol] } {
+ synth::report_error "Framebuf device: missing protocol number for device $name\n"
+ return ""
+ }
+ if { $protocol != 1 } {
+ synth::report_error "Framebuf device: protocol mismatch\n \
+ Target uses protocol version $protocol\n \
+ Host is only up to version 1\n"
+ return ""
+ }
+ set framebuf::settings($devid,name) $name
+ set result [regexp -- {^(\d*),(\d*),(\d*),(\d*),(\d*),(\d*),(\d*),(\d*),(\d*),(\d*),(.*)$} $data junk protocol \
+ framebuf::settings($devid,fbid) \
+ framebuf::settings($devid,depth) \
+ framebuf::settings($devid,little_endian) \
+ framebuf::settings($devid,width) \
+ framebuf::settings($devid,height) \
+ framebuf::settings($devid,viewport_width) \
+ framebuf::settings($devid,viewport_height) \
+ framebuf::settings($devid,stride) \
+ framebuf::settings($devid,number_pages) \
+ framebuf::settings($devid,format)]
+ if { ! $result } {
+ synth::report_error "Framebuf device: invalid parameter string $data\n"
+ return ""
+ }
+ set framebuf::settings($devid,magnification) $framebuf::settings(fb$framebuf::settings($devid,fbid),magnification)
+
+ # Spawn the framebuf process. Its stdin and stdout are pipes
+ # connected to ecosynth. Its stderr is redirected to the current
+ # tty for debugging/diagnostics.
+ set cmd "|$framebuf::framebuf_executable "
+ append cmd "$framebuf::settings($devid,fbid) "
+ append cmd "$framebuf::settings($devid,depth) "
+ append cmd "$framebuf::settings($devid,little_endian) "
+ append cmd "$framebuf::settings($devid,width) "
+ append cmd "$framebuf::settings($devid,height) "
+ append cmd "$framebuf::settings($devid,viewport_width) "
+ append cmd "$framebuf::settings($devid,viewport_height) "
+ append cmd "$framebuf::settings($devid,stride) "
+ append cmd "$framebuf::settings($devid,number_pages) "
+ append cmd "$framebuf::settings($devid,format) "
+ append cmd "$framebuf::settings($devid,magnification) "
+
+ DEBUG 1 $devid "spawning framebuf program : $cmd\n"
+ if { [catch { set framebuf::settings($devid,fd) [open "$cmd 2>/dev/tty" "w+"] } message] } {
+ synth::report_error "Failed to spawn framebuf process for device $name\n $message"
+ return ""
+ }
+ set framebuf::settings($devid,reply) 0
+ set framebuf::settings($devid,got_reply) 0
+ fconfigure $framebuf::settings($devid,fd) -translation binary -blocking 0
+ fileevent $framebuf::settings($devid,fd) readable "framebuf::handle_framebuf_reply $devid"
+
+ # Now wait for the framebuf device to initialize. It should send back a single byte,
+ # 0 for failure followed by an error string, 1 for success followed by a string with
+ # the connectivity information.
+ DEBUG 1 $devid "waiting for initial reply from framebuf program\n"
+ vwait framebuf::settings($devid,reply)
+ if { "" == $framebuf::settings($devid,reply) } {
+ synth::report_error "framebuf process for device $name exited unexpectedly.\n"
+ catch { close $framebuf::settings($devid,fd) }
+ return ""
+ }
+ set code [string index $framebuf::settings($devid,reply) 0]
+ if { "0" == $code } {
+ synth::report_error "framebuf process was unable to initialize eCos device $name\n $message"
+ catch { close $framebuf::settings($devid,fd) }
+ return ""
+ }
+ if { "1" != $code } {
+ synth::report_error "Unexpected response $code from framebuf process for eCos device $name\n"
+ catch { close $framebuf::settings($devid,fd) }
+ return ""
+ }
+ set framebuf::settings($devid,connectivity) [string range $framebuf::settings($devid,reply) 1 end]
+
+ # Now the the framebuf program is up and running, create the frame.
+ # Doing this earlier could result in spurious frames appearing if
+ # the framebuf program failed, and also causes timing problems
+ # between the <Map> binding and the framebuf program being ready.
+ DEBUG 1 $devid "invoking create_frame procedure $framebuf::create_frame_proc\n"
+ set framebuf::settings($devid,frame) \
+ [$framebuf::create_frame_proc \
+ $framebuf::settings($devid,fbid) \
+ $framebuf::settings($devid,magnification) \
+ $framebuf::settings($devid,depth) \
+ $framebuf::settings($devid,little_endian) \
+ $framebuf::settings($devid,width) \
+ $framebuf::settings($devid,height) \
+ $framebuf::settings($devid,viewport_width) \
+ $framebuf::settings($devid,viewport_height) \
+ $framebuf::settings($devid,stride) \
+ $framebuf::settings($devid,number_pages) \
+ $framebuf::settings($devid,format) \
+ ]
+ DEBUG 1 $devid "frame is $framebuf::settings($devid,frame)\n"
+ if { "" == $framebuf::settings($devid,frame) } {
+ return ""
+ }
+
+ # Everything appears to be up and running. When the frame becomes visible,
+ # inform the framebuf program.
+ if { [winfo ismapped $framebuf::settings($devid,frame)] } {
+ framebuf::mapped $devid
+ } else {
+ bind $framebuf::settings($devid,frame) <Map> "framebuf::mapped $devid"
+ }
+ DEBUG 1 $devid "instantiate succeeded, connectivity $framebuf::settings($devid,connectivity)\n"
+
+ return framebuf::handle_ecos_request
+ }
+}
+
+if { $framebuf::init_ok } {
+ return framebuf::instantiate
+} else {
+ synth::report "Framebuffer cannot be instantiated, initialization failed.\n"
+ return ""
+}
Index: host/framebuf.tdf
===================================================================
RCS file: host/framebuf.tdf
diff -N host/framebuf.tdf
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/framebuf.tdf 7 Oct 2008 21:00:31 -0000
@@ -0,0 +1,37 @@
+# Target definition file fragment for framebuffer devices.
+#
+# The main support available is for controlled creation
+# of the Tk frames in which the eCos framebuffer data will
+# be displayed. By default the main framebuf.tcl script will
+# create the
+
+proc my_framebuf_create_frame { id magnification depth little_endian width height viewport_width viewport_height stride number_pages format} {
+
+ toplevel .ecosfb$id
+ wm title .ecosfb$id "eCos FB[set id]: $width*$height*\#depth"
+ wm iconbitmap .ecosfb$id $framebuf::image_framebuf_icon
+ wm iconmask .ecosfb$id $framebuf::image_framebufmask_icon
+ wm protocol .ecosfb$id ""
+
+ frame .ecosfb$id.frame -container 1 -height [expr $magnification * $viewport_height] -width [expr $magnification * $viewport_width]
+ pack .ecosfb$id.frame -side top -expand 0
+
+ return .ecosfb$id.frame
+}
+
+synth_device framebuf {
+
+ # Customize how the eCos framebuffer appears on the X display.
+ # The argument should be a function which takes a long list of
+ # arguments, as above, and returns a Tk frame id. Spawning the
+ # C program is still the responsibility of the main framebuf.tcl
+ # script.
+ create_frame_proc my_framebuf_create_frame
+
+ # Optional magnification for all four permitted framebuffer
+ # devices. Magnification can be 1, 2, 3 or 4
+ # fb0_magnification 2
+ # fb1_magnification 4
+ # fb2_magnification 3
+ # fb4_magnification 1
+}
Index: host/framebuf_icon.xbm
===================================================================
RCS file: host/framebuf_icon.xbm
diff -N host/framebuf_icon.xbm
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/framebuf_icon.xbm 7 Oct 2008 21:00:31 -0000
@@ -0,0 +1,10 @@
+#define framebuf_icon_width 40
+#define framebuf_icon_height 16
+static unsigned char framebuf_icon_bits[] = {
+ 0xfc, 0xff, 0xff, 0xff, 0x3f, 0x06, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00,
+ 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x54, 0xba, 0xe2,
+ 0x86, 0x21, 0x55, 0x92, 0x22, 0x8a, 0x21, 0xd4, 0x92, 0x22, 0x8a, 0xc1,
+ 0xd4, 0x92, 0xe3, 0x86, 0x01, 0x49, 0x93, 0x22, 0x8a, 0x01, 0x49, 0x93,
+ 0x22, 0x8a, 0x21, 0x49, 0x92, 0x22, 0x8a, 0xc1, 0x48, 0x92, 0x22, 0x86,
+ 0x01, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x00,
+ 0x00, 0x00, 0x60, 0xfc, 0xff, 0xff, 0xff, 0x3f};
Index: host/framebuf_iconmask.xbm
===================================================================
RCS file: host/framebuf_iconmask.xbm
diff -N host/framebuf_iconmask.xbm
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ host/framebuf_iconmask.xbm 7 Oct 2008 21:00:31 -0000
@@ -0,0 +1,10 @@
+#define ecosiconmask_width 40
+#define ecosiconmask_height 16
+static unsigned char ecosiconmask_bits[] = {
+ 0xfc, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff,
+ 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0x3f};
Index: misc/example.c
===================================================================
RCS file: misc/example.c
diff -N misc/example.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ misc/example.c 7 Oct 2008 21:00:32 -0000
@@ -0,0 +1,374 @@
+//==========================================================================
+//
+// example.c
+//
+// Demonstration of the synthetic target framebuffer capabilities
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s): bartv
+// Date: 2008-10-06
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/io/framebuf.h>
+#include <cyg/kernel/kapi.h>
+#include <string.h>
+#include <stdio.h>
+
+#define BLACK colours[0x00]
+#define BLUE colours[0x01]
+#define GREEN colours[0x02]
+#define CYAN colours[0x03]
+#define RED colours[0x04]
+#define MAGENTA colours[0x05]
+#define BROWN colours[0x06]
+#define LIGHTGREY colours[0x07]
+#define DARKGREY colours[0x08]
+#define LIGHTBLUE colours[0x09]
+#define LIGHTGREEN colours[0x0A]
+#define LIGHTCYAN colours[0x0B]
+#define LIGHTRED colours[0x0C]
+#define LIGHTMAGENTA colours[0x0D]
+#define YELLOW colours[0x0E]
+#define WHITE colours[0x0F]
+
+// ----------------------------------------------------------------------------
+// FB0. 320x240 32bpp true 0888. Just draw a simple image as per the fb.c
+// example and return to main().
+
+static void
+fb0_thread(cyg_addrword_t arg)
+{
+#define FRAMEBUF cyg_synth_fb0
+ static cyg_ucount32 colours[16];
+ cyg_ucount16 block_width;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ colours[i] = cyg_fb_make_colour(&FRAMEBUF,
+ cyg_fb_palette_vga[i + i + i], cyg_fb_palette_vga[i + i + i + 1],cyg_fb_palette_vga[i + i + i + 2]);
+ }
+
+ cyg_fb_on(&FRAMEBUF);
+ // A white background
+ cyg_fb_fill_block(&FRAMEBUF, 0, 0, FRAMEBUF.fb_width, FRAMEBUF.fb_height, WHITE);
+ // A black block in the middle, 25 pixels in.
+ cyg_fb_fill_block(&FRAMEBUF, 25, 25, FRAMEBUF.fb_width - 50, FRAMEBUF.fb_height - 50, BLACK);
+
+ // Four diagonal lines in the corners. Red in the top left, blue in the top right,
+ // green in the bottom left, and yellow in the bottom right.
+ for (i = 0; i < 25; i++) {
+ cyg_fb_write_pixel(&FRAMEBUF, i, i, RED);
+ cyg_fb_write_pixel(&FRAMEBUF, (FRAMEBUF.fb_width - 1) - i, i, BLUE);
+ cyg_fb_write_pixel(&FRAMEBUF, i, (FRAMEBUF.fb_height - 1) - i, GREEN);
+ cyg_fb_write_pixel(&FRAMEBUF, (FRAMEBUF.fb_width - 1) - i, (FRAMEBUF.fb_height - 1) - i, YELLOW);
+ }
+
+ // Horizontal and vertical lines. Cyan at the top, magenta on the bottom,
+ // brown on the left, lightgrey on the right.
+ cyg_fb_write_hline(&FRAMEBUF, 25, 12, FRAMEBUF.fb_width - 50, CYAN);
+ cyg_fb_write_hline(&FRAMEBUF, 25, FRAMEBUF.fb_height - 12, FRAMEBUF.fb_width - 50, MAGENTA);
+ cyg_fb_write_vline(&FRAMEBUF, 12, 25, FRAMEBUF.fb_height - 50, BROWN);
+ cyg_fb_write_vline(&FRAMEBUF, FRAMEBUF.fb_width - 12, 25, FRAMEBUF.fb_height - 50, LIGHTGREY);
+
+ // And 14 vertical stripes, from blue to yellow, in the centre of the box.
+ block_width = (FRAMEBUF.fb_width - 100) / 14;
+ for (i = 1; i <= 14; i++) {
+ cyg_fb_fill_block(&FRAMEBUF, 50 + ((i - 1) * block_width), 50, block_width, FRAMEBUF.fb_height - 100, colours[i]);
+ }
+
+ cyg_fb_synch(&FRAMEBUF, CYG_FB_UPDATE_NOW);
+#undef FRAMEBUF
+}
+
+// ----------------------------------------------------------------------------
+// FB1, 320x240 15bpp, true 555, two pages. Draw a set of horizontal lines
+// in one page, vertical lines in the other, and flip between them at
+// one second intervals.
+
+static void
+fb1_thread(cyg_addrword_t arg)
+{
+#define FRAMEBUF cyg_synth_fb1
+ static cyg_ucount32 colours[16];
+ struct cyg_fb_ioctl_page_flip page_flip;
+ size_t len;
+ int result;
+ int i;
+
+ cyg_fb_on(&FRAMEBUF);
+ for (i = 0; i < 16; i++) {
+ colours[i] = cyg_fb_make_colour(&FRAMEBUF,
+ cyg_fb_palette_vga[i + i + i], cyg_fb_palette_vga[i + i + i + 1],cyg_fb_palette_vga[i + i + i + 2]);
+ }
+
+ // Draw the horizontal stripes on page 0.
+ page_flip.fbpf_visible_page = 0;
+ page_flip.fbpf_drawable_page = 1;
+ page_flip.fbpf_when = CYG_FB_UPDATE_NOW;
+ len = sizeof(page_flip);
+ result = cyg_fb_ioctl(&FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES, &page_flip, &len);
+ if (result != 0) {
+ fprintf(stderr, "fb1_thread: initial page flip failed.\n");
+ }
+ // 16 colours, 240 rows -> 15 rows/colour
+ for (i = 0; i < 16; i++) {
+ cyg_fb_fill_block(&FRAMEBUF, 0, 15 * i, 320, 15, colours[i]);
+ }
+
+ // Show the horizontal stripes and draw the vertical stripes on page 0.
+ page_flip.fbpf_visible_page = 1;
+ page_flip.fbpf_drawable_page = 0;
+ page_flip.fbpf_when = CYG_FB_UPDATE_NOW;
+ len = sizeof(page_flip);
+ result = cyg_fb_ioctl(&FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES, &page_flip, &len);
+ if (result != 0) {
+ fprintf(stderr, "fb1_thread: second page flip failed.\n");
+ }
+ // 16 colours, 320 columns -> 20 columns/colour
+ for (i = 0; i < 16; i++) {
+ cyg_fb_fill_block(&FRAMEBUF, 20 * i, 0, 20, 240, colours[i]);
+ }
+
+ for ( i = 0; ; i = 1 - i) {
+ page_flip.fbpf_visible_page = i;
+ page_flip.fbpf_drawable_page = 1 - i;
+ page_flip.fbpf_when = CYG_FB_UPDATE_NOW;
+ len = sizeof(page_flip);
+ result = cyg_fb_ioctl(&FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES, &page_flip, &len);
+ if (result != 0) {
+ fprintf(stderr, "fb1_thread: ongoing page flip failed.\n");
+ }
+ cyg_thread_delay(100);
+ }
+#undef FRAMEBUF
+}
+
+// ----------------------------------------------------------------------------
+// FB2, 320x240 15bpp, true 565, with a 160x120 viewport. Draw a simple image
+// as per the fbmacro.c example. Then move around within the viewport in a
+// clockwise direction at 110ms intervals.
+
+static void
+fb2_thread(cyg_addrword_t arg)
+{
+#define FRAMEBUF fb2
+#define WIDTH 320
+#define HEIGHT 240
+
+ static cyg_ucount32 colours[16];
+ cyg_ucount16 block_width;
+ int i, j;
+ int x = 0, y = 0;
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ CYG_FB_PIXEL1_VAR(FRAMEBUF);
+ cyg_fb_ioctl_viewport viewport;
+ size_t len;
+
+ CYG_FB_ON(FRAMEBUF);
+ for (i = 0; i < 16; i++) {
+ colours[i] = CYG_FB_MAKE_COLOUR(FRAMEBUF,
+ cyg_fb_palette_vga[i + i + i], cyg_fb_palette_vga[i + i + i + 1],cyg_fb_palette_vga[i + i + i + 2]);
+ }
+ // A white background
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0, WIDTH, HEIGHT, WHITE);
+ // A black block in the middle, 25 pixels in.
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 32, 32, WIDTH - 64, HEIGHT - 64, BLACK);
+
+ // Four diagonal lines in the corners. Red in the top left, blue in the top right,
+ // green in the bottom left, and yellow in the bottom right.
+ for (i = 0; i < 32; i++) {
+ CYG_FB_WRITE_PIXEL(FRAMEBUF, i, i, RED);
+ CYG_FB_WRITE_PIXEL(FRAMEBUF, (WIDTH - 1) - i, i, BLUE);
+ CYG_FB_WRITE_PIXEL(FRAMEBUF, i, (HEIGHT - 1) - i, GREEN);
+ CYG_FB_WRITE_PIXEL(FRAMEBUF, (WIDTH - 1) - i, (HEIGHT - 1) - i, YELLOW);
+ }
+
+ // Horizontal and vertical lines. Cyan at the top, magenta on the bottom,
+ // brown on the left, lightgrey on the right.
+ CYG_FB_WRITE_HLINE(FRAMEBUF, 32, 16, WIDTH - 64, CYAN);
+ CYG_FB_WRITE_HLINE(FRAMEBUF, 32, HEIGHT - 16, WIDTH - 64, MAGENTA);
+ CYG_FB_WRITE_VLINE(FRAMEBUF, 16, 32, HEIGHT - 64, BROWN);
+ CYG_FB_WRITE_VLINE(FRAMEBUF, WIDTH - 16, 32, HEIGHT - 64, LIGHTGREY);
+
+ // Top left, diagonal lines away from 0,0 with increasing spacing horizontally
+ for (i = 0; i < 16; i++) {
+ CYG_FB_PIXEL0_SET(FRAMEBUF, i + 16, i);
+ for (j = 0; j < 16; j++) {
+ CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, j);
+ }
+ }
+
+ // Top right, diagonal lines away from the corner, with increasing spacing horizontally
+ for (i = 0; i < 16; i++) {
+ CYG_FB_PIXEL0_SET(FRAMEBUF, WIDTH - (i + 16), i);
+ for (j = 0; j < 16; j++) {
+ CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * j);
+ }
+ }
+
+ // Top left, diagonal lines away from the corner, with increasing spacing vertically
+ for (i = 0; i < 16; i++) {
+ CYG_FB_PIXEL0_SET(FRAMEBUF, i, i + 16);
+ for (j = 0; j < 16; j++) {
+ CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+ CYG_FB_PIXEL0_ADDY(FRAMEBUF, j);
+ }
+ }
+ // Bottom left, diagonal lines away from the corner, with increasing spacing vertically
+ for (i = 0; i < 16; i++) {
+ CYG_FB_PIXEL0_SET(FRAMEBUF, i, HEIGHT - (i + 16));
+ for (j = 0; j < 16; j++) {
+ CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+ CYG_FB_PIXEL0_ADDY(FRAMEBUF, -1 * j);
+ }
+ }
+
+ // Thin vertical bars in the top-middle of the screen, between the hline and the box.
+ // Starting in the center and moving out with increasing spacing.
+ for (j = 0; j < 8; j++) {
+ CYG_FB_PIXEL0_SET(FRAMEBUF, (WIDTH / 2) - 2, 20 + j);
+ CYG_FB_PIXEL0_GET(FRAMEBUF, x, y);
+ CYG_FB_PIXEL1_SET(FRAMEBUF, x + 3, y);
+ for (i = 0; i < 16; i++) {
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * i);
+ CYG_FB_PIXEL1_ADDX(FRAMEBUF, i);
+ CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+ CYG_FB_PIXEL1_WRITE(FRAMEBUF, colours[i]);
+ }
+ }
+
+ block_width = (WIDTH - 100) / 14;
+ for (i = 1; i <= 14; i++) {
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 50 + ((i - 1) * block_width), 50, block_width, HEIGHT - 100, colours[i]);
+ }
+
+
+ for ( ; ; ) {
+ for (x = 0; x <= 160; x += 5) {
+ viewport.fbvp_x = x;
+ viewport.fbvp_y = 0;
+ viewport.fbvp_when = CYG_FB_UPDATE_NOW;
+ len = sizeof(viewport);
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_VIEWPORT_SET_POSITION, &viewport, &len);
+ cyg_thread_delay(11);
+ }
+ for (y = 0; y < 120; y += 5) {
+ viewport.fbvp_x = 160;
+ viewport.fbvp_y = y;
+ viewport.fbvp_when = CYG_FB_UPDATE_NOW;
+ len = sizeof(viewport);
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_VIEWPORT_SET_POSITION, &viewport, &len);
+ cyg_thread_delay(11);
+ }
+ for (x = 160; x >= 0; x -= 5) {
+ viewport.fbvp_x = x;
+ viewport.fbvp_y = 120;
+ viewport.fbvp_when = CYG_FB_UPDATE_NOW;
+ len = sizeof(viewport);
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_VIEWPORT_SET_POSITION, &viewport, &len);
+ cyg_thread_delay(11);
+ }
+ for (y = 120; y >= 0; y -= 5) {
+ viewport.fbvp_x = 0;
+ viewport.fbvp_y = y;
+ viewport.fbvp_when = CYG_FB_UPDATE_NOW;
+ len = sizeof(viewport);
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_VIEWPORT_SET_POSITION, &viewport, &len);
+ cyg_thread_delay(11);
+ }
+ }
+#undef FRAMEBUF
+#undef WIDTH
+#undef HEIGHT
+}
+
+// ----------------------------------------------------------------------------
+// FB3, 320x240 8bpp, paletted 888. Draw a series of vertical stripes, 5 pixels
+// wide, and rotate through the palette at 210ms intervals.
+
+static void
+fb3_thread(cyg_addrword_t arg)
+{
+#define FRAMEBUF fb3
+ static cyg_uint8 palette[(128 +16) * 3];
+ int i;
+
+ CYG_FB_ON(FRAMEBUF);
+
+ // Read in the first 128 palette entries, and copy the first 16
+ // entries to give a wrap-around. After 128 the palette gets less
+ // interesting.
+ CYG_FB_READ_PALETTE(FRAMEBUF, 0, 128, palette);
+ memcpy(&(palette[128 * 3]), palette, 16 * 3);
+
+ for (i = 0; i < 32; i++) {
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 10 * i, 0, 10, 240, i);
+ }
+
+ for ( i = 0; ; i = (i + 1) % 128 ) {
+ cyg_thread_delay(21);
+ CYG_FB_WRITE_PALETTE(FRAMEBUF, 0, 64, &(palette[i * 3]), CYG_FB_UPDATE_NOW);
+ }
+#undef FRAMEBUF
+}
+
+// ----------------------------------------------------------------------------
+// main(). Start up separate threads for FB1 and FB2, run the FB0 code since
+// it just does some drawing and finishes, then run the FB3 code.
+static cyg_thread fb1_thread_data;
+static cyg_handle_t fb1_thread_handle;
+static unsigned char fb1_thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+static cyg_thread fb2_thread_data;
+static cyg_handle_t fb2_thread_handle;
+static unsigned char fb2_thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+
+int
+main(int argc, char** argv)
+{
+ cyg_thread_create(10, &fb1_thread, 0, "fb1", fb1_thread_stack, CYGNUM_HAL_STACK_SIZE_TYPICAL, &fb1_thread_handle, &fb1_thread_data);
+ cyg_thread_create(10, &fb2_thread, 0, "fb2", fb2_thread_stack, CYGNUM_HAL_STACK_SIZE_TYPICAL, &fb2_thread_handle, &fb2_thread_data);
+ cyg_thread_resume(fb1_thread_handle);
+ cyg_thread_resume(fb2_thread_handle);
+ fb0_thread(0);
+ fb3_thread(0);
+ return 0;
+}
+
Index: misc/example.ecm
===================================================================
RCS file: misc/example.ecm
diff -N misc/example.ecm
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ misc/example.ecm 7 Oct 2008 21:00:32 -0000
@@ -0,0 +1,85 @@
+cdl_configuration eCos {
+ package CYGPKG_IO_FRAMEBUF ;
+};
+
+cdl_component CYGPKG_DEVS_FRAMEBUF_SYNTH_FB0 {
+ user_value 1
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB0_WIDTH {
+ user_value 320
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB0_HEIGHT {
+ user_value 240
+};
+
+cdl_option CYGDAT_DEVS_FRAMEBUF_SYNTH_FB0_FORMAT {
+ user_value 32BPP_TRUE_0888
+};
+
+cdl_component CYGPKG_DEVS_FRAMEBUF_SYNTH_FB1 {
+ user_value 1
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB1_WIDTH {
+ user_value 320
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB1_HEIGHT {
+ user_value 240
+};
+
+cdl_option CYGDAT_DEVS_FRAMEBUF_SYNTH_FB1_FORMAT {
+ user_value 16BPP_TRUE_555
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB1_PAGE_FLIPPING {
+ user_value 1 2
+};
+
+cdl_component CYGPKG_DEVS_FRAMEBUF_SYNTH_FB2 {
+ user_value 1
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB2_WIDTH {
+ user_value 320
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB2_HEIGHT {
+ user_value 240
+};
+
+cdl_option CYGDAT_DEVS_FRAMEBUF_SYNTH_FB2_FORMAT {
+ user_value 16BPP_TRUE_565
+};
+
+cdl_component CYGIMP_DEVS_FRAMEBUF_SYNTH_FB2_VIEWPORT {
+ user_value 1
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB2_VIEWPORT_WIDTH {
+ user_value 160
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB2_VIEWPORT_HEIGHT {
+ user_value 120
+};
+
+cdl_component CYGPKG_DEVS_FRAMEBUF_SYNTH_FB3 {
+ user_value 1
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB3_WIDTH {
+ user_value 320
+};
+
+cdl_option CYGNUM_DEVS_FRAMEBUF_SYNTH_FB3_HEIGHT {
+ user_value 240
+};
+
+cdl_option CYGDAT_DEVS_FRAMEBUF_SYNTH_FB3_FORMAT {
+ user_value 8BPP_PAL888
+};
+
+
Index: misc/example.tdf
===================================================================
RCS file: misc/example.tdf
diff -N misc/example.tdf
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ misc/example.tdf 7 Oct 2008 21:00:32 -0000
@@ -0,0 +1,42 @@
+# An example framebuffer create function. This is for use with the
+# synthetic target framebuffer example program which uses four
+# devices:
+#
+# fb0: 320x240 32bpp true 0888
+# fb1: 320x240 16bpp true 555 with two pages
+# fb2: 320x240 16bpp true 565 with a viewport of 160x120
+# fb3: 320x240 8bpp pal 888
+#
+# These are all created in a single toplevel .synth_framebufs, one above the other,
+# with labels in between.
+proc my_framebuf_create_frame { fb_id magnification depth little_endian width height viewport_width viewport_height stride number_pages format } {
+ if { ![winfo exists .synth_framebufs] } {
+ toplevel .synth_framebufs
+ wm title .synth_framebufs "Synthetic target framebuffers"
+ wm protocol .synth_framebufs WM_DELETE_WINDOW {}
+ wm geometry .synth_framebufs +1000+0
+
+ label .synth_framebufs.fb0_label -text "FB0 320x240 32bpp true 0888"
+ frame .synth_framebufs.fb0 -container 1 -height 240 -width 320
+ label .synth_framebufs.fb1_label -text "FB1 320x240 16bpp true 0555 two pages"
+ frame .synth_framebufs.fb1 -container 1 -height 240 -width 320
+ label .synth_framebufs.fb2_label -text "FB2 320x240 16bpp true 0565\nviewport 160x120 magnified *2"
+ frame .synth_framebufs.fb2 -container 1 -height 240 -width 320
+ label .synth_framebufs.fb3_label -text "FB3 320x240 8bpp paletted 888"
+ frame .synth_framebufs.fb3 -container 1 -height 240 -width 320
+ pack .synth_framebufs.fb0_label -side top -expand 1 -anchor w -fill x
+ pack .synth_framebufs.fb0 -side top -expand 0 -anchor w
+ pack .synth_framebufs.fb1_label -side top -expand 1 -anchor w -fill x
+ pack .synth_framebufs.fb1 -side top -expand 0 -anchor w
+ pack .synth_framebufs.fb2_label -side top -expand 1 -anchor w -fill x
+ pack .synth_framebufs.fb2 -side top -expand 0 -anchor w
+ pack .synth_framebufs.fb3_label -side top -expand 1 -anchor w -fill x
+ pack .synth_framebufs.fb3 -side top -expand 0 -anchor w
+ }
+ return .synth_framebufs.fb$fb_id
+}
+
+synth_device framebuf {
+ fb2_magnification 2
+ create_frame_proc my_framebuf_create_frame
+}
Index: src/gen_synthfb.tcl
===================================================================
RCS file: src/gen_synthfb.tcl
diff -N src/gen_synthfb.tcl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/gen_synthfb.tcl 7 Oct 2008 21:00:32 -0000
@@ -0,0 +1,352 @@
+#!/bin/bash
+# restart using a Tcl shell \
+ exec sh -c 'for tclshell in tclsh tclsh83 cygtclsh80 ; do \
+ ( echo | $tclshell ) 2> /dev/null && exec $tclshell "`( cygpath -w \"$0\" ) 2> /dev/null || echo $0`" "$@" ; \
+ done ; \
+ echo "gen_synthfb.tcl: cannot find Tcl shell" ; exit 1' "$0" "$@"
+
+#===============================================================================
+#
+# gen_synthfb.tcl
+#
+# Generate header files for all enabled synthetic target framebuffer devices.
+#
+#===============================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+# -------------------------------------------
+# This file is part of eCos, the Embedded Configurable Operating System.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# eCos 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 2 or (at your option) any later version.
+#
+# eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# As a special exception, if other files instantiate templates or use macros
+# or inline functions from this file, or you compile this file and link it
+# with other works to produce a work based on this file, this file does not
+# by itself cause the resulting work to be covered by the GNU General Public
+# License. However the source code for this file must still be made available
+# in accordance with section (3) of the GNU General Public License.
+#
+# This exception does not invalidate any other reasons why a work based on
+# this file might be covered by the GNU General Public License.
+# -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+#===============================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): bartv
+# Date: 2005-10-28
+#
+# This script is invoked via a custom make rule to generate files
+# <cyg/io/framebufs/synth_fb.h> and synth_fbs.c
+#
+#####DESCRIPTIONEND####
+#===============================================================================
+
+proc do_it { prefix } {
+ set pkgconf_file [file join $prefix "include/pkgconf/devs_framebuf_synth.h"]
+ if { ! [file exists $pkgconf_file] } {
+ puts stderr "gen_synthfb.tcl: missing configuration header $pkgconf_file"
+ exit 1
+ }
+ set fd [open $pkgconf_file "r"]
+ set data [read $fd]
+ close $fd
+
+ array set defines [list]
+ foreach line [split $data "\n"] {
+ if { [regexp -- {^\#define[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]+([^[:space:]]+)$} $line junk symbol value] } {
+ set defines($symbol) $value
+ }
+ }
+
+ set data \
+ "/*
+ * File <cyg/io/framebufs/synth_fb.h>
+ *
+ * This is a generated file - do not edit!
+ * It should not be \#include'd directly. Instead use <cyg/io/framebuf.h>
+ */
+
+#include <cyg/io/framebuf.inl>
+
+"
+
+ for { set fb 0 } { $fb < 4 } { incr fb } {
+ if { ! [info exists defines(CYGPKG_DEVS_FRAMEBUF_SYNTH_FB[set fb])] } {
+ continue
+ }
+
+ set width $defines(CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set fb]_WIDTH)
+ set height $defines(CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set fb]_HEIGHT)
+ set flags0 "(CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER | \\\n CYG_FB_FLAGS0_DOUBLE_BUFFER | \\\n"
+ if { [info exists defines(CYGIMP_DEVS_FRAMEBUF_SYNTH_FB[set fb]_VIEWPORT) ] } {
+ set viewport_width $defines(CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set fb]_VIEWPORT_WIDTH)
+ set viewport_height $defines(CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set fb]_VIEWPORT_HEIGHT)
+ append flags0 " CYG_FB_FLAGS0_VIEWPORT | \\\n"
+ } else {
+ set viewport_width $width
+ set viewport_height $height
+ }
+ if { [info exists defines(CYGNUM_DEVS_FRAMEBUF_SYNTH_FB[set fb]_PAGE_FLIPPING)] } {
+ append flags0 " CYG_FB_FLAGS0_PAGE_FLIPPING | \\\n"
+ }
+ set paletted 1
+ switch -- $defines(CYGDAT_DEVS_FRAMEBUF_SYNTH_FB[set fb]_FORMAT) {
+ 1BPP_BE_PAL888 {
+ set format "CYG_FB_FORMAT_1BPP_PAL888"
+ set suffix "1BE"
+ set depth 1
+ set stride [expr ($width + 7) >> 3]
+ }
+ 1BPP_LE_PAL888 {
+ append flags0 " CYG_FB_FLAGS0_LE | \\\n"
+ set format "CYG_FB_FORMAT_1BPP_PAL888"
+ set suffix "1LE"
+ set depth 1
+ set stride [expr ($width + 7) >> 3]
+ }
+ 2BPP_BE_PAL888 {
+ set format "CYG_FB_FORMAT_2BPP_PAL888"
+ set suffix "2BE"
+ set depth 2
+ set stride [expr ($width + 3) >> 2]
+ }
+ 2BPP_LE_PAL888 {
+ append flags0 " CYG_FB_FLAGS0_LE | \\\n"
+ set format "CYG_FB_FORMAT_2BPP_PAL888"
+ set suffix "2LE"
+ set depth 2
+ set stride [expr ($width + 3) >> 2]
+ }
+ 4BPP_BE_PAL888 {
+ set format "CYG_FB_FORMAT_4BPP_PAL888"
+ set suffix "4BE"
+ set depth 4
+ set stride [expr ($width + 1) >> 1]
+ }
+ 4BPP_LE_PAL888 {
+ append flags0 " CYG_FB_FLAGS0_LE | \\\n"
+ set format "CYG_FB_FORMAT_4BPP_PAL888"
+ set suffix "4LE"
+ set depth 4
+ set stride [expr ($width + 1) >> 1]
+ }
+ 8BPP_PAL888 {
+ set format "CYG_FB_FORMAT_8BPP_PAL888"
+ set suffix "8"
+ set depth 8
+ set stride $width
+ }
+ 8BPP_TRUE_332 {
+ set format "CYG_FB_FORMAT_8BPP_TRUE_332"
+ set suffix "8"
+ set paletted 0
+ set make_colour_fn "cyg_fb_dev_make_colour_8bpp_true_332"
+ set break_colour_fn "cyg_fb_dev_break_colour_8bpp_true_332"
+ set make_colour_macro "CYG_FB_MAKE_COLOUR_8BPP_TRUE_332"
+ set break_colour_macro "CYG_FB_BREAK_COLOUR_8BPP_TRUE_332"
+ set depth 8
+ set stride $width
+ }
+ 16BPP_TRUE_565 {
+ set format "CYG_FB_FORMAT_16BPP_TRUE_565"
+ set suffix "16"
+ set paletted 0
+ set make_colour_fn "cyg_fb_dev_make_colour_16bpp_true_565"
+ set break_colour_fn "cyg_fb_dev_break_colour_16bpp_true_565"
+ set make_colour_macro "CYG_FB_MAKE_COLOUR_16BPP_TRUE_565"
+ set break_colour_macro "CYG_FB_BREAK_COLOUR_16BPP_TRUE_565"
+ set depth 16
+ set stride [expr $width * 2]
+ }
+ 16BPP_TRUE_555 {
+ set format "CYG_FB_FORMAT_16BPP_TRUE_555"
+ set suffix "16"
+ set paletted 0
+ set make_colour_fn "cyg_fb_dev_make_colour_16bpp_true_555"
+ set break_colour_fn "cyg_fb_dev_break_colour_16bpp_true_555"
+ set make_colour_macro "CYG_FB_MAKE_COLOUR_16BPP_TRUE_555"
+ set break_colour_macro "CYG_FB_BREAK_COLOUR_16BPP_TRUE_555"
+ set depth 16
+ set stride [expr $width * 2]
+ }
+ 32BPP_TRUE_0888 {
+ set format "CYG_FB_FORMAT_32BPP_TRUE_0888"
+ set suffix "32"
+ set paletted 0
+ set make_colour_fn "cyg_fb_dev_make_colour_32bpp_true_0888"
+ set break_colour_fn "cyg_fb_dev_break_colour_32bpp_true_0888"
+ set make_colour_macro "CYG_FB_MAKE_COLOUR_32BPP_TRUE_0888"
+ set break_colour_macro "CYG_FB_BREAK_COLOUR_32BPP_TRUE_0888"
+ set depth 32
+ set stride [expr $width * 4]
+ }
+ }
+ if { $paletted } {
+ append flags0 " CYG_FB_FLAGS0_PALETTE | \\\n CYG_FB_FLAGS0_WRITEABLE_PALETTE | \\\n"
+ set write_palette_fn "cyg_synth_fb_write_palette"
+ set read_palette_fn "cyg_synth_fb_read_palette"
+ set make_colour_fn "cyg_fb_nop_make_colour"
+ set break_colour_fn "cyg_fb_nop_break_colour"
+ } else {
+ append flags0 " CYG_FB_FLAGS0_TRUE_COLOUR | \\\n"
+ set write_palette_fn "cyg_fb_nop_write_palette"
+ set read_palette_fn "cyg_fb_nop_read_palette"
+ }
+ append flags0 " CYG_FB_FLAGS0_BLANK)"
+
+ # The framebuffer parameters
+ append data \
+ "
+extern cyg_fb cyg_synth_fb[set fb];
+extern cyg_uint8* cyg_synth_fb[set fb]_base;
+#define CYG_FB_fb[set fb]_STRUCT cyg_synth_fb[set fb]
+#define CYG_FB_fb[set fb]_DEPTH $depth
+#define CYG_FB_fb[set fb]_FORMAT $format
+#define CYG_FB_fb[set fb]_WIDTH $width
+#define CYG_FB_fb[set fb]_HEIGHT $height
+#define CYG_FB_fb[set fb]_VIEWPORT_WIDTH $viewport_width
+#define CYG_FB_fb[set fb]_VIEWPORT_HEIGHT $viewport_height
+#define CYG_FB_fb[set fb]_BASE cyg_synth_fb[set fb]_base
+#define CYG_FB_fb[set fb]_STRIDE $stride
+#define CYG_FB_fb[set fb]_FLAGS0 $flags0
+#define CYG_FB_fb[set fb]_FLAGS1 0
+#define CYG_FB_fb[set fb]_FLAGS2 0
+#define CYG_FB_fb[set fb]_FLAGS3 0
+"
+
+ # These macros are not part of the usual framebuffer set, but are
+ # useful because of the configurable nature of the synthetic target
+ append data \
+ "
+#define CYG_FB_fb[set fb]_SUFFIX $suffix
+#define CYG_FB_fb[set fb]_READ_PALETTE_FN $read_palette_fn
+#define CYG_FB_fb[set fb]_WRITE_PALETTE_FN $write_palette_fn
+#define CYG_FB_fb[set fb]_MAKE_COLOUR_FN $make_colour_fn
+#define CYG_FB_fb[set fb]_BREAK_COLOUR_FN $break_colour_fn
+"
+ # And the macro API, all done in terms of the linear framebuffer functions.
+ append data \
+ "
+#define CYG_FB_fb[set fb]_PIXELx_VAR( _fb_, _id_) CYG_FB_PIXELx_VAR_[set suffix]( _fb_, _id_)
+#define CYG_FB_fb[set fb]_PIXELx_SET( _fb_, _id_, _x_, _y_) \\
+ CYG_MACRO_START \\
+ CYG_FB_PIXELx_SET_[set suffix]( _fb_, _id_, CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, _x_, _y_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_PIXELx_GET( _fb_, _id_, _x_, _y_) \\
+ CYG_MACRO_START \\
+ CYG_FB_PIXELx_GET_[set suffix]( _fb_, _id_, CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, _x_, _y_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_PIXELx_ADDX( _fb_, _id_, _incr_) \\
+ CYG_MACRO_START \\
+ CYG_FB_PIXELx_ADDX_[set suffix]( _fb_, _id_, CYG_FB_fb[set fb]_STRIDE, _incr_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_PIXELx_ADDY( _fb_, _id_, _incr_) \\
+ CYG_MACRO_START \\
+ CYG_FB_PIXELx_ADDY_[set suffix]( _fb_, _id_, CYG_FB_fb[set fb]_STRIDE, _incr_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_PIXELx_WRITE(_fb_, _id_, _colour_) \\
+ CYG_MACRO_START \\
+ CYG_FB_PIXELx_WRITE_[set suffix](_fb_, _id_, _colour_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_PIXELx_READ( _fb_, _id_) \\
+ ({ CYG_FB_PIXELx_READ_[set suffix]( _fb_, _id_); })
+#define CYG_FB_fb[set fb]_PIXELx_FLUSHABS( _fb_, _id_, _x0_, _y0_, _width_, _height_) \\
+ CYG_MACRO_START \\
+ CYG_FB_PIXELx_FLUSHABS_[set suffix](_fb_, _id_, _x0_, _y0_, _width_, _height_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_PIXELx_FLUSHREL( _fb_, _id_, _x0_, _y0_, _dx_, _dy_) \\
+ CYG_MACRO_START \\
+ CYG_FB_PIXELx_FLUSHREL_[set suffix](_fb_, _id_, _x0_, _y0_, _dx_, _dy_); \\
+ CYG_MACRO_END
+
+#define CYG_FB_fb[set fb]_WRITE_PIXEL(_x_, _y_, _colour_) \\
+ CYG_MACRO_START \\
+ cyg_fb_linear_write_pixel_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, \\
+ _x_, _y_, _colour_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_READ_PIXEL(_x_, _y_) \\
+ ({ cyg_fb_linear_read_pixel_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, _x_, _y_); })
+#define CYG_FB_fb[set fb]_WRITE_HLINE(_x_, _y_, _len_, _colour_) \\
+ CYG_MACRO_START \\
+ cyg_fb_linear_write_hline_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, \\
+ _x_, _y_, _len_, _colour_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_WRITE_VLINE(_x_, _y_, _len_, _colour_) \\
+ CYG_MACRO_START \\
+ cyg_fb_linear_write_vline_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, \\
+ _x_, _y_, _len_, _colour_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_FILL_BLOCK(_x_, _y_, _width_, _height_, _colour_) \\
+ CYG_MACRO_START \\
+ cyg_fb_linear_fill_block_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, \\
+ _x_, _y_, _width_, _height_, _colour_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_WRITE_BLOCK(_x_, _y_, _width_, _height_, _data_, _offset_, _data_stride_) \\
+ CYG_MACRO_START \\
+ cyg_fb_linear_write_block_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, \\
+ _x_, _y_, _width_, _height_, _data_, _offset_, _data_stride_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_READ_BLOCK(_x_, _y_, _width_, _height_, _data_, _offset_, _data_stride_) \\
+ CYG_MACRO_START \\
+ cyg_fb_linear_read_block_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, \\
+ _x_, _y_, _width_, _height_, _data_, _offset_, _data_stride_); \\
+ CYG_MACRO_END
+#define CYG_FB_fb[set fb]_MOVE_BLOCK(_x_, _y_, _width_, _height_, _new_x_, _new_y_) \\
+ CYG_MACRO_START \\
+ cyg_fb_linear_move_block_[set suffix]_inl(CYG_FB_fb[set fb]_BASE, CYG_FB_fb[set fb]_STRIDE, \\
+ _x_, _y_, _width_, _height_, _new_x_, _new_y_); \\
+ CYG_MACRO_END
+"
+ if { !$paletted } {
+ append data \
+ "
+#define CYG_FB_fb[set fb]_MAKE_COLOUR(_r_, _g_, _b_) \\
+ ({ [set make_colour_macro](_r_, _g_, _b_); })
+#define CYG_FB_fb[set fb]_BREAK_COLOUR(_colour_, _r_, _g_, _b_) \\
+ CYG_MACRO_START \\
+ [set break_colour_macro](_colour_, _r_, _g_, _b_); \\
+ CYG_MACRO_END
+"
+ }
+ }
+
+ set old_data ""
+ set framebuf_file [file join $prefix "include/cyg/io/framebufs/synth_fb.h"]
+ if { [file exists $framebuf_file] && [file readable $framebuf_file] } {
+ set fd [open $framebuf_file "r"]
+ set old_data [read $fd]
+ close $fd
+ }
+ if { ! [string equal $old_data $data] } {
+ if { ! [info exists [file dirname $framebuf_file]] } {
+ file mkdir [file dirname $framebuf_file]
+ }
+ set fd [open $framebuf_file "w"]
+ puts -nonewline $fd $data
+ close $fd
+ }
+}
+
+if { 0 == $::argc } {
+ puts stderr "gen_synthfb.tcl: missing argument for install directory"
+ exit 1
+}
+if { [catch { do_it [lindex $::argv 0] } msg] } {
+ puts stderr "gen_synthfb.tcl: internal error"
+ puts stderr " $msg"
+ exit 1
+}
+exit 0
+
Index: src/protocol.h
===================================================================
RCS file: src/protocol.h
diff -N src/protocol.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/protocol.h 7 Oct 2008 21:00:32 -0000
@@ -0,0 +1,123 @@
+//==========================================================================
+//
+// protocol.h
+//
+// Data common to host and target.
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s): bartv
+// Date: 2005-10-28
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+// These requests are sent by eCos to the I/O auxiliary and the
+// framebuf.tcl script.
+//
+// Protocol version number
+#define SYNTH_FB_PROTOCOL_VERSION 0x01
+
+// Initialize, getting back various file names.
+#define SYNTH_FB_INIT 0x01
+// Abort, failed to open the file names
+#define SYNTH_FB_ABORT 0x02
+// Switch a device back on.
+#define SYNTH_FB_ON 0x03
+// Or off
+#define SYNTH_FB_OFF 0x04
+
+// These requests are sent by eCos to the host-side framebuf program
+// to indicate what has changed.
+//
+// All connected
+#define SYNTH_FB_OK 0x01
+// A double buffer synch.
+#define SYNTH_FB_SYNC 0x02
+// Palette change, redraw the lot
+#define SYNTH_FB_WRITE_PALETTE 0x03
+// Blank or unblank the screen
+#define SYNTH_FB_BLANK 0x04
+// Move the viewport
+#define SYNTH_FB_VIEWPORT 0x05
+// Page flipping
+#define SYNTH_FB_PAGE_FLIP 0x06
+
+// These requests go from the framebuf.tcl script to the framebuf
+// program.
+typedef struct synth_fb_auxiliary_request {
+ unsigned int command;
+ unsigned int arg1;
+ unsigned int arg2;
+} synth_fb_auxiliary_request;
+
+// This is sent when the frame becomes visible. It is followed
+// by a 32-bit windows id.
+#define SYNTH_FB_AUX_MAPPED 0x01
+// ON, processed by auxiliary and then passed on to framebuf
+#define SYNTH_FB_AUX_ON 0x02
+// OFF, processed by auxiliary and then passed on to framebuf
+#define SYNTH_FB_AUX_OFF 0x03
+// Refresh, sent by the auxiliary a second after mapping.
+#define SYNTH_FB_AUX_REDRAW 0x04
+
+// This data structure is in the shared memory region.
+typedef struct synth_fb_data {
+ // Do we have a connection to a host-side framebuf program to do
+ // the drawing?
+ int connected;
+ // Named fifo between framebuf and the synthetic target.
+ int fifo_to_framebuf;
+ int fifo_from_framebuf;
+ // The device id for the auxiliary
+ int devid;
+ // The bounding box for syncs.
+ int sync_x0;
+ int sync_y0;
+ int sync_x1;
+ int sync_y1;
+ // Is the display on?
+ int display_on;
+ // Current blank state
+ int blank_on;
+ // Current viewport position, top left
+ int viewport_x;
+ int viewport_y;
+ // Current page for page flipping
+ int page_visible;
+ int page_drawable;
+ // The palette, if used.
+ unsigned char palette[3 * 256];
+ // The framebuffer data follows.
+ unsigned int framebuf[1];
+} synth_fb_data;
Index: src/synthfb.c
===================================================================
RCS file: src/synthfb.c
diff -N src/synthfb.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/synthfb.c 7 Oct 2008 21:00:34 -0000
@@ -0,0 +1,679 @@
+//==========================================================================
+//
+// synthfb.c
+//
+// Provide one or more framebuffer devices for the synthetic target.
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s): bartv
+// Date: 2005-10-28
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <pkgconf/devs_framebuf_synth.h>
+#include <pkgconf/io_framebuf.h>
+#include <cyg/io/framebuf.h>
+#include <errno.h>
+#include <string.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_io.h>
+#include "protocol.h"
+
+// Set the DEBUG_LEVEL to 0 for no debugging, 2 for maximum debugging.
+#define DEBUG_LEVEL 0
+#define DEBUG(_level_, _str_, ...) \
+ CYG_MACRO_START \
+ if (_level_ <= DEBUG_LEVEL) { \
+ diag_printf( _str_, ## __VA_ARGS__); \
+ } \
+ CYG_MACRO_END
+
+// Achieving high performance graphics operations in the synthetic
+// target is difficult. Theoretically it might be possible to access
+// the Linux framebuffer directly using MIT-SHM or DGA. However there
+// is no practical way to handle the relevant parts of the X prococol,
+// e.g. expose events. We also don't want to go via the
+// general-purpose xchgmsg() functionality and a Tcl script, those
+// are not appropriate for high performance.
+//
+// Instead if the I/O auxiliary is running a framebuffer device is
+// instantiated, and the framebuf.tcl script will start a program
+// framebuf. That program will create a shared memory region which
+// then gets mapped into the synthetic target's address space. The
+// shared memory region holds a synth_fb_data structure followed by
+// the framebuffer data. If there are multiple framebuffer devices
+// then there will be multiple invocations of the framebuf program.
+//
+// The framebuf program needs to respond to requests from several
+// different sources. The X server may send events like expose.
+// The synthetic target application can send synchronization requests,
+// palette updates, and so on. The X events will come via a socket,
+// and the requests from framebuf.tcl can come via a pipe. select()
+// will serve for this. Several mechanisms can be used for the
+// communication between the synthetic target application and framebuf
+// including shared memory semaphores and reliable signals. To fit in
+// neatly with the select() a named fifo is used.
+//
+// So assuming a framebuf program is running fb_op() writes a single
+// byte to the fifo, then waits for framebuf to complete the
+// operation. That wait also uses a named fifo. This keeps everything
+// synchronous, and avoids some portability problems between
+// Linux on various architectures.
+static void
+fb_op(cyg_fb* fb, int command)
+{
+ synth_fb_data* fb_data = (synth_fb_data*) fb->fb_driver2;
+ DEBUG(2, "target synthfb: fb_op %d\n", command);
+ if (fb_data->connected) {
+ cyg_uint8 data[1];
+ int rc;
+
+ data[0] = (cyg_uint8)command;
+ do {
+ rc = cyg_hal_sys_write(fb_data->fifo_to_framebuf, (const void*) data, 1);
+ } while (-CYG_HAL_SYS_EINTR == rc);
+ do {
+ rc = cyg_hal_sys_read(fb_data->fifo_from_framebuf, (void*) data, 1);
+ } while (-CYG_HAL_SYS_EINTR == rc);
+ if (rc < 0) {
+ diag_printf("Internal error: unexpected result %d when receiving response from the framebuf program.\n", rc);
+ diag_printf(" : disabling framebuffer device fb%d.\n", fb->fb_driver0);
+ fb_data->connected = 0;
+ }
+ }
+ DEBUG(2, "target synthfb: fb_op %d done\n", command);
+}
+
+// Create a framebuffer device. This gets called from a C++
+// static constructor, to ensure that all the framebuffer
+// windows are created early on during initialization before
+// the host-side ecosynth support performs any cleanups.
+void
+_cyg_synth_fb_instantiate(struct cyg_fb* fb)
+{
+ synth_fb_data* local_fb_data = (synth_fb_data*) fb->fb_driver2;
+ synth_fb_data* shared_fb_data;
+ char device_data[512];
+ char fb_name[4];
+ char* fb_format = 0;
+ char* ptr;
+ char* filename;
+ int fd;
+ int len;
+ int reply;
+ cyg_uint8* fb_base;
+ DEBUG(1, "target synth_fb_instantiate\n");
+
+ if (!synth_auxiliary_running) {
+ diag_printf("cyg_synth_fb_instantiate(): no I/O auxiliary, sticking with in-memory framebuffer\n");
+ return;
+ }
+
+ diag_sprintf(fb_name, "fb%d", fb->fb_driver0);
+ switch(fb->fb_format) {
+ // Only bother with the formats used by gensynth_fb.tcl
+ case CYG_FB_FORMAT_1BPP_PAL888:
+ {
+ static const cyg_uint8 fb_1bpp_palette[2 * 3] = {
+ 0x00, 0x00, 0x00, // colour 0 == black
+ 0xFF, 0xFF, 0xFF // colour 1 == white
+ };
+ fb_format = "1BPP_PAL888";
+ memcpy(local_fb_data->palette, fb_1bpp_palette, sizeof(fb_1bpp_palette));
+ break;
+ }
+ case CYG_FB_FORMAT_2BPP_PAL888:
+ {
+ static const cyg_uint8 fb_2bpp_palette[4 * 3] = {
+ 0x00, 0x00, 0x00, // colour 0 == black
+ 0x54, 0x54, 0x54, // dark grey
+ 0xA8, 0xA8, 0xA8, // light grey
+ 0xFF, 0xFF, 0xFF // colour 3 == white
+ } ;
+ fb_format = "2BPP_PAL888";
+ memcpy(local_fb_data->palette, fb_2bpp_palette, sizeof(fb_2bpp_palette));
+ break;
+ }
+ case CYG_FB_FORMAT_4BPP_PAL888:
+ fb_format = "4BPP_PAL888";
+ memcpy(local_fb_data->palette, cyg_fb_palette_ega, 16 * 3);
+ break;
+ case CYG_FB_FORMAT_8BPP_PAL888:
+ fb_format = "8BPP_PAL888";
+ memcpy(local_fb_data->palette, cyg_fb_palette_vga, 256 * 3);
+ break;
+ case CYG_FB_FORMAT_8BPP_TRUE_332:
+ fb_format = "8BPP_TRUE_332";
+ break;
+ case CYG_FB_FORMAT_16BPP_TRUE_565:
+ fb_format = "16BPP_TRUE_565";
+ break;
+ case CYG_FB_FORMAT_16BPP_TRUE_555:
+ fb_format = "16BPP_TRUE_555";
+ break;
+ case CYG_FB_FORMAT_32BPP_TRUE_0888:
+ fb_format = "32BPP_TRUE_0888";
+ break;
+ }
+
+ diag_sprintf(device_data, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s",
+ SYNTH_FB_PROTOCOL_VERSION,
+ fb->fb_driver0, /* id 0-3 */
+ fb->fb_depth,
+ fb->fb_flags0 & CYG_FB_FLAGS0_LE,
+ fb->fb_width, fb->fb_height,
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+ fb->fb_viewport_width, fb->fb_viewport_height,
+#else
+ fb->fb_width, fb->fb_height,
+#endif
+ fb->fb_stride,
+ fb->fb_driver1, /* number of pages */
+ fb_format);
+
+ local_fb_data->devid = synth_auxiliary_instantiate("devs/framebuf/synth", SYNTH_MAKESTRING(CYGPKG_DEVS_FRAMEBUF_SYNTH),
+ "framebuf", fb_name, device_data);
+ if (local_fb_data->devid < 0) {
+ // The I/O auxiliary should have reported a suitable error.
+ // Just stick with an in-memory device.
+ diag_printf("cyg_synth_fb_instantiate(): failed to instantiate device, sticking with in-memory framebuffer\n");
+ return;
+ } else {
+ DEBUG(1, "target synth_auxiliary_instantiate(), host-side framebuf utility running\n");
+ // At this point the framebuf.tcl script has run, the window has
+ // been created, the framebuf program has been started, it will
+ // have created the shared memory region and the two fifos,
+ // passed the names back up to framebuf.tcl, and everything should
+ // be running. This xchgmsg() retrieves the file names from
+ // framebuf.tcl.
+ synth_auxiliary_xchgmsg(local_fb_data->devid, SYNTH_FB_INIT, 0, 0, 0, 0, &reply, (unsigned char*)device_data, &len, 512);
+ // First filename is the shared memory region.
+ filename = device_data;
+ for (ptr = device_data; *ptr != ';'; ptr++)
+ ;
+ *ptr++ = '\0';
+ DEBUG(1, "target : Opening shared memory region %s\n", filename);
+ fd = cyg_hal_sys_open(filename, CYG_HAL_SYS_O_RDWR, 0);
+ if (fd < 0) {
+ synth_auxiliary_xchgmsg(local_fb_data->devid, SYNTH_FB_ABORT, 0, 0, 0, 0, 0, 0, 0, 0);
+ return;
+ }
+ shared_fb_data = (synth_fb_data*)cyg_hal_sys_mmap(0,
+ sizeof(synth_fb_data) + (fb->fb_height * fb->fb_stride * fb->fb_driver1),
+ CYG_HAL_SYS_PROT_READ | CYG_HAL_SYS_PROT_WRITE,
+ CYG_HAL_SYS_MAP_SHARED,
+ fd,
+ 0
+ );
+ if (shared_fb_data <= 0) {
+ synth_auxiliary_xchgmsg(local_fb_data->devid, SYNTH_FB_ABORT, 0, 0, 0, 0, 0, 0, 0, 0);
+ cyg_hal_sys_close(fd);
+ return;
+ }
+ DEBUG(1, "target: mmap()'d shared memory region -> %p\n", shared_fb_data);
+ shared_fb_data->devid = local_fb_data->devid;
+
+ // Next filename is the fifo to the framebuf program.
+ filename = ptr;
+ for (ptr = device_data; *ptr != ';'; ptr++)
+ ;
+ *ptr++ = '\0';
+ DEBUG(1, "target: Opening fifo to framebuf %s\n", filename);
+ shared_fb_data->fifo_to_framebuf = cyg_hal_sys_open(filename, CYG_HAL_SYS_O_WRONLY, 0);
+ if (shared_fb_data->fifo_to_framebuf < 0) {
+ synth_auxiliary_xchgmsg(shared_fb_data->devid, SYNTH_FB_ABORT, 0, 0, 0, 0, 0, 0, 0, 0);
+ cyg_hal_sys_close(fd);
+ return;
+ }
+ // And finally the fifo from the framebuf program.
+ filename = ptr;
+ for (ptr = device_data; *ptr != ';'; ptr++)
+ ;
+ *ptr = '\0';
+ DEBUG(1, "target: Opening fifo from framebuf %s\n", filename);
+ shared_fb_data->fifo_from_framebuf = cyg_hal_sys_open(filename, CYG_HAL_SYS_O_RDONLY, 0);
+ if (shared_fb_data->fifo_from_framebuf < 0) {
+ synth_auxiliary_xchgmsg(shared_fb_data->devid, SYNTH_FB_ABORT, 0, 0, 0, 0, 0, 0, 0, 0);
+ cyg_hal_sys_close(fd);
+ cyg_hal_sys_close(shared_fb_data->fifo_to_framebuf);
+ return;
+ }
+
+ // We have a shared memory region and the two files. Copy
+ // all existing fb_data contents (e.g. the palettes) and
+ // the framebuffer contents to the shared memory region.
+ // The MUST_BE_ON flag is not set for synthetic target
+ // framebuffers so there may already be contents.
+ fb_base = (cyg_uint8*)fb->fb_base;
+ fb_base -= (fb->fb_height * fb->fb_stride * shared_fb_data->page_drawable);
+ memcpy(&(shared_fb_data->palette[0]), &(local_fb_data->palette[0]), 3 * 256);
+ memcpy(&(shared_fb_data->framebuf[0]), fb_base, fb->fb_height * fb->fb_stride * fb->fb_driver1);
+ shared_fb_data->connected = 1;
+ fb->fb_driver2 = (CYG_ADDRWORD)shared_fb_data;
+
+ fb_base = (cyg_uint8*)&(shared_fb_data->framebuf[0]);
+ fb_base += (fb->fb_height * fb->fb_stride * shared_fb_data->page_drawable);
+ fb->fb_base = fb_base;
+ *(cyg_uint8**)fb->fb_driver3 = fb_base;
+
+ DEBUG(1, "target: Fully instantiated, fb_data %p, blank_on %d, display_on %d\n",
+ shared_fb_data, shared_fb_data->blank_on, shared_fb_data->display_on);
+ DEBUG(1, "target: devid %d, t2h %d, h2t %d\n",
+ shared_fb_data->devid, shared_fb_data->fifo_to_framebuf, shared_fb_data->fifo_from_framebuf);
+ // Finally tell the framebuf program everything is ready.
+ fb_op(fb, SYNTH_FB_OK);
+ DEBUG(1, "target: Sent SYNTH_FB_OK\n");
+ }
+}
+
+
+// Switch on a framebuffer device. This may get called multiple
+// times, e.g. when switching between different screen modes.
+// It just involves sending a message to the auxiliary.
+static int
+cyg_synth_fb_on(struct cyg_fb* fb)
+{
+ synth_fb_data* fb_data = (synth_fb_data*) fb->fb_driver2;
+ if (fb_data->connected) {
+ synth_auxiliary_xchgmsg(fb_data->devid, SYNTH_FB_ON, 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+
+ return 0;
+}
+
+static int
+cyg_synth_fb_off(struct cyg_fb* fb)
+{
+ synth_fb_data* fb_data = (synth_fb_data*) fb->fb_driver2;
+ if (fb_data->connected) {
+ synth_auxiliary_xchgmsg(fb_data->devid, SYNTH_FB_OFF, 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+ return 0;
+}
+
+static int
+cyg_synth_fb_ioctl(struct cyg_fb* fb, cyg_ucount16 key, void* data, size_t* len)
+{
+ synth_fb_data* fb_data = (synth_fb_data*) fb->fb_driver2;
+ int result = ENOSYS;
+
+ switch(key) {
+ case CYG_FB_IOCTL_VIEWPORT_GET_POSITION:
+ DEBUG(1, "cyg_synth_fb_ioctl: viewport_get_position\n");
+ if (fb->fb_flags0 & CYG_FB_FLAGS0_VIEWPORT) {
+ cyg_fb_ioctl_viewport* viewport = (cyg_fb_ioctl_viewport*)data;
+ CYG_ASSERT(*len == sizeof(cyg_fb_ioctl_viewport), "data argument should be a cyg_fb_ioctl_viewport structure");
+ viewport->fbvp_x = fb_data->viewport_x;
+ viewport->fbvp_y = fb_data->viewport_y;
+ result = 0;
+ DEBUG(1, " : current viewport x %d, y %d\n", fb_data->viewport_x, fb_data->viewport_y);
+ } else {
+ DEBUG(1, " : framebuffer does not support a viewport\n");
+ }
+ break;
+ case CYG_FB_IOCTL_VIEWPORT_SET_POSITION:
+ DEBUG(1, "cyg_synth_fb_ioctl: viewport_set_position\n");
+ if (fb->fb_flags0 & CYG_FB_FLAGS0_VIEWPORT) {
+ cyg_fb_ioctl_viewport* viewport = (cyg_fb_ioctl_viewport*)data;
+ CYG_ASSERT(*len == sizeof(cyg_fb_ioctl_viewport), "data argument should be a cyg_fb_ioctl_viewport structure");
+ CYG_ASSERT(((viewport->fbvp_x + fb->fb_viewport_width) <= fb->fb_width) &&
+ ((viewport->fbvp_y + fb->fb_viewport_height) <= fb->fb_height),
+ "viewport should be within framebuffer dimensions");
+ DEBUG(1, " : setting viewport from x %d, y %d to x %d, y %d\n",
+ fb_data->viewport_x, fb_data->viewport_y, (int) viewport->fbvp_x, (int) viewport->fbvp_y);
+ if ((fb_data->viewport_x != (int)viewport->fbvp_x) || (fb_data->viewport_y != (int)viewport->fbvp_y)) {
+ fb_data->viewport_x = (int)viewport->fbvp_x;
+ fb_data->viewport_y = (int)viewport->fbvp_y;
+ fb_op(fb, SYNTH_FB_VIEWPORT);
+ }
+ result = 0;
+ } else {
+ DEBUG(1, " : framebuffer does not support a viewport\n");
+ }
+ break;
+ case CYG_FB_IOCTL_PAGE_FLIPPING_GET_PAGES:
+ DEBUG(1, "cyg_synth_fb_ioctl: page_flipping_get_pages\n");
+ if (fb->fb_flags0 & CYG_FB_FLAGS0_PAGE_FLIPPING) {
+ cyg_fb_ioctl_page_flip* page_flip = (cyg_fb_ioctl_page_flip*)data;
+ CYG_ASSERT(*len == sizeof(cyg_fb_ioctl_page_flip), "data argument should be a cyg_fb_ioctl_page_flip structure");
+ page_flip->fbpf_number_pages = fb->fb_driver1;
+ page_flip->fbpf_visible_page = fb_data->page_visible;
+ page_flip->fbpf_drawable_page = fb_data->page_drawable;
+ result = 0;
+ DEBUG(1, " : number_pages %d, visible page %d, drawable page %d\n",
+ fb->fb_driver1, fb_data->page_visible, fb_data->page_drawable);
+ } else {
+ DEBUG(1, " : framebuffer does not support page flipping\n");
+ }
+ break;
+ case CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES:
+ DEBUG(1, "cyg_synth_fb_ioctl: page_flipping_set_pages\n");
+ if (fb->fb_flags0 & CYG_FB_FLAGS0_PAGE_FLIPPING) {
+ cyg_fb_ioctl_page_flip* page_flip = (cyg_fb_ioctl_page_flip*)data;
+ cyg_uint8* fb_base;
+
+ CYG_ASSERT(*len == sizeof(cyg_fb_ioctl_page_flip), "data argument should be a cyg_fb_ioctl_page_flip structure");
+ CYG_ASSERT((page_flip->fbpf_visible_page < fb->driver1) &&
+ (page_flip->fbpf_drawable_page < fb->driver1),
+ "framebuffer does not have that many pages");
+ DEBUG(1, " : drawable page was %d, now %d, visible page was %d, now %d\n",
+ fb_data->page_drawable, (int)page_flip->fbpf_drawable_page,
+ fb_data->page_visible, (int)page_flip->fbpf_visible_page);
+ fb_base = (cyg_uint8*)fb->fb_base;
+ fb_base -= (fb->fb_height * fb->fb_stride * fb_data->page_drawable);
+ fb_data->page_drawable = page_flip->fbpf_drawable_page;
+ fb_base += (fb->fb_height * fb->fb_stride * fb_data->page_drawable);
+ fb->fb_base = fb_base;
+ *(cyg_uint8**)fb->fb_driver3 = fb_base;
+ if (fb_data->page_visible != (int)page_flip->fbpf_visible_page) {
+ fb_data->page_visible = (int)page_flip->fbpf_visible_page;
+ fb_op(fb, SYNTH_FB_PAGE_FLIP);
+ }
+ result = 0;
+ } else {
+ DEBUG(1, " : framebuffer does not support page flipping\n");
+ }
+ break;
+ case CYG_FB_IOCTL_BLANK_GET:
+ {
+ cyg_fb_ioctl_blank* blank = (cyg_fb_ioctl_blank*)data;
+ DEBUG(1, "cyg_synth_fb_ioctl: blank_get, current on state %d\n", fb_data->blank_on);
+ CYG_ASSERT(*len == sizeof(cyg_fb_ioctl_blank), "data argument should be a cyg_fb_ioctl_blank structure");
+ blank->fbbl_on = fb_data->blank_on;
+ result = 0;
+ }
+ break;
+ case CYG_FB_IOCTL_BLANK_SET:
+ {
+ cyg_fb_ioctl_blank* blank = (cyg_fb_ioctl_blank*)data;
+ CYG_ASSERT(*len == sizeof(cyg_fb_ioctl_blank), "data argument should be a cyg_fb_ioctl_blank structure");
+ DEBUG(1, "cyg_synth_fb_ioctl: blank_set, on was %d, now %d\n", fb_data->blank_on, blank->fbbl_on);
+ if (blank->fbbl_on != fb_data->blank_on) {
+ fb_data->blank_on = blank->fbbl_on;
+ fb_op(fb, SYNTH_FB_BLANK);
+ }
+ result = 0;
+ }
+ break;
+ default:
+ result = ENOSYS;
+ break;
+ }
+ return result;
+}
+
+void
+cyg_synth_fb_synch(struct cyg_fb* fb, cyg_ucount16 when)
+{
+ // FIXME: update synch_x0/y0/x1/y1 once the generic framebuffer
+ // code actually maintains a bounding box.
+ fb_op(fb, SYNTH_FB_SYNC);
+}
+
+#ifdef CYGHWR_DEVS_FRAMEBUF_SYNTH_FUNCTIONALITY_PALETTED
+// The palette is held in the synth_fb_data structure.
+static void
+cyg_synth_fb_read_palette(struct cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, void* dest)
+{
+ synth_fb_data* fb_data = (synth_fb_data*) fb->fb_driver2;
+ CYG_ASSERT(fb->fb_flags0 & CYG_FB_FLAGS0_PALETTE, "reading palette of non-paletted display");
+ CYG_ASSERT((first + count) <= (0x01 << fb->fb_depth), "palette size exceeded");
+
+ memcpy(dest, &(fb_data->palette[3 * first]), 3 * count);
+}
+
+static void
+cyg_synth_fb_write_palette(struct cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, const void* source, cyg_ucount16 when)
+{
+ synth_fb_data* fb_data = (synth_fb_data*) fb->fb_driver2;
+ CYG_ASSERT(fb->fb_flags0 & CYG_FB_FLAGS0_PALETTE, "reading palette of non-paletted display");
+ CYG_ASSERT((first + count) <= (0x01 << fb->fb_depth), "palette size exceeded");
+
+ DEBUG(1, "write_palette: fb %p, first %d, count %d, source %p\n", fb, first, count, source);
+ memcpy(&(fb_data->palette[3 * first]), source, 3 * count);
+ fb_op(fb, SYNTH_FB_WRITE_PALETTE);
+ CYG_UNUSED_PARAM(cyg_ucount16, when);
+}
+#endif
+
+#define LINEAR1(_fn_, _suffix_) cyg_fb_linear_ ## _fn_ ## _ ## _suffix_
+#define LINEAR( _fn_, _suffix_) LINEAR1(_fn_, _suffix_)
+
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB0
+# ifdef CYGNUM_DEVS_FRAMEBUF_SYNTH_FB0_PAGE_FLIPPING
+# define FB0_PAGES CYGNUM_DEVS_FRAMEBUF_SYNTH_FB0_PAGE_FLIPPING
+# else
+# define FB0_PAGES 1
+#endif
+
+// A default area of memory for the framebuffer, if the auxiliary is not
+// running.
+static cyg_uint8 cyg_synth_fb0_default_base[CYG_FB_fb0_HEIGHT * CYG_FB_fb0_STRIDE * FB0_PAGES];
+
+// Pointer to framebuffer memory. This defaults to a statically
+// allocated memory but will switch to a shared memory region if
+// the auxiliary is running. It may also change if page flipping
+// is enabled.
+cyg_uint8* cyg_synth_fb0_base = cyg_synth_fb0_default_base;
+
+// Driver-specific data needed for interacting with the auxiliary.
+static synth_fb_data cyg_synth_fb0_data;
+
+CYG_FB_FRAMEBUFFER(CYG_FB_fb0_STRUCT,
+ CYG_FB_fb0_DEPTH,
+ CYG_FB_fb0_FORMAT,
+ CYG_FB_fb0_WIDTH,
+ CYG_FB_fb0_HEIGHT,
+ CYG_FB_fb0_VIEWPORT_WIDTH,
+ CYG_FB_fb0_VIEWPORT_HEIGHT,
+ cyg_synth_fb0_default_base,
+ CYG_FB_fb0_STRIDE,
+ CYG_FB_fb0_FLAGS0,
+ CYG_FB_fb0_FLAGS1,
+ CYG_FB_fb0_FLAGS2,
+ CYG_FB_fb0_FLAGS3,
+ (CYG_ADDRWORD) 0, // id, 0 - 3
+ (CYG_ADDRWORD) FB0_PAGES,
+ (CYG_ADDRWORD) &cyg_synth_fb0_data,
+ (CYG_ADDRWORD) &cyg_synth_fb0_base,
+ &cyg_synth_fb_on,
+ &cyg_synth_fb_off,
+ &cyg_synth_fb_ioctl,
+ &cyg_synth_fb_synch,
+ &CYG_FB_fb0_READ_PALETTE_FN,
+ &CYG_FB_fb0_WRITE_PALETTE_FN,
+ &CYG_FB_fb0_MAKE_COLOUR_FN,
+ &CYG_FB_fb0_BREAK_COLOUR_FN,
+ LINEAR(write_pixel, CYG_FB_fb0_SUFFIX),
+ LINEAR(read_pixel, CYG_FB_fb0_SUFFIX),
+ LINEAR(write_hline, CYG_FB_fb0_SUFFIX),
+ LINEAR(write_vline, CYG_FB_fb0_SUFFIX),
+ LINEAR(fill_block, CYG_FB_fb0_SUFFIX),
+ LINEAR(write_block, CYG_FB_fb0_SUFFIX),
+ LINEAR(read_block, CYG_FB_fb0_SUFFIX),
+ LINEAR(move_block, CYG_FB_fb0_SUFFIX),
+ 0, 0, 0, 0 // Spare0 -> spare3
+ );
+
+#endif
+
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB1
+
+# ifdef CYGNUM_DEVS_FRAMEBUF_SYNTH_FB1_PAGE_FLIPPING
+# define FB1_PAGES CYGNUM_DEVS_FRAMEBUF_SYNTH_FB1_PAGE_FLIPPING
+# else
+# define FB1_PAGES 1
+#endif
+static cyg_uint8 cyg_synth_fb1_default_base[CYG_FB_fb1_HEIGHT * CYG_FB_fb1_STRIDE * FB1_PAGES];
+cyg_uint8* cyg_synth_fb1_base = cyg_synth_fb1_default_base;
+static synth_fb_data cyg_synth_fb1_data;
+
+CYG_FB_FRAMEBUFFER(CYG_FB_fb1_STRUCT,
+ CYG_FB_fb1_DEPTH,
+ CYG_FB_fb1_FORMAT,
+ CYG_FB_fb1_WIDTH,
+ CYG_FB_fb1_HEIGHT,
+ CYG_FB_fb1_VIEWPORT_WIDTH,
+ CYG_FB_fb1_VIEWPORT_HEIGHT,
+ cyg_synth_fb1_default_base,
+ CYG_FB_fb1_STRIDE,
+ CYG_FB_fb1_FLAGS0,
+ CYG_FB_fb1_FLAGS1,
+ CYG_FB_fb1_FLAGS2,
+ CYG_FB_fb1_FLAGS3,
+ (CYG_ADDRWORD) 1, // id, 0 - 3
+ (CYG_ADDRWORD) FB1_PAGES,
+ (CYG_ADDRWORD) &cyg_synth_fb1_data,
+ (CYG_ADDRWORD) &cyg_synth_fb1_base,
+ &cyg_synth_fb_on,
+ &cyg_synth_fb_off,
+ &cyg_synth_fb_ioctl,
+ &cyg_synth_fb_synch,
+ &CYG_FB_fb1_READ_PALETTE_FN,
+ &CYG_FB_fb1_WRITE_PALETTE_FN,
+ &CYG_FB_fb1_MAKE_COLOUR_FN,
+ &CYG_FB_fb1_BREAK_COLOUR_FN,
+ LINEAR(write_pixel, CYG_FB_fb1_SUFFIX),
+ LINEAR(read_pixel, CYG_FB_fb1_SUFFIX),
+ LINEAR(write_hline, CYG_FB_fb1_SUFFIX),
+ LINEAR(write_vline, CYG_FB_fb1_SUFFIX),
+ LINEAR(fill_block, CYG_FB_fb1_SUFFIX),
+ LINEAR(write_block, CYG_FB_fb1_SUFFIX),
+ LINEAR(read_block, CYG_FB_fb1_SUFFIX),
+ LINEAR(move_block, CYG_FB_fb1_SUFFIX),
+ 0, 0, 0, 0 // Spare0 -> spare3
+ );
+
+#endif
+
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB2
+
+# ifdef CYGNUM_DEVS_FRAMEBUF_SYNTH_FB2_PAGE_FLIPPING
+# define FB2_PAGES CYGNUM_DEVS_FRAMEBUF_SYNTH_FB2_PAGE_FLIPPING
+# else
+# define FB2_PAGES 1
+#endif
+static cyg_uint8 cyg_synth_fb2_default_base[CYG_FB_fb2_HEIGHT * CYG_FB_fb2_STRIDE * FB2_PAGES];
+cyg_uint8* cyg_synth_fb2_base = cyg_synth_fb2_default_base;
+static synth_fb_data cyg_synth_fb2_data;
+
+CYG_FB_FRAMEBUFFER(CYG_FB_fb2_STRUCT,
+ CYG_FB_fb2_DEPTH,
+ CYG_FB_fb2_FORMAT,
+ CYG_FB_fb2_WIDTH,
+ CYG_FB_fb2_HEIGHT,
+ CYG_FB_fb2_VIEWPORT_WIDTH,
+ CYG_FB_fb2_VIEWPORT_HEIGHT,
+ cyg_synth_fb2_default_base,
+ CYG_FB_fb2_STRIDE,
+ CYG_FB_fb2_FLAGS0,
+ CYG_FB_fb2_FLAGS1,
+ CYG_FB_fb2_FLAGS2,
+ CYG_FB_fb2_FLAGS3,
+ (CYG_ADDRWORD) 2, // id, 0 - 3
+ (CYG_ADDRWORD) FB2_PAGES,
+ (CYG_ADDRWORD) &cyg_synth_fb2_data,
+ (CYG_ADDRWORD) &cyg_synth_fb2_base,
+ &cyg_synth_fb_on,
+ &cyg_synth_fb_off,
+ &cyg_synth_fb_ioctl,
+ &cyg_synth_fb_synch,
+ &CYG_FB_fb2_READ_PALETTE_FN,
+ &CYG_FB_fb2_WRITE_PALETTE_FN,
+ &CYG_FB_fb2_MAKE_COLOUR_FN,
+ &CYG_FB_fb2_BREAK_COLOUR_FN,
+ LINEAR(write_pixel, CYG_FB_fb2_SUFFIX),
+ LINEAR(read_pixel, CYG_FB_fb2_SUFFIX),
+ LINEAR(write_hline, CYG_FB_fb2_SUFFIX),
+ LINEAR(write_vline, CYG_FB_fb2_SUFFIX),
+ LINEAR(fill_block, CYG_FB_fb2_SUFFIX),
+ LINEAR(write_block, CYG_FB_fb2_SUFFIX),
+ LINEAR(read_block, CYG_FB_fb2_SUFFIX),
+ LINEAR(move_block, CYG_FB_fb2_SUFFIX),
+ 0, 0, 0, 0 // Spare0 -> spare3
+ );
+
+#endif
+
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB3
+
+# ifdef CYGNUM_DEVS_FRAMEBUF_SYNTH_FB3_PAGE_FLIPPING
+# define FB3_PAGES CYGNUM_DEVS_FRAMEBUF_SYNTH_FB3_PAGE_FLIPPING
+# else
+# define FB3_PAGES 1
+#endif
+static cyg_uint8 cyg_synth_fb3_default_base[CYG_FB_fb3_HEIGHT * CYG_FB_fb3_STRIDE * FB3_PAGES];
+cyg_uint8* cyg_synth_fb3_base = cyg_synth_fb3_default_base;
+static synth_fb_data cyg_synth_fb3_data;
+
+CYG_FB_FRAMEBUFFER(CYG_FB_fb3_STRUCT,
+ CYG_FB_fb3_DEPTH,
+ CYG_FB_fb3_FORMAT,
+ CYG_FB_fb3_WIDTH,
+ CYG_FB_fb3_HEIGHT,
+ CYG_FB_fb3_VIEWPORT_WIDTH,
+ CYG_FB_fb3_VIEWPORT_HEIGHT,
+ cyg_synth_fb3_default_base,
+ CYG_FB_fb3_STRIDE,
+ CYG_FB_fb3_FLAGS0,
+ CYG_FB_fb3_FLAGS1,
+ CYG_FB_fb3_FLAGS2,
+ CYG_FB_fb3_FLAGS3,
+ (CYG_ADDRWORD) 3, // id, 0 - 3
+ (CYG_ADDRWORD) FB3_PAGES,
+ (CYG_ADDRWORD) &cyg_synth_fb3_data,
+ (CYG_ADDRWORD) &cyg_synth_fb3_base,
+ &cyg_synth_fb_on,
+ &cyg_synth_fb_off,
+ &cyg_synth_fb_ioctl,
+ &cyg_synth_fb_synch,
+ &CYG_FB_fb3_READ_PALETTE_FN,
+ &CYG_FB_fb3_WRITE_PALETTE_FN,
+ &CYG_FB_fb3_MAKE_COLOUR_FN,
+ &CYG_FB_fb3_BREAK_COLOUR_FN,
+ LINEAR(write_pixel, CYG_FB_fb3_SUFFIX),
+ LINEAR(read_pixel, CYG_FB_fb3_SUFFIX),
+ LINEAR(write_hline, CYG_FB_fb3_SUFFIX),
+ LINEAR(write_vline, CYG_FB_fb3_SUFFIX),
+ LINEAR(fill_block, CYG_FB_fb3_SUFFIX),
+ LINEAR(write_block, CYG_FB_fb3_SUFFIX),
+ LINEAR(read_block, CYG_FB_fb3_SUFFIX),
+ LINEAR(move_block, CYG_FB_fb3_SUFFIX),
+ 0, 0, 0, 0 // Spare0 -> spare3
+ );
+
+#endif
Index: src/synthfb_init.cxx
===================================================================
RCS file: src/synthfb_init.cxx
diff -N src/synthfb_init.cxx
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/synthfb_init.cxx 7 Oct 2008 21:00:34 -0000
@@ -0,0 +1,70 @@
+//==========================================================================
+//
+// synthfb_init.cxx
+//
+// Instantiate one or more framebuffer devices for the synthetic target.
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s): bartv
+// Date: 2007-02-0
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <pkgconf/devs_framebuf_synth.h>
+#include <cyg/io/framebuf.h>
+
+extern "C" void _cyg_synth_fb_instantiate(struct cyg_fb*);
+
+class _synth_fb_init {
+
+ public:
+ _synth_fb_init(void)
+ {
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB0
+ _cyg_synth_fb_instantiate(&cyg_synth_fb0);
+#endif
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB1
+ _cyg_synth_fb_instantiate(&cyg_synth_fb1);
+#endif
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB2
+ _cyg_synth_fb_instantiate(&cyg_synth_fb2);
+#endif
+#ifdef CYGPKG_DEVS_FRAMEBUF_SYNTH_FB3
+ _cyg_synth_fb_instantiate(&cyg_synth_fb3);
+#endif
+ }
+};
+
+static _synth_fb_init _synth_fb_init_object CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);