Mercurial > ecos
changeset 2565:f9d071633ee7
Contribute eCosCentric's framebuffer infrastructure.
| author | bartv |
|---|---|
| date | Tue, 07 Oct 2008 10:15:04 +0000 |
| parents | 2ccc43202018 |
| children | 2063ee669faf |
| files | packages/io/framebuf/current/ChangeLog packages/io/framebuf/current/cdl/framebuf.cdl packages/io/framebuf/current/doc/framebuf.sgml packages/io/framebuf/current/include/framebuf.h packages/io/framebuf/current/include/framebuf.inl packages/io/framebuf/current/src/framebuf.c packages/io/framebuf/current/src/gen_framebufs.tcl packages/io/framebuf/current/src/linear.c packages/io/framebuf/current/src/palette.c packages/io/framebuf/current/tests/fb.c packages/io/framebuf/current/tests/fbmacro.c |
| diffstat | 11 files changed, 7462 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/ChangeLog @@ -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#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/cdl/framebuf.cdl @@ -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" + } + } +}
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/doc/framebuf.sgml @@ -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>
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/include/framebuf.h @@ -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
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/include/framebuf.inl @@ -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
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/src/framebuf.c @@ -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); +} +
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/src/gen_framebufs.tcl @@ -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
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/src/linear.c @@ -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); +}
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/src/palette.c @@ -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 +};
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/tests/fb.c @@ -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
new file mode 100644 --- /dev/null +++ b/packages/io/framebuf/current/tests/fbmacro.c @@ -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
