This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
framebuffer contribution
- From: Bart Veer <bartv at ecoscentric dot com>
- To: ecos-patches at sourceware dot org
- Date: Tue, 07 Oct 2008 11:13:24 +0100
- Subject: framebuffer contribution
This patch is a contribution of eCosCentric's generic framebuffer
support. The original driving force behind this code was to facilitate
porting of Swell Software's PEG and C/PEG libraries. However the code
is general-purpose and should be readily usable for porting other
higher-level graphics libraries, or for use directly by application
code.
The current code is incomplete in various ways. It only supports
displays with depths of 8 bits/pixel, 16bpp or 32bpp. The design also
allows for 1bpp, 2bpp and 4bpp displays but there is no implementation
yet for these. An important optimization for double-buffered displays,
bounding boxes, is still missing. However, within these limitations,
the code has already proved valuable.
A reference device driver will follow soon.
Bart
Index: ChangeLog
===================================================================
RCS file: ChangeLog
diff -N ChangeLog
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ChangeLog 7 Oct 2008 10:02:55 -0000
@@ -0,0 +1,68 @@
+2008-10-06 Bart Veer <bartv@ecoscentric.com>
+
+ * src/gen_framebufs.tcl, cdl/framebuf.cdl, tests/*: add some
+ examples/testcases.
+
+2007-10-11 Bart Veer <bartv@ecoscentric.com>
+
+ * include/framebuf.h: fix 555 true colour manipulation macros.
+
+2006-04-05 John Dallaway <jld@ecoscentric.com>
+
+ * cdl/framebuf.cdl: Add reference to package documentation.
+
+2005-11-21 Bart Veer <bartv@ecoscentric.com>
+
+ * include/framebuf.h, src/framebuf.c: fix aliasing of the
+ make/break colour functions, needed with more recent compilers.
+
+ * doc/framebuf.sgml: fix blanking support typo
+
+ * cdl/framebuf.cdl: run gen_framebufs.tcl slightly later
+ in the build process in case other packages create framebuf header
+ files at build-time.
+
+ * src/gen_framebufs.tcl: fix typo in diagnostic.
+
+ * src/framebuf.c (cyg_fb_synch), include/framebuf.h
+ (CYG_FB_FRAMEBUFFER): fix double buffer support.
+
+2005-06-20 John Dallaway <jld@ecoscentric.com>
+
+ * doc/framebuf.sgml: Fix typographical errors.
+
+2005-03-29 Bart Veer <bartv@ecoscentric.com>
+
+ * Generic framebuffer package created
+
+//===========================================================================
+//####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.cdl
===================================================================
RCS file: cdl/framebuf.cdl
diff -N cdl/framebuf.cdl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cdl/framebuf.cdl 7 Oct 2008 10:02:55 -0000
@@ -0,0 +1,232 @@
+# ====================================================================
+#
+# framebuf.cdl
+#
+# Generic framebuffer package configuration data
+#
+# ====================================================================
+#####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-03-29
+#
+#####DESCRIPTIONEND####
+#========================================================================
+
+cdl_package CYGPKG_IO_FRAMEBUF {
+ display "Framebuffer support"
+ doc ref/io-framebuf.html
+ requires CYGPKG_INFRA CYGPKG_HAL CYGPKG_ERROR
+ include_dir cyg/io
+ compile framebuf.c linear.c palette.c
+
+ # A custom build step to generate a single header with details of all
+ # the framebuffers for this target. The dependency on <pkgconf/system.h>
+ # copes with the case of a framebuffer device driver package being removed
+ make -priority 2 {
+ $(PREFIX)/include/cyg/io/framebufs/framebufs.h : $(REPOSITORY)/$(PACKAGE)/src/gen_framebufs.tcl \
+ $(PREFIX)/include/pkgconf/system.h \
+ $(subst $(PREFIX)/include/cyg/io/framebufs/framebufs.h,,$(wildcard $(PREFIX)/include/cyg/io/framebufs/*.h*))
+ sh $< $(dir $@)
+ }
+
+ description "
+ The generic framebuffer package provides an API for accessing
+ one or more framebuffers, plus support for appropriate device
+ drivers."
+
+ cdl_interface CYGINT_IO_FRAMEBUF_DEVICES {
+ display "Number of available framebuffer devices"
+ flavor data
+ description "
+ This interface specifies the number of framebuffer devices
+ supported by device driver(s) on this platform."
+ }
+
+ cdl_option CYGDAT_IO_FRAMEBUF_DEVICES {
+ display "Names of available framebuffer devices"
+ default_value { "" }
+ flavor data
+ description "
+ This option provides a list of the framebuffer devices available
+ on the current platform. It is controlled by the appropriate
+ device driver(s) and should not be edited by users."
+ }
+
+ cdl_option CYGDAT_IO_FRAMEBUF_TEST_DEVICE {
+ display "Framebuffer device to use for testing"
+ active_if CYGINT_IO_FRAMEBUF_DEVICES
+ flavor booldata
+ default_value 0
+ requires { is_substr(CYGDAT_IO_FRAMEBUF_DEVICES, " " . CYGDAT_IO_FRAMEBUF_TEST_DEVICE . " ") }
+ description "
+ This option determines the framebuffer device to be used for running
+ the testcases. By default the build system will automatically select
+ the first entry in CYGDAT_IO_FRAMEBUF_DEVICES, which will be the
+ only entry if there is only framebuffer device in the system."
+ }
+
+ cdl_component CYGPKG_IO_FRAMEBUF_FUNCTIONALITY {
+ display "Functionality supported by the platform's framebuffer(s)"
+ flavor none
+ description "
+ This component holds details of the functionality provided by the
+ framebuffer device driver(s) for the current platform."
+
+ cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_32BPP {
+ display "32bpp pixel support required"
+ flavor booldata
+ description "
+ This interface will be implemented if any of the framebuffer
+ device drivers for the current platform provides a 32 bits
+ per pixel display. This constrains the cyg_colour data type
+ to be at least 32 bits."
+ }
+
+ cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR {
+ display "Framebuffer supports true colour mode"
+ flavor booldata
+ define CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOR
+ description "
+ This interface will be implemented if any of the framebuffer
+ device drivers for the current platform support true colour
+ operation. In other words the contents of the framebuffer
+ defines the colours directly and there is no indirection via
+ a palette."
+ }
+
+ cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE {
+ display "Framebuffer uses a palette for colours"
+ flavor booldata
+ description "
+ This interface will be implemented if any of the framebuffer
+ device drivers for the current platform use a palette. In
+ other words the contents of the framebuffer's memory do not
+ represent colours directly, but instead are treated as indices
+ into a separate table known as the palette."
+ }
+
+ cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE {
+ display "Framebuffer uses a writeable palette for colours"
+ flavor booldata
+ description "
+ This interface will be implemented if any of the framebuffer
+ device drivers for the current platform use a palette, and this
+ palette can be modified at run-time. In other words the contents
+ of the framebuffer's memory do not represent colours directly,
+ but instead are treated as indices into a separate table known
+ as the palette."
+ }
+
+ cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT {
+ display "Framebuffer provides viewport support"
+ flavor booldata
+ description "
+ This interface will be implemented if any of the framebuffer
+ device drivers for the current platform provide viewport support.
+ 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_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER {
+ display "Framebuffer provides double buffering support"
+ flavor booldata
+ description "
+ This interface will be implemented if any of the framebuffer
+ device drivers for the current platform provide support for
+ double buffering. In other words the framebuffer memory that
+ is updated by graphics operations is not what actually gets
+ displayed. Instead there is a separate hidden area of memory
+ used for the display, and when drawing is complete a flush
+ operation is needed to move the framebuffer contents to that
+ hidden area. This makes it possible to update the display more
+ smoothly, at the cost of potentially expensive memory copy
+ operations."
+ }
+ }
+
+ cdl_option CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE {
+ display "Framebuffers should install a default palette"
+ flavor bool
+ default_value 1
+ active_if CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+ description "
+ Framebuffer devices which involve a writeable palette may set this
+ to a default palette when activated by cyg_fb_on() or equivalent
+ functionality. This is useful when the application will access the
+ framebuffer directly. It is less useful if a higher-level graphics
+ library is in use because typically that will install its own
+ palette, and typically there is a code/data overhead of approximately 1K."
+ }
+
+ cdl_component CYGPKG_IO_FRAMEBUF_OPTIONS {
+ display "Framebuffer build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building the generic frame
+ buffer package, and details of which tests are built."
+
+ cdl_option CYGPKG_IO_FRAMEBUF_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the generic framebuffer package. These flags
+ are used in addition to the set of global flags."
+ }
+
+ cdl_option CYGPKG_IO_FRAMEBUF_CFLAGS_REMOVE {
+ display "Suppressed compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the generic framebuffer package. These flags
+ are removed from the set of global flags if present."
+ }
+
+ cdl_option CYGPKG_IO_FRAMEBUF_TESTS {
+ display "Framebuffer tests"
+ active_if CYGINT_IO_FRAMEBUF_DEVICES
+ flavor booldata
+ calculated { "tests/fb tests/fbmacro" }
+ description "
+ This option specifies the set of tests for the framebuffer package"
+ }
+ }
+}
Index: doc/framebuf.sgml
===================================================================
RCS file: doc/framebuf.sgml
diff -N doc/framebuf.sgml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ doc/framebuf.sgml 7 Oct 2008 10:03:01 -0000
@@ -0,0 +1,2914 @@
+<!-- DOCTYPE part PUBLIC "-//OASIS//DTD DocBook V3.1//EN" -->
+
+<!-- {{{ Banner -->
+
+<!-- =============================================================== -->
+<!-- -->
+<!-- framebuf.sgml -->
+<!-- -->
+<!-- Generic framebuffer documentation. -->
+<!-- -->
+<!-- =============================================================== -->
+<!-- ####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 -->
+<!-- Date: 2005/03/29 -->
+<!-- -->
+<!-- ####DESCRIPTIONEND#### -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<part id="io-framebuf"><title>Framebuffer Support</title>
+
+<!-- {{{ Overview -->
+
+<refentry id="framebuf">
+ <refmeta>
+ <refentrytitle>Overview</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Overview</refname>
+ <refpurpose>eCos Support for Framebuffer Devices</refpurpose>
+ </refnamediv>
+
+ <refsect1 id="framebuf-description">
+ <title>Description</title>
+ <para>
+Framebuffer devices are the most common way for a computer system to
+display graphical output to users. There are immense variations in the
+implementations of such devices. <varname>CYGPKG_IO_FRAMEBUF</varname>
+provides an abstraction layer for use by application code and other
+packages. It defines an API for manipulating framebuffers, mapping
+this API on to functionality provided by the appropriate device
+driver. It also defines the interface which such device drivers should
+implement. For simple hardware it provides default implementations of
+much of this interface, greatly reducing the effort needed to write a
+device driver.
+ </para>
+ <para>
+This package does not constitute a graphics library. It does not
+implement functionality like drawing text or arbitrary lines, let
+alone any kind of windowing system. Instead it operates at the lower
+level of individual pixels and blocks of pixels, in addition to
+control operations such as hardware initialization. Some applications
+may use the framebuffer API directly. Others will instead use a
+higher-level graphics library, and it is that library which uses the
+framebuffer API.
+ </para>
+ <para>
+It is assumed that users are already familiar with the fundamentals of
+computer graphics, and no attempt is made here to explain terms like
+display depth, palette or pixel.
+ </para>
+ <note>
+ <para>
+This package is work-in-progress. The support for 1bpp, 2bpp and 4bpp
+display depths is incomplete. For double-buffered displays the code
+does not yet maintain a bounding box of the updated parts of the
+display. The package has also been designed to allow for
+<link linkend="framebuf-porting-expansion">expansion</link> with new
+functionality.
+ </para>
+ </note>
+ </refsect1>
+
+ <refsect1 id="framebuf-configuration">
+ <title>Configuration</title>
+ <para>
+<varname>CYGPKG_IO_FRAMEBUF</varname> only contains
+hardware-independent code. It should be complemented by one or more
+framebuffer device drivers appropriate for the target platform. These
+drivers may be specific to the platform, or they may be more generic
+with platform-specific details such as the framebuffer memory base
+address provided by the platform HAL. When creating a configuration
+for a given target the device driver(s) will always be included
+automatically (assuming one has been written or ported). However by
+default this driver will be inactive and will not get built, so does
+not add any unnecessary size overhead for applications which do not
+require graphics. To activate the device driver
+<varname>CYGPKG_IO_FRAMEBUF</varname> must be added explicitly to the
+configuration, for example using
+<command>ecosconfig add framebuf</command>. After this the
+full framebuffer API will be available to other packages and to
+application code.
+ </para>
+ <para>
+This package contains very few configuration options. Instead it is
+left to device drivers or higher-level code to provide appropriate
+configurability. One option,
+<varname>CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE</varname>, relates
+to the initialization of <link
+linkend="framebuf-colour-palette">paletted displays</link>.
+ </para>
+ <para>
+There are a number of calculated and inferred configuration options
+and a number of interfaces. These provide information such as whether
+or not there is a backlight. The most important one is
+<varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>, which holds a list of
+framebuffer identifiers for use with the <link
+linkend="framebuf-api">macro-based API</link>. If there is a single
+framebuffer device driver which supports one display in either
+landscape or portrait mode, the configuration option may hold a value
+like <literal> 240x320x8 320x240x8r90</literal>.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-api">
+ <title>Application Programmer Interfaces</title>
+ <para>
+Framebuffer devices require a difficult choice between flexibility and
+performance. On the one hand the API should be able to support
+multiple devices driving separate displays, or a single device
+operating in different modes at different times. On the other hand
+graphics tends to involve very large amounts of I/O: even something as
+simple as drawing a background image can involve setting many
+thousands of pixels. Efficiency requires avoiding all possible
+overheads including function calls. Instead the API should make
+extensive use of macros or inline functions. Ideally details of the
+framebuffer device such as the stride would be known constants at
+compile-time, giving the compiler as much opportunity as possible to
+optimize the code. Clearly this is difficult if multiple framebuffer
+devices are in use or if the device mode may get changed at run-time.
+ </para>
+ <para>
+To meet the conflicting requirements the generic framebuffer package
+provides two APIs: a fast macro API which requires selecting a single
+framebuffer device at compile or configure time; and a slower function
+API without this limitation. The two are very similar, for example:
+ </para>
+ <programlisting width=72>
+#include <cyg/io/framebuf.h>
+
+void
+clear_screen(cyg_fb* fb, cyg_fb_colour colour)
+{
+ cyg_fb_fill_block(fb, 0, 0,
+ fb->fb_width, fb->fb_height,
+ colour);
+}
+ </programlisting>
+ <para>
+or the equivalent macro version:
+ </para>
+<programlisting width=72>
+#include <cyg/io/framebuf.h>
+
+#define FRAMEBUF 240x320x8
+
+void
+clear_screen(cyg_fb_colour colour)
+{
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+ CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+ colour);
+}
+ </programlisting>
+ <para>
+The function-based API works in terms of
+<structname>cyg_fb</structname> structures, containing all the
+information needed to manipulate the device. Each framebuffer device
+driver will export one or more of these structures, for example
+<varname>cyg_alaia_fb_240x320x8</varname>, and the driver
+documentation should list the variable names. The macro API works in
+terms of identifiers such as <literal>240x320x8</literal>, and by a
+series of substitutions the main macro gets expanded to the
+appropriate device-specific code, usually inline. Again the device
+driver documentation should list the supported identifiers. In
+addition the configuration option
+<varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname> will contain the full
+list. By convention the identifier will be specified by a
+<literal>#define</literal>'d symbol such as
+<varname>FRAMEBUF</varname>, or in the case of graphics libraries by a
+configuration option.
+ </para>
+ <para>
+If a platform has multiple framebuffer devices connected to different
+displays then there will be separate <structname>cyg_fb</structname>
+structures and macro identifiers for each one. In addition some
+devices can operate in multiple modes. For example a PC VGA card can
+operate in a monochome 640x480 mode, an 8bpp 320x200 mode, and many
+other modes, but only one of these can be active at a time. The
+different modes are also represented by different
+<structname>cyg_fb</structname> structures and identifiers,
+effectively treating the modes as separate devices. It is the
+responsibility of higher-level code to ensure that only one mode is in
+use at a time.
+ </para>
+ <para>
+It is possible to use the macro API with more than one device,
+basically by compiling the code twice with different values of
+<varname>FRAMEBUF</varname>, taking appropriate care to avoid
+identifier name clashes. This gives the higher performance of the
+macros at the cost of increased code size.
+ </para>
+ <para>
+All of the framebuffer API, including exports of the device-specific
+<structname>cyg_fb</structname> structures, is available through a
+single header file <filename><cyg/io/framebuf.h></filename>. The
+API follows a number of conventions. Coordinates (0,0) correspond to
+the top-left corner of the display. All functions and macros which
+take a pair of coordinates have x first, y second. For block
+operations these coordinates are followed by width, then height.
+Coordinates and dimensions use <type>cyg_ucount16</type> variables,
+which for any processor should be the most efficient unsigned data
+type with at least 16 bits - usually plain unsigned integers. Colours
+are identified by <type>cyg_fb_colour</type> variables, again usually
+unsigned integers.
+ </para>
+ <para>
+To allow for the different variants of the English language, the API
+allows for a number of alternate spellings. Colour and color can be
+used interchangeably, so there are data types
+<type>cyg_fb_colour</type> and <type>cyg_fb_color</type>, and
+functions <function>cyg_fb_make_colour</function> and
+<function>cyg_fb_make_color</function>. Similarly gray is accepted as
+a variant of grey so the predefined colours
+<literal>CYG_FB_DEFAULT_PALETTE_LIGHTGREY</literal> and
+<literal>CYG_FB_DEFAULT_PALETTE_LIGHTGRAY</literal> are equivalent.
+ </para>
+ <para>
+The API is split into the following categories:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><link linkend="framebuf-parameters">parameters</link></term>
+ <listitem><para>
+getting information about a given framebuffer device such as width,
+height and depth. Colours management is complicated so has its own
+<link linkend="framebuf-colour">category</link>.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><link linkend="framebuf-control">control</link></term>
+ <listitem><para>
+operations such as switching the display on and off, and more
+device-specific ones such as manipulating the backlight.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><link linkend="framebuf-colour">colours</link></term>
+ <listitem><para>
+determining the colour format (monochrome, paletted, &hellip),
+manipulating the palette, or constructing true colours.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><link linkend="framebuf-drawing">drawing</link></term>
+ <listitem><para>
+primitives for manipulating pixels and blocks of pixels.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><link linkend="framebuf-iterating">iteration</link></term>
+ <listitem><para>
+efficiently iterating over blocks of pixels.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="framebuf-threads">
+ <title>Thread Safety</title>
+ <para>
+The framebuffer API never performs any locking so is not thread-safe.
+Instead it assumes that higher-level code such as a graphics library
+performs any locking that may be needed. Adding a mutex lock and
+unlock around every drawing primitive, including pixel writes, would
+be prohibitively expensive.
+ </para>
+ <para>
+It is also assumed that the framebuffer will only be updated from
+thread context. With most hardware it will also be possible to access
+a framebuffer from DSR or ISR context, but this should be avoided in
+portable code.
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Framebuffer parameters -->
+
+<refentry id="framebuf-parameters">
+ <refmeta>
+ <refentrytitle>Framebuffer Parameters</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Parameters</refname>
+ <refpurpose>determining framebuffer capabilities</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>
+#include <cyg/io/framebuf.h>
+
+typedef struct cyg_fb {
+ cyg_ucount16 fb_depth;
+ cyg_ucount16 fb_format;
+ cyg_ucount16 fb_width;
+ cyg_ucount16 fb_height;
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+ cyg_ucount16 fb_viewport_width;
+ cyg_ucount16 fb_viewport_height;
+#endif
+ void* fb_base;
+ cyg_ucount16 fb_stride;
+ cyg_uint32 fb_flags0;
+ …
+} cyg_fb;
+ </funcsynopsisinfo>
+ <funcprototype>
+ <funcdef>cyg_fb* <function>CYG_FB_STRUCT</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_DEPTH</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_FORMAT</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_WIDTH</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_HEIGHT</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_VIEWPORT_WIDTH</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_VIEWPORT_HEIGHT</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void* <function>CYG_FB_BASE</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_STRIDE</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_uint32 <function>CYG_FB_FLAGS0</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="framebuf-parameters-description">
+ <title>Description</title>
+ <para>
+When developing an application for a specific platform the various
+framebuffer parameters such as width and height are known, and the
+code can be written accordingly. However when writing code that should
+work on many platforms with different framebuffer devices, for example
+a graphics library, the code must be able to get these parameters and
+adapt.
+ </para>
+ <para>
+Code using the function API can extract the parameters from the
+<structname>cyg_fb</structname> structures at run-time. The macro API
+provides dedicated macros for each parameter. These do not follow the
+usual eCos convention where the result is provided via an extra
+argument. Instead the result is returned as normal, and is guaranteed
+to be a compile-time constant. This allows code like the following:
+ </para>
+ <programlisting width=72>
+#if CYG_FB_DEPTH(FRAMEBUF) < 8
+ …
+#else
+ …
+#endif
+ </programlisting>
+ <para>
+or alternatively:
+ </para>
+ <programlisting width=72>
+ if (CYG_FB_DEPTH(FRAMEBUF) < 8) {
+ …
+ } else {
+ …
+ }
+ </programlisting>
+ <para>
+or:
+ </para>
+ <programlisting width=72>
+ switch (CYG_FB_DEPTH(FRAMEBUF)) {
+ case 1 : … break;
+ case 2 : … break;
+ case 4 : … break;
+ case 8 : … break;
+ case 16 : … break;
+ case 32 : … break;
+ }
+ </programlisting>
+ <para>
+In terms of the code actually generated by the compiler these
+approaches have much the same effect. The macros expand to a
+compile-time constant so unnecessary code can be easily eliminated.
+ </para>
+ <para>
+The available parameters are as follows:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>depth</term>
+ <listitem><para>
+The number of bits per pixel or bpp. The common depths are 1, 2, 4, 8,
+16 and 32.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>format</term>
+ <listitem><para>
+How the pixel values are mapped on to visible <link
+linkend="framebuf-colour">colours</link>, for example true colour
+or paletted or greyscale.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>width</term>
+ <term>height</term>
+ <listitem><para>
+The number of framebuffer pixels horizontally and vertically.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>viewport width</term>
+ <term>viewport height</term>
+ <listitem><para>
+With some devices the framebuffer height and/or width are greater than
+what the display can actually show. The display is said to offer a
+viewport into the larger framebuffer. The number of visible pixels is
+determined from the viewport width and height. The position of the
+viewport is controlled via an <link
+linkend="framebuf-control-ioctl-viewport"><function>ioctl</function></link>.
+Within a <structname>cyg_fb</structname> structure these fields are
+only present if
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT</varname>
+is defined, to avoid wasting data space on fields that are unnecessary
+for the current platform. For the macro API the viewport macros should only be used
+if <literal>CYG_FB_FLAGS0_VIEWPORT</literal> is set for the framebuffer:
+ </para>
+ <programlisting width=72>
+#if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_VIEWPORT)
+ …
+#endif
+ </programlisting></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>base</term>
+ <term>stride</term>
+ <listitem><para>
+For <link linkend="framebuf-parameters-linear">linear</link>
+framebuffers these parameters provide the information needed to access
+framebuffer memory. The stride is in bytes.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>flags0</term>
+ <listitem><para>
+This gives further information about the hardware capabilities.
+Some of this overlaps with other parameters, especially when it comes
+to colour, because it is often easier to test for a single flag than
+for a range of colour modes. The current flags are:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER</literal></term>
+ <listitem><para>
+Framebuffer memory is organized in a conventional fashion and can be
+<link linkend="framebuf-parameters-linear">accessed</link> directly by
+higher-level code using the base and stride parameters.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_LE</literal></term>
+ <listitem><para>
+This flag is only relevant for 1bpp, 2bpp and 4bpp devices and
+controls how the pixels are organized within each byte. If the flag is
+set then the layout is little-endian: for a 1bpp device pixel (0,0)
+occupies bit 0 of the first byte of framebuffer memory. The more
+common layout is big-endian where pixel (0,0) occupies bit 7 of the
+first byte.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_TRUE_COLOUR</literal></term>
+ <listitem><para>
+The framebuffer uses a true colour format where the value of each
+pixel directly encodes the red, green and blue intensities. This is
+common for 16bpp and 32bpp devices, and is occasionally used for 8bpp
+devices.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_PALETTE</literal></term>
+ <listitem><para>
+The framebuffer uses a palette. A pixel value does not directly encode
+the colours, but instead acts as an index into a separate table of
+colour values. That table may be read-only or read-write. Paletted
+displays are common for 8bpp and some 4bpp displays.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal></term>
+ <listitem><para>
+The palette is read-write.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_DELAYED_PALETTE_UPDATE</literal></term>
+ <listitem><para>
+Palette updates can be synchronized to a vertical blank, in other
+words a brief time period when the display is not being updated,
+by using <literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal> as the last
+argument to <function>cyg_fb_write_palette</function> or
+<function>CYG_FB_WRITE_PALETTE</function>. With some hardware updating
+the palette in the middle of a screen update may result in visual noise.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_VIEWPORT</literal></term>
+ <listitem><para>
+The framebuffer contains more pixels than can be shown on the display.
+Instead the display provides a viewport into the framebuffer. An
+<link linkend="framebuf-control-ioctl-viewport"><function>ioctl</function></link>
+can be used to move the viewport.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_DOUBLE_BUFFER</literal></term>
+ <listitem><para>
+The display does not show the current contents of the framebuffer, so
+the results of drawing into the framebuffer are not immediately
+visible. Instead higher-level code needs to perform an explicit
+<link linkend="framebuf-drawing-synch">synch</link> operation to
+update the display.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_PAGE_FLIPPING</literal></term>
+ <listitem><para>
+The hardware supports two or more pages, each of width*height pixels,
+only one of which is visible on the display. This allows higher-level
+code to update one page without disturbing what is currently visible.
+An <link
+linkend="framebuf-control-ioctl-pageflip"><function>ioctl</function></link>
+is used to switch the visible page.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_BLANK</literal></term>
+ <listitem><para>
+The display can be <link linkend="framebuf-control-ioctl-blank">blanked</link>
+without affecting the framebuffer contents or settings.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_BACKLIGHT</literal></term>
+ <listitem><para>
+There is a backlight which can be <link
+linkend="framebuf-control-ioctl-backlight">switched</link>
+on or off. Some hardware provides finer-grained control over the
+backlight intensity.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FLAGS0_MUST_BE_ON</literal></term>
+ <listitem><para>
+Often it is desirable to perform some initialization such as clearing
+the screen or setting the palette before the display is <link
+linkend="framebuf-control-onoff">switched on</link>, to avoid visual
+noise. However not all hardware allows this. If this flag is set then
+it is possible to access framebuffer memory and the palette before the
+<function>cyg_fb_on</function> or <function>CYG_FB_ON</function>
+operation. It may also be possible to perform some other operations
+such as activating the backlight, but that is implementation-defined.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+To allow for future expansion there are also flags1, flags2, and
+flags3 fields. These may get used for encoding additional
+<function>ioctl</function> functionality, support for hardware
+acceleration, and similar features.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-parameters-linear">
+ <title>Linear Framebuffers</title>
+ <para>
+There are drawing primitives for writing and reading individual
+pixels. However these involve a certain amount of arithmetic each time
+to get from a position to an address within the frame buffer, plus
+function call overhead if the function API is used, and this will slow
+down graphics operations.
+ </para>
+ <para>
+When the framebuffer device is known at compile-time and the macro API
+is used then there are additional macros specifically for <link
+linkend="framebuf-iterating">iterating</link> over parts of the frame
+buffer. These should prove very efficient for many graphics
+operations. However if the device is selected at run-time then the
+macros are not appropriate and code may want to manipulate framebuffer
+memory directly. This is possible if two conditions are satisfied:
+ </para>
+ <orderedlist>
+ <listitem><para>
+The <literal>CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER</literal> flag must be
+set. Otherwise framebuffer memory is either not directly accessible or
+has a non-linear layout.
+ </para></listitem>
+ <listitem><para>
+The <literal>CYG_FB_FLAGS0_DOUBLE_BUFFER</literal> flag must be clear.
+An efficient double buffer synch operation requires knowing what part
+of the framebuffer have been updated, and the various drawing
+primitives will keep track of this. If higher-level code then starts
+manipulating the framebuffer directly the synch operation may perform
+only a partial update.
+ </para></listitem>
+ </orderedlist>
+ <para>
+The base, stride, depth, width and height parameters, plus the
+<literal>CYG_FB_FLAGS0_LE</literal> flag for 1bpp, 2bpp and 4bpp
+devices, provide all the information needed to access framebuffer
+memory. A linear framebuffer has pixel (0,0) at the base address.
+Incrementing y means adding stride bytes to the pointer.
+ </para>
+ <para>
+The base and stride parameters may be set even if
+<literal>CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER</literal> is clear. This can
+be useful if for example the display is rotated in software from
+landscape to portrait mode. However the meaning of these parameters
+for non-linear framebuffers is implementation-defined.
+ </para>
+ </refsect1>
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Control Operations -->
+
+<refentry id="framebuf-control">
+ <refmeta>
+ <refentrytitle>Framebuffer Control Operations</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Control Operations</refname>
+ <refpurpose>managing a framebuffer</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>
+#include <cyg/io/framebuf.h>
+ </funcsynopsisinfo>
+ <funcprototype>
+ <funcdef>int <function>cyg_fb_on</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>int <function>cyg_fb_off</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>int <function>cyg_fb_ioctl</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_uint16 <parameter>key</parameter></paramdef>
+ <paramdef>void* <parameter>data</parameter></paramdef>
+ <paramdef>size_t* <parameter>len</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>int <function>CYG_FB_ON</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>int <function>CYG_FB_OFF</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>int <function>CYG_FB_IOCTL</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_uint16 <parameter>key</parameter></paramdef>
+ <paramdef>void* <parameter>data</parameter></paramdef>
+ <paramdef>size_t* <parameter>len</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="framebuf-control-description">
+ <title>Description</title>
+ <para>
+The main operations on a framebuffer are drawing and colour
+management. However on most hardware it is also necessary to switch
+the display <link linkend="framebuf-control-onoff">on</link> before the
+user can see anything, and application code should be able to control
+when this happens. There are also miscellaneous operations such as
+manipulating the backlight or moving the viewpoint. These do not
+warrant dedicated functions, especially since the functionality will
+only be available on some hardware, so an <link
+linkend="framebuf-control-ioctl"><function>ioctl</function></link>
+interface is used.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-control-onoff">
+ <title>Switching the Display On or Off</title>
+ <para>
+With most hardware nothing will be visible until there is a call to
+<function>cyg_fb_on</function> or an invocation of the
+<function>CYG_FB_ON</function> macro. This will initialize the
+framebuffer control circuitry, start sending the data signals to the
+display unit, and switch on the display if necessary. The exact
+initialization semantics are left to the framebuffer device driver. In
+some cases the hardware may already be partially or fully initialized
+by a static constructor or by boot code that ran before eCos.
+ </para>
+ <para>
+There are some circumstances in which initialization can fail, and
+this is indicated by a POSIX error code such as
+<literal>ENODEV</literal>. An example would be plug and play hardware
+where the framebuffer device is not detected at run-time. Another
+example is hardware which can operate in several modes, with separate
+<structname>cyg_fb</structname> structures for each mode, if the
+hardware is already in use for a different mode. A return value of 0
+indicates success.
+ </para>
+ <para>
+Some but not all hardware allows the framebuffer memory and, if
+present, the palette to be manipulated before the device is switched
+on. That way the user does not see random noise on the screen during
+system startup. The flag <literal>CYG_FB_FLAGS0_MUST_BE_ON</literal>
+should be checked:
+ </para>
+ <programlisting width=72>
+static void
+init_screen(cyg_fb_colour background)
+{
+ int result;
+
+#if (! (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_MUST_BE_ON))
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+ CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+ background);
+#endif
+
+ result = CYG_FB_ON(FRAMEBUF);
+ if (0 != result) {
+ <handle unusual error condition>
+ }
+
+#if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_MUST_BE_ON)
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+ CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+ background);
+#endif
+}
+ </programlisting>
+ <para>
+Obviously if the application has already manipulated framebuffer
+memory or the palette but then the <function>cyg_fb_on</function>
+operation fails, the system is left in an undefined state.
+ </para>
+ <para>
+It is also possible to switch a framebuffer device off, using the
+function <function>cyg_fb_off</function> or the macro
+<function>CYG_FB_OFF</function>, although this functionality is rarely
+used in embedded systems. The exact semantics of switching a device
+off are implementation-defined, but typically it involves shutting
+down the display, stopping the data signals to the display, and
+halting the control circuitry. The framebuffer memory and the palette
+are left in an undefined state, and application code should assume
+that both need full reinitializing when the device is switched back
+on. Some hardware may also provide a <link
+linkend="framebuf-control-ioctl-blank">blank</link> operation which
+typically just manipulates the display, not the whole framebuffer
+device. Normally <function>cyg_fb_on</function> returns 0. The API
+allows for a POSIX error code as with <function>cyg_fb_on</function>,
+but switching a device off is not an operation that is likely to fail.
+ </para>
+ <para>
+If a framebuffer device can operate in several modes, represented by
+several <structname>cyg_fb</structname> structures and macro
+identifiers, then switching modes requires turning the current device
+off before turning the next one one.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-control-ioctl">
+ <title>Miscellaneous Control Operations</title>
+ <para>
+Some hardware functionality such as an LCD panel backlight is common
+but not universal. Supporting these does not warrant dedicated
+functions. Instead a catch-all <function>ioctl</function> interface is
+provided, with the arguments just passed straight to the device
+driver. This approach also allows for future expansion and for
+device-specific operations. <function>cyg_fb_ioctl</function> and
+<function>CYG_FB_IOCTL</function> take four arguments: a
+<structname>cyg_fb</structname> structure or framebuffer identifier; a
+key that specifies the operation to be performed; an arbitrary
+pointer, which should usually be a pointer to a data structure
+specific to the key; and a length field. Key values from 0 to 0x7fff
+are generic. Key values from 0x8000 onwards are reserved for the
+individual framebuffer device drivers, for device-specific
+functionality. The length field should be set to the size of the data
+structure, and may get updated by the device driver.
+ </para>
+ <para>
+With most ioctl operations the device can indicate whether or not it
+supports the functionality by one of the flags, for example:
+ </para>
+ <programlisting width=72>
+void
+backlight_off(cyg_fb* fb)
+{
+ if (fb->fb_flags0 & CYG_FB_FLAGS0_BACKLIGHT) {
+ cyg_fb_ioctl_backlight new_setting;
+ size_t len = sizeof(cyg_fb_ioctl_backlight);
+ int result;
+
+ new_setting.fbbl_current = 0;
+ result = cyg_fb_ioctl(fb, CYG_FB_IOCTL_BACKLIGHT_SET,
+ &new_setting, &len);
+ if (0 != result) {
+ …
+ }
+ }
+}
+ </programlisting>
+ <para>
+The operation returns zero for success or a POSIX error code on
+failure, for example <literal>ENOSYS</literal> if the device driver
+does not implement the requested functionality.
+ </para>
+
+ <refsect2 id="framebuf-control-ioctl-viewport">
+ <title>Viewport</title>
+ <programlisting width=72>
+# define CYG_FB_IOCTL_VIEWPORT_GET_POSITION 0x0100
+# define CYG_FB_IOCTL_VIEWPORT_SET_POSITION 0x0101
+
+typedef struct cyg_fb_ioctl_viewport {
+ cyg_ucount16 fbvp_x; // position of top-left corner of the viewport within
+ cyg_ucount16 fbvp_y; // the framebuffer
+ cyg_ucount16 fbvp_when; // set-only, now or vert retrace
+} cyg_fb_ioctl_viewport;
+ </programlisting>
+ <para>
+On some targets the framebuffer device has a higher resolution than
+the display. Only a subset of the pixels, the viewport, is currently
+visible. Application code can exploit this functionality to achieve
+certain effects, for example smooth scrolling. Framebuffers which
+support this functionality will have the
+<literal>CYG_FB_FLAGS0_VIEWPORT</literal> flag set. The viewport
+dimensions are available as additional <link
+linkend="framebuf-parameters">parameters</link> to the normal
+framebuffer width and height.
+ </para>
+ <para>
+The current position of the viewport can be obtained using an
+<literal>CYG_FB_IOCTL_VIEWPORT_GET_POSITION</literal> ioctl operation.
+The data argument should be a pointer to a
+<structname>cyg_fb_ioctl_viewport</structname> structure. On return
+the <structfield>fbvp_x</structfield> and
+<structfield>fbvp_y</structfield> fields will be filled in. To move
+the viewport use <literal>CYG_FB_IOCTL_VIEWPORT_SET_POSITION</literal>
+with <structfield>fbvp_x</structfield> and
+<structfield>fbvp_y</structfield> set to the top left corner of the
+new viewport within the framebuffer, and
+<structfield>fbvp_when</structfield> set to either
+<literal>CYG_FB_UPDATE_NOW</literal> or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>. If the device
+driver cannot easily synchronize to a vertical retrace period then
+this last field is ignored.
+ </para>
+ <programlisting width=72>
+void
+move_viewport(cyg_fb* fb, int dx, int dy)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+ cyg_fb_ioctl_viewport viewport;
+ int len = sizeof(cyg_fb_ioctl_viewport);
+ int result;
+
+ result = cyg_fb_ioctl(fb, CYG_FB_IOCTL_VIEWPORT_GET_POSITION,
+ &viewport, &len);
+ if (result != 0) {
+ …
+ }
+ if (((int)viewport.fbvp_x + dx) < 0) {
+ viewport.fbvp_x = 0;
+ } else if ((viewport.fbvp_x + dx + fb->fb_viewport_width) > fb->fb_width) {
+ viewport.fbvp_x = fb->fb_width - fb->fb_viewport_width;
+ } else {
+ viewport.fbvp_x += dx;
+ }
+ if (((int)viewport.fbvp_y + dy) < 0) {
+ viewport.fbvp_y = 0;
+ } else if ((viewport.fbvp_y + dy + fb->fb_viewport_height) > fb->fb_height) {
+ viewport.fbvp_y = fb->fb_height - fb->fb_viewport_height;
+ } else {
+ viewport.fbvp_y += dy;
+ }
+ result = cyg_fb_ioctl(fb, CYG_FB_IOCTL_VIEWPORT_SET_POSITION,
+ &viewport, &len);
+ if (result != 0) {
+ …
+ }
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(int, dx);
+ CYG_UNUSED_PARAM(int, dy);
+#endif
+}
+ </programlisting>
+ <para>
+If an attempt is made to move the viewport beyond the boundaries of
+the framebuffer then the resulting behaviour is undefined. Some
+hardware may behave reasonably, wrapping around as appropriate, but
+portable code cannot assume this. The above code fragment is careful
+to clip the viewport to the framebuffer dimensions.
+ </para>
+ </refsect2>
+
+ <refsect2 id="framebuf-control-ioctl-pageflip">
+ <title>Page Flipping</title>
+ <programlisting width=72>
+# define CYG_FB_IOCTL_PAGE_FLIPPING_GET_PAGES 0x0200
+# define CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES 0x0201
+
+typedef struct cyg_fb_ioctl_page_flip {
+ cyg_uint32 fbpf_number_pages;
+ cyg_uint32 fbpf_visible_page;
+ cyg_uint32 fbpf_drawable_page;
+ cyg_ucount16 fbpf_when; // set-only, now or vert retrace
+} cyg_fb_ioctl_page_flip;
+ </programlisting>
+ <para>
+On some targets the framebuffer has enough memory for several pages,
+only one of which is visible at a time. This allows the application
+to draw into one page while displaying another. Once drawing is
+complete the display is flipped to the newly drawn page, and the
+previously displayed page is now available for updating. This
+technique is used for smooth animation, especially in games. The flag
+<literal>CYG_FB_FLAGS0_PAGE_FLIPPING</literal> indicates support for
+this functionality.
+ </para>
+ <para>
+<literal>CYG_FB_IOCTL_PAGE_FLIPPING_GET_PAGES</literal> can be used to
+get the current settings of the page flipping support. The data
+argument should be a pointer to a
+<structname>cyg_fb_ioctl_page_flip</structname> structure. The
+resulting <structfield>fbpf_number_pages</structfield> field indicates
+the total number of pages available: 2 is common, but more pages are
+possible. <structfield>fbpf_visible_page</structfield> gives the page
+that is currently visible to the user, and will be between 0 and
+(<structfield>fbpf_number_pages</structfield> - 1).
+Similarly <structfield>fbpf_drawable_page</structfield> gives the page
+that is currently visible. It is implementation-defined whether or not
+the visible and drawable page can be the same one.
+ </para>
+ <para>
+<literal>CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES</literal> can be used to
+change the visible and drawable page. The
+<structfield>fbpf_number_pages</structfield> field is ignored.
+<structfield>fbpf_visible_page</structfield> and
+<structfield>fbpf_drawable_page</structfield> give the new settings.
+<structfield>fbpf_when</structfield> should be one of
+<literal>CYG_FB_UPDATE_NOW</literal> or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>, but may be ignored
+by some device drivers.
+ </para>
+ <programlisting width=72>
+#if !(CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_PAGE_FLIPPING)
+# error Current framebuffer device does not support page flipping
+#endif
+
+static cyg_uint32 current_visible = 0;
+
+static void
+page_flip_init(cyg_fb_colour background)
+{
+ cyg_fb_ioctl_page_flip flip;
+ size_t len = sizeof(cyg_fb_ioctl_page_flip);
+
+ flip.fbpf_visible_page = current_visible;
+ flip.fbpf_drawable_page = 1 - current_visible;
+ flip.fbpf_when = CYG_FB_UPDATE_NOW;
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES,
+ &flip, &len);
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+ CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+ background);
+ flip.fbpf_visible_page = 1 - current_visible;
+ flip.fbpf_drawable_page = current_visible;
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES,
+ &flip, &len);
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+ CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+ background);
+ current_visible = 1 - current_visible;
+}
+
+static void
+page_flip_toggle(void)
+{
+ cyg_fb_ioctl_page_flip flip;
+ size_t len = sizeof(cyg_fb_ioctl_page_flip);
+
+ flip.fbpf_visible_page = 1 - current_visible;
+ flip.fbpf_drawable_page = current_visible;
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES,
+ &flip, &len);
+ current_visible = 1 - current_visible;
+}
+ </programlisting>
+ <para>
+A page flip typically just changes a couple of pointers within the
+hardware and device driver. No attempt is made to synchronize the
+contents of the pages, that is left to higher-level code.
+ </para>
+ </refsect2>
+
+ <refsect2 id="framebuf-control-ioctl-blank">
+ <title>Blanking the Screen</title>
+ <programlisting width=72>
+# define CYG_FB_IOCTL_BLANK_GET 0x0300
+# define CYG_FB_IOCTL_BLANK_SET 0x0301
+
+typedef struct cyg_fb_ioctl_blank {
+ cyg_bool fbbl_on;
+} cyg_fb_ioctl_blank;
+ </programlisting>
+ <para>
+Some hardware allows the display to be switched off or blanked without
+shutting down the entire framebuffer device, greatly reducing power
+consumption. The current blanking state can be obtained using
+<literal>CYG_FB_IOCTL_BLANK_GET</literal> and the state can be updated
+using <literal>CYG_FB_IOCTL_BLANK_SET</literal>. The data argument
+should be a pointer to a <structname>cyg_fb_ioctl_blank</structname>
+structure. Support for this functionality is indicated by the
+<literal>CYG_FB_FLAGS0_BLANK</literal> flag.
+ </para>
+ <programlisting width=72>
+static cyg_bool
+display_blanked(cyg_fb_* fb)
+{
+ cyg_fb_ioctl_blank blank;
+ size_t len = sizeof(cyg_fb_ioctl_blank);
+
+ if (! (fb->fb_flags0 & CYG_FB_FLAGS0_BLANK)) {
+ return false;
+ }
+ (void) cyg_fb_ioctl(fb, CYG_FB_IOCTL_BLANK_GET, &blank, &len);
+ return !blank.fbbl_on;
+}
+ </programlisting>
+ </refsect2>
+
+ <refsect2 id="framebuf-control-ioctl-backlight">
+ <title>Controlling the Backlight</title>
+ <programlisting width=72>
+# define CYG_FB_IOCTL_BACKLIGHT_GET 0x0400
+# define CYG_FB_IOCTL_BACKLIGHT_SET 0x0401
+
+typedef struct cyg_fb_ioctl_backlight {
+ cyg_ucount32 fbbl_current;
+ cyg_ucount32 fbbl_max;
+} cyg_fb_ioctl_backlight;
+ </programlisting>
+ <para>
+Many LCD panels provide some sort of backlight, making the display
+easier to read at the cost of increased power consumption. Support for
+this is indicated by the <literal>CYG_FB_FLAGS0_BACKLIGHT</literal>
+flag. <literal>CYG_FB_IOCTL_BACKLIGHT_GET</literal> can be used to get
+both the current setting and the maximum value. If the maximum is 1
+then the backlight can only be switched on or off. Otherwise it is
+possible to control the intensity.
+ </para>
+ <programlisting width=72>
+static void
+set_backlight_50_percent(void)
+{
+#if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_BACKLIGHT)
+ cyg_fb_ioctl_backlight backlight;
+ size_t len = sizeof(cyg_fb_ioctl_backlight);
+
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_BACKLIGHT_GET, &backlight, &len);
+ backlight.fbbl_current = (backlight.fbbl_max + 1) >> 1;
+ CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_BACKLIGHT_SET, &backlight, &len);
+#endif
+}
+ </programlisting>
+ </refsect2>
+ </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Colour Management -->
+
+<refentry id="framebuf-colour">
+ <refmeta>
+ <refentrytitle>Framebuffer Colours</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Colours</refname>
+ <refpurpose>formats and palette management</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>
+#include <cyg/io/framebuf.h>
+
+typedef struct cyg_fb {
+ cyg_ucount16 fb_depth;
+ cyg_ucount16 fb_format;
+ cyg_uint32 fb_flags0;
+ …
+} cyg_fb;
+
+extern const cyg_uint8 cyg_fb_palette_ega[16 * 3];
+extern const cyg_uint8 cyg_fb_palette_vga[256 * 3];
+
+#define CYG_FB_DEFAULT_PALETTE_BLACK 0x00
+#define CYG_FB_DEFAULT_PALETTE_BLUE 0x01
+#define CYG_FB_DEFAULT_PALETTE_GREEN 0x02
+#define CYG_FB_DEFAULT_PALETTE_CYAN 0x03
+#define CYG_FB_DEFAULT_PALETTE_RED 0x04
+#define CYG_FB_DEFAULT_PALETTE_MAGENTA 0x05
+#define CYG_FB_DEFAULT_PALETTE_BROWN 0x06
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREY 0x07
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGRAY 0x07
+#define CYG_FB_DEFAULT_PALETTE_DARKGREY 0x08
+#define CYG_FB_DEFAULT_PALETTE_DARKGRAY 0x08
+#define CYG_FB_DEFAULT_PALETTE_LIGHTBLUE 0x09
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREEN 0x0A
+#define CYG_FB_DEFAULT_PALETTE_LIGHTCYAN 0x0B
+#define CYG_FB_DEFAULT_PALETTE_LIGHTRED 0x0C
+#define CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA 0x0D
+#define CYG_FB_DEFAULT_PALETTE_YELLOW 0x0E
+#define CYG_FB_DEFAULT_PALETTE_WHITE 0x0F
+ </funcsynopsisinfo>
+ <funcprototype>
+ <funcdef>cyg_ucount16 <function>CYG_FB_FORMAT</function></funcdef>
+ <paramdef><parameter>framebuf</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_read_palette</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+ <paramdef>void* <parameter>data</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_write_palette</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+ <paramdef>const void* <parameter>data</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_fb_colour <function>cyg_fb_make_colour</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+ <paramdef>cyg_ucount8 <parameter>r</parameter></paramdef>
+ <paramdef>cyg_ucount8 <parameter>g</parameter></paramdef>
+ <paramdef>cyg_ucount8 <parameter>b</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_break_colour</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ <paramdef>cyg_ucount8* <parameter>r</parameter></paramdef>
+ <paramdef>cyg_ucount8* <parameter>g</parameter></paramdef>
+ <paramdef>cyg_ucount8* <parameter>b</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_READ_PALETTE</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+ <paramdef>void* <parameter>data</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_WRITE_PALETTE</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+ <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+ <paramdef>const void* <parameter>data</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_fb_colour <function>CYG_FB_MAKE_COLOUR</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount8 <parameter>r</parameter></paramdef>
+ <paramdef>cyg_ucount8 <parameter>g</parameter></paramdef>
+ <paramdef>cyg_ucount8 <parameter>b</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_BREAK_COLOUR</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ <paramdef>cyg_ucount8* <parameter>r</parameter></paramdef>
+ <paramdef>cyg_ucount8* <parameter>g</parameter></paramdef>
+ <paramdef>cyg_ucount8* <parameter>b</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="framebuf-colour-description">
+ <title>Description</title>
+ <para>
+Managing colours can be one of the most difficult aspects of writing
+graphics code, especially if that code is intended to be portable to
+many different platforms. Displays can vary from 1bpp monochrome, via
+2bpp and 4bpp greyscale, through 4bpp and 8bpp paletted, and up to
+16bpp and 32bpp true colour - and those are just the more common
+scenarios. The various <link linkend="framebuf-drawing">drawing
+primitives</link> like <function>cyg_fb_write_pixel</function> work in
+terms of <type>cyg_fb_colour</type> values, usually an unsigned
+integer. Exactly how the hardware interprets a
+<type>cyg_fb_colour</type> depends on the format.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-colour-formats">
+ <title>Colour Formats</title>
+ <para>
+There are a number of ways of finding out how these values will be
+interpreted by the hardware:
+ </para>
+ <orderedlist>
+ <listitem><para>
+The <literal>CYG_FB_FLAGS0_TRUE_COLOUR</literal> flag is set for all
+true colour displays. The format parameter can be examined for more
+details but this is not usually necessary. Instead code can use
+<link
+linkend="framebuf-colour-true"><function>cyg_fb_make_colour</function></link>
+or <link
+linkend="framebuf-colour-true"><function>CYG_FB_MAKE_COLOUR</function></link>
+to construct a <type>cyg_fb_colour</type> value from red, green and
+blue components.
+ </para></listitem>
+ <listitem><para>
+If the <literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal> flag is set
+then a <type>cyg_fb_colour</type> value is an index into a lookup
+table known as the palette, and this table contains red, green and
+blue components. The size of the palette is determined by the display
+depth, so 16 entries for a 4bpp display and 256 entries for an 8bpp
+display. Application code or a graphics library can <link
+linkend="framebuf-colour-palette">install</link> its own palette so
+can control exactly what colour each <type>cyg_fb_colour</type> value
+corresponds to. Alternatively there is support for installing a
+default palette.
+ </para></listitem>
+ <listitem><para>
+If <literal>CYG_FB_FLAGS0_PALETTE</literal> is set but
+<literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal> is clear then the
+hardware uses a fixed palette. There is no easy way for portable
+software to handle this case. The palette can be read at run-time,
+allowing the application's desired colours to be mapped to whichever
+palette entry provides the best match. However normally it will be
+necessary to write code specifically for the fixed palette.
+ </para></listitem>
+ <listitem><para>
+Otherwise the display is monochrome or greyscale, depending on the
+depth. There are still variations, for example on a monochrome display
+colour 0 can be either white or black.
+ </para></listitem>
+ </orderedlist>
+ <para>
+As an alternative or to provide additional information, the exact
+colour format is provided by the <structfield>fb_format</structfield>
+field of the <structname>cyg_fb</structname> structure or by the
+<function>CYG_FB_FORMAT</function> macro. It can be one of the
+following (more entries may be added in future):
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_1BPP_MONO_0_BLACK</literal></term>
+ <listitem><para>
+simple 1bpp monochrome display, with 0 as black or the darker of the
+two colours, and 1 as white or the ligher colour.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_1BPP_MONO_0_WHITE</literal></term>
+ <listitem><para>
+simple 1bpp monochrome display, with 0 as white or the lighter of the
+two colours, and 1 as black or the darker colour.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_1BPP_PAL888</literal></term>
+ <listitem><para>
+a 1bpp display which cannot easily be described as monochrome. This is
+unusual and not readily supported by portable code. It can happen if
+the framebuffer normally runs at a higher depth, for example 4bpp or
+8bpp paletted, but is run at only 1bpp to save memory. Hence only two
+of the palette entries are used, but can be set to arbitrary colours.
+The palette may be read-only or read-write.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_2BPP_GREYSCALE_0_BLACK</literal></term>
+ <listitem><para>
+a 2bpp display offering four shades of grey, with 0 as black or the
+darkest of the four shades, and 3 as white or the lightest.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_2BPP_GREYSCALE_0_WHITE</literal></term>
+ <listitem><para>
+a 2bpp display offering four shades of grey, with 0 as white or the
+lightest of the four shades, and 3 as black or the darkest.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_2BPP_PAL888</literal></term>
+ <listitem><para>
+a 2bpp display which cannot easily be described as greyscale, for
+example providing black, red, blue and white as the four colours.
+This is unusual and not readily supported by portable code. It can
+happen if the framebuffer normally runs at a higher depth, for example
+4bpp or 8bpp paletted, but is run at only 2bpp to save memory. Hence
+only four of the palette entries are used, but can be set to arbitrary
+colours. The palette may be read-only or read-write.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_4BPP_GREYSCALE_0_BLACK</literal></term>
+ <listitem><para>
+a 4bpp display offering sixteen shades of grey, with 0 as black or the
+darkest of the 16 shades, and 15 as white or the lighest.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_4BPP_GREYSCALE_0_WHITE</literal></term>
+ <listitem><para>
+a 4bpp display offering sixteen shades of grey, with 0 as white or the
+lightest of the 16 shades, and 15 as black or the darkest.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_4BPP_PAL888</literal></term>
+ <listitem><para>
+a 4bpp paletted display, allowing for 16 different colours on screen
+at the same time. The palette may be read-only or read-write.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_8BPP_PAL888</literal></term>
+ <listitem><para>
+an 8bpp paletted display, allowing for 256 different colours on screen
+at the same time. The palette may be read-only or read-write.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_8BPP_TRUE_332</literal></term>
+ <listitem><para>
+an 8bpp true colour display. Bits 0 and 1 of each pixel value control
+four levels of blue intensity, bits 2 to 4 control eight levels of
+green, and bits 5 to 7 control eight levels of red.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_16BPP_TRUE_565</literal></term>
+ <listitem><para>
+a 16bpp true colour display. Bits 0 to 4 of each pixel value control
+the blue intensity, bits 5 to 10 the green intensity, and bits 11 to
+15 the red intensity.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_16BPP_TRUE_555</literal></term>
+ <listitem><para>
+a 16bpp true colour display, with the top bit unused. Bits 0 to 4 of
+each pixel value control the blue intensity, bits 5 to 9 the green
+intensity, and bits 10 to 14 the red intensity.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>CYG_FB_FORMAT_32BPP_TRUE_0888</literal></term>
+ <listitem><para>
+a 32bpp true colour display, with the top byte unused. Bits 0 to 7 of
+each pixel value control the blue intensity, bits 8 to 15 the green
+intensity, and bits 16 to 23 the red intensity.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="framebuf-colour-palette">
+ <title>Paletted Displays</title>
+ <para>
+Palettes are the common way of implementing low-end colour displays.
+There are two variants. A read-only palette provides a fixed set of
+colours and it is up to application code to use these colours
+appropriately. A read-write palette allows the application to select
+its own set of colours. Displays providing a read-write palette will
+have the <literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal> flag set
+in addition to <literal>CYG_FB_FLAGS0_PALETTE</literal>.
+ </para>
+ <para>
+Even if application code can install its own palette, many
+applications do not exploit this functionality and instead stick with
+a default. There are two standard palettes: the 16-entry PC EGA for
+4bpp displays; and the 256-entry PC VGA, a superset of the EGA one,
+for 8bpp displays. This package provides the data for both, in the
+form of arrays <varname>cyg_fb_palette_ega</varname> and
+<varname>cyg_fb_palette_vga</varname>, and 16
+<literal>#define</literal>'s such as
+<varname>CYG_FB_DEFAULT_PALETTE_BLACK</varname> for the EGA colours
+and the first 16 VGA colours. By default device drivers for read-write
+paletted displays will install the appropriate default palette, but
+this can be suppressed using configuration option
+<varname>CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE</varname>. If a
+custom palette will be used then installing the default palette
+involves wasting 48 or 768 bytes of memory.
+ </para>
+ <para>
+It should be emphasized that displays vary widely. A colour such
+as <varname>CYG_FB_DEFAULT_PALETTE_YELLOW</varname> may appear rather
+differently on two different displays, although it should always be
+recognizable as yellow. Developers may wish to fine-tune the palette
+for specific hardware.
+ </para>
+ <para>
+The current palette can be retrieved using
+<function>cyg_fb_read_palette</function> or
+<function>CYG_FB_READ_PALETTE</function>. The
+<parameter>first</parameter> and <parameter>count</parameter>
+arguments control which palette entries should be retrieved. For
+example, to retrieve just palette entry 12
+<parameter>first</parameter> should be set to 12 and
+<parameter>count</parameter> should be set to 1. To retrieve all 256
+entries for an 8bpp display, <parameter>first</parameter> should be
+set to 0 and <parameter>count</parameter> should be set to 256. The
+<parameter>data</parameter> argument should point at an array of
+bytes, allowing three bytes for every entry. Byte 0 will contain the red
+intensity for the first entry, byte 1 green and byte 2 blue.
+ </para>
+ <para>
+For read-write palettes the palette can be updated using
+<function>cyg_fb_write_palette</function> or
+<function>CYG_FB_WRITE_PALETTE</function>. The
+<parameter>first</parameter> and <parameter>count</parameter> arguments
+are the same as for <function>cyg_fb_read_palette</function>, and the
+<parameter>data</parameter> argument should point at a suitable byte
+array packed in the same way. The <parameter>when</parameter> argument
+should be one of <literal>CYG_FB_UPDATE_NOW</literal> or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>. With some displays
+updating the palette in the middle of an update may result in visual
+noise, so synchronizing to the vertical retrace avoids this. However
+not all device drivers will support this.
+ </para>
+ <para>
+There is an assumption that palette entries use 8 bits for each of the
+red, green and blue colour intensities. This is not always the case,
+but the device drivers will perform appropriate adjustments. Some
+hardware may use only 6 bits per colour, and the device driver will
+ignore the bottom two bits of the supplied intensity values.
+Occasionally hardware may use more than 8 bits, in which case the
+supplied 8 bits are shifted left appropriately and zero-padded. Device
+drivers for such hardware may also provide device-specific routines to
+manipulate the palette in a non-portable fashion.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-colour-true">
+ <title>True Colour displays</title>
+ <para>
+True colour displays are often easier to manage than paletted
+displays. However this comes at the cost of extra memory. A 16bpp true
+colour display requires twice as much memory as an 8bpp paletted
+display, yet can offer only 32 or 64 levels of intensity for each
+colour as opposed to the 256 levels provided by a palette. It also
+requires twice as much video memory bandwidth to send all the pixel
+data to the display for every refresh, which may impact the
+performance of the rest of the system. A 32bpp true colour display
+offers the same colour intensities but requires four times the memory
+and four times the bandwidth.
+ </para>
+ <para>
+There are two ways of determining a <type>cyg_fb_colour</type> pixel
+value for a given colour. The first is to decode the colour format,
+for example <literal>CYG_FB_FORMAT_16BPP_TRUE_565</literal>, and
+perform the appropriate arithmetic. The second is to use the supplied
+<function>cyg_fb_make_colour</function> or
+<function>CYG_FB_MAKE_COLOUR</function> primitives. These take 8-bit
+intensity levels for red, green and blue, and return the corresponding
+<type>cyg_fb_colour</type>. When using the macro interface the
+arithmetic happens at compile-time, for example:
+ </para>
+ <programlisting width=72>
+#define BLACK CYG_FB_MAKE_COLOUR(FRAMEBUF, 0, 0, 0)
+#define WHITE CYG_FB_MAKE_COLOUR(FRAMEBUF, 255, 255, 255)
+#define RED CYG_FB_MAKE_COLOUR(FRAMEBUF, 255, 0, 0)
+#define GREEN CYG_FB_MAKE_COLOUR(FRAMEBUF, 0, 255, 0)
+#define BLUE CYG_FB_MAKE_COLOUR(FRAMEBUF, 0, 0, 255)
+#define YELLOW CYG_FB_MAKE_COLOUR(FRAMEBUF, 255, 255, 80)
+ </programlisting>
+ <para>
+Displays vary widely so the numbers may need to be adjusted to give
+the exact desired colours.
+ </para>
+ <para>
+For symmetry there are also <function>cyg_fb_break_colour</function>
+and <function>CYG_FB_BREAK_COLOUR</function> primitives. These take a
+<type>cyg_fb_colour</type> value and decompose it into its red, green
+and blue components.
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Drawing primitives -->
+
+<refentry id="framebuf-drawing">
+ <refmeta>
+ <refentrytitle>Framebuffer Drawing Primitives</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Drawing Primitives</refname>
+ <refpurpose>updating the display</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>
+#include <cyg/io/framebuf.h>
+ </funcsynopsisinfo>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_write_pixel</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_fb_colour <function>cyg_fb_read_pixel</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_write_hline</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_write_vline</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_fill_block</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_write_block</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>const void* <parameter>data</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_read_block</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>void* <parameter>data</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_move_block</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>new_x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>new_y</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>cyg_fb_synch</function></funcdef>
+ <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_WRITE_PIXEL</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_fb_colour <function>CYG_FB_READ_PIXEL</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_WRITE_HLINE</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_WRITE_VLINE</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_FILL_BLOCK</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_WRITE_BLOCK</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>const void* <parameter>data</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_READ_BLOCK</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>void* <parameter>data</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_MOVE_BLOCK</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>new_x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>new_y</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_SYNCH</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="framebuf-drawing-description">
+ <title>Description</title>
+ <para>
+The eCos framebuffer infrastructure defines a small number of drawing
+primitives. These are not intended to provide full graphical
+functionality like multiple windows, drawing text in arbitrary fonts,
+or anything like that. Instead they provide building blocks for
+higher-level graphical toolkits. The available primitives are:
+ </para>
+ <orderedlist>
+ <listitem><para>
+Manipulating individual pixels.
+ </para></listitem>
+ <listitem><para>
+Drawing horizontal and vertical lines.
+ </para></listitem>
+ <listitem><para>
+Block fills.
+ </para></listitem>
+ <listitem><para>
+Moving blocks between the framebuffer and main memory.
+ </para></listitem>
+ <listitem><para>
+Moving blocks within the framebuffer.
+ </para></listitem>
+ <listitem><para>
+For double-buffered devices, synchronizing the framebuffer contents
+with the actual display.
+ </para></listitem>
+ </orderedlist>
+ <para>
+There are two versions for each primitive: a macro and a function. The
+macro can be used if the desired framebuffer device is known at
+compile-time. Its first argument should be a framebuffer identifier,
+for example <literal>320x240x16</literal>, and must be one of the
+entries in the configuration option
+<varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>. In the examples below
+it is assumed that <varname>FRAMEBUF</varname> has been
+<literal>#define</literal>'d to a suitable identifier. The function
+can be used if the desired framebuffer device is selected at
+run-time. Its first argument should be a pointer to the appropriate
+<structname>cyg_fb</structname> structure.
+ </para>
+ <para>
+The pixel, line, and block fill primitives take a
+<type>cyg_fb_colour</type> argument. For details of colour handling
+see <xref linkend="framebuf-colour">. This argument should have no
+more bits set than are appropriate for the display depth. For example
+on a 4bpp only the bottom four bits of the colour may be set,
+otherwise the behaviour is undefined.
+ </para>
+ <para>
+None of the primitives will perform any run-time error checking,
+except possibly for some assertions in a debug build. If higher-level
+code provides invalid arguments, for example trying to write a block
+which extends past the right hand side of the screen, then the
+system's behaviour is undefined. It is the responsibility of
+higher-level code to perform clipping to the screen boundaries.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-drawing-pixels">
+ <title>Manipulating Individual Pixels</title>
+ <para>
+The primitives for manipulating individual pixels are very simple: a
+pixel can be written or read back. The following example shows one way
+of drawing a diagonal line:
+ </para>
+ <programlisting width=72>
+void
+draw_diagonal(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len,
+ cyg_fb_colour colour)
+{
+ while ( len-- ) {
+ cyg_fb_write_pixel(fb, x++, y++, colour);
+ }
+}
+ </programlisting>
+ <para>
+The next example shows how to draw a horizontal XOR line on a 1bpp
+display.
+ </para>
+ <programlisting width=72>
+void
+draw_horz_xor(cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len)
+{
+ cyg_fb_colour colour;
+ while ( len--) {
+ colour = CYG_FB_READ_PIXEL(FRAMEBUF, x, y);
+ CYG_FB_WRITE_PIXEL(FRAMEBUF, x++, y, colour ^ 0x01);
+ }
+}
+ </programlisting>
+ <para>
+The pixel macros should normally be avoided. Determining the correct
+location within framebuffer memory corresponding to a set of
+coordinates for each pixel is a comparatively expensive operation.
+Instead there is direct support for <link
+linkend="framebuf-iterating">iterating</link> over parts of the
+display, avoiding unnecessary overheads.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-drawing-lines">
+ <title>Drawing Simple Lines</title>
+ <para>
+Higher-level graphics code often needs to draw single-pixel horizontal
+and vertical lines. If the application involves multiple windows then
+these will usually have thin borders around them. Widgets such as
+buttons and scrollbars also often have thin borders.
+ </para>
+ <para>
+<function>cyg_fb_draw_hline</function> and
+<function>CYG_FB_DRAW_HLINE</function> draw a horizontal line of the
+specified <parameter>colour</parameter>, starting at the
+<parameter>x</parameter> and <parameter>y</parameter> coordinates and
+extending to the right (increasing x) for a total of
+<parameter>len</parameter> pixels. A 50 pixel line starting at
+(100,100) will end at (149,100).
+ </para>
+ <para>
+<function>cyg_fb_draw_vline</function> and
+<function>CYG_FB_DRAW_VLINE</function> take the same arguments, but
+the line extends down (increasing y).
+ </para>
+ <para>
+These primitives do not directly support drawing lines more than one
+pixel thick, but <link linkend="framebuf-drawing-fill">block
+fills</link> can be used to achieve those. There is no generic support
+for drawing arbitrary lines, instead that is left to higher-level
+graphics toolkits.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-drawing-fill">
+ <title>Block Fills</title>
+ <para>
+Filling a rectangular part of the screen with a solid colour is
+another common requirement for higher-level code. The simplest example
+is during initialization, to set the display's whole background to a
+known value. Block fills are also often used when creating new windows
+or drawing the bulk of a simple button or scrollbar widget.
+<function>cyg_fb_fill_block</function> and
+<function>CYG_FB_FILL_BLOCK</function> provide this functionality.
+ </para>
+ <para>
+The <parameter>x</parameter> and <parameter>y</parameter> arguments
+specify the top-left corner of the block to be filled. The
+<parameter>width</parameter> and <parameter>height</parameter>
+arguments specify the number of pixels affected, a total of
+<literal>width * height</literal>. The following example
+illustrates part of the process for initializing a framebuffer,
+assumed here to have a writeable palette with default settings.
+ </para>
+ <programlisting width=72>
+int
+display_init(void)
+{
+ int result = CYG_FB_ON(FRAMEBUF);
+ if ( result ) {
+ return result;
+ }
+ CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+ CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+ CYG_FB_DEFAULT_PALETTE_WHITE);
+ …
+}
+ </programlisting>
+ </refsect1>
+
+ <refsect1 id="framebuf-drawing-block-transfers">
+ <title>Copying Blocks between the Framebuffer and Main Memory</title>
+ <para>
+The block transfer primitives serve two main purposes: drawing images.
+and saving parts of the current display to be restored later. For
+simple linear framebuffers the primitives just implement copy
+operations, with no data conversion of any sort. For non-linear ones
+the primitives act as if the framebuffer memory was linear. For
+example, consider a 2bpp display where the two bits for a single pixel
+are split over two separate bytes in framebuffer memory, or two
+planes. For a block write operation the source data should still be
+organized with four full pixels per byte, as for a linear framebuffer
+of the same depth. and the block write primitive will distribute the
+bits over the framebuffer memory as required. Similarly a block read
+will combine the appropriate bits from different locations in
+framebuffer memory and the resulting memory block will have four full
+pixels per byte.
+ </para>
+ <para>
+Because the block transfer primitives perform no data conversion, if
+they are to be used for rendering images then those images should be
+pre-formatted appropriately for the framebuffer device. For small
+images this would normally happen on the host-side as part of the
+application build process. For larger images it will usually be better
+to store them in a compressed format and decompress them at run-time,
+trading off memory for cpu cycles.
+ </para>
+ <para>
+The <parameter>x</parameter> and <parameter>y</parameter> arguments
+specify the top-left corner of the block to be transferred, and the
+<parameter>width</parameter> and <parameter>height</parameter>
+arguments determine the size. The <parameter>data</parameter>,
+<parameter>offset</parameter> and <parameter>stride</parameter>
+arguments determine the location and layout of the block in main
+memory:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><parameter>data</parameter></term>
+ <listitem><para>
+The source or destination for the transfer. For 1bpp, 2bpp and 4bpp
+devices the data will be packed in accordance with the framebuffer
+device's endianness as per the <literal>CYG_FB_FLAGS0_LE</literal>
+flag. Each row starts in a new byte so there may be some padding on
+the right. For 16bpp and 32bpp the data should be aligned to the
+appropriate boundary.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>offset</parameter></term>
+ <listitem><para>
+Sometimes only part of an image should be written to the screen. A
+vertical offset can be achieved simply by adjusting
+<parameter>data</parameter> to point at the appropriate row within the
+image instead of the top row. For 8bpp, 16bpp and 32bpp displays
+an additional horizontal offset can also be achieved by adjusting
+<parameter>data</parameter>. However for 1bpp, 2bpp and 4bpp displays
+the starting position within the image may be in the middle of a byte.
+Hence the horizontal pixel offset can instead be specified with the
+<parameter>offset</parameter> argument.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>stride</parameter></term>
+ <listitem><para>
+This indicates the number of bytes between rows. Usually it will be
+related to the <parameter>width</parameter>, but there are exceptions
+such as when drawing only part of an image.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+The following example fills a 4bpp display with an image held in
+memory and already in the right format. If the image is smaller than
+the display it will be centered. If the image is larger then the
+center portion will fill the entire display.
+ </para>
+ <programlisting width=72>
+void
+draw_image(const void* data, int width, int height)
+{
+ cyg_ucount16 stride;
+ cyg_ucount16 x, y, offset;
+
+#if (4 != CYG_FB_DEPTH(FRAMEBUF))
+# error This code assumes a 4bpp display
+#endif
+
+ stride = (width + 1) >> 1; // 4bpp to byte stride
+
+ if (width < CYG_FB_WIDTH(FRAMEBUF)) {
+ x = (CYG_FB_WIDTH(FRAMEBUF) - width) >> 1;
+ offset = 0;
+ } else {
+ x = 0;
+ offset = (width - CYG_FB_WIDTH(FRAMEBUF)) >> 1;
+ width = CYG_FB_WIDTH(FRAMEBUF);
+ }
+ if (height < CYG_FB_HEIGHT(FRAMEBUF)) {
+ y = (CYG_FB_HEIGHT(FRAMEBUF) - height) >> 1;
+ } else {
+ y = 0;
+ data = (const void*)((const cyg_uint8*)data +
+ (stride * ((height - CYG_FB_HEIGHT(FRAMEBUF)) >> 1));
+ height = CYG_FB_HEIGHT(FRAMEBUF);
+ }
+ CYG_FB_WRITE_BLOCK(FRAMEBUF, x, y, width, height, data, offset, stride);
+}
+ </programlisting>
+ </refsect1>
+
+ <refsect1 id="framebuf-drawing-block-moves">
+ <title>Moving Blocks with the Framebuffer</title>
+ <para>
+Sometimes it is necessary to move a block of data around the screen,
+especially when using a higher-level graphics toolkit that supports
+multiple windows. Block moves can be implemented by a read into main
+memory followed by a write block, but this is expensive and imposes an
+additional memory requirement. Instead the framebuffer infrastructure
+provides a generic block move primitive. It will handle all cases
+where the source and destination positions overlap. The
+<parameter>x</parameter> and <parameter>y</parameter> arguments
+specify the top-left corner of the block to be moved, and
+<parameter>width</parameter> and <parameter>height</parameter>
+determine the block size. <parameter>new_x</parameter> and
+<parameter>new_y</parameter> specify the destination. The source data
+will remain unchanged except in areas where it overlaps the destination.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-drawing-synch">
+ <title>Synchronizing Double-Buffered Displays</title>
+ <para>
+Some framebuffer devices are double-buffered: the framebuffer memory
+that gets manipulated by the drawing primitives is separate from what
+is actually displayed, and a synch operation is needed to update the
+display. In some cases this may be because the actual display memory
+is not directly accessible by the processor, for example it may
+instead be attached via an SPI bus. Instead drawing happens in a
+buffer in main memory, and then this gets transferred over the SPI bus
+to the actual display hardware during a synch. In other cases it may
+be a software artefact. Some drawing operations, especially ones
+involving complex curves, can take a very long time and it may be
+considered undesirable to have the user see this happening a few
+pixels at a time. Instead the drawing happens in a separate buffer in
+main memory and then a double buffer synch just involves a block move
+to framebuffer memory. Typically that block move is much faster than
+the drawing operation. Obviously there is a cost: an extra area of
+memory, and the synch operation itself can consume many cycles and
+much of the available memory bandwidth.
+ </para>
+ <para>
+It is the responsibility of the framebuffer device driver to provide
+the extra main memory. As far as higher-level code is concerned the
+only difference between an ordinary and a double-buffered display is
+that with the latter changes do not become visible until a synch
+operation has been performed. The framebuffer infrastructure provides
+support for a bounding box, keeping track of what has been updated
+since the last synch. This means only the updated part of the screen
+has to be transferred to the display hardware.
+ </para>
+ <para>
+The synch primitives take two arguments. The first identifies the
+framebuffer device. The second should be one of
+<literal>CYG_FB_UPDATE_NOW</literal> for an immediate update, or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>. Some display
+hardware involves a lengthy vertical retrace period every 10-20
+milliseconds during which nothing gets drawn to the screen, and
+performing the synch during this time means that the end user is
+unaware of the operation (assuming the synch can be completed in the
+time available). When the hardware supports it, specifying
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal> means that the synch
+operation will block until the next vertical retrace takes place and
+then perform the update. This may be an expensive operation, for
+example it may involve polling a bit in a register. In a
+multi-threaded environment it may also be unreliable because the
+thread performing the synch may get interrupted or rescheduled in the
+middle of the operation. When the hardware does not involve vertical
+retraces, or when there is no easy way to detect them, the second
+argument to the synch operation will just be ignored and the update
+will always happen immediately.
+ </para>
+ <para>
+It is up to higher level code to determine when a synch operation is
+appropriate. One approach for typical event-driven code is to perform
+the synch at the start of the event loop, just before waiting for an
+input or timer event. This may not be optimal. For example if there
+two small updates to opposite corners of the screen then it would be
+better to make two synch calls with small bounding boxes, rather than
+a single synch call with a a large bounding box that requires most of
+the framebuffer memory to be updated.
+ </para>
+ <para>
+Leaving out the synch operations leads to portability problems. On
+hardware which does not involve double-buffering the synch operation
+is a no-op, usually eliminated at compile-time, so invoking synch does
+not add any code size or cpu cycle overhead. On double-buffered
+hardware, leaving out the synch means the user cannot see what has
+been drawn into the framebuffer.
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Iteration -->
+
+<refentry id="framebuf-iterating">
+ <refmeta>
+ <refentrytitle>Framebuffer Pixel Manipulation</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Pixel Manipulation</refname>
+ <refpurpose>iterating over the display</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>
+#include <cyg/io/framebuf.h>
+ </funcsynopsisinfo>
+ <funcprototype>
+ <funcdef><function>CYG_FB_PIXEL0_VAR</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_PIXEL0_SET</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_PIXEL0_GET</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_PIXEL0_ADDX</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>incr</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_PIXEL0_ADDY</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>incr</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_PIXEL0_WRITE</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>cyg_fb_colour <function>CYG_FB_PIXEL0_READ</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_PIXEL0_FLUSHABS</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x0</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y0</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+ </funcprototype>
+ <funcprototype>
+ <funcdef>void <function>CYG_FB_PIXEL0_FLUSHREL</function></funcdef>
+ <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>x0</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>y0</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>dx</parameter></paramdef>
+ <paramdef>cyg_ucount16 <parameter>dy</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="framebuf-iteration-description">
+ <title>Description</title>
+ <para>
+A common requirement for graphics code is to iterate over parts of the
+framebuffer. Drawing text typically involves iterating over a block
+of pixels for each character, say 8 by 8, setting each pixel to either
+a foreground or background colour. Drawing arbitrary lines typically
+involves moving to the start position and then adjusting the x and y
+coordinates until the end position is reached, setting a single pixel
+each time around the loop. Drawing images which are not in the frame
+buffer's native format typically involves iterating over a block of
+pixels, from top to bottom and left to right, setting pixels as the
+image is decoded.
+ </para>
+ <para>
+Functionality like this can be implemented in several ways. One
+approach is to use the pixel write primitive. Typically this involves
+some arithmetic to get from the x and y coordinates to a location
+within framebuffer memory so it is fairly expensive compared with a
+loop which just increments a pointer. Another approach is to write the
+data first to a separate buffer in memory and then use a block write
+primitive to move it to the framebuffer, but again this involves
+overhead. The eCos framebuffer support provides a third approach: a
+set of macros specifically for iterating over the frame buffer.
+Depending on the operation being performed and the details of the
+framebuffer implementation, these macros may be optimal or
+near-optimal. Obviously there are limitations. Most importantly the
+framebuffer device must be known at compile-time: the compiler can do
+a better job optimizing the code if information such as the frame
+buffer width are constant. Also each iteration must be performed
+within a single variable scope: it is not possible to do some of the
+iteration in one function, some in another.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-iteration-macros">
+ <title>The Pixel Macros</title>
+ <para>
+All the pixel macros take a framebuffer identifier as their first
+argument. This is the same identifier that can be used with the other
+macros like <function>CYG_FB_WRITE_HLINE</function> and
+<function>CYG_FB_ON</function>, one of the entries in the
+configuration option <varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>.
+Using an invalid identifier will result in numerous compile-time error
+messages which may bear little resemblance to the original code. In
+the examples below it is assumed that <varname>FRAMEBUF</varname> has
+been <literal>#define</literal>'d to a suitable identifier.
+ </para>
+ <para>
+Typical use of the pixel macros will look like this:
+ </para>
+<programlisting width=72>
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ …
+ CYG_FB_PIXEL0_FLUSHABS(FRAMEBUF, x, y, width, height);
+</programlisting>
+ <para>
+The <literal>VAR</literal> macro will define one or more local
+variables to keep track of the current pixel position, as appropriate
+to the framebuffer device. The other pixel macros will then use these
+variables. For a simple 8bpp linear framebuffer there will be just a
+byte pointer. For a 1bpp display there may be several variables: a
+byte pointer, a bit index within that byte, and possibly a cached
+byte; using a cached value means that the framebuffer may only get
+read and written once for every 8 pixels, and the compiler may well
+allocate a register for the cached value; on some platforms
+framebuffer access will bypass the processor's main cache, so reading
+from or writing to framebuffer memory will be slow; reducing the
+number of framebuffer accesses may greatly improve performance.
+ </para>
+ <para>
+Because the <literal>VAR</literal> macro defines one or more local
+variables it is normally placed at the start of a function or block,
+alongside other local variable definitions.
+ </para>
+ <para>
+One the iteration has been completed there should be a
+<function>FLUSHABS</function> or <function>FLUSHREL</function> macro.
+This serves two purposes. First, if the local variables involve a
+dirty cached value or similar state then this will be written back.
+Second, for double-buffered displays the macro sets a bounding box for
+the part of the screen that has been updated. This allows the double
+buffer synch operation to update only the part of the display that has
+been modified, without having to keep track of the current bounding
+box for every updated pixel. For <literal>FLUSHABS</literal> the
+<parameter>x0</parameter> and <parameter>y0</parameter> arguments
+specify the top-left corner of the bounding box, which extends for
+<parameter>width</parameter> by <parameter>height</parameter> pixels.
+For <literal>FLUSHREL</literal> <parameter>x0</parameter> and
+<parameter>y0</parameter> still specify the top-left corner, but the
+bottom-right corner is now determined from the current pixel position
+offset by <parameter>dx</parameter> and <parameter>dy</parameter>.
+More specifically, <parameter>dx</parameter> should move the current
+horizontal position one pixel to the right of the right-most pixel
+modified, such that
+<literal>(x + dx) - x0</literal> gives the width
+of the bounding box. Similarly <parameter>dy</parameter> should move
+the current vertical position one pixel below the bottom-most pixel
+modified. In typical code the current pixel position will already
+correspond in part or in whole to the bounding box corner, as a
+consequence of iterating over the block of memory.
+ </para>
+ <para>
+If a pixel variable has been used only for reading framebuffer memory,
+not for modifying it, then it should still be flushed. A
+<literal>FLUSHABS</literal> with a width and height of 0 can be used
+to indicate that the bounding box is empty. If it is known that the
+framebuffer device being used does not support double-buffering then
+again it is possible to specify an empty bounding box. Otherwise
+portable code should specify a correct bounding box. If the
+framebuffer device that ends up being used does not support double
+buffering then the relevant macro arguments are eliminated at
+compile-time and do not result in any unnecessary code. In addition if
+there is no cached value or other state then the whole flush operation
+will be a no-op and no code will be generated.
+ </para>
+ <para>
+Failure to perform the flush may result in strange drawing artefacts
+on some displays which can be very hard to debug. A
+<function>FLUSHABS</function> or <function>FLUSHREL</function> macro
+only needs to be invoked once, at the end of the iteration.
+ </para>
+ <para>
+The <literal>SET</literal> macro sets the current position within the
+framebuffer. It can be used many times within an iteration. However
+it tends to be somewhat more expensive than <literal>ADDX</literal> or
+<literal>ADDY</literal>, so usually <literal>SET</literal> is only
+executed once at the start of an iteration.
+ </para>
+<programlisting width=72>
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+ …
+ CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, 0, 0);
+</programlisting>
+ <para>
+The <literal>GET</literal> macro retrieves the x and y coordinates
+corresponding to the current position. It is provided mainly for
+symmetry, but can prove useful for debugging.
+ </para>
+<programlisting width=72>
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+ …
+#ifdef DEBUG
+ CYG_FB_PIXEL0_GET(FRAMEBUF, new_x, new_y);
+ diag_printf("Halfway through: x now %d, y now %d\n", new_x, new_y);
+#endif
+ …
+ CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, 0, 0);
+</programlisting>
+ <para>
+The <literal>ADDX</literal> and <literal>ADDY</literal> macros adjust
+the current position. The most common increments are 1 and -1, moving
+to the next or previous pixel horizontally or vertically, but any
+increment can be used.
+ </para>
+<programlisting width=72>
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+ for (rows = height; rows; rows--) {
+ for (columns = width; columns; columns--) {
+ <perform operation>
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, 1);
+ }
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * width);
+ CYG_FB_PIXEL0_ADDY(FRAMEBUF, 1);
+ }
+ CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, width, 0);
+</programlisting>
+ <para>
+Here the current position is moved one pixel to the right each time
+around the inner loop. In the outer loop the position is first moved
+back to the start of the current row, then moved one pixel down.
+For the final flush the current x position is off by
+<literal>width</literal>, but the current y position is already correct.
+ </para>
+ <para>
+The final two macros <literal>READ</literal> and
+<literal>WRITE</literal> can be used to examine or update the current
+pixel value.
+ </para>
+<programlisting width=72>
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+ for (rows = height; rows; rows--) {
+ for (columns = width; columns; columns--) {
+ cyg_fb_colour colour = CYG_FB_PIXEL0_READ(FRAMEBUF);
+ if (colour == colour_to_replace) {
+ CYG_FB_PIXEL0_WRITE(FRAMEBUF, replacement);
+ }
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, 1);
+ }
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * width);
+ CYG_FB_PIXEL0_ADDY(FRAMEBUF, 1);
+ }
+ CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, width, 0);
+</programlisting>
+ </refsect1>
+
+ <refsect1 id="framebuf-iteration-other">
+ <title>Concurrent Iterations</title>
+ <para>
+Although uncommon, in some cases application code may need to iterate
+over two or more blocks. An example might be an advanced block move
+where each copied pixel requires some processing. To support this
+there are <literal>PIXEL1</literal>, <literal>PIXEL2</literal> and
+<literal>PIXEL3</literal> variants of all the
+<literal>PIXEL0</literal> macros. For example:
+ </para>
+<programlisting width=72>
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ CYG_FB_PIXEL1_VAR(FRAMEBUF);
+
+ CYG_FB_PIXEL0_SET(FRAMEBUF, dest_x, dest_y_);
+ CYG_FB_PIXEL1_SET(FRAMEBUF, source_x, source_y);
+ for (rows = height; rows; rows--) {
+ for (columns = width; columns; columns--) {
+ colour = CYG_FB_PIXEL1_READ(FRAMEBUF);
+ <do some processing on colour>
+ CYG_FB_PIXEL0_WRITE(FRAMEBUF, colour);
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, 1);
+ CYG_FB_PIXEL1_ADDX(FRAMEBUF, 1);
+ }
+ CYG_FB_PIXEL0_ADDX(FRAMEBUF, -100);
+ CYG_FB_PIXEL0_ADDY(FRAMEBUF, 1);
+ CYG_FB_PIXEL1_ADDX(FRAMEBUF, -100);
+ CYG_FB_PIXEL1_ADDY(FRAMEBUF, 1);
+ }
+
+ CYG_FB_PIXEL0_FLUSHABS(FRAMEBUF, source_x, source_y, width, height);
+ CYG_FB_PIXEL1_FLUSHABS(FRAMEBUF, 0, 0, 0, 0); // Only used for reading
+</programlisting>
+ <para>
+The <literal>PIXEL0</literal>, <literal>PIXEL1</literal>,
+<literal>PIXEL2</literal> and <literal>PIXEL3</literal> macros all use
+different local variables so there are no conflicts. The variable
+names also depend on the framebuffer device. If the target has two
+displays and two active framebuffer devices then the pixel macros can
+be used with the two devices without conflict:
+ </para>
+<programlisting width=72>
+ CYG_FB_PIXEL0_VAR(FRAMEBUF0);
+ CYG_FB_PIXEL0_VAR(FRAMEBUF1);
+ …
+</programlisting>
+ </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Porting -->
+
+<refentry id="framebuf-porting">
+ <refmeta>
+ <refentrytitle>Writing a Framebuffer Device Driver</refentrytitle>
+ </refmeta>
+ <refnamediv>
+ <refname>Porting</refname>
+ <refpurpose>writing a new framebuffer device driver</refpurpose>
+ </refnamediv>
+
+ <refsect1 id="framebuf-porting-description">
+ <title>Description</title>
+ <para>
+As with most device drivers, the easiest way to write a new
+framebuffer package is to start with an existing one. Suitable ones
+include the PC VGA mode13 driver, an 8bpp paletted display, and the
+ARM iPAQ driver, a 16bpp true colour display. This document only
+outlines the process.
+ </para>
+ <para>
+Before writing any code it is necessary to decide how many framebuffer
+devices should be provided by the device driver. Each such device
+requires a <structname>cyg_fb</structname> structure and appropriate
+functions, and an identifier for use with the macro API plus
+associated macros. There are no hard rules here. Some device drivers
+may support just a single device, others may support many devices
+which drive the hardware in different modes or orientations. Optional
+functionality such as viewports and page flipping may be supported by
+having different <structname>cyg_fb</structname> devices, or by a
+number of configuration options which affect a single
+<structname>cyg_fb</structname> device. Usually providing multiple
+<structname>cyg_fb</structname> structures is harmless because the
+unused ones will get eliminated at link-time.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-porting-configuration">
+ <title>Configuration</title>
+ <para>
+The CDL for a framebuffer package is usually straightforward. A
+framebuffer package should be a hardware package and reside in the
+<filename class="directory">devs/framebuf</filename> hierarchy,
+further organized by architecture. Generic framebuffer packages, if
+any, can go into a <filename class="directory">generic</filename>
+subdirectory, and will normally rely on the platform HAL to provide
+some platform-specific information such as base addresses. The package
+should be part of the target definition and hence loaded
+automatically, but should be
+<literal>active_if CYGPKG_IO_FRAMEBUF</literal> so that the
+driver only gets built if the generic framebuffer support is
+explicitly added to the configuration.
+ </para>
+ <para>
+The configuration option <varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>
+should hold all the valid identifiers which can be used as the first
+argument for the macro API. This helps application developers to
+select the appropriate identifier, and allows higher-level graphics
+library packages to check that they have been configured correctly.
+This is achieved using something like the following, where
+<literal>mode13_320x200x8</literal> is a valid identifier for the PC
+VGA driver:
+ </para>
+ <programlisting width=72>
+ requires { is_substr(CYGDAT_IO_FRAMEBUF_DEVICES, " mode13_320x200x8 ") }
+ </programlisting>
+ <para>
+The spaces ensure that the CDL inference engine keeps the identifiers
+separate.
+ </para>
+ <para>
+<varname>CYGPKG_IO_FRAMEBUF</varname> contains a number of interfaces
+which should be implemented by individual device drivers when
+appropriate. This is used to eliminate some code or data structure
+fields at compile-time, keeping down memory requirements. The
+interfaces are
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_32BPP</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER</varname>,
+and <varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT</varname>.
+For example if a device driver provides a true colour display but
+fails to implement the relevant interface then functions like
+<function>cyg_fb_make_colour</function> will be no-ops.
+ </para>
+ <para>
+Device drivers for paletted displays should observe the generic
+configuration option
+<varname>CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE</varname> and
+install either <varname>cyg_fb_palette_ega</varname> or
+<varname>cyg_fb_palette_vga</varname> as part of their
+<function>cyg_fb_on</function> implementation.
+ </para>
+ </refsect1>
+
+ <refsect1 id="framebuf-porting-header">
+ <title>Exported Header File(s)</title>
+ <para>
+Each framebuffer device driver should export one or more header files
+to <filename class="directory">cyg/io/framebufs</filename>. A custom
+build step in <varname>CYGPKG_IO_FRAMEBUF</varname> ensures that
+application code can just <literal>#include</literal> <filename
+class="headerfile">cyg/io/framebuf.h</filename> and this will
+automatically include the device-specific headers. Drivers may export
+one header per <structname>cyg_fb</structname> device or a single
+header for all devices, without affecting any code outside the device
+driver.
+ </para>
+ <para>
+Each exported header serves two purposes. First it defines the
+<link linkend="framebuf-parameters">parameters</link>, <link
+linkend="framebuf-drawing">drawing primitive</link> macros, and
+<link linkend="framebuf-iterating">iteration</link> macros for each
+device. Second it declares the <structname>cyg_fb</structname>
+structure.
+ </para>
+ <refsect2 id="framebuf-porting-header-parameters">
+ <title>Parameters</title>
+ <para>
+The parameter section should resemble the following:
+ </para>
+ <programlisting width=72>
+#define CYG_FB_320x240x16_STRUCT cyg_ipaq_fb_320x240x16
+#define CYG_FB_320x240x16_DEPTH 16
+#define CYG_FB_320x240x16_FORMAT CYG_FB_FORMAT_16BPP_TRUE_565
+#define CYG_FB_320x240x16_WIDTH 320
+#define CYG_FB_320x240x16_HEIGHT 240
+#define CYG_FB_320x240x16_VIEWPORT_WIDTH 320
+#define CYG_FB_320x240x16_VIEWPORT_HEIGHT 240
+#define CYG_FB_320x240x16_FLAGS0 (CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER | \
+ CYG_FB_FLAGS0_TRUE_COLOUR | \
+ CYG_FB_FLAGS0_BLANK | \
+ CYG_FB_FLAGS0_BACKLIGHT)
+#define CYG_FB_320x240x16_FLAGS1 0
+#define CYG_FB_320x240x16_FLAGS2 0
+#define CYG_FB_320x240x16_FLAGS3 0
+#define CYG_FB_320x240x16_BASE ((void*)0x01FC0020)
+#define CYG_FB_320x240x16_STRIDE 640
+ </programlisting>
+ <para>
+Here <literal>320x240x16</literal> is the framebuffer identifier for
+use with the macro API. Application code like:
+ </para>
+ <programlisting width=72>
+#define FRAMEBUF 320x240x16
+cyg_ucount16 width = CYG_FB_WIDTH(FRAMEBUF);
+ </programlisting>
+ <para>
+will end up using the <varname>CYG_FB_320x240x16_WIDTH</varname>
+definition. To allow for efficient portable code all parameters must
+be compile-time constants. If the hardware may allow some of the
+parameters to be varied, for example different resolutions, then this
+should be handled either by defining separate devices for each
+resolution or by configuration options.
+ </para>
+ <para>
+The viewport width and height should always be defined. If the device
+driver does not support a viewport then these will be the same as the
+standard width and height.
+ </para>
+ <para>
+To allow for future expansion there are <literal>FLAGS1</literal>,
+<literal>FLAGS2</literal> and <literal>FLAGS3</literal> parameters. No
+flags are defined for these at present, but device drivers should
+still define the parameters.
+ </para>
+ </refsect2>
+
+ <refsect2 id="framebuf-porting-header-drawing">
+ <title>Drawing Primitives</title>
+ <para>
+For each device the exported header file should define macros for the
+drawing primitives, using the same naming convention as for
+parameters. In the case of true colour displays there should also be
+macros for the make-colour and break-colour primitives:
+ </para>
+ <programlisting width=72>
+#define CYG_FB_320x240x16_WRITE_PIXEL(_x_, _y_, _colour_) …
+#define CYG_FB_320x240x16_READ_PIXEL(_x_, _y_) …
+#define CYG_FB_320x240x16_WRITE_HLINE(_x_, _y_, _len_, _colour_) …
+#define CYG_FB_320x240x16_WRITE_VLINE(_x_, _y_, _len_, _colour_) …
+#define CYG_FB_320x240x16_FILL_BLOCK(_x_, _y_, _w_, _h_, _colour_) …
+#define CYG_FB_320x240x16_WRITE_BLOCK(_x_, _y_, _w_, _h_, _data_, _off_, _s_) …
+#define CYG_FB_320x240x16_READ_BLOCK(_x_, _y_, _w_, _h_, _data_, _off_, _s_) …
+#define CYG_FB_320x240x16_MOVE_BLOCK(_x_, _y_, _w_, _h_, _new_x_, _new_y_) …
+#define CYG_FB_320x240x16_MAKE_COLOUR(_r_, _g_, _b_) …
+#define CYG_FB_320x240x16_BREAK_COLOUR(_colour_, _r_, _g_, _b_) …
+ </programlisting>
+ <para>
+For typical linear framebuffers there are default implementations of
+all of these primitives in the generic framebuffer package, held in
+the exported header <filename
+class="headerfile">cyg/io/framebuf.inl</filename>. Hence the
+definitions will typically look something like:
+ </para>
+ <programlisting width=72>
+#include <cyg/io/framebuf.inl>
+…
+#define CYG_FB_320x240x16_WRITE_PIXEL(_x_, _y_, _colour_) \
+ CYG_MACRO_START \
+ cyg_fb_linear_write_pixel_16_inl(CYG_FB_320x240x16_BASE, \
+ CYG_FB_320x240x16_STRIDE, \
+ _x_, _y_, _colour_); \
+ CYG_MACRO_END
+#define CYG_FB_320x240x16_READ_PIXEL(_x_, _y_) \
+ ({ cyg_fb_linear_read_pixel_16_inl(CYG_FB_320x240x16_BASE, \
+ CYG_FB_320x240x16_STRIDE, \
+ _x_, _y_); })
+…
+ </programlisting>
+ <para>
+All of the drawing primitives have variants for the common display
+depths and layouts: 1le, 1be, 2le, 2be, 4le, 4be, 8, 16 and 32. The
+inlines take the framebuffer memory base address as the first
+argument, and the stride in bytes as the second. Similarly there are
+default definitions of the true colour primitives for
+<literal>8BPP_TRUE_332</literal>, <literal>16BPP_TRUE_565</literal>,
+<literal>16BPP_TRUE_555</literal>, and <literal>32BPP_TRUE_0888</literal>:
+ </para>
+ <programlisting width=72>
+#define CYG_FB_320x240x16_MAKE_COLOUR(_r_, _g_, _b_) \
+ ({ CYG_FB_MAKE_COLOUR_16BPP_TRUE_565(_r_, _g_, _b_); })
+#define CYG_FB_320x240x16_BREAK_COLOUR(_colour_, _r_, _g_, _b_) \
+ CYG_MACRO_START \
+ CYG_FB_BREAK_COLOUR_16BPP_TRUE_565(_colour_, _r_, _g_, _b_); \
+ CYG_MACRO_END
+ </programlisting>
+ <para>
+If the hardware does not implement a linear framebuffer then obviously
+writing the device driver will be significantly more work. The macros
+will have to perform the operations themselves instead of relying on
+generic implementations. The required functionality should be obvious,
+and the generic implementations can still be consulted as a reference.
+For complicated hardware it may be appropriate to map the macros onto
+function calls, rather than try to implement everything inline.
+ </para>
+ <note><para> At the time of writing the support for linear
+framebuffers is incomplete. Only 8bpp, 16bpp and 32bpp depths have
+full support. There may also be future extensions, for example
+<literal>r90</literal>, <literal>r180</literal> and
+<literal>r270</literal> variants to support rotation in software, and
+<literal>db</literal> variants to support double-buffered displays.
+ </para></note>
+ </refsect2>
+
+ <refsect2 id="framebuf-porting-header-iterating">
+ <title>Iteration Macros</title>
+ <para>
+In addition to the drawing primitives the exported header file should
+define iteration macros:
+ </para>
+ <programlisting width=72>
+#define CYG_FB_320x240x16_PIXELx_VAR( _fb_, _id_) …
+#define CYG_FB_320x240x16_PIXELx_SET( _fb_, _id_, _x_, _y_) …
+#define CYG_FB_320x240x16_PIXELx_GET( _fb_, _id_, _x_, _y_) …
+#define CYG_FB_320x240x16_PIXELx_ADDX( _fb_, _id_, _incr_) …
+#define CYG_FB_320x240x16_PIXELx_ADDY( _fb_, _id_, _incr_) …
+#define CYG_FB_320x240x16_PIXELx_WRITE(_fb_, _id_, _colour_) …
+#define CYG_FB_320x240x16_PIXELx_READ( _fb_, _id_)…
+#define CYG_FB_320x240x16_PIXELx_FLUSHABS( _fb_, _id_, _x0_, _y0_, _w_, _h_) …
+#define CYG_FB_320x240x16_PIXELx_FLUSHREL( _fb_, _id_, _x0_, _y0_, _dx_, _dy_) …
+ </programlisting>
+ <para>
+The <parameter>_fb_</parameter> argument will be the identifier, in
+this case <literal>320x240x16</literal>, and the
+<parameter>_id_</parameter> will be a small number, 0 for a
+<literal>PIXEL0</literal> iteration, 1 for <literal>PIXEL1</literal>,
+and so on. Together these two should allow unique local variable names
+to be constructed. Again there are default definitions of the macros
+in <filename class="headerfile">cyg/io/framebuf.inl</filename> for
+linear framebuffers:
+ </para>
+ <programlisting width=72>
+#define CYG_FB_320x240x16_PIXELx_VAR( _fb_, _id_) \
+ CYG_FB_PIXELx_VAR_16( _fb_, _id_)
+#define CYG_FB_320x240x16_PIXELx_SET( _fb_, _id_, _x_, _y_) \
+ CYG_MACRO_START \
+ CYG_FB_PIXELx_SET_16( _fb_, _id_, \
+ CYG_FB_320x240x16_BASE, \
+ 320, _x_, _y_); \
+ CYG_MACRO_END
+ </programlisting>
+ <para>
+The linear <literal>SET</literal> and <literal>GET</literal> macros
+take base and stride information. The <literal>ADDX</literal> and
+<literal>ADDY</literal> macros only need the stride. By convention
+most of the macros are wrapped in
+<literal>CYG_MACRO_START</literal>/<literal>CYG_MACRO_END</literal> or
+<literal>({</literal>/<literal>})</literal> pairs, allowing debug code
+to be inserted if necessary. However the <literal>_VAR</literal> macro
+must not be wrapped in this way: its purpose is to define one or more
+local variables; wrapping the macro would declare the variables in a
+new scope, inaccessible to the other macros.
+ </para>
+ <para>
+Again for non-linear framebuffers it will be necessary to implement
+these macros fully rather than rely on generic implementations, but
+the generic versions can be consulted as a reference.
+ </para>
+ </refsect2>
+
+ <refsect2 id="framebuf-porting-header-fb">
+ <title>The <structname>cyg_fb</structname> declaration</title>
+ <para>
+Finally there should be an export of the
+<structname>cyg_fb</structname> structure or structures. Typically
+this uses the <literal>_STRUCT</literal> parameter, reducing the
+possibility of an accidental mismatch between the macro and function APIs:
+ </para>
+ <programlisting width=72>
+extern cyg_fb CYG_FB_320x240x16_STRUCT;
+ </programlisting>
+ </refsect2>
+
+</refsect1>
+
+ <refsect1 id="framebuf-porting-source">
+ <title>Driver-Specific Source Code</title>
+ <para>
+Exporting parameters and macros in a header file is not enough. It is
+also necessary to actually define the <structname>cyg_fb</structname>
+structure or structures, and to provide hardware-specific versions of
+the control operations. For non-linear framebuffers it will also be
+necessary to provide the drawing functions. There is a utility macro
+<function>CYG_FB_FRAMEBUFFER</function> for instantiating a
+<structname>cyg_fb</structname> structure. Drivers may ignore this
+macro and do the work themselves, but at an increased risk of
+compatibility problems with future versions of the generic code.
+ </para>
+ <programlisting width=72>
+CYG_FB_FRAMEBUFFER(CYG_FB_320x240x16_STRUCT,
+ CYG_FB_320x240x16_DEPTH,
+ CYG_FB_320x240x16_FORMAT,
+ CYG_FB_320x240x16_WIDTH,
+ CYG_FB_320x240x16_HEIGHT,
+ CYG_FB_320x240x16_VIEWPORT_WIDTH,
+ CYG_FB_320x240x16_VIEWPORT_HEIGHT,
+ CYG_FB_320x240x16_BASE,
+ CYG_FB_320x240x16_STRIDE,
+ CYG_FB_320x240x16_FLAGS0,
+ CYG_FB_320x240x16_FLAGS1,
+ CYG_FB_320x240x16_FLAGS2,
+ CYG_FB_320x240x16_FLAGS3,
+ 0, 0, 0, 0, // fb_driver0 -> fb_driver3
+ &cyg_ipaq_fb_on,
+ &cyg_ipaq_fb_off,
+ &cyg_ipaq_fb_ioctl,
+ &cyg_fb_nop_synch,
+ &cyg_fb_nop_read_palette,
+ &cyg_fb_nop_write_palette,
+ &cyg_fb_dev_make_colour_16bpp_true_565,
+ &cyg_fb_dev_break_colour_16bpp_true_565,
+ &cyg_fb_linear_write_pixel_16,
+ &cyg_fb_linear_read_pixel_16,
+ &cyg_fb_linear_write_hline_16,
+ &cyg_fb_linear_write_vline_16,
+ &cyg_fb_linear_fill_block_16,
+ &cyg_fb_linear_write_block_16,
+ &cyg_fb_linear_read_block_16,
+ &cyg_fb_linear_move_block_16,
+ 0, 0, 0, 0 // fb_spare0 -> fb_spare3
+);
+ </programlisting>
+ <para>
+The first 13 arguments to the macro correspond to the device
+parameters. The next four are arbitrary <type>CYG_ADDRWORD</type>
+values for use by the device driver. Typically these are used to share
+on/off/ioctl functions between multiple
+<structname>cyg_fb</structname> structure. They are followed by
+function pointers: on/off/ioctl control; double buffer synch; palette
+management; true colour support; and the drawing primitives.
+<literal>nop</literal> versions of the on, off, ioctl, synch, palette
+management and true colour functions are provided by the generic
+framebuffer package, and often these arguments to the
+<function>CYG_FB_FRAMEBUFFER</function> macro will be discarded
+at compile-time because the relevant CDL interface is not implemented.
+The final four arguments are currently unused and should be 0. They
+are intended for future expansion, with a value of 0 indicating that a
+device driver does not implement non-core functionality.
+ </para>
+ <para>
+As with the macros there are default implementations of the true
+colour primitives for <literal>8bpp_true_332</literal>,
+<literal>16bpp_true_565</literal>, <literal>16bpp_true_555</literal>
+and <literal>32bpp_true_0888</literal>. There are also default
+implementations of the drawing primitives for linear framebuffers,
+with variants for the common display depths and layouts. Obviously
+non-linear framebuffers will need rather more work.
+ </para>
+ <para>
+Typically a true colour or grey scale framebuffer device driver will
+have to implement just three hardware-specific functions:
+ </para>
+ <programlisting width=72>
+int
+cyg_ipaq_fb_on(cyg_fb* fb)
+{
+ …
+}
+
+int
+cyg_ipaq_fb_off(cyg_fb* fb)
+{
+ …
+}
+
+int
+cyg_ipaq_fb_ioctl(cyg_fb* fb, cyg_ucount16 key, void* data, size_t* len)
+{
+ int result;
+
+ switch(key) {
+ case CYG_FB_IOCTL_BLANK_GET: …
+ …
+ default: result = ENOSYS; break;
+ }
+ return result;
+}
+ </programlisting>
+ <para>
+These control operations are entirely hardware-specific and cannot be
+implemented by generic code. Paletted displays will need two more
+functions, again hardware-specific:
+ </para>
+ <programlisting width=72>
+void
+cyg_pcvga_fb_read_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 len,
+ void* data)
+{
+ …
+}
+
+void
+cyg_pcvga_fb_write_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 len,
+ const void* data, cyg_ucount16 when)
+{
+ …
+}
+ </programlisting>
+ </refsect1>
+
+ <refsect1 id="framebuf-porting-expansion">
+ <title>Future Expansion</title>
+ <para>
+As has been mentioned before framebuffer hardware varies widely. The
+design of a generic framebuffer API requires complicated trade-offs
+between efficiency, ease of use, ease of porting, and still supporting
+a very wide range of hardware. To some extent this requires a lowest
+common denominator approach, but the design allows for some future
+expansion and optional support for more advanced features like
+hardware acceleration.
+ </para>
+ <para>
+The most obvious route for expansion is the <function>ioctl</function>
+interface. Device drivers can define their own keys, values
+<literal>0x8000</literal> and higher, for any operation. Alternatively
+a device driver does not have to implement just the interface provided
+by the generic framebuffer package: additional functions and macros
+can be exported as required.
+ </para>
+ <para>
+Currently there are only a small number of <function>ioctl</function>
+operations. Additional ones may get added in future, for example to
+support a hardware mouse cursor, but only in cases where the
+functionality is likely to be provided by a significant number of
+framebuffer devices. Adding new generic functionality adds to the
+maintenance overhead of both code and documentation. When a new
+generic <function>ioctl</function> operation is added there will
+usually also be one or more new flags, so that device drivers can
+indicate they support the functionality. At the time of writing only
+12 of the 32 <literal>FLAGS0</literal> flags are used, and a further
+96 are available in <literal>FLAGS1</literal>,
+<literal>FLAGS2</literal> and <literal>FLAGS3</literal>.
+ </para>
+ <para>
+Another route for future expansion is the four spare arguments to the
+<function>CYG_FB_FRAMEBUFFER</function> macro. As an example of how
+these may get used in future, consider support for 3d hardware
+acceleration. One of the spare fields would become another table of
+function pointers to the various accelerators, or possibly a
+structure. A <literal>FLAGS0</literal> flag would indicate that the
+device driver implements such functionality.
+ </para>
+ <para>
+Other forms of expansion such as defining a new standard drawing
+primitive would be more difficult, since this would normally involve
+changing the <function>CYG_FB_FRAMEBUFFER</function> macro. Such
+expansion should not be necessary because the existing primitives
+provide all reasonable core functionality. Instead other packages such
+as graphics libraries can work on top of the existing primitives.
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+
+</part>
Index: include/framebuf.h
===================================================================
RCS file: include/framebuf.h
diff -N include/framebuf.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/framebuf.h 7 Oct 2008 10:03:04 -0000
@@ -0,0 +1,1024 @@
+#ifndef CYGONCE_IO_FRAMEBUF_H
+#define CYGONCE_IO_FRAMEBUF_H
+
+//=============================================================================
+//
+// framebuf.h
+//
+// Generic API for accessing framebuffers
+//
+//=============================================================================
+//###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-03-29
+//####DESCRIPTIONEND####
+//=============================================================================
+
+#include <pkgconf/infra.h>
+#include <pkgconf/io_framebuf.h>
+#include <cyg/infra/cyg_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ----------------------------------------------------------------------------
+// The colour data type. For now this is a cyg_ucount32. On 16-bit targets
+// where the display depth is less than 32bpp a cyg_ucount16 would suffice
+// and be more efficient. A separate cyg_fb_colour type is used to allow this
+// change to be made in future.
+typedef cyg_ucount32 cyg_fb_colour;
+typedef cyg_fb_colour cyg_fb_color;
+
+// ----------------------------------------------------------------------------
+// Each framebuffer device exports one of these structures
+typedef struct cyg_fb {
+#ifdef CYGPKG_INFRA_DEBUG
+ cyg_ucount32 fb_magic;
+#endif
+ cyg_ucount16 fb_depth; // 1, 2, 4, 8, 16, or 32 bits per pixel
+ cyg_ucount16 fb_format; // detailed format, e.g. 8-bit paletted, or 32-bit 0888
+ cyg_ucount16 fb_width; // of the framebuffer, not the viewport
+ cyg_ucount16 fb_height;
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+ cyg_ucount16 fb_viewport_width;
+ cyg_ucount16 fb_viewport_height;
+#endif
+ void* fb_base; // Base address of the framebuffer, or 0 if not directly accessible
+ cyg_ucount16 fb_stride; // number of bytes per line
+ cyg_uint32 fb_flags0;
+ cyg_uint32 fb_flags1;
+ cyg_uint32 fb_flags2;
+ cyg_uint32 fb_flags3;
+
+ CYG_ADDRWORD fb_driver0; // Driver private fields
+ CYG_ADDRWORD fb_driver1;
+ CYG_ADDRWORD fb_driver2;
+ CYG_ADDRWORD fb_driver3;
+
+ int (*fb_on_fn)(struct cyg_fb*);
+ int (*fb_off_fn)(struct cyg_fb*);
+ int (*fb_ioctl_fn)( struct cyg_fb*, cyg_ucount16, void*, size_t*);
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER
+ void (*fb_synch_fn)( struct cyg_fb*, cyg_ucount16);
+#endif
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+ void (*fb_read_palette_fn)(struct cyg_fb*, cyg_ucount32, cyg_ucount32, void*);
+#endif
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+ void (*fb_write_palette_fn)(struct cyg_fb*, cyg_ucount32, cyg_ucount32, const void*, cyg_ucount16);
+#endif
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+ cyg_fb_colour (*fb_make_colour_fn)(struct cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+ void (*fb_break_colour_fn)(struct cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+#endif
+
+ void (*fb_write_pixel_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+ cyg_fb_colour (*fb_read_pixel_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16);
+ void (*fb_write_hline_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+ void (*fb_write_vline_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+ void (*fb_fill_block_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+ void (*fb_write_block_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, const void*, cyg_ucount16, cyg_ucount16);
+ void (*fb_read_block_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, void*, cyg_ucount16, cyg_ucount16);
+ void (*fb_move_block_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16);
+} cyg_fb;
+
+// A magic number used to validate an fb pointer
+#define CYG_FB_MAGIC 0xC201e147
+
+// The various supported colour formats. A 16-bit value.
+#define CYG_FB_FORMAT_1BPP_MONO_0_BLACK 0x0000
+#define CYG_FB_FORMAT_1BPP_MONO_0_WHITE 0x0001
+#define CYG_FB_FORMAT_1BPP_PAL888 0x0002
+
+#define CYG_FB_FORMAT_2BPP_GREYSCALE_0_BLACK 0x0100
+#define CYG_FB_FORMAT_2BPP_GRAYSCALE_0_BLACK 0x0100
+#define CYG_FB_FORMAT_2BPP_GREYSCALE_0_WHITE 0x0101
+#define CYG_FB_FORMAT_2BPP_GRAYSCALE_0_WHITE 0x0101
+#define CYG_FB_FORMAT_2BPP_PAL888 0x0102
+
+#define CYG_FB_FORMAT_4BPP_GREYSCALE_0_BLACK 0x0200
+#define CYG_FB_FORMAT_4BPP_GRAYSCALE_0_BLACK 0x0200
+#define CYG_FB_FORMAT_4BPP_GREYSCALE_0_WHITE 0x0201
+#define CYG_FB_FORMAT_4BPP_GRAYSCALE_0_WHITE 0x0202
+#define CYG_FB_FORMAT_4BPP_PAL888 0x0203
+
+#define CYG_FB_FORMAT_8BPP_PAL888 0x0300
+#define CYG_FB_FORMAT_8BPP_TRUE_332 0x0301
+
+#define CYG_FB_FORMAT_16BPP_TRUE_565 0x0400
+#define CYG_FB_FORMAT_16BPP_TRUE_555 0x0401
+
+#define CYG_FB_FORMAT_32BPP_TRUE_0888 0x0500
+
+// Flags indicating exactly what the device driver can support.
+// Each fb structure has four flags fields for a maximum of
+// 128 flags, allowing for future expansion at a relatively
+// low cost.
+
+// The framebuffer memory is directly accessible and organized in a
+// conventional fashion, i.e. increasing x means the addresses
+// increase by 1 bit/nibble/byte/short/int as appropriate, and
+// increasing y means adding n bytes/shorts/ints
+#define CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER (0x01 << 0)
+// Only relevant for 1bpp, 2bpp and 4bpp displays. Little-endian
+// means that pixel (0,0) occupies bit 0 of framebuffer byte 0.
+// 0. Big-endian means that pixel(0,0) occupies bit 7.
+#define CYG_FB_FLAGS0_LE (0x01 << 1)
+
+#define CYG_FB_FLAGS0_TRUE_COLOUR (0x01 << 8)
+#define CYG_FB_FLAGS0_TRUE_COLOR (0x01 << 8)
+#define CYG_FB_FLAGS0_PALETTE (0x01 << 9)
+#define CYG_FB_FLAGS0_WRITEABLE_PALETTE (0x01 << 10)
+
+#define CYG_FB_FLAGS0_DELAYED_PALETTE_UPDATE (0x01 << 16)
+#define CYG_FB_FLAGS0_VIEWPORT (0x01 << 17)
+#define CYG_FB_FLAGS0_DOUBLE_BUFFER (0x01 << 18)
+#define CYG_FB_FLAGS0_PAGE_FLIPPING (0x01 << 19)
+#define CYG_FB_FLAGS0_BLANK (0x01 << 20)
+#define CYG_FB_FLAGS0_BACKLIGHT (0x01 << 21)
+#define CYG_FB_FLAGS0_MUST_BE_ON (0x01 << 22)
+
+// Some operations including updating the palette, double-buffer
+// synch, page flipping and moving the viewport take an argument
+// to specify when the operation should happen. Driver support
+// for this is optional.
+#define CYG_FB_UPDATE_NOW 0x0000
+#define CYG_FB_UPDATE_VERTICAL_RETRACE 0x0001
+
+// ----------------------------------------------------------------------------
+// Macro to define a framebuffer. A couple of auxiliary macros are used
+// for the conditional fields.
+#ifdef CYGPKG_INFRA_DEBUG
+# define CYG_FB_FRAMEBUFFER_DEBUG \
+ .fb_magic = CYG_FB_MAGIC,
+#else
+# define CYG_FB_FRAMEBUFFER_DEBUG
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+# define CYG_FB_FRAMEBUFFER_VIEWPORT(_width_, _height_) \
+ .fb_viewport_width = _width_, \
+ .fb_viewport_height = _height_,
+#else
+# define CYG_FB_FRAMEBUFFER_VIEWPORT(_width_, _height_)
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER
+# define CYG_FB_FRAMEBUFFER_SYNCH_FN(_fn_) \
+ .fb_synch_fn = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_SYNCH_FN(_fn_)
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+# define CYG_FB_FRAMEBUFFER_READ_PALETTE_FN(_fn_) \
+ .fb_read_palette_fn = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_READ_PALETTE_FN(_fn_)
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+# define CYG_FB_FRAMEBUFFER_WRITE_PALETTE_FN(_fn_) \
+ .fb_write_palette_fn = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_WRITE_PALETTE_FN(_fn_)
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+# define CYG_FB_FRAMEBUFFER_MAKE_COLOUR_FN(_fn_) \
+ .fb_make_colour_fn = _fn_,
+# define CYG_FB_FRAMEBUFFER_BREAK_COLOUR_FN(_fn_) \
+ .fb_break_colour_fn = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_MAKE_COLOUR_FN(_fn_)
+# define CYG_FB_FRAMEBUFFER_BREAK_COLOUR_FN(_fn_)
+#endif
+
+#define CYG_FB_FRAMEBUFFER(_name_, _depth_, _format_, \
+ _width_, _height_, _viewport_width_, _viewport_height_, \
+ _base_, _stride_, \
+ _flags0_, _flags1_, _flags2_, _flags3_, \
+ _driver0_, _driver1_, _driver2_, _driver3_, \
+ _on_fn_, _off_fn_, _ioctl_fn_, _synch_fn_, \
+ _read_palette_fn_, _write_palette_fn_, \
+ _make_colour_fn_, _break_colour_fn_, \
+ _write_pixel_fn_, _read_pixel_fn_, _write_hline_fn_, _write_vline_fn_, \
+ _fill_block_fn_, _write_block_fn_, _read_block_fn_, _move_block_fn_, \
+ _spare0_, _spare1_, _spare2_, _spare3_ ) \
+struct cyg_fb _name_ = { \
+ CYG_FB_FRAMEBUFFER_DEBUG \
+ .fb_depth = _depth_, \
+ .fb_format = _format_, \
+ .fb_width = _width_, \
+ .fb_height = _height_, \
+ CYG_FB_FRAMEBUFFER_VIEWPORT(_viewport_width_, _viewport_height_) \
+ .fb_stride = _stride_, \
+ .fb_base = _base_, \
+ .fb_flags0 = _flags0_, \
+ .fb_flags1 = _flags1_, \
+ .fb_flags2 = _flags2_, \
+ .fb_flags3 = _flags3_, \
+ .fb_driver0 = _driver0_, \
+ .fb_driver1 = _driver1_, \
+ .fb_driver2 = _driver2_, \
+ .fb_driver3 = _driver3_, \
+ .fb_on_fn = _on_fn_, \
+ .fb_off_fn = _off_fn_, \
+ .fb_ioctl_fn = _ioctl_fn_, \
+ CYG_FB_FRAMEBUFFER_SYNCH_FN(_synch_fn_) \
+ CYG_FB_FRAMEBUFFER_READ_PALETTE_FN(_read_palette_fn_) \
+ CYG_FB_FRAMEBUFFER_WRITE_PALETTE_FN(_write_palette_fn_) \
+ CYG_FB_FRAMEBUFFER_MAKE_COLOUR_FN(_make_colour_fn_) \
+ CYG_FB_FRAMEBUFFER_BREAK_COLOUR_FN(_break_colour_fn_) \
+ .fb_write_pixel_fn = _write_pixel_fn_, \
+ .fb_read_pixel_fn = _read_pixel_fn_, \
+ .fb_write_hline_fn = _write_hline_fn_, \
+ .fb_write_vline_fn = _write_vline_fn_, \
+ .fb_fill_block_fn = _fill_block_fn_, \
+ .fb_write_block_fn = _write_block_fn_, \
+ .fb_read_block_fn = _read_block_fn_, \
+ .fb_move_block_fn = _move_block_fn_ \
+}
+
+
+// ----------------------------------------------------------------------------
+// ioctl() operations: these are defined by a 16-bit key. The top byte
+// gives a category, with values of 0x8000 onwards reserved for use by
+// individual device drivers. The bottom byte defines the actual
+// operation. This gives 128 generic ioctl categories.
+
+# define CYG_FB_IOCTL_VIEWPORT_GET_POSITION 0x0100
+# define CYG_FB_IOCTL_VIEWPORT_SET_POSITION 0x0101
+
+typedef struct cyg_fb_ioctl_viewport {
+ cyg_ucount16 fbvp_x; // position of top-left corner of the viewport within
+ cyg_ucount16 fbvp_y; // the framebuffer
+ cyg_ucount16 fbvp_when; // set-only, now or vert retrace
+} cyg_fb_ioctl_viewport;
+
+# define CYG_FB_IOCTL_PAGE_FLIPPING_GET_PAGES 0x0200
+# define CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES 0x0201
+
+typedef struct cyg_fb_ioctl_page_flip {
+ cyg_uint32 fbpf_number_pages;
+ cyg_uint32 fbpf_visible_page;
+ cyg_uint32 fbpf_drawable_page;
+ cyg_ucount16 fbpf_when; // set-only, now or vert retrace
+} cyg_fb_ioctl_page_flip;
+
+# define CYG_FB_IOCTL_BLANK_GET 0x0300
+# define CYG_FB_IOCTL_BLANK_SET 0x0301
+
+typedef struct cyg_fb_ioctl_blank {
+ cyg_bool fbbl_on;
+} cyg_fb_ioctl_blank;
+
+# define CYG_FB_IOCTL_BACKLIGHT_GET 0x0400
+# define CYG_FB_IOCTL_BACKLIGHT_SET 0x0401
+
+typedef struct cyg_fb_ioctl_backlight {
+ cyg_ucount32 fbbl_current;
+ cyg_ucount32 fbbl_max;
+} cyg_fb_ioctl_backlight;
+
+// ----------------------------------------------------------------------------
+// The functional API. This can be implemented either by inlines or by
+// explicit functions, the latter allowing extra assertions.
+
+#if defined(CYGPKG_INFRA_DEBUG) || defined(__CYG_FB_IN_FRAMEBUF_C)
+
+extern int cyg_fb_on(cyg_fb*);
+extern int cyg_fb_off(cyg_fb*);
+extern void cyg_fb_write_pixel( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern cyg_fb_colour cyg_fb_read_pixel( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern void cyg_fb_write_hline( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_write_vline( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_fill_block( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_write_block( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* source stride */);
+extern void cyg_fb_read_block( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* source stride */);
+extern void cyg_fb_move_block( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern int cyg_fb_ioctl( cyg_fb*,
+ cyg_uint16 /* key */,
+ void* /* data */,
+ size_t* /* len */);
+
+extern void cyg_fb_synch( cyg_fb*,
+ cyg_ucount16 /* when */);
+
+extern void cyg_fb_write_palette( cyg_fb*,
+ cyg_ucount32 /* first */,
+ cyg_ucount32 /* count */,
+ const void* /* source */,
+ cyg_ucount16 /* when */);
+extern void cyg_fb_read_palette( cyg_fb*,
+ cyg_ucount32 /* first */,
+ cyg_ucount32 /* count */,
+ void* /* dest */);
+
+extern cyg_fb_colour cyg_fb_make_colour( cyg_fb*,
+ cyg_ucount8 /* r */, cyg_ucount8 /* g */, cyg_ucount8 /* b */);
+
+extern void cyg_fb_break_colour( cyg_fb*,
+ cyg_fb_colour,
+ cyg_ucount8* /* r */, cyg_ucount8* /* g */, cyg_ucount8* /* b */);
+
+#else
+
+extern __inline__ int
+cyg_fb_on(cyg_fb* _fb_)
+{
+ return (*(_fb_->fb_on_fn))(_fb_);
+}
+
+extern __inline__ int
+cyg_fb_off(cyg_fb* _fb_)
+{
+ return (*(_fb_->fb_off_fn))(_fb_);
+}
+
+extern __inline__ void
+cyg_fb_write_pixel(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_count32 _colour_)
+{
+ (*(_fb_->fb_write_pixel_fn))(_fb_, _x_, _y_, _colour_);
+}
+
+extern __inline__ cyg_fb_colour
+cyg_fb_read_pixel(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_)
+{
+ return (*(_fb_->fb_read_pixel_fn))(_fb_, _x_, _y_);
+}
+
+extern __inline__ void
+cyg_fb_write_hline(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_)
+{
+ (*(_fb_->fb_write_hline_fn))(_fb_, _x_, _y_, _len_, _colour_);
+}
+
+extern __inline__ void
+cyg_fb_write_vline(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_)
+{
+ (*(_fb_->fb_write_vline_fn))(_fb_, _x_, _y_, _len_, _colour_);
+}
+
+extern __inline__ void
+cyg_fb_fill_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_)
+{
+ (*(_fb_->fb_fill_block_fn))(_fb_, _x_, _y_, _width_, _height_, _colour_);
+}
+
+extern __inline__ void
+cyg_fb_write_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ const void* _source_, cyg_ucount16 _offset_, cyg_ucount16 _stride_)
+{
+ (*(_fb_->fb_write_block_fn))(_fb_, _x_, _y_, _width_, _height_, _source_, _offset_, _stride_);
+}
+
+extern __inline__ void
+cyg_fb_read_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ void* _dest_, cyg_ucount16 _offset_, cyg_ucount16 _stride_)
+{
+ (*((_fb_)->fb_read_block_fn))(_fb_, _x_, _y_, _width_, _height_, _dest_, _offset_, _stride_);
+}
+
+extern __inline__ void
+cyg_fb_move_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_ucount16 _newx_, cyg_ucount16 _newy_)
+{
+ (*(_fb_->fb_move_block_fn))(_fb_, _x_, _y_, _width_, _height_, _newx_, _newy_);
+}
+
+extern __inline__ int
+cyg_fb_ioctl(cyg_fb* _fb_, cyg_uint16 _key_, void* _data_, size_t* _len_)
+{
+ int result = (*(_fb_->fb_ioctl_fn))(_fb_, _key_, _data_, _len_);
+ return result;
+}
+
+extern __inline__ void
+cyg_fb_synch(cyg_fb* _fb_, cyg_ucount16 _when_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER
+ (*(_fb_->fb_synch_fn))(_fb_, _when_);
+#else
+ // Synch is a no-op
+#endif
+}
+
+extern __inline__ void
+cyg_fb_read_palette(cyg_fb* _fb_, cyg_ucount32 _first_, cyg_ucount32 _count_, void* _dest_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+ (*(_fb_->fb_read_palette_fn))(_fb_, _first_, _count_, _dest_);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+ CYG_UNUSED_PARAM(cyg_ucount32, _first_);
+ CYG_UNUSED_PARAM(cyg_ucount32, _count_);
+ CYG_UNUSED_PARAM(void*, _dest_);
+#endif
+}
+
+extern __inline__ void
+cyg_fb_write_palette(cyg_fb* _fb_, cyg_ucount32 _first_, cyg_ucount32 _count_, const void* _dest_, cyg_ucount16 _when_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+ (*(_fb_->fb_write_palette_fn))(_fb_, _first_, _count_, _dest_, _when_);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+ CYG_UNUSED_PARAM(cyg_ucount32, _first_);
+ CYG_UNUSED_PARAM(cyg_ucount32, _count_);
+ CYG_UNUSED_PARAM(const void*, _dest_);
+ CYG_UNUSED_PARAM(cyg_ucount16, _when_);
+#endif
+}
+
+extern __inline__ cyg_fb_colour
+cyg_fb_make_colour(cyg_fb* _fb_, cyg_ucount8 _r_, cyg_ucount8 _g_, cyg_ucount8 _b_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+ return (*(_fb_->fb_make_colour_fn))(_fb_, _r_, _g_, _b_);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+ CYG_UNUSED_PARAM(cyg_ucount8, _r_);
+ CYG_UNUSED_PARAM(cyg_ucount8, _g_);
+ CYG_UNUSED_PARAM(cyg_ucount8, _b_);
+ return 0;
+#endif
+}
+
+extern __inline__ void
+cyg_fb_break_colour(cyg_fb* _fb_, cyg_fb_colour _colour_, cyg_ucount8* _r_, cyg_ucount8* _g_, cyg_ucount8* _b_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+ (*(_fb_->fb_break_colour_fn))(_fb_, _colour_, _r_, _g_, _b_);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+ CYG_UNUSED_PARAM(cyg_fb_colour, _colour_);
+ CYG_UNUSED_PARAM(cyg_ucount8*, _r_);
+ CYG_UNUSED_PARAM(cyg_ucount8*, _g_);
+ CYG_UNUSED_PARAM(cyg_ucount8*, _b_);
+#endif
+}
+
+#endif // defined(CYGPKG_INFRA_DEBUG) || defined(__CYG_FB_IN_FRAMEBUF_C)
+
+// ----------------------------------------------------------------------------
+// The MACRO API
+#define CYG_FB__AUX(_fb_, _field_) CYG_FB_ ## _fb_ ## _field_
+
+#define CYG_FB_STRUCT(_fb_) CYG_FB__AUX(_fb_, _STRUCT)
+#define CYG_FB_DEPTH(_fb_) CYG_FB__AUX(_fb_, _DEPTH)
+#define CYG_FB_FORMAT(_fb_) CYG_FB__AUX(_fb_, _FORMAT)
+#define CYG_FB_WIDTH(_fb_) CYG_FB__AUX(_fb_, _WIDTH)
+#define CYG_FB_HEIGHT(_fb_) CYG_FB__AUX(_fb_, _HEIGHT)
+#define CYG_FB_VIEWPORT_WIDTH(_fb_) CYG_FB__AUX(_fb_, _VIEWPORT_WIDTH)
+#define CYG_FB_VIEWPORT_HEIGHT(_fb_) CYG_FB__AUX(_fb_, _VIEWPORT_HEIGHT)
+#define CYG_FB_STRIDE(_fb_) CYG_FB__AUX(_fb_, _STRIDE)
+#define CYG_FB_BASE(_fb_) CYG_FB__AUX(_fb_, _BASE)
+#define CYG_FB_FLAGS0(_fb_) CYG_FB__AUX(_fb_, _FLAGS0)
+#define CYG_FB_FLAGS1(_fb_) CYG_FB__AUX(_fb_, _FLAGS1)
+#define CYG_FB_FLAGS2(_fb_) CYG_FB__AUX(_fb_, _FLAGS2)
+#define CYG_FB_FLAGS3(_fb_) CYG_FB__AUX(_fb_, _FLAGS3)
+
+#define CYG_FB_PIXELx_VAR( _fb_, _id_) CYG_FB__AUX(_fb_, _PIXELx_VAR)( _fb_, _id_)
+#define CYG_FB_PIXELx_SET( _fb_, _id_, _x_, _y_) CYG_FB__AUX(_fb_, _PIXELx_SET)( _fb_, _id_, _x_, _y_)
+#define CYG_FB_PIXELx_GET( _fb_, _id_, _x_, _y_) CYG_FB__AUX(_fb_, _PIXELx_GET)( _fb_, _id_, _x_, _y_)
+#define CYG_FB_PIXELx_ADDX( _fb_, _id_, _incr_) CYG_FB__AUX(_fb_, _PIXELx_ADDX)( _fb_, _id_, _incr_)
+#define CYG_FB_PIXELx_ADDY( _fb_, _id_, _incr_) CYG_FB__AUX(_fb_, _PIXELx_ADDY)( _fb_, _id_, _incr_)
+#define CYG_FB_PIXELx_WRITE(_fb_, _id_, _colour_) CYG_FB__AUX(_fb_, _PIXELx_WRITE)( _fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READ( _fb_, _id_) CYG_FB__AUX(_fb_, _PIXELx_READ)( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS(_fb_, _id_, _x0_, _y0_, _width_, _height_) CYG_FB__AUX(_fb_, _PIXELx_FLUSHABS)( _fb_, _id_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL(_fb_, _id_, _x0_, _y0_, _dx_, _dy_) CYG_FB__AUX(_fb_, _PIXELx_FLUSHREL)( _fb_, _id_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL0_VAR( _fb_) CYG_FB_PIXELx_VAR( _fb_, 0)
+#define CYG_FB_PIXEL0_SET( _fb_, _x_, _y_) CYG_FB_PIXELx_SET( _fb_, 0, _x_, _y_)
+#define CYG_FB_PIXEL0_GET( _fb_, _x_, _y_) CYG_FB_PIXELx_GET( _fb_, 0, _x_, _y_)
+#define CYG_FB_PIXEL0_ADDX( _fb_, _incr_) CYG_FB_PIXELx_ADDX( _fb_, 0, _incr_)
+#define CYG_FB_PIXEL0_ADDY( _fb_, _incr_) CYG_FB_PIXELx_ADDY( _fb_, 0, _incr_)
+#define CYG_FB_PIXEL0_WRITE(_fb_, _colour_) CYG_FB_PIXELx_WRITE(_fb_, 0, _colour_)
+#define CYG_FB_PIXEL0_READ( _fb_) CYG_FB_PIXELx_READ( _fb_, 0)
+#define CYG_FB_PIXEL0_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_) CYG_FB_PIXELx_FLUSHABS( _fb_, 0, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL0_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_) CYG_FB_PIXELx_FLUSHREL( _fb_, 0, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL1_VAR( _fb_) CYG_FB_PIXELx_VAR( _fb_, 1)
+#define CYG_FB_PIXEL1_SET( _fb_, _x_, _y_) CYG_FB_PIXELx_SET( _fb_, 1, _x_, _y_)
+#define CYG_FB_PIXEL1_GET( _fb_, _x_, _y_) CYG_FB_PIXELx_GET( _fb_, 1, _x_, _y_)
+#define CYG_FB_PIXEL1_ADDX( _fb_, _incr_) CYG_FB_PIXELx_ADDX( _fb_, 1, _incr_)
+#define CYG_FB_PIXEL1_ADDY( _fb_, _incr_) CYG_FB_PIXELx_ADDY( _fb_, 1, _incr_)
+#define CYG_FB_PIXEL1_WRITE(_fb_, _colour_) CYG_FB_PIXELx_WRITE(_fb_, 1, _colour_)
+#define CYG_FB_PIXEL1_READ( _fb_) CYG_FB_PIXELx_READ( _fb_, 1)
+#define CYG_FB_PIXEL1_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_) CYG_FB_PIXELx_FLUSHABS( _fb_, 1, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL1_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_) CYG_FB_PIXELx_FLUSHREL( _fb_, 1, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL2_VAR( _fb_) CYG_FB_PIXELx_VAR( _fb_, 2)
+#define CYG_FB_PIXEL2_SET( _fb_, _x_, _y_) CYG_FB_PIXELx_SET( _fb_, 2, _x_, _y_)
+#define CYG_FB_PIXEL2_GET( _fb_, _x_, _y_) CYG_FB_PIXELx_GET( _fb_, 2, _x_, _y_)
+#define CYG_FB_PIXEL2_ADDX( _fb_, _incr_) CYG_FB_PIXELx_ADDX( _fb_, 2, _incr_)
+#define CYG_FB_PIXEL2_ADDY( _fb_, _incr_) CYG_FB_PIXELx_ADDY( _fb_, 2, _incr_)
+#define CYG_FB_PIXEL2_WRITE(_fb_, _colour_) CYG_FB_PIXELx_WRITE(_fb_, 2, _colour_)
+#define CYG_FB_PIXEL2_READ( _fb_) CYG_FB_PIXELx_READ( _fb_, 2)
+#define CYG_FB_PIXEL2_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_) CYG_FB_PIXELx_FLUSHABS( _fb_, 2, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL2_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_) CYG_FB_PIXELx_FLUSHREL( _fb_, 2, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL3_VAR( _fb_) CYG_FB_PIXELx_VAR( _fb_, 3)
+#define CYG_FB_PIXEL3_SET( _fb_, _x_, _y_) CYG_FB_PIXELx_SET( _fb_, 3, _x_, _y_)
+#define CYG_FB_PIXEL3_GET( _fb_, _x_, _y_) CYG_FB_PIXELx_GET( _fb_, 3, _x_, _y_)
+#define CYG_FB_PIXEL3_ADDX( _fb_, _incr_) CYG_FB_PIXELx_ADDX( _fb_, 3, _incr_)
+#define CYG_FB_PIXEL3_ADDY( _fb_, _incr_) CYG_FB_PIXELx_ADDY( _fb_, 3, _incr_)
+#define CYG_FB_PIXEL3_WRITE(_fb_, _colour_) CYG_FB_PIXELx_WRITE(_fb_, 3, _colour_)
+#define CYG_FB_PIXEL3_READ( _fb_) CYG_FB_PIXELx_READ( _fb_, 3)
+#define CYG_FB_PIXEL3_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_) CYG_FB_PIXELx_FLUSHABS( _fb_, 3, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL3_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_) CYG_FB_PIXELx_FLUSHREL( _fb_, 3, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_ON(_fb_) ({ cyg_fb_on(& CYG_FB_STRUCT(_fb_)); })
+#define CYG_FB_OFF(_fb_) ({ cyg_fb_off(& CYG_FB_STRUCT(_fb_)); })
+#define CYG_FB_IOCTL(_fb_, _key_, _data_, _len_) ({ cyg_fb_ioctl(& CYG_FB_STRUCT(_fb_), _key_, _data_, _len_); })
+#define CYG_FB_SYNCH(_fb_, _when_) \
+ CYG_MACRO_START \
+ cyg_fb_synch(& CYG_FB_STRUCT(_fb_), _when_); \
+ CYG_MACRO_END
+#define CYG_FB_WRITE_PALETTE(_fb_, _first_, _count_, _data_, _when_) \
+ CYG_MACRO_START \
+ cyg_fb_write_palette(& CYG_FB_STRUCT(_fb_), _first_, _count_, _data_, _when_); \
+ CYG_MACRO_END
+#define CYG_FB_READ_PALETTE(_fb_, _first_, _count_, _data_) \
+ CYG_MACRO_START \
+ cyg_fb_read_palette(& CYG_FB_STRUCT(_fb_), _first_, _count_, _data_); \
+ CYG_MACRO_END
+
+#define CYG_FB_WRITE_PIXEL(_fb_, _x_, _y_, _colour_) \
+ CYG_FB__AUX(_fb_, _WRITE_PIXEL)(_x_, _y_, _colour_)
+#define CYG_FB_READ_PIXEL(_fb_, _x_, _y_) \
+ CYG_FB__AUX(_fb_, _READ_PIXEL)(_x_, _y_)
+#define CYG_FB_WRITE_HLINE(_fb_, _x_, _y_, _len_, _colour_) \
+ CYG_FB__AUX(_fb_, _WRITE_HLINE)(_x_, _y_, _len_, _colour_)
+#define CYG_FB_WRITE_VLINE(_fb_, _x_, _y_, _len_, _colour_) \
+ CYG_FB__AUX(_fb_, _WRITE_VLINE)(_x_, _y_, _len_, _colour_)
+#define CYG_FB_FILL_BLOCK(_fb_, _x_, _y_, _width_, _height_, _colour_) \
+ CYG_FB__AUX(_fb_, _FILL_BLOCK)(_x_, _y_, _width_, _height_, _colour_)
+#define CYG_FB_WRITE_BLOCK(_fb_, _x_, _y_, _width_, _height_, _data_, _offset_, _stride_) \
+ CYG_FB__AUX(_fb_, _WRITE_BLOCK)(_x_, _y_, _width_, _height_, _data_, _offset_, _stride_)
+#define CYG_FB_READ_BLOCK(_fb_, _x_, _y_, _width_, _height_, _data_, _offset_, _stride_) \
+ CYG_FB__AUX(_fb_, _READ_BLOCK)(_x_, _y_, _width_, _height_, _data_, _offset_, _stride_)
+#define CYG_FB_MOVE_BLOCK(_fb_, _x_, _y_, _width_, _height_, _new_x_, _new_y_) \
+ CYG_FB__AUX(_fb_, _MOVE_BLOCK)(_x_, _y_, _width_, _height_, _new_x_, _new_y_)
+#define CYG_FB_MAKE_COLOUR(_fb_, _r_, _g_, _b_) \
+ CYG_FB__AUX(_fb_, _MAKE_COLOUR)(_r_, _g_, _b_)
+#define CYG_FB_MAKE_COLOR(_fb_, _r_, _g_, _b_) \
+ CYG_FB__AUX(_fb_, _MAKE_COLOUR)(_r_, _g_, _b_)
+#define CYG_FB_BREAK_COLOUR(_fb_, _colour_, _r_, _g_, _b_) \
+ CYG_FB__AUX(_fb_, _BREAK_COLOUR)(_colour_, _r_, _g_, _b_)
+#define CYG_FB_BREAK_COLOR(_fb_, _colour_, _r_, _g_, _b_) \
+ CYG_FB__AUX(_fb_, _BREAK_COLOUR)(_colour_, _r_, _g_, _b_)
+
+// ----------------------------------------------------------------------------
+// Default implementations of some of the per-device functions for linear
+// framebuffers. Control operations like initialization are always
+// device-specific and cannot be implemented by the generic package.
+
+extern void cyg_fb_linear_write_pixel_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_fb_colour);
+
+extern cyg_fb_colour cyg_fb_linear_read_pixel_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour cyg_fb_linear_read_pixel_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+
+extern void cyg_fb_linear_write_hline_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+
+extern void cyg_fb_linear_write_vline_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* len */,
+ cyg_fb_colour);
+
+extern void cyg_fb_linear_fill_block_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_fb_colour);
+
+extern void cyg_fb_linear_write_block_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+
+extern void cyg_fb_linear_write_block_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ const void* /* source */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+
+extern void cyg_fb_linear_read_block_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_read_block_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ void* /* dest */,
+ cyg_ucount16 /* offset */, cyg_ucount16 /* stride */);
+
+extern void cyg_fb_linear_move_block_1LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_1BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_2LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_2BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_4LE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_4BE( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_8( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_16( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_32( cyg_fb*,
+ cyg_ucount16 /* x */, cyg_ucount16 /* y */,
+ cyg_ucount16 /* width */, cyg_ucount16 /* height */,
+ cyg_ucount16 /* new_x */, cyg_ucount16 /* new_y */);
+
+// ----------------------------------------------------------------------------
+// Dummy implementations of various device functions
+
+extern int cyg_fb_nop_on(cyg_fb*);
+extern int cyg_fb_nop_off(cyg_fb*);
+extern int cyg_fb_nop_ioctl(cyg_fb*, cyg_uint16, void*, size_t*);
+extern void cyg_fb_nop_synch(cyg_fb*, cyg_ucount16);
+extern void cyg_fb_nop_write_palette(cyg_fb*, cyg_ucount32, cyg_ucount32, const void*, cyg_ucount16);
+extern void cyg_fb_nop_read_palette( cyg_fb*, cyg_ucount32, cyg_ucount32, void*);
+extern cyg_fb_colour cyg_fb_nop_make_colour(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern cyg_fb_colour cyg_fb_nop_make_color(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void cyg_fb_nop_break_colour(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern void cyg_fb_nop_break_color(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+
+// ----------------------------------------------------------------------------
+// Standard palettes. The generic framebuffer package provides EGA and VGA
+// palettes.
+extern const cyg_uint8 cyg_fb_palette_ega[16 * 3];
+extern const cyg_uint8 cyg_fb_palette_vga[256 * 3];
+
+#define CYG_FB_DEFAULT_PALETTE_BLACK 0x00
+#define CYG_FB_DEFAULT_PALETTE_BLUE 0x01
+#define CYG_FB_DEFAULT_PALETTE_GREEN 0x02
+#define CYG_FB_DEFAULT_PALETTE_CYAN 0x03
+#define CYG_FB_DEFAULT_PALETTE_RED 0x04
+#define CYG_FB_DEFAULT_PALETTE_MAGENTA 0x05
+#define CYG_FB_DEFAULT_PALETTE_BROWN 0x06
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREY 0x07
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGRAY 0x07
+#define CYG_FB_DEFAULT_PALETTE_DARKGREY 0x08
+#define CYG_FB_DEFAULT_PALETTE_DARKGRAY 0x08
+#define CYG_FB_DEFAULT_PALETTE_LIGHTBLUE 0x09
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREEN 0x0A
+#define CYG_FB_DEFAULT_PALETTE_LIGHTCYAN 0x0B
+#define CYG_FB_DEFAULT_PALETTE_LIGHTRED 0x0C
+#define CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA 0x0D
+#define CYG_FB_DEFAULT_PALETTE_YELLOW 0x0E
+#define CYG_FB_DEFAULT_PALETTE_WHITE 0x0F
+
+// ----------------------------------------------------------------------------
+// Support for some common true colour modes
+#define CYG_FB_MAKE_COLOUR_8BPP_TRUE_332(_r_, _g_, _b_) \
+ ({ cyg_fb_colour _colour_; \
+ _colour_ = ((((_r_) & 0x00E0) >> 0) | (((_g_) & 0x00E0) >> 3) | (((_b_) & 0x00C0) >> 6)); \
+ _colour_; })
+
+#define CYG_FB_BREAK_COLOUR_8BPP_TRUE_332(_colour_, _r_, _g_, _b_ ) \
+ CYG_MACRO_START \
+ *(_r_) = ((_colour_) << 0) & 0x00E0; \
+ *(_g_) = ((_colour_) << 3) & 0x00E0; \
+ *(_g_) = ((_colour_) << 6) & 0x00C0; \
+ CYG_MACRO_END
+
+#define CYG_FB_MAKE_COLOUR_16BPP_TRUE_565(_r_, _g_, _b_) \
+ ({ ((((_r_) & 0x00F8) << 8) | (((_g_) & 0x00FC) << 3) | (((_b_) & 0x00F8) >> 3)); })
+
+#define CYG_FB_BREAK_COLOUR_16BPP_TRUE_565(_colour_, _r_, _g_, _b_) \
+ CYG_MACRO_START \
+ *(_r_) = ((_colour_) >> 8) & 0x00F8; \
+ *(_g_) = ((_colour_) >> 3) & 0x00FC; \
+ *(_b_) = ((_colour_) << 3) & 0x00F8; \
+ CYG_MACRO_END
+
+#define CYG_FB_MAKE_COLOUR_16BPP_TRUE_555(_r_, _g_, _b_) \
+ ({ ((((_r_) & 0x00F8) << 7) | (((_g_) & 0x00F8) << 2) | (((_b_) & 0x00F8) >> 3)); })
+
+#define CYG_FB_BREAK_COLOUR_16BPP_TRUE_555(_colour_, _r_, _g_, _b_) \
+ CYG_MACRO_START \
+ *(_r_) = ((_colour_) >> 7) & 0x00F8; \
+ *(_g_) = ((_colour_) >> 2) & 0x00F8; \
+ *(_b_) = ((_colour_) << 3) & 0x00F8; \
+ CYG_MACRO_END
+
+#define CYG_FB_MAKE_COLOUR_32BPP_TRUE_0888(_r_, _g_, _b_) \
+ ({ (((_r_) << 16) | ((_g_) << 8) | (_b_)); })
+
+#define CYG_FB_BREAK_COLOUR_32BPP_TRUE_0888(_colour_, _r_, _g_, _b_) \
+ CYG_MACRO_START \
+ *(_r_) = ((_colour_) >> 16) & 0x00FF; \
+ *(_g_) = ((_colour_) >> 8) & 0x00FF; \
+ *(_b_) = ((_colour_) ) & 0x00FF; \
+ CYG_MACRO_END
+
+extern cyg_fb_colour cyg_fb_dev_make_colour_8bpp_true_332(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void cyg_fb_dev_break_colour_8bpp_true_332(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern cyg_fb_colour cyg_fb_dev_make_colour_16bpp_true_565(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void cyg_fb_dev_break_colour_16bpp_true_565(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern cyg_fb_colour cyg_fb_dev_make_colour_16bpp_true_555(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void cyg_fb_dev_break_colour_16bpp_true_555(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern cyg_fb_colour cyg_fb_dev_make_colour_32bpp_true_0888(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void cyg_fb_dev_break_colour_32bpp_true_0888(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+
+// ----------------------------------------------------------------------------
+// A custom build step combines all the header files from the various
+// framebuffer devices (usually just one) into a single header. This
+// makes it easier for portable higher-level code to work with
+// whatever devices happen to be available.
+#include <cyg/io/framebufs/framebufs.h>
+
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // ifndef CYGONCE_IO_FRAMEBUF_H
+// End of framebuf.h
Index: include/framebuf.inl
===================================================================
RCS file: include/framebuf.inl
diff -N include/framebuf.inl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/framebuf.inl 7 Oct 2008 10:03:08 -0000
@@ -0,0 +1,958 @@
+#include <cyg/infra/diag.h>
+#ifndef CYGONCE_IO_FRAMEBUF_INL
+#define CYGONCE_IO_FRAMEBUF_INL
+
+//=============================================================================
+//
+// framebuf.inl
+//
+// Inline functions for manipulating linear framebuffers
+//
+//=============================================================================
+//###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-03-29
+//####DESCRIPTIONEND####
+//=============================================================================
+
+// There are numerous ways of implementing the functions in this file.
+// For example for depths >= 8 many operations can be performed using
+// memset()/memcpy()/memmove(), or
+// __builtin_memset()/__builtin_memcpy()/ memmove(), or by explicit
+// direct accesses to framebuffer memory. The first of these can be
+// discarded because the builtins are never worse than explicit
+// function calls. The choice between the builtins and direct accesses
+// is not so clear. On the one hand the library functions may well
+// involve architecture-specific optimizations. On the other hand
+// function calls are not free. This decision really needs to be taken
+// on a per-architecture basis after careful measurements.
+//
+// A similar question arises regarding the handling of row numbers.
+// One implementation involves multiplying by the width. Another
+// involves keeping a table of pointers to the start of each row,
+// avoiding a multiplication but adding a memory access. Again the
+// trade off is not immediately obvious.
+//
+// For direct accesses the bus width is an issue. Typically the frame
+// buffer will not be cached so the framebuffer memory accesses will
+// account for much of the inner loop. For now 32-bit accesses are
+// preferred. If the target has h/w support for 64-bit accesses that
+// would improve performance, at the cost of extra code to handle
+// alignments. If the video device is accessed via a 16-bit bus then
+// it is assumed that the h/w will fix up 32->16 bit accesses faster
+// than any s/w workaround.
+//
+// For now the code prefers builtins and multiplies.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ----------------------------------------------------------------------------
+// Macro definitions for the pixel manipulation.
+// Little-endian means pixel 0 occupies bit 0 within a byte
+// Big-endian means pixel 0 occupies bit 7
+#define CYG_FB_PIXELx_VARx_1LE( _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_1LE( _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_1LE( _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDx_1LE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDx_1LE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_1LE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_1LE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_1LE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_1LE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_1BE( _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_1BE( _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_1BE( _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDXx_1BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDYx_1BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_1BE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_1BE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_1BE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_1BE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_2LE( _fb_, _id_, _which_)
+#define CYG_FB_PIXELx_SETx_2LE( _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_2LE( _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDx_2LE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDx_2LE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_2LE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_2LE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_2LE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_2LE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_2BE( _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_2BE( _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_2BE( _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDXx_2BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDYx_2BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_2BE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_2BE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_2BE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_2BE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_4LE( _fb_, _id_, _which_)
+#define CYG_FB_PIXELx_SETx_4LE( _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_4LE( _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDx_4LE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDx_4LE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_4LE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_4LE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_4LE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_4LE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_4BE( _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_4BE( _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_4BE( _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDXx_4BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDYx_4BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_4BE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_4BE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_4BE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_4BE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+
+// ----------------------------------------------------------------------------
+#define CYG_FB_PIXELx_VAR_8(_fb_, _which_) cyg_uint8* _cyg_fb_pixelpos8_ ## _fb_ ## _which_
+#define CYG_FB_PIXELx_SET_8(_fb_, _which_, _fbaddr_, _stride_, _x_, _y_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos8_ ## _fb_ ## _which_ = (cyg_uint8*)_fbaddr_; \
+ _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += ((_stride_) * (_y_)); \
+ _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += (_x_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_GET_8(_fb_, _which_, _fbaddr_, _stride_, _x_ ,_y_) \
+ CYG_MACRO_START \
+ cyg_uint32 _offset_; \
+ _offset_ = (_cyg_fb_pixelpos8_ ## _fb_ ## _which_) - (cyg_uint8*)(_fbaddr_); \
+ _y_ = _offset_ / (_stride_); \
+ _x_ = _offset_ % (_stride_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_ADDX_8(_fb_, _which_, _stride_, _incr_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += (_incr_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_ADDY_8(_fb_, _which_, _stride_, _incr_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += ((_incr_) * (_stride_)); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_WRITE_8(_fb_, _which_, _colour_) \
+ CYG_MACRO_START \
+ * _cyg_fb_pixelpos8_ ## _fb_ ## _which_ = (_colour_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_READ_8(_fb_, _which_) ({ * _cyg_fb_pixelpos8_ ## _fb_ ## _which_; })
+
+#define CYG_FB_PIXELx_FLUSHABS_8(_fb_, _which_, _x0_, _y0_, _x1_, _y1_) \
+ CYG_MACRO_START \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_FLUSHREL_8(_fb_, _which_, _x0_, _y0_, _dx_, _dy_) \
+ CYG_MACRO_START \
+ CYG_MACRO_END
+
+// ----------------------------------------------------------------------------
+#define CYG_FB_PIXELx_VAR_16(_fb_, _which_) cyg_uint16* _cyg_fb_pixelpos16_ ## _fb_ ## _which_
+#define CYG_FB_PIXELx_SET_16(_fb_, _which_, _fbaddr_, _stride8_, _x_, _y_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos16_ ## _fb_ ## _which_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + ((_stride8_) * (_y_)))) + (_x_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_GET_16(_fb_, _which_, _fbaddr_, _stride8_, _x_ ,_y_) \
+ CYG_MACRO_START \
+ cyg_ucount16 _stride_ = (_stride8_) >> 1; \
+ cyg_uint32 _offset_; \
+ _offset_ = (_cyg_fb_pixelpos16_ ## _fb_ ## _which_) - (cyg_uint16*)(_fbaddr_); \
+ _y_ = _offset_ / (_stride_); \
+ _x_ = _offset_ % (_stride_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_ADDX_16(_fb_, _which_, _stride8_, _incr_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos16_ ## _fb_ ## _which_ += (_incr_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_ADDY_16(_fb_, _which_, _stride8_, _incr_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos16_ ## _fb_ ## _which_ += ((_incr_) * ((_stride8_) >> 1)); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_WRITE_16(_fb_, _which_, _colour_) \
+ CYG_MACRO_START \
+ * _cyg_fb_pixelpos16_ ## _fb_ ## _which_ = (_colour_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_READ_16(_fb_, _which_) \
+ ({ * _cyg_fb_pixelpos16_ ## _fb_ ## _which_; })
+
+#define CYG_FB_PIXELx_FLUSHABS_16(_fb_, _which_, _x0_, _y0_, _x1_, _y1_) \
+ CYG_MACRO_START \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_FLUSHREL_16(_fb_, _which_, _x0_, _y0_, _dx_, _dy_) \
+ CYG_MACRO_START \
+ CYG_MACRO_END
+
+// ----------------------------------------------------------------------------
+#define CYG_FB_PIXELx_VAR_32(_fb_, _which_) cyg_uint32* _cyg_fb_pixelpos32_ ## _fb_ ## _which_
+#define CYG_FB_PIXELx_SET_32(_fb_, _which_, _fbaddr_, _stride8_, _x_, _y_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos32_ ## _fb_ ## _which_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + ((_stride8_) * (_y_)))) + (_x_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_GET_32(_fb_, _which_, _fbaddr_, _stride8_, _x_ ,_y_) \
+ CYG_MACRO_START \
+ cyg_ucount16 _stride_ = (_stride8_) >> 2; \
+ cyg_uint32 _offset_; \
+ _offset_ = (_cyg_fb_pixelpos32_ ## _fb_ ## _which_) - (cyg_uint32*)(_fbaddr_); \
+ _y_ = _offset_ / (_stride_); \
+ _x_ = _offset_ % (_stride_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_ADDX_32(_fb_, _which_, _stride8_, _incr_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos32_ ## _fb_ ## _which_ += (_incr_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_ADDY_32(_fb_, _which_, _stride8_, _incr_) \
+ CYG_MACRO_START \
+ _cyg_fb_pixelpos32_ ## _fb_ ## _which_ += ((_incr_) * ((_stride8_) >> 2)); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_WRITE_32(_fb_, _which_, _colour_) \
+ CYG_MACRO_START \
+ * _cyg_fb_pixelpos32_ ## _fb_ ## _which_ = (_colour_); \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_READ_32(_fb_, _which_) ({ * _cyg_fb_pixelpos32_ ## _fb_ ## _which_; })
+
+#define CYG_FB_PIXELx_FLUSHABS_32(_fb_, _which_, _x0_, _y0_, _x1_, _y1_) \
+ CYG_MACRO_START \
+ CYG_MACRO_END
+
+#define CYG_FB_PIXELx_FLUSHREL_32(_fb_, _which_, _x0_, _y0_, _dx_, _dy_) \
+ CYG_MACRO_START \
+ CYG_MACRO_END
+
+// ----------------------------------------------------------------------------
+// Some of the functions could be speeded up by using 32-bit accesses
+// instead of byte accesses, but that would introduce another endianness
+// complication.
+
+// The always_inline attribute must be a applied to a declaration, not a
+// definition, so combine the two via a single macro.
+#define CYG_FB_LINEAR_INLINE_FN(_type_, _name_, _args_) \
+static __inline__ _type_ _name_ _args_ __attribute__((__always_inline__)); \
+static __inline__ _type_ _name_ _args_
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_1LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+ cyg_uint8 _mask_ = 0x0001 << (_x_ & 0x07);
+ if (_colour_) {
+ *_ptr8_ |= _mask_;
+ } else {
+ *_ptr8_ &= ~_mask_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_1BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+ cyg_uint8 _mask_ = 0x0080 >> (_x_ & 0x07);
+ if (_colour_) {
+ *_ptr8_ |= _mask_;
+ } else {
+ *_ptr8_ &= ~_mask_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_1LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+ cyg_uint8 _mask_ = 0x0001 << (_x_ & 0x07);
+ return (*_ptr8_ & _mask_) ? 1 : 0;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_1BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+ cyg_uint8 _mask_ = 0x0080 >> (_x_ & 0x07);
+ return (*_ptr8_ & _mask_) ? 1 : 0;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_1LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+ cyg_uint8 _mask_ = 0x0001 << (_x_ & 0x07);
+ if (_colour_) {
+ for ( ; _len_; _len_--) {
+ *_ptr8_ |= _mask_;
+ _ptr8_ += _stride_;
+ }
+ } else {
+ _mask_ = ~_mask_;
+ for ( ; _len_; _len_--) {
+ *_ptr8_ &= _mask_;
+ _ptr8_ += _stride_;
+ }
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_1BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+ cyg_uint8 _mask_ = 0x0080 >> (_x_ & 0x07);
+ if (_colour_) {
+ for ( ; _len_; _len_--) {
+ *_ptr8_ |= _mask_;
+ _ptr8_ += _stride_;
+ }
+ } else {
+ _mask_ = ~_mask_;
+ for ( ; _len_; _len_--) {
+ *_ptr8_ &= _mask_;
+ _ptr8_ += _stride_;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_2LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ cyg_uint8 _shift_ = (_x_ & 0x03) << 1;
+
+ *_ptr8_ = (*_ptr8_ & ~(0x03 << _shift_)) | (_colour_ << _shift_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_2BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ cyg_uint8 _shift_ = 6 - ((_x_ & 0x03) << 1);
+
+ *_ptr8_ = (*_ptr8_ & ~(0x03 << _shift_)) | (_colour_ << _shift_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_2LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ cyg_uint8 _shift_ = (_x_ & 0x03) << 1;
+
+ return (*_ptr8_ >> _shift_) & 0x03;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_2BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ cyg_uint8 _shift_ = 6 - ((_x_ & 0x03) << 1);
+
+ return (*_ptr8_ >> _shift_) & 0x03;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_2LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ cyg_uint8 _shift_ = (_x_ & 0x03) << 1;
+ cyg_uint8 _mask_ = ~(0x03 << _shift_);
+ _colour_ <<= _shift_;
+
+ for ( ; _len_; _len_--) {
+ *_ptr8_ = (*_ptr8_ & _mask_) | _colour_;
+ _ptr8_ += _stride_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_2BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ cyg_uint8 _shift_ = 6 - ((_x_ & 0x03) << 1);
+ cyg_uint8 _mask_ = ~(0x03 << _shift_);
+ _colour_ <<= _shift_;
+
+ for ( ; _len_; _len_--) {
+ *_ptr8_ = (*_ptr8_ & _mask_) | _colour_;
+ _ptr8_ += _stride_;
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_4LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+ if (_x_ & 0x01) {
+ *_ptr8_ = (*_ptr8_ & 0x000F) | (_colour_ << 4);
+ } else {
+ *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_4BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+ if (_x_ & 0x01) {
+ *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+ } else {
+ *_ptr8_ = (*_ptr8_ & 0x000F) | (_colour_ << 4);
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_4LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+ if (_x_ & 0x01) {
+ return (*_ptr8_ >> 4) & 0x000F;
+ } else {
+ return *_ptr8_ & 0x000F;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_4BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+ if (_x_ & 0x01) {
+ return *_ptr8_ & 0x000F;
+ } else {
+ return (*_ptr8_ >> 4) & 0x000F;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_4LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ if (_x_ & 0x01) {
+ _colour_ <<= 4;
+ for ( ; _len_; _len_--) {
+ *_ptr8_ = (*_ptr8_ & 0x000F) | _colour_;
+ _ptr8_ += _stride_;
+ }
+ } else {
+ for ( ; _len_; _len_--) {
+ *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+ }
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_4BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+ if (_x_ & 0x01) {
+ for ( ; _len_; _len_--) {
+ *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+ }
+ } else {
+ _colour_ <<= 4;
+ for ( ; _len_; _len_--) {
+ *_ptr8_ = (*_ptr8_ & 0x000F) | _colour_;
+ _ptr8_ += _stride_;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+ *_ptr8_ = _colour_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+ return *_ptr8_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_hline_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+ __builtin_memset(_ptr8_, _colour_, _len_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+ for ( ; _len_; _len_--) {
+ *_ptr8_ = _colour_;
+ _ptr8_ += _stride_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_fill_block_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+ for ( ; _height_; _height_--) {
+ __builtin_memset(_ptr8_, _colour_, _width_);
+ _ptr8_ += _stride_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_block_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ const void* _source_,
+ cyg_ucount16 _offset_, cyg_ucount16 _source_stride_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+ cyg_uint8* _src8_ = ((cyg_uint8*) _source_) + _offset_;
+
+ for ( ; _height_; _height_--) {
+ __builtin_memcpy(_ptr8_, _src8_, _width_);
+ _ptr8_ += _stride_;
+ _src8_ += _source_stride_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_read_block_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ void* _dest_,
+ cyg_ucount16 _offset_, cyg_ucount16 _dest_stride_))
+{
+ cyg_uint8* _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+ cyg_uint8* _dst8_ = ((cyg_uint8*)_dest_) + _offset_;
+
+ for ( ; _height_; _height_--) {
+ __builtin_memcpy(_dst8_, _ptr8_, _width_);
+ _ptr8_ += _stride_;
+ _dst8_ += _dest_stride_;
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ *_ptr16_ = _colour_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ return *_ptr16_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_hline_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ cyg_uint32* _ptr32_;
+ cyg_bool _right_;
+
+ if (_x_ & 0x01) {
+ *_ptr16_++ = _colour_;
+ _len_ -= 1;
+ }
+ _ptr32_ = (cyg_uint32*) _ptr16_;
+ _colour_ |= (_colour_ << 16);
+ _right_ = (_len_ & 0x01);
+ for ( _len_ >>= 1; _len_; _len_--) {
+ *_ptr32_++ = _colour_;
+ }
+ if (_right_) {
+ *((cyg_uint16*)_ptr32_) = _colour_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ for ( ; _len_; _len_--) {
+ *_ptr16_ = _colour_;
+ _ptr16_ = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_fill_block_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_))
+{
+ cyg_bool _left_, _right_;
+ cyg_uint16* _ptr16_;
+ cyg_uint32* _ptr32_;
+ cyg_ucount16 _stride32_;
+
+ _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ _left_ = (_x_ & 0x01);
+ if (_left_) {
+ _width_ -= 1;
+ }
+ _right_ = (_width_ & 0x01);
+
+ if (_left_) {
+ _ptr32_ = (cyg_uint32*) &(_ptr16_[1]);
+ for (_y_ = _height_; _y_; _y_--) {
+ *_ptr16_ = _colour_;
+ _ptr16_ = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+ }
+ } else {
+ _ptr32_ = (cyg_uint32*) _ptr16_;
+ }
+ _width_ >>= 1;
+ _stride32_ = _stride8_ - (_width_ << 2);
+ _colour_ |= (_colour_ << 16);
+ _ptr16_ = (cyg_uint16*) &(_ptr32_[_width_]);
+
+ for ( _y_ = _height_; _y_; _y_--) {
+ for ( _x_ = _width_; _x_; _x_--) {
+ *_ptr32_++ = _colour_;
+ }
+ _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride32_);
+ }
+ if (_right_) {
+ for (_y_ = _height_; _y_; _y_--) {
+ *_ptr16_ = _colour_;
+ _ptr16_ = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+ }
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_block_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ const void* _source_,
+ cyg_ucount16 _offset_, cyg_ucount16 _source_stride8_))
+{
+ cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ cyg_uint16* _src16_ = ((cyg_uint16*) _source_) + _offset_;
+
+ _width_ <<= 1;
+ for ( ; _height_; _height_--) {
+ __builtin_memcpy(_ptr16_, _src16_, _width_);
+ _ptr16_ = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+ _src16_ = (cyg_uint16*)(((cyg_uint8*)_src16_) + _source_stride8_);
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_read_block_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ void* _dest_,
+ cyg_ucount16 _offset_, cyg_ucount16 _dest_stride8_))
+{
+ cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ cyg_uint16* _dst16_ = ((cyg_uint16*)_dest_) + _offset_;
+
+ _width_ <<= 1;
+ for ( ; _height_; _height_--) {
+ __builtin_memcpy(_dst16_, _ptr16_, _width_);
+ _ptr16_ = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+ _dst16_ = (cyg_uint16*)(((cyg_uint8*)_dst16_) + _dest_stride8_);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_pixel_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+ cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ *_ptr32_ = _colour_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+ cyg_fb_linear_read_pixel_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+ cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ return *_ptr32_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_hline_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ while (_len_--) {
+ *_ptr32_++ = _colour_;
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_vline_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+ cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ while (_len_--) {
+ *_ptr32_ = _colour_;
+ _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_fill_block_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_))
+{
+ cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ cyg_ucount16 _len_;
+
+ _stride8_ -= (_width_ << 2);
+ for ( ; _height_; _height_--) {
+ for (_len_ = _width_; _len_; _len_--) {
+ *_ptr32_++ = _colour_;
+ }
+ _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_write_block_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ const void* _source_,
+ cyg_ucount16 _offset_, cyg_ucount16 _source_stride8_))
+{
+ cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ cyg_uint32* _src32_ = ((cyg_uint32*) _source_) + _offset_;
+
+ _width_ <<= 2;
+ for ( ; _height_; _height_--) {
+ __builtin_memcpy(_ptr32_, _src32_, _width_);
+ _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+ _src32_ = (cyg_uint32*)(((cyg_uint8*)_src32_) + _source_stride8_);
+ }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_read_block_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride8_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ void* _dest_,
+ cyg_ucount16 _offset_, cyg_ucount16 _dest_stride8_))
+{
+ cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+ cyg_uint32* _dst32_ = ((cyg_uint32*)_dest_) + _offset_;
+
+ _width_ <<= 2;
+ for ( ; _height_; _height_--) {
+ __builtin_memcpy(_dst32_, _ptr32_, _width_);
+ _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+ _dst32_ = (cyg_uint32*)(((cyg_uint8*)_dst32_) + _dest_stride8_);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// The actual move block functions are not inlined, but it is convenient to
+// have dummy _inl functions anyway.
+
+extern void cyg_fb_linear_move_block_1LE_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_1BE_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_2LE_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_2BE_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_4LE_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_4BE_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_8_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_16_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_32_impl(void*, cyg_ucount16 /* stride */,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16,
+ cyg_ucount16, cyg_ucount16);
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_1LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_1LE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_1BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_1BE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_2LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_2LE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_2BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_2BE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_4LE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_4LE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_4BE_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_4BE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_8_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_8_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_16_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_16_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+ cyg_fb_linear_move_block_32_inl,
+ (void* _fbaddr_, cyg_ucount16 _stride_,
+ cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+ cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+ cyg_fb_linear_move_block_32_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // ifndef CYGONCE_IO_FRAMEBUF_H
+// End of framebuf.h
Index: src/framebuf.c
===================================================================
RCS file: src/framebuf.c
diff -N src/framebuf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/framebuf.c 7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,492 @@
+//==========================================================================
+//
+// framebuf.c
+//
+// Generic API for accessing framebuffers
+//
+//==========================================================================
+//###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-03-29
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#define __CYG_FB_IN_FRAMEBUF_C 1
+#include <cyg/io/framebuf.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <errno.h>
+
+// Implementations of the framebuffer functions. Production code
+// normally uses extern inline versions of these, defined in
+// framebuf.h. However real functions are supplied here in case
+// higher-level code chooses to take the address of a function for
+// some reason. Also when building for debugging (CYGPKG_INFRA_DEBUG)
+// the inline functions are suppressed and the real functions here
+// contain lots of useful assertions.
+
+int
+cyg_fb_on(cyg_fb* fb)
+{
+ int result;
+
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_on_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_off_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_pixel_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_read_pixel_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_hline_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_vline_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_fill_block_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_block_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_read_block_fn);
+ CYG_CHECK_FUNC_PTRC(fb->fb_move_block_fn);
+
+ result = (*(fb->fb_on_fn))(fb);
+ return result;
+}
+
+int
+cyg_fb_off(cyg_fb* fb)
+{
+ int result;
+
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_off_fn);
+
+ result = (*(fb->fb_off_fn))(fb);
+ return result;
+}
+
+void
+cyg_fb_write_pixel(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_pixel_fn);
+
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+ CYG_PRECONDITIONC((colour <= 1) || (fb->fb_depth > 1));
+ CYG_PRECONDITIONC((colour <= 3) || (fb->fb_depth > 2));
+ CYG_PRECONDITIONC((colour <= 15) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC((colour <= 255) || (fb->fb_depth > 8));
+ CYG_PRECONDITIONC((colour <= 65535) || (fb->fb_depth > 16));
+
+ (*(fb->fb_write_pixel_fn))(fb, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_read_pixel(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_read_pixel_fn);
+
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+
+ return (*(fb->fb_read_pixel_fn))(fb, x, y);
+}
+
+void
+cyg_fb_write_hline(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_hline_fn);
+
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+ CYG_PRECONDITIONC((x + len) <= fb->fb_width);
+ CYG_PRECONDITIONC((colour <= 1) || (fb->fb_depth > 1));
+ CYG_PRECONDITIONC((colour <= 3) || (fb->fb_depth > 2));
+ CYG_PRECONDITIONC((colour <= 15) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC((colour <= 255) || (fb->fb_depth > 8));
+ CYG_PRECONDITIONC((colour <= 65535) || (fb->fb_depth > 16));
+
+ (*(fb->fb_write_hline_fn))(fb, x, y, len, colour);
+}
+
+void
+cyg_fb_write_vline(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_vline_fn);
+
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+ CYG_PRECONDITIONC((y + len) <= fb->fb_height);
+ CYG_PRECONDITIONC((colour <= 1) || (fb->fb_depth > 1));
+ CYG_PRECONDITIONC((colour <= 3) || (fb->fb_depth > 2));
+ CYG_PRECONDITIONC((colour <= 15) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC((colour <= 255) || (fb->fb_depth > 8));
+ CYG_PRECONDITIONC((colour <= 65535) || (fb->fb_depth > 16));
+
+ (*(fb->fb_write_vline_fn))(fb, x, y, len, colour);
+}
+
+void
+cyg_fb_fill_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_fill_block_fn);
+
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+ CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+ CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+ CYG_PRECONDITIONC((colour <= 1) || (fb->fb_depth > 1));
+ CYG_PRECONDITIONC((colour <= 3) || (fb->fb_depth > 2));
+ CYG_PRECONDITIONC((colour <= 15) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC((colour <= 255) || (fb->fb_depth > 8));
+ CYG_PRECONDITIONC((colour <= 65535) || (fb->fb_depth > 16));
+
+ (*(fb->fb_fill_block_fn))(fb, x, y, width, height, colour);
+}
+
+void
+cyg_fb_write_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 stride)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_block_fn);
+
+ CYG_CHECK_DATA_PTRC(source);
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+ CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+ CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+
+ (*(fb->fb_write_block_fn))(fb, x, y, width, height, source, offset, stride);
+}
+
+void
+cyg_fb_read_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 stride)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_read_block_fn);
+
+ CYG_CHECK_DATA_PTRC(dest);
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+ CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+ CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+
+ (*(fb->fb_read_block_fn))(fb, x, y, width, height, dest, offset, stride);
+}
+
+void
+cyg_fb_move_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_move_block_fn);
+
+ CYG_PRECONDITIONC(x != new_x);
+ CYG_PRECONDITIONC(y != new_y);
+ CYG_PRECONDITIONC(x < fb->fb_width);
+ CYG_PRECONDITIONC(y < fb->fb_height);
+ CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+ CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+ CYG_PRECONDITIONC(new_x < fb->fb_width);
+ CYG_PRECONDITIONC(new_y < fb->fb_height);
+ CYG_PRECONDITIONC((new_x + width) <= fb->fb_width);
+ CYG_PRECONDITIONC((new_y + height) <= fb->fb_height);
+
+ (*(fb->fb_move_block_fn))(fb, x, y, width, height, new_x, new_y);
+}
+
+int
+cyg_fb_ioctl(cyg_fb* fb, cyg_uint16 key, void* data, size_t* len)
+{
+ int result;
+
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_ioctl_fn);
+
+ result = (*(fb->fb_ioctl_fn))(fb, key, data, len);
+ return result;
+}
+
+void
+cyg_fb_synch(cyg_fb* fb, cyg_ucount16 when)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_move_block_fn);
+ (*(fb->fb_synch_fn))(fb, when);
+#else
+ // Synch is a no-op
+#endif
+}
+
+void
+cyg_fb_read_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, void* dest)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_read_palette_fn);
+ CYG_CHECK_DATA_PTRC(dest);
+
+ CYG_PRECONDITIONC( (first < 16) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC(((first + count) < 16) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC( (first < 256) || (fb->fb_depth > 8));
+ CYG_PRECONDITIONC(((first + count) <= 256) || (fb->fb_depth > 8));
+
+ (*(fb->fb_read_palette_fn))(fb, first, count, dest);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_ucount32, first);
+ CYG_UNUSED_PARAM(cyg_ucount32, count);
+ CYG_UNUSED_PARAM(void*, dest);
+#endif
+}
+
+void
+cyg_fb_write_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, const void* source, cyg_ucount16 when)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_write_palette_fn);
+ CYG_CHECK_DATA_PTRC(source);
+
+ CYG_PRECONDITIONC( (first < 16) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC(((first + count) < 16) || (fb->fb_depth > 4));
+ CYG_PRECONDITIONC( (first < 256) || (fb->fb_depth > 8));
+ CYG_PRECONDITIONC(((first + count) <= 256) || (fb->fb_depth > 8));
+
+ (*(fb->fb_write_palette_fn))(fb, first, count, source, when);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_ucount32, first);
+ CYG_UNUSED_PARAM(cyg_ucount32, count);
+ CYG_UNUSED_PARAM(const void*, source);
+ CYG_UNUSED_PARAM(cyg_ucount16, when);
+#endif
+}
+
+cyg_fb_colour
+cyg_fb_make_colour(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_make_colour_fn);
+ CYG_PRECONDITIONC((r <= 0x00FF) && (g <= 0x00FF) && (b <= 0x00FF));
+
+ return (*(fb->fb_make_colour_fn))(fb, r, g, b);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_ucount8, r);
+ CYG_UNUSED_PARAM(cyg_ucount8, g);
+ CYG_UNUSED_PARAM(cyg_ucount8, b);
+ return 0;
+#endif
+}
+
+void
+cyg_fb_break_colour(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+ CYG_CHECK_DATA_PTRC(fb);
+ CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+ CYG_CHECK_FUNC_PTRC(fb->fb_break_colour_fn);
+ CYG_CHECK_DATA_PTRC(r);
+ CYG_CHECK_DATA_PTRC(g);
+ CYG_CHECK_DATA_PTRC(b);
+
+ (*(fb->fb_break_colour_fn))(fb, colour, r, g, b);
+#else
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_fb_colour, colour);
+ CYG_UNUSED_PARAM(cyg_ucount8*, r);
+ CYG_UNUSED_PARAM(cyg_ucount8*, g);
+ CYG_UNUSED_PARAM(cyg_ucount8*, b);
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// Dummy functions for use by device drivers when instantiating a cyg_fb
+// structure
+
+int
+cyg_fb_nop_on(cyg_fb* fb)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ return 0;
+}
+
+int
+cyg_fb_nop_off(cyg_fb* fb)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ return 0;
+}
+
+int
+cyg_fb_nop_ioctl(cyg_fb* fb, cyg_uint16 key, void* data, size_t* len)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_uint16, key);
+ CYG_UNUSED_PARAM(void*, data);
+ CYG_UNUSED_PARAM(size_t*, len);
+ return ENOSYS;
+}
+
+void
+cyg_fb_nop_synch(cyg_fb* fb, cyg_ucount16 when)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_ucount16, when);
+}
+
+void
+cyg_fb_nop_write_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, const void* source, cyg_ucount16 when)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_ucount32, first);
+ CYG_UNUSED_PARAM(cyg_ucount32, count);
+ CYG_UNUSED_PARAM(const void*, source);
+ CYG_UNUSED_PARAM(cyg_ucount16, when);
+}
+
+void
+cyg_fb_nop_read_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, void* dest)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_ucount32, first);
+ CYG_UNUSED_PARAM(cyg_ucount32, count);
+ CYG_UNUSED_PARAM(void*, dest);
+}
+
+cyg_fb_colour
+cyg_fb_nop_make_colour(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_ucount8, r);
+ CYG_UNUSED_PARAM(cyg_ucount8, g);
+ CYG_UNUSED_PARAM(cyg_ucount8, b);
+ return 0;
+}
+
+cyg_fb_colour
+cyg_fb_nop_make_color(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+ __attribute__((alias("cyg_fb_nop_make_colour")));
+
+void
+cyg_fb_nop_break_colour(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_UNUSED_PARAM(cyg_fb_colour, colour);
+ CYG_UNUSED_PARAM(cyg_ucount8*, r);
+ CYG_UNUSED_PARAM(cyg_ucount8*, g);
+ CYG_UNUSED_PARAM(cyg_ucount8*, b);
+}
+
+void
+cyg_fb_nop_break_color(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+ __attribute__((alias("cyg_fb_nop_break_colour")));
+
+// ----------------------------------------------------------------------------
+// Utility functions for common true colour modes
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_8bpp_true_332(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ return CYG_FB_MAKE_COLOUR_8BPP_TRUE_332(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_8bpp_true_332(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_FB_BREAK_COLOUR_8BPP_TRUE_332(colour, r, g, b);
+}
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_16bpp_true_565(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ return CYG_FB_MAKE_COLOUR_16BPP_TRUE_565(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_16bpp_true_565(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_FB_BREAK_COLOUR_16BPP_TRUE_565(colour, r, g, b);
+}
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_16bpp_true_555(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ return CYG_FB_MAKE_COLOUR_16BPP_TRUE_555(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_16bpp_true_555(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_FB_BREAK_COLOUR_16BPP_TRUE_555(colour, r, g, b);
+}
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_32bpp_true_0888(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ return CYG_FB_MAKE_COLOUR_32BPP_TRUE_0888(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_32bpp_true_0888(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+ CYG_UNUSED_PARAM(cyg_fb*, fb);
+ CYG_FB_BREAK_COLOUR_32BPP_TRUE_0888(colour, r, g, b);
+}
+
Index: src/gen_framebufs.tcl
===================================================================
RCS file: src/gen_framebufs.tcl
diff -N src/gen_framebufs.tcl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/gen_framebufs.tcl 7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,130 @@
+#!/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_framebufs.tcl: cannot find Tcl shell" ; exit 1' "$0" "$@"
+
+#===============================================================================
+#
+# gen_framebufs.tcl
+#
+# Amalgamate the various framebuffers available on a given platform
+#
+#===============================================================================
+#####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-03-29
+#
+# This script is invoked via a custom make rule to generate a file
+# <cyg/io/framebufs/framebufs.h>
+#
+#####DESCRIPTIONEND####
+#===============================================================================
+
+proc do_it { dir } {
+
+ # dir should be set to <prefix>/install/include/cyg/io/framebufs
+ if { ! [file exists $dir] } {
+ file mkdir $dir
+ }
+ if { ! [file isdirectory $dir] } {
+ puts stderr "gen_framebufs.tcl: strange build tree, $dir should be a directory"
+ exit 1
+ }
+
+ set framebufs_file [file join $dir "framebufs.h"]
+ set current_data ""
+ if { [file exists $framebufs_file] } {
+ set fd [open $framebufs_file "r"]
+ set current_data [read $fd]
+ close $fd
+ }
+
+ set headers [lsort [glob -nocomplain [file join $dir "*.h*"]]]
+
+ set new_data \
+ "\#ifndef CYGONCE_IO_FRAMEBUFS_FRAMEBUFS_H
+# define CYGONCE_IO_FRAMEBUFS_FRAMEBUFS_H
+
+/* This is a generated file - do not edit! */
+/* <cyg/io/framebufs/framebufs.h> should not be #include'd */
+/* directly, instead use <cyg/io/framebuf.h> */
+"
+
+ foreach header $headers {
+ set header [file tail $header]
+ if { [string equal "framebufs.h" $header] } {
+ continue
+ }
+ append new_data "#include <cyg/io/framebufs/[set header]>\n"
+ }
+
+ # Next, work out the default test device. We need to read pkgconf/io_framebuf.h,
+ # look for CYGDAT_IO_FRAMEBUF_DEVICES, and extract the first entry.
+ set pkgconf_file [file join $dir "../../../pkgconf/io_framebuf.h"]
+ if { ! [file exists $pkgconf_file] || ! [file readable $pkgconf_file] } {
+ puts stderr "gen_framebufs.tcl: strange build tree, no access to $pkgconf_file"
+ exit 1
+ }
+ set fd [open $pkgconf_file "r"]
+ while { ! [eof $fd] } {
+ set line [gets $fd]
+ if { [regexp {^#define\s*CYGDAT_IO_FRAMEBUF_DEVICES\s*(\S*)\s+.*$} $line junk fb] } {
+ append new_data "#define CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE $fb\n"
+ break
+ }
+ }
+
+ # Close the #ifndef CYGONCE_
+ append new_data "#endif\n"
+
+ if { ! [string equal $current_data $new_data] } {
+ set fd [open $framebufs_file "w"]
+ puts -nonewline $fd $new_data
+ close $fd
+ }
+}
+
+if { 0 == $::argc } {
+ puts stderr "gen_framebufs.tcl: missing argument for install directory"
+ exit 1
+}
+
+if { [catch { do_it [lindex $::argv 0] } msg] } {
+ puts stderr "gen_framebufs.tcl: internal error"
+ puts stderr " $msg"
+ exit 1
+}
+exit 0
Index: src/linear.c
===================================================================
RCS file: src/linear.c
diff -N src/linear.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/linear.c 7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,807 @@
+//==========================================================================
+//
+// linear.c
+//
+// Generic implementations of some of the driver functions for linear
+// framebuffers.
+//
+//==========================================================================
+//###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-03-29
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/framebuf.h>
+
+// The real implementations for most of the functions are actually
+// inlines held in framebuf.inl. That allows the implementation to be
+// shared between the functions and the macros.
+#include <cyg/io/framebuf.inl>
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_1LE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_1LE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_1LE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_1LE_impl(void* fbaddr, cyg_ucount16 stride,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_1LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_1LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_1BE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_1BE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_1BE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_1BE_impl(void* fbaddr, cyg_ucount16 stride,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_1BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_1LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+
+void
+cyg_fb_linear_write_pixel_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_2LE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_2LE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_2LE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_2LE_impl(void* fbaddr, cyg_ucount16 stride,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_2LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_2LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+
+void
+cyg_fb_linear_write_pixel_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_2BE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_2BE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_2BE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_2BE_impl(void* fbaddr, cyg_ucount16 stride,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_2BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_2BE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_4LE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_4LE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_4LE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_4LE_impl(void* fbaddr, cyg_ucount16 stride,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_4LE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_4LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_4BE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_4BE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_4BE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_fill_block_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_4BE_impl(void* fbaddr, cyg_ucount16 stride,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_4BE(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_4BE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+
+void
+cyg_fb_linear_write_pixel_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_8_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_8_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_hline_8_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_8_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+ cyg_fb_linear_fill_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, colour);
+}
+
+void
+cyg_fb_linear_write_block_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+ cyg_fb_linear_write_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, source, offset, source_stride);
+}
+
+void
+cyg_fb_linear_read_block_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+ cyg_fb_linear_read_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, dest, offset, dest_stride);
+}
+
+void
+cyg_fb_linear_move_block_8_impl(void* fbaddr, cyg_ucount16 stride,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_uint8* source;
+ cyg_uint8* dest;
+ int i;
+
+ source = ((cyg_uint8*)fbaddr) + ( y * stride) + x;
+ dest = ((cyg_uint8*)fbaddr) + (new_y * stride) + new_x;
+
+ if ((new_y < y) || // Possible overlapping blocks but no conflict
+ (new_y > (y + height)) || // No overlap
+ ((new_x + width) < x) || // No overlap
+ (new_x > (x + width))) { // No overlap
+
+ for ( ; height; height--) {
+ __builtin_memcpy(dest, source, width);
+ source += stride;
+ dest += stride;
+ }
+ return;
+ }
+
+ // There is an overlap. Can we do a safe bottom-to-top lot of memcpy()'s ?
+ if (new_y > y) {
+ source += (height * stride);
+ dest += (height * stride);
+
+ for ( ; height; height--) {
+ __builtin_memcpy(dest, source, width);
+ source -= stride;
+ dest -= stride;
+ }
+ return;
+ }
+
+ // We must have (y == new_y) and an overlap, i.e. a short
+ // horizontal move. We could use memmove() but the default
+ // implementation is no better than what we can do here.
+ if (new_x < x) {
+ stride -= width;
+ for ( ; height; height--) {
+ for ( i = width; i ; i--) {
+ *dest++ = *source++;
+ }
+ source += stride;
+ dest += stride;
+ }
+ } else if (new_x > x) {
+ source += width;
+ dest += width;
+ stride += width;
+ for ( ; height; height--) {
+ for ( i = width; i; i--) {
+ *--dest = *--source;
+ }
+ source += stride;
+ dest += stride;
+ }
+ }
+}
+
+void
+cyg_fb_linear_move_block_8(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_16_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_16_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_hline_16_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_16_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+ cyg_fb_linear_fill_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, colour);
+}
+
+void
+cyg_fb_linear_write_block_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+ cyg_fb_linear_write_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, source, offset, source_stride);
+}
+
+void
+cyg_fb_linear_read_block_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+ cyg_fb_linear_read_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, dest, offset, dest_stride);
+}
+
+void
+cyg_fb_linear_move_block_16_impl(void* fbaddr, cyg_ucount16 stride8,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_uint16* source;
+ cyg_uint16* dest;
+ int i;
+
+ source = ((cyg_uint16*)(((cyg_uint8*)fbaddr) + ( y * stride8))) + x;
+ dest = ((cyg_uint16*)(((cyg_uint8*)fbaddr) + (new_y * stride8))) + new_x;
+
+ if ((new_y < y) || // Possible overlapping blocks but no conflict
+ (new_y > (y + height)) || // No overlap
+ ((new_x + width) < x) || // No overlap
+ (new_x > (x + width))) { // No overlap
+
+ width <<= 1;
+ for ( ; height; height--) {
+ __builtin_memcpy(dest, source, width);
+ source = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+ dest = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+ }
+ return;
+ }
+
+ // There is an overlap. Can we do a safe bottom-to-top lot of memcpy()'s ?
+ if (new_y > y) {
+ source = (cyg_uint16*)(((cyg_uint8*)source) + (height * stride8));
+ dest = (cyg_uint16*)(((cyg_uint8*)dest) + (height * stride8));
+ width <<= 1;
+ for ( ; height; height--) {
+ __builtin_memcpy(dest, source, width);
+ source = (cyg_uint16*)(((cyg_uint8*)source) - stride8);
+ dest = (cyg_uint16*)(((cyg_uint8*)dest) - stride8);
+ }
+ return;
+ }
+
+ // We must have (y == new_y) and an overlap, i.e. a short
+ // horizontal move. We could use memmove() but the default
+ // implementation is no better than what we can do here.
+ if (new_x < x) {
+ stride8 -= (width << 1);
+ for ( ; height; height--) {
+ for ( i = width; i ; i--) {
+ *dest++ = *source++;
+ }
+ source = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+ dest = (cyg_uint16*)(((cyg_uint8*)dest) + stride8);
+ }
+ } else if (new_x > x) {
+ source += width;
+ dest += width;
+ stride8 += (width << 1);
+ for ( ; height; height--) {
+ for ( i = width; i ; i--) {
+ *--dest = *--source;
+ }
+ source = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+ dest = (cyg_uint16*)(((cyg_uint8*)dest) + stride8);
+ }
+ }
+}
+
+void
+cyg_fb_linear_move_block_16(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_pixel_32_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y)
+{
+ return cyg_fb_linear_read_pixel_32_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_hline_32_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+ cyg_fb_linear_write_vline_32_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+ cyg_fb_linear_fill_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, colour);
+}
+
+void
+cyg_fb_linear_write_block_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+ cyg_fb_linear_write_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, source, offset, source_stride);
+}
+
+void
+cyg_fb_linear_read_block_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+ cyg_fb_linear_read_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, dest, offset, dest_stride);
+}
+
+void
+cyg_fb_linear_move_block_32_impl(void* fbaddr, cyg_ucount16 stride8,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_uint32* source;
+ cyg_uint32* dest;
+ int i;
+
+ source = ((cyg_uint32*)(((cyg_uint8*)fbaddr) + ( y * stride8))) + x;
+ dest = ((cyg_uint32*)(((cyg_uint8*)fbaddr) + (new_y * stride8))) + new_x;
+
+ if ((new_y < y) || // Possible overlapping blocks but no conflict
+ (new_y > (y + height)) || // No overlap
+ ((new_x + width) < x) || // No overlap
+ (new_x > (x + width))) { // No overlap
+
+ width <<= 2;
+ for ( ; height; height--) {
+ __builtin_memcpy(dest, source, width);
+ source = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+ dest = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+ }
+ return;
+ }
+
+ // There is an overlap. Can we do a safe bottom-to-top lot of memcpy()'s ?
+ if (new_y > y) {
+ source = (cyg_uint32*)(((cyg_uint8*)source) + (height * stride8));
+ dest = (cyg_uint32*)(((cyg_uint8*)dest) + (height * stride8));
+ width <<= 2;
+ for ( ; height; height--) {
+ __builtin_memcpy(dest, source, width);
+ source = (cyg_uint32*)(((cyg_uint8*)source) - stride8);
+ dest = (cyg_uint32*)(((cyg_uint8*)dest) - stride8);
+ }
+ return;
+ }
+
+ // We must have (y == new_y) and an overlap, i.e. a short
+ // horizontal move. We could use memmove() but the default
+ // implementation is no better than what we can do here.
+ if (new_x < x) {
+ stride8 -= (width << 2);
+ for ( ; height; height--) {
+ for ( i = width; i ; i--) {
+ *dest++ = *source++;
+ }
+ source = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+ dest = (cyg_uint32*)(((cyg_uint8*)dest) + stride8);
+ }
+ } else if (new_x > x) {
+ source += width;
+ dest += width;
+ stride8 += (width << 2);
+ for ( ; height; height--) {
+ for ( i = width; i ; i--) {
+ *--dest = *--source;
+ }
+ source = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+ dest = (cyg_uint32*)(((cyg_uint8*)dest) + stride8);
+ }
+ }
+}
+
+void
+cyg_fb_linear_move_block_32(cyg_fb* fb,
+ cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+ cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+ cyg_fb_linear_move_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
Index: src/palette.c
===================================================================
RCS file: src/palette.c
diff -N src/palette.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/palette.c 7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,327 @@
+//==========================================================================
+//
+// palette.c
+//
+// Provide default palettes
+//
+//==========================================================================
+//###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-03-29
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <cyg/io/framebuf.h>
+
+// These figures were taken from a real VGA card. The VGA palette
+// registers only use six bits so the values were shifted by two,
+// then 0xFC was converted to 0xFF to get maximum brightness.
+
+const cyg_uint8 cyg_fb_palette_ega[16 * 3] = {
+ 0x00, 0x00, 0x00, // 0 black
+ 0x00, 0x00, 0xa8, // 1 blue
+ 0x00, 0xa8, 0x00, // 2 green
+ 0x00, 0xa8, 0xa8, // 3 cyan
+ 0xa8, 0x00, 0x00, // 4 red
+ 0xa8, 0x00, 0xa8, // 5 magenta
+ 0xa8, 0x54, 0x00, // 6 brown
+ 0xa8, 0xa8, 0xa8, // 7 light grey
+ 0x54, 0x54, 0x54, // 8 dark grey
+ 0x54, 0x54, 0xff, // 9 light blue
+ 0x54, 0xff, 0x54, // 10 light green
+ 0x54, 0xff, 0xff, // 11 light cyan
+ 0xff, 0x54, 0x54, // 12 light red
+ 0xff, 0x54, 0xff, // 13 light magenta
+ 0xff, 0xff, 0x54, // 14 yellow
+ 0xff, 0xff, 0xff // 15 white
+};
+
+const cyg_uint8 cyg_fb_palette_vga[256 * 3] = {
+ 0x00, 0x00, 0x00, // 0 black
+ 0x00, 0x00, 0xa8, // 1 blue
+ 0x00, 0xa8, 0x00, // 2 green
+ 0x00, 0xa8, 0xa8, // 3 cyan
+ 0xa8, 0x00, 0x00, // 4 red
+ 0xa8, 0x00, 0xa8, // 5 magenta
+ 0xa8, 0x54, 0x00, // 6 brown
+ 0xa8, 0xa8, 0xa8, // 7 light grey
+ 0x54, 0x54, 0x54, // 8 dark grey
+ 0x54, 0x54, 0xff, // 9 light blue
+ 0x54, 0xff, 0x54, // 10 light green
+ 0x54, 0xff, 0xff, // 11 light cyan
+ 0xff, 0x54, 0x54, // 12 light red
+ 0xff, 0x54, 0xff, // 13 light magenta
+ 0xff, 0xff, 0x54, // 14 yellow
+ 0xff, 0xff, 0xff, // 15 white
+ 0x00, 0x00, 0x00, // 16
+ 0x14, 0x14, 0x14, // 17
+ 0x20, 0x20, 0x20, // 18
+ 0x2c, 0x2c, 0x2c, // 19
+ 0x38, 0x38, 0x38, // 20
+ 0x44, 0x44, 0x44, // 21
+ 0x50, 0x50, 0x50, // 22
+ 0x60, 0x60, 0x60, // 23
+ 0x70, 0x70, 0x70, // 24
+ 0x80, 0x80, 0x80, // 25
+ 0x90, 0x90, 0x90, // 26
+ 0xa0, 0xa0, 0xa0, // 27
+ 0xb4, 0xb4, 0xb4, // 28
+ 0xc8, 0xc8, 0xc8, // 29
+ 0xe0, 0xe0, 0xe0, // 30
+ 0xff, 0xff, 0xff, // 31
+ 0x00, 0x00, 0xff, // 32
+ 0x40, 0x00, 0xff, // 33
+ 0x7c, 0x00, 0xff, // 34
+ 0xbc, 0x00, 0xff, // 35
+ 0xff, 0x00, 0xff, // 36
+ 0xff, 0x00, 0xbc, // 37
+ 0xff, 0x00, 0x7c, // 38
+ 0xff, 0x00, 0x40, // 39
+ 0xff, 0x00, 0x00, // 40
+ 0xff, 0x40, 0x00, // 41
+ 0xff, 0x7c, 0x00, // 42
+ 0xff, 0xbc, 0x00, // 43
+ 0xff, 0xff, 0x00, // 44
+ 0xbc, 0xff, 0x00, // 45
+ 0x7c, 0xff, 0x00, // 46
+ 0x40, 0xff, 0x00, // 47
+ 0x00, 0xff, 0x00, // 48
+ 0x00, 0xff, 0x40, // 49
+ 0x00, 0xff, 0x7c, // 50
+ 0x00, 0xff, 0xbc, // 51
+ 0x00, 0xff, 0xff, // 52
+ 0x00, 0xbc, 0xff, // 53
+ 0x00, 0x7c, 0xff, // 54
+ 0x00, 0x40, 0xff, // 55
+ 0x7c, 0x7c, 0xff, // 56
+ 0x9c, 0x7c, 0xff, // 57
+ 0xbc, 0x7c, 0xff, // 58
+ 0xdc, 0x7c, 0xff, // 59
+ 0xff, 0x7c, 0xff, // 60
+ 0xff, 0x7c, 0xdc, // 61
+ 0xff, 0x7c, 0xbc, // 62
+ 0xff, 0x7c, 0x9c, // 63
+ 0xff, 0x7c, 0x7c, // 64
+ 0xff, 0x9c, 0x7c, // 65
+ 0xff, 0xbc, 0x7c, // 66
+ 0xff, 0xdc, 0x7c, // 67
+ 0xff, 0xff, 0x7c, // 68
+ 0xdc, 0xff, 0x7c, // 69
+ 0xbc, 0xff, 0x7c, // 70
+ 0x9c, 0xff, 0x7c, // 71
+ 0x7c, 0xff, 0x7c, // 72
+ 0x7c, 0xff, 0x9c, // 73
+ 0x7c, 0xff, 0xbc, // 74
+ 0x7c, 0xff, 0xdc, // 75
+ 0x7c, 0xff, 0xff, // 76
+ 0x7c, 0xdc, 0xff, // 77
+ 0x7c, 0xbc, 0xff, // 78
+ 0x7c, 0x9c, 0xff, // 79
+ 0xb4, 0xb4, 0xff, // 80
+ 0xc4, 0xb4, 0xff, // 81
+ 0xd8, 0xb4, 0xff, // 82
+ 0xe8, 0xb4, 0xff, // 83
+ 0xff, 0xb4, 0xff, // 84
+ 0xff, 0xb4, 0xe8, // 85
+ 0xff, 0xb4, 0xd8, // 86
+ 0xff, 0xb4, 0xc4, // 87
+ 0xff, 0xb4, 0xb4, // 88
+ 0xff, 0xc4, 0xb4, // 89
+ 0xff, 0xd8, 0xb4, // 90
+ 0xff, 0xe8, 0xb4, // 91
+ 0xff, 0xff, 0xb4, // 92
+ 0xe8, 0xff, 0xb4, // 93
+ 0xd8, 0xff, 0xb4, // 94
+ 0xc4, 0xff, 0xb4, // 95
+ 0xb4, 0xff, 0xb4, // 96
+ 0xb4, 0xff, 0xc4, // 97
+ 0xb4, 0xff, 0xd8, // 98
+ 0xb4, 0xff, 0xe8, // 99
+ 0xb4, 0xff, 0xff, // 100
+ 0xb4, 0xe8, 0xff, // 101
+ 0xb4, 0xd8, 0xff, // 102
+ 0xb4, 0xc4, 0xff, // 103
+ 0x00, 0x00, 0x70, // 104
+ 0x1c, 0x00, 0x70, // 105
+ 0x38, 0x00, 0x70, // 106
+ 0x54, 0x00, 0x70, // 107
+ 0x70, 0x00, 0x70, // 108
+ 0x70, 0x00, 0x54, // 109
+ 0x70, 0x00, 0x38, // 110
+ 0x70, 0x00, 0x1c, // 111
+ 0x70, 0x00, 0x00, // 112
+ 0x70, 0x1c, 0x00, // 113
+ 0x70, 0x38, 0x00, // 114
+ 0x70, 0x54, 0x00, // 115
+ 0x70, 0x70, 0x00, // 116
+ 0x54, 0x70, 0x00, // 117
+ 0x38, 0x70, 0x00, // 118
+ 0x1c, 0x70, 0x00, // 119
+ 0x00, 0x70, 0x00, // 120
+ 0x00, 0x70, 0x1c, // 121
+ 0x00, 0x70, 0x38, // 122
+ 0x00, 0x70, 0x54, // 123
+ 0x00, 0x70, 0x70, // 124
+ 0x00, 0x54, 0x70, // 125
+ 0x00, 0x38, 0x70, // 126
+ 0x00, 0x1c, 0x70, // 127
+ 0x38, 0x38, 0x70, // 128
+ 0x44, 0x38, 0x70, // 129
+ 0x54, 0x38, 0x70, // 130
+ 0x60, 0x38, 0x70, // 131
+ 0x70, 0x38, 0x70, // 132
+ 0x70, 0x38, 0x60, // 133
+ 0x70, 0x38, 0x54, // 134
+ 0x70, 0x38, 0x44, // 135
+ 0x70, 0x38, 0x38, // 136
+ 0x70, 0x44, 0x38, // 137
+ 0x70, 0x54, 0x38, // 138
+ 0x70, 0x60, 0x38, // 139
+ 0x70, 0x70, 0x38, // 140
+ 0x60, 0x70, 0x38, // 141
+ 0x54, 0x70, 0x38, // 142
+ 0x44, 0x70, 0x38, // 143
+ 0x38, 0x70, 0x38, // 144
+ 0x38, 0x70, 0x44, // 145
+ 0x38, 0x70, 0x54, // 146
+ 0x38, 0x70, 0x60, // 147
+ 0x38, 0x70, 0x70, // 148
+ 0x38, 0x60, 0x70, // 149
+ 0x38, 0x54, 0x70, // 150
+ 0x38, 0x44, 0x70, // 151
+ 0x50, 0x50, 0x70, // 152
+ 0x58, 0x50, 0x70, // 153
+ 0x60, 0x50, 0x70, // 154
+ 0x68, 0x50, 0x70, // 155
+ 0x70, 0x50, 0x70, // 156
+ 0x70, 0x50, 0x68, // 157
+ 0x70, 0x50, 0x60, // 158
+ 0x70, 0x50, 0x58, // 159
+ 0x70, 0x50, 0x50, // 160
+ 0x70, 0x58, 0x50, // 161
+ 0x70, 0x60, 0x50, // 162
+ 0x70, 0x68, 0x50, // 163
+ 0x70, 0x70, 0x50, // 164
+ 0x68, 0x70, 0x50, // 165
+ 0x60, 0x70, 0x50, // 166
+ 0x58, 0x70, 0x50, // 167
+ 0x50, 0x70, 0x50, // 168
+ 0x50, 0x70, 0x58, // 169
+ 0x50, 0x70, 0x60, // 170
+ 0x50, 0x70, 0x68, // 171
+ 0x50, 0x70, 0x70, // 172
+ 0x50, 0x68, 0x70, // 173
+ 0x50, 0x60, 0x70, // 174
+ 0x50, 0x58, 0x70, // 175
+ 0x00, 0x00, 0x40, // 176
+ 0x10, 0x00, 0x40, // 177
+ 0x20, 0x00, 0x40, // 178
+ 0x30, 0x00, 0x40, // 179
+ 0x40, 0x00, 0x40, // 180
+ 0x40, 0x00, 0x30, // 181
+ 0x40, 0x00, 0x20, // 182
+ 0x40, 0x00, 0x10, // 183
+ 0x40, 0x00, 0x00, // 184
+ 0x40, 0x10, 0x00, // 185
+ 0x40, 0x20, 0x00, // 186
+ 0x40, 0x30, 0x00, // 187
+ 0x40, 0x40, 0x00, // 188
+ 0x30, 0x40, 0x00, // 189
+ 0x20, 0x40, 0x00, // 190
+ 0x10, 0x40, 0x00, // 191
+ 0x00, 0x40, 0x00, // 192
+ 0x00, 0x40, 0x10, // 193
+ 0x00, 0x40, 0x20, // 194
+ 0x00, 0x40, 0x30, // 195
+ 0x00, 0x40, 0x40, // 196
+ 0x00, 0x30, 0x40, // 197
+ 0x00, 0x20, 0x40, // 198
+ 0x00, 0x10, 0x40, // 199
+ 0x20, 0x20, 0x40, // 200
+ 0x28, 0x20, 0x40, // 201
+ 0x30, 0x20, 0x40, // 202
+ 0x38, 0x20, 0x40, // 203
+ 0x40, 0x20, 0x40, // 204
+ 0x40, 0x20, 0x38, // 205
+ 0x40, 0x20, 0x30, // 206
+ 0x40, 0x20, 0x28, // 207
+ 0x40, 0x20, 0x20, // 208
+ 0x40, 0x28, 0x20, // 209
+ 0x40, 0x30, 0x20, // 210
+ 0x40, 0x38, 0x20, // 211
+ 0x40, 0x40, 0x20, // 212
+ 0x38, 0x40, 0x20, // 213
+ 0x30, 0x40, 0x20, // 214
+ 0x28, 0x40, 0x20, // 215
+ 0x20, 0x40, 0x20, // 216
+ 0x20, 0x40, 0x28, // 217
+ 0x20, 0x40, 0x30, // 218
+ 0x20, 0x40, 0x38, // 219
+ 0x20, 0x40, 0x40, // 220
+ 0x20, 0x38, 0x40, // 221
+ 0x20, 0x30, 0x40, // 222
+ 0x20, 0x28, 0x40, // 223
+ 0x2c, 0x2c, 0x40, // 224
+ 0x30, 0x2c, 0x40, // 225
+ 0x34, 0x2c, 0x40, // 226
+ 0x3c, 0x2c, 0x40, // 227
+ 0x40, 0x2c, 0x40, // 228
+ 0x40, 0x2c, 0x3c, // 229
+ 0x40, 0x2c, 0x34, // 230
+ 0x40, 0x2c, 0x30, // 231
+ 0x40, 0x2c, 0x2c, // 232
+ 0x40, 0x30, 0x2c, // 233
+ 0x40, 0x34, 0x2c, // 234
+ 0x40, 0x3c, 0x2c, // 235
+ 0x40, 0x40, 0x2c, // 236
+ 0x3c, 0x40, 0x2c, // 237
+ 0x34, 0x40, 0x2c, // 238
+ 0x30, 0x40, 0x2c, // 239
+ 0x2c, 0x40, 0x2c, // 240
+ 0x2c, 0x40, 0x30, // 241
+ 0x2c, 0x40, 0x34, // 242
+ 0x2c, 0x40, 0x3c, // 243
+ 0x2c, 0x40, 0x40, // 244
+ 0x2c, 0x3c, 0x40, // 245
+ 0x2c, 0x34, 0x40, // 246
+ 0x2c, 0x30, 0x40, // 247
+ 0x00, 0x00, 0x00, // 248
+ 0x00, 0x00, 0x00, // 249
+ 0x00, 0x00, 0x00, // 250
+ 0x00, 0x00, 0x00, // 251
+ 0x00, 0x00, 0x00, // 252
+ 0x00, 0x00, 0x00, // 253
+ 0x00, 0x00, 0x00, // 254
+ 0x00, 0x00, 0x00 // 255
+};
Index: tests/fb.c
===================================================================
RCS file: tests/fb.c
diff -N tests/fb.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/fb.c 7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,226 @@
+//==========================================================================
+//
+// fb.c
+//
+// Framebuffer testcase
+//
+//==========================================================================
+//###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 <pkgconf/system.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/testcase.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <pkgconf/io_framebuf.h>
+#include <cyg/io/framebuf.h>
+
+#if defined(CYGDAT_IO_FRAMEBUF_TEST_DEVICE)
+# define FB CYGDAT_IO_FRAMEBUF_TEST_DEVICE
+#elif defined(CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE)
+# define FB CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE
+#else
+# define NA_MSG "No framebuffer test device selected"
+#endif
+
+#ifndef NA_MSG
+# if (CYG_FB_DEPTH(FB) < 4)
+# define NA_MSG "Testcase requires a display depth of at least 4 bits/pixel"
+# else
+# define FRAMEBUF CYG_FB_STRUCT(FB)
+# endif
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA(NA_MSG);
+}
+#else
+
+#define STRING1(_a_) # _a_
+#define STRING(_a_) STRING1(_a_)
+
+// A simple bitmap. Black on the outside, then blue,
+// then green, and a red centre.
+static cyg_uint8 bitmap8[8][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint16 bitmap16[8][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint32 bitmap32[8][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+// The colours used by this test code. Default to the standard palette
+// but if running on a true colour display then adjust.
+static cyg_ucount32 colours[16] = {
+ CYG_FB_DEFAULT_PALETTE_BLACK,
+ CYG_FB_DEFAULT_PALETTE_BLUE,
+ CYG_FB_DEFAULT_PALETTE_GREEN,
+ CYG_FB_DEFAULT_PALETTE_CYAN,
+ CYG_FB_DEFAULT_PALETTE_RED,
+ CYG_FB_DEFAULT_PALETTE_MAGENTA,
+ CYG_FB_DEFAULT_PALETTE_BROWN,
+ CYG_FB_DEFAULT_PALETTE_LIGHTGREY,
+ CYG_FB_DEFAULT_PALETTE_DARKGREY,
+ CYG_FB_DEFAULT_PALETTE_LIGHTBLUE,
+ CYG_FB_DEFAULT_PALETTE_LIGHTGREEN,
+ CYG_FB_DEFAULT_PALETTE_LIGHTCYAN,
+ CYG_FB_DEFAULT_PALETTE_LIGHTRED,
+ CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA,
+ CYG_FB_DEFAULT_PALETTE_YELLOW,
+ CYG_FB_DEFAULT_PALETTE_WHITE
+};
+
+#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]
+
+static void
+reset_colours_to_true(void)
+{
+ int i, j;
+ 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]);
+ }
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ bitmap16[i][j] = colours[bitmap16[i][j]];
+ bitmap32[i][j] = colours[bitmap32[i][j]];
+ }
+ }
+}
+
+void
+cyg_start(void)
+{
+ int i;
+ cyg_ucount16 block_width;
+
+ CYG_TEST_INIT();
+ diag_printf("Frame buffer %s\n", STRING(FRAMEBUF));
+ diag_printf("Depth %d, width %d, height %d\n", FRAMEBUF.fb_depth, FRAMEBUF.fb_width, FRAMEBUF.fb_height);
+ cyg_fb_on(&FRAMEBUF);
+
+ if (FRAMEBUF.fb_flags0 & CYG_FB_FLAGS0_TRUE_COLOUR) {
+ reset_colours_to_true();
+ }
+
+ // 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);
+
+ // Display a simple bitmap on the left, halfway down.
+ if (8 == FRAMEBUF.fb_depth) {
+ cyg_fb_write_block(&FRAMEBUF, 0, FRAMEBUF.fb_height / 2, 8, 8, bitmap8, 0, 8);
+ } else if (16 == FRAMEBUF.fb_depth) {
+ cyg_fb_write_block(&FRAMEBUF, 0, FRAMEBUF.fb_height / 2, 8, 8, bitmap16, 0, 8);
+ } else if (32 == FRAMEBUF.fb_depth) {
+ cyg_fb_write_block(&FRAMEBUF, 0, FRAMEBUF.fb_height / 2, 8, 8, bitmap32, 0, 8);
+ }
+
+ // 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);
+
+ CYG_TEST_EXIT("Done");
+}
+#endif // NA_MSG
Index: tests/fbmacro.c
===================================================================
RCS file: tests/fbmacro.c
diff -N tests/fbmacro.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/fbmacro.c 7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,284 @@
+//==========================================================================
+//
+// fbmacro.c
+//
+// Framebuffer testcase
+//
+//==========================================================================
+//###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 <pkgconf/system.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/testcase.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <pkgconf/io_framebuf.h>
+#include <cyg/io/framebuf.h>
+
+#if defined(CYGDAT_IO_FRAMEBUF_TEST_DEVICE)
+# define FRAMEBUF CYGDAT_IO_FRAMEBUF_TEST_DEVICE
+#elif defined(CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE)
+# define FRAMEBUF CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE
+#else
+# define NA_MSG "No framebuffer test device selected"
+#endif
+
+#ifndef NA_MSG
+# if (CYG_FB_DEPTH(FRAMEBUF) < 4)
+# define NA_MSG "Testcase requires a display depth of at least 4 bits/pixel"
+# endif
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA(NA_MSG);
+}
+#else
+
+#define STRING1(_a_) # _a_
+#define STRING(_a_) STRING1(_a_)
+
+// A simple bitmap. Black on the outside, then blue,
+// then green, and a red centre.
+static cyg_uint8 bitmap8[8][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint16 bitmap16[8][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint32 bitmap32[8][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+ { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+// The colours used by this test code. Default to the standard palette
+// but if running on a true colour display then adjust.
+static cyg_ucount32 colours[16] = {
+ CYG_FB_DEFAULT_PALETTE_BLACK,
+ CYG_FB_DEFAULT_PALETTE_BLUE,
+ CYG_FB_DEFAULT_PALETTE_GREEN,
+ CYG_FB_DEFAULT_PALETTE_CYAN,
+ CYG_FB_DEFAULT_PALETTE_RED,
+ CYG_FB_DEFAULT_PALETTE_MAGENTA,
+ CYG_FB_DEFAULT_PALETTE_BROWN,
+ CYG_FB_DEFAULT_PALETTE_LIGHTGREY,
+ CYG_FB_DEFAULT_PALETTE_DARKGREY,
+ CYG_FB_DEFAULT_PALETTE_LIGHTBLUE,
+ CYG_FB_DEFAULT_PALETTE_LIGHTGREEN,
+ CYG_FB_DEFAULT_PALETTE_LIGHTCYAN,
+ CYG_FB_DEFAULT_PALETTE_LIGHTRED,
+ CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA,
+ CYG_FB_DEFAULT_PALETTE_YELLOW,
+ CYG_FB_DEFAULT_PALETTE_WHITE
+};
+
+#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]
+
+static void
+reset_colours_to_true(void)
+{
+#if (CYG_FB_FLAGS0_TRUE_COLOUR & CYG_FB_FLAGS0(FRAMEBUF))
+ int i, j;
+
+ 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]);
+ }
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ bitmap16[i][j] = colours[bitmap16[i][j]];
+ bitmap32[i][j] = colours[bitmap32[i][j]];
+ }
+ }
+#endif
+}
+
+void
+cyg_start(void)
+{
+ int i, j;
+ int x = 0, y = 0;
+ int result;
+ cyg_ucount16 block_width;
+
+ CYG_FB_PIXEL0_VAR(FRAMEBUF);
+ CYG_FB_PIXEL1_VAR(FRAMEBUF);
+
+#define DEPTH CYG_FB_DEPTH(FRAMEBUF)
+#define WIDTH CYG_FB_WIDTH(FRAMEBUF)
+#define HEIGHT CYG_FB_HEIGHT(FRAMEBUF)
+
+ CYG_TEST_INIT();
+
+ diag_printf("Frame buffer %s\n", STRING(FRAMEBUF));
+ diag_printf("Depth %d, width %d, height %d\n", DEPTH, WIDTH, HEIGHT);
+
+ result = CYG_FB_ON(FRAMEBUF);
+
+ if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_TRUE_COLOUR) {
+ reset_colours_to_true();
+ }
+
+ // 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]);
+ }
+ }
+
+
+ if (8 == DEPTH) {
+ CYG_FB_WRITE_BLOCK(FRAMEBUF, 0, HEIGHT / 2, 8, 8, bitmap8, 0, 8);
+ } else if (16 == DEPTH) {
+ CYG_FB_WRITE_BLOCK(FRAMEBUF, 0, HEIGHT / 2, 8, 8, bitmap16, 0, 8);
+ } else if (32 == DEPTH) {
+ CYG_FB_WRITE_BLOCK(FRAMEBUF, 0, HEIGHT / 2, 8, 8, bitmap32, 0, 8);
+ }
+
+ 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]);
+ }
+
+ CYG_TEST_EXIT("Done");
+}
+#endif // NA_MSG