aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Becker <ampernand@gmail.com>2016-10-17 08:53:00 -0400
committerJeff Becker <ampernand@gmail.com>2016-10-17 08:53:00 -0400
commit6e720aaabb40c6f6b41e8c439b0bb4784c273171 (patch)
tree5ac361147dd93383dd2544445b34c9eb14f595bc
parentbf4c55b7cf5fd27e8da1f9682c1b4a016a2c3e5a (diff)
downloadwterm-6e720aaabb40c6f6b41e8c439b0bb4784c273171.zip
wterm-6e720aaabb40c6f6b41e8c439b0bb4784c273171.tar.gz
wterm-6e720aaabb40c6f6b41e8c439b0bb4784c273171.tar.bz2
changes
-rw-r--r--.gitignore3
-rw-r--r--Makefile43
-rw-r--r--config.mk4
-rw-r--r--include/config.h0
-rw-r--r--include/wayland-drm.xml185
-rw-r--r--include/xdg-shell.xml485
-rw-r--r--src/arg.h63
-rw-r--r--src/st.c (renamed from st.c)2
-rw-r--r--src/wld/.gitignore11
-rw-r--r--src/wld/COPYING20
-rw-r--r--src/wld/Makefile186
-rw-r--r--src/wld/README.md16
-rw-r--r--src/wld/TODO6
-rw-r--r--src/wld/buffer.c137
-rw-r--r--src/wld/buffered_surface.c224
-rw-r--r--src/wld/color.c850
-rw-r--r--src/wld/common.mk11
-rw-r--r--src/wld/config.mk20
-rw-r--r--src/wld/context.c70
-rw-r--r--src/wld/drm-private.h46
-rw-r--r--src/wld/drm.c98
-rw-r--r--src/wld/drm.h52
-rw-r--r--src/wld/dumb.c235
-rw-r--r--src/wld/font.c235
-rw-r--r--src/wld/intel.c390
-rw-r--r--src/wld/intel/batch.c99
-rw-r--r--src/wld/intel/batch.h104
-rw-r--r--src/wld/intel/blt.h347
-rw-r--r--src/wld/intel/i965_pci_ids.h93
-rw-r--r--src/wld/intel/local.mk6
-rw-r--r--src/wld/intel/mi.h50
-rw-r--r--src/wld/interface/buffer.h33
-rw-r--r--src/wld/interface/context.h50
-rw-r--r--src/wld/interface/drm.h43
-rw-r--r--src/wld/interface/renderer.h68
-rw-r--r--src/wld/interface/surface.h41
-rw-r--r--src/wld/interface/wayland.h41
-rw-r--r--src/wld/nouveau/g80_2d.xml.h547
-rw-r--r--src/wld/nouveau/g80_defs.xml.h382
-rw-r--r--src/wld/nouveau/nouveau.c678
-rw-r--r--src/wld/nouveau/nv_object.xml.h452
-rw-r--r--src/wld/pixman.c450
-rw-r--r--src/wld/pixman.h44
-rw-r--r--src/wld/protocol/local.mk18
-rw-r--r--src/wld/protocol/wayland-drm.xml185
-rw-r--r--src/wld/renderer.c157
-rw-r--r--src/wld/surface.c70
-rw-r--r--src/wld/wayland-drm.c296
-rw-r--r--src/wld/wayland-private.h60
-rw-r--r--src/wld/wayland-shm.c294
-rw-r--r--src/wld/wayland.c308
-rw-r--r--src/wld/wayland.h84
-rw-r--r--src/wld/wld-private.h243
-rw-r--r--src/wld/wld.h283
-rw-r--r--src/wld/wld.pc.in13
55 files changed, 8929 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 3ac9aa9..6dc28a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*~
*\#*
*.o
-wterm \ No newline at end of file
+*-client-protocol.h
+wterm
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..86847e8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+
+include config.mk
+
+SRC=src
+WLDSRC=$(SRC)/wld
+
+PKGS = fontconfig wayland-client wayland-cursor xkbcommon pixman-1 libdrm
+
+SOURCES = $(wildcard $(WLDSRC)/*.c)
+SOURCES += $(wildcard $(SRC)/*.c)
+
+ifeq ($(ENABLE_INTEL),1)
+PKGS += libdrm_intel
+SOURCES += $(wildcard $(WLDSRC)/intel/*.c)
+endif
+ifeq ($(ENABLE_NOUVEAU),1)
+PKGS += libdrm_nouveau
+SOURCES += $(wildcard $(WLDSRC)/nouveau/*.c)
+endif
+
+CFLAGS = -std=c99 -Wall -Wextra
+CFLAGS += $(shell pkg-config --cflags $(PKGS)) -I include -I $(WLDSRC)
+LDFLAGS = $(shell pkg-config --libs $(PKGS))
+
+
+OBJECTS = $(SOURCES:.c=.o)
+
+WAYLAND_HEADERS = $(wildcard include/*.xml)
+
+HDRS = $(WAYLAND_HEADERS:.xml=-client-protocol.h)
+
+all: wterm
+
+$(HDRS): $(WAYLAND_HEADERS)
+ wayland-scanner client-header < $< > $@
+
+$(OBJECTS): $(HDRS)
+
+wterm: $(OBJECTS)
+ $(CC) -o wterm $(OBJECTS) $(LDFLAGS)
+
+clean:
+ rm -f $(OBJECTS) $(HDRS)
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..56a640d
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,4 @@
+
+
+ENABLE_INTEL = 1
+ENABLE_NOUVEAU = 0
diff --git a/include/config.h b/include/config.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/config.h
diff --git a/include/wayland-drm.xml b/include/wayland-drm.xml
new file mode 100644
index 0000000..5e64622
--- /dev/null
+++ b/include/wayland-drm.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm">
+
+ <copyright>
+ Copyright © 2008-2011 Kristian Høgsberg
+ Copyright © 2010-2011 Intel Corporation
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that\n the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <!-- drm support. This object is created by the server and published
+ using the display's global event. -->
+ <interface name="wl_drm" version="2">
+ <enum name="error">
+ <entry name="authenticate_fail" value="0"/>
+ <entry name="invalid_format" value="1"/>
+ <entry name="invalid_name" value="2"/>
+ </enum>
+
+ <enum name="format">
+ <!-- The drm format codes match the #defines in drm_fourcc.h.
+ The formats actually supported by the compositor will be
+ reported by the format event. -->
+ <entry name="c8" value="0x20203843"/>
+ <entry name="rgb332" value="0x38424752"/>
+ <entry name="bgr233" value="0x38524742"/>
+ <entry name="xrgb4444" value="0x32315258"/>
+ <entry name="xbgr4444" value="0x32314258"/>
+ <entry name="rgbx4444" value="0x32315852"/>
+ <entry name="bgrx4444" value="0x32315842"/>
+ <entry name="argb4444" value="0x32315241"/>
+ <entry name="abgr4444" value="0x32314241"/>
+ <entry name="rgba4444" value="0x32314152"/>
+ <entry name="bgra4444" value="0x32314142"/>
+ <entry name="xrgb1555" value="0x35315258"/>
+ <entry name="xbgr1555" value="0x35314258"/>
+ <entry name="rgbx5551" value="0x35315852"/>
+ <entry name="bgrx5551" value="0x35315842"/>
+ <entry name="argb1555" value="0x35315241"/>
+ <entry name="abgr1555" value="0x35314241"/>
+ <entry name="rgba5551" value="0x35314152"/>
+ <entry name="bgra5551" value="0x35314142"/>
+ <entry name="rgb565" value="0x36314752"/>
+ <entry name="bgr565" value="0x36314742"/>
+ <entry name="rgb888" value="0x34324752"/>
+ <entry name="bgr888" value="0x34324742"/>
+ <entry name="xrgb8888" value="0x34325258"/>
+ <entry name="xbgr8888" value="0x34324258"/>
+ <entry name="rgbx8888" value="0x34325852"/>
+ <entry name="bgrx8888" value="0x34325842"/>
+ <entry name="argb8888" value="0x34325241"/>
+ <entry name="abgr8888" value="0x34324241"/>
+ <entry name="rgba8888" value="0x34324152"/>
+ <entry name="bgra8888" value="0x34324142"/>
+ <entry name="xrgb2101010" value="0x30335258"/>
+ <entry name="xbgr2101010" value="0x30334258"/>
+ <entry name="rgbx1010102" value="0x30335852"/>
+ <entry name="bgrx1010102" value="0x30335842"/>
+ <entry name="argb2101010" value="0x30335241"/>
+ <entry name="abgr2101010" value="0x30334241"/>
+ <entry name="rgba1010102" value="0x30334152"/>
+ <entry name="bgra1010102" value="0x30334142"/>
+ <entry name="yuyv" value="0x56595559"/>
+ <entry name="yvyu" value="0x55595659"/>
+ <entry name="uyvy" value="0x59565955"/>
+ <entry name="vyuy" value="0x59555956"/>
+ <entry name="ayuv" value="0x56555941"/>
+ <entry name="nv12" value="0x3231564e"/>
+ <entry name="nv21" value="0x3132564e"/>
+ <entry name="nv16" value="0x3631564e"/>
+ <entry name="nv61" value="0x3136564e"/>
+ <entry name="yuv410" value="0x39565559"/>
+ <entry name="yvu410" value="0x39555659"/>
+ <entry name="yuv411" value="0x31315559"/>
+ <entry name="yvu411" value="0x31315659"/>
+ <entry name="yuv420" value="0x32315559"/>
+ <entry name="yvu420" value="0x32315659"/>
+ <entry name="yuv422" value="0x36315559"/>
+ <entry name="yvu422" value="0x36315659"/>
+ <entry name="yuv444" value="0x34325559"/>
+ <entry name="yvu444" value="0x34325659"/>
+ </enum>
+
+ <!-- Call this request with the magic received from drmGetMagic().
+ It will be passed on to the drmAuthMagic() or
+ DRIAuthConnection() call. This authentication must be
+ completed before create_buffer could be used. -->
+ <request name="authenticate">
+ <arg name="id" type="uint"/>
+ </request>
+
+ <!-- Create a wayland buffer for the named DRM buffer. The DRM
+ surface must have a name using the flink ioctl -->
+ <request name="create_buffer">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="uint"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="stride" type="uint"/>
+ <arg name="format" type="uint"/>
+ </request>
+
+ <!-- Create a wayland buffer for the named DRM buffer. The DRM
+ surface must have a name using the flink ioctl -->
+ <request name="create_planar_buffer">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="uint"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="format" type="uint"/>
+ <arg name="offset0" type="int"/>
+ <arg name="stride0" type="int"/>
+ <arg name="offset1" type="int"/>
+ <arg name="stride1" type="int"/>
+ <arg name="offset2" type="int"/>
+ <arg name="stride2" type="int"/>
+ </request>
+
+ <!-- Notification of the path of the drm device which is used by
+ the server. The client should use this device for creating
+ local buffers. Only buffers created from this device should
+ be be passed to the server using this drm object's
+ create_buffer request. -->
+ <event name="device">
+ <arg name="name" type="string"/>
+ </event>
+
+ <event name="format">
+ <arg name="format" type="uint"/>
+ </event>
+
+ <!-- Raised if the authenticate request succeeded -->
+ <event name="authenticated"/>
+
+ <enum name="capability" since="2">
+ <description summary="wl_drm capability bitmask">
+ Bitmask of capabilities.
+ </description>
+ <entry name="prime" value="1" summary="wl_drm prime available"/>
+ </enum>
+
+ <event name="capabilities">
+ <arg name="value" type="uint"/>
+ </event>
+
+ <!-- Version 2 additions -->
+
+ <!-- Create a wayland buffer for the prime fd. Use for regular and planar
+ buffers. Pass 0 for offset and stride for unused planes. -->
+ <request name="create_prime_buffer" since="2">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="fd"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="format" type="uint"/>
+ <arg name="offset0" type="int"/>
+ <arg name="stride0" type="int"/>
+ <arg name="offset1" type="int"/>
+ <arg name="stride1" type="int"/>
+ <arg name="offset2" type="int"/>
+ <arg name="stride2" type="int"/>
+ </request>
+
+ </interface>
+
+</protocol>
diff --git a/include/xdg-shell.xml b/include/xdg-shell.xml
new file mode 100644
index 0000000..3656e10
--- /dev/null
+++ b/include/xdg-shell.xml
@@ -0,0 +1,485 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="xdg_shell">
+
+ <copyright>
+ Copyright © 2008-2013 Kristian Høgsberg
+ Copyright © 2013 Rafael Antognolli
+ Copyright © 2013 Jasper St. Pierre
+ Copyright © 2010-2013 Intel Corporation
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <interface name="xdg_shell" version="1">
+ <description summary="create desktop-style surfaces">
+ xdg_shell allows clients to turn a wl_surface into a "real window"
+ which can be dragged, resized, stacked, and moved around by the
+ user. Everything about this interface is suited towards traditional
+ desktop environments.
+ </description>
+
+ <enum name="version">
+ <description summary="latest protocol version">
+ The 'current' member of this enum gives the version of the
+ protocol. Implementations can compare this to the version
+ they implement using static_assert to ensure the protocol and
+ implementation versions match.
+ </description>
+ <entry name="current" value="5" summary="Always the latest version"/>
+ </enum>
+
+ <enum name="error">
+ <entry name="role" value="0" summary="given wl_surface has another role"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy xdg_shell">
+ Destroy this xdg_shell object.
+
+ Destroying a bound xdg_shell object while there are surfaces
+ still alive with roles from this interface is illegal and will
+ result in a protocol error. Make sure to destroy all surfaces
+ before destroying this object.
+ </description>
+ </request>
+
+ <request name="use_unstable_version">
+ <description summary="enable use of this unstable version">
+ Negotiate the unstable version of the interface. This
+ mechanism is in place to ensure client and server agree on the
+ unstable versions of the protocol that they speak or exit
+ cleanly if they don't agree. This request will go away once
+ the xdg-shell protocol is stable.
+ </description>
+ <arg name="version" type="int"/>
+ </request>
+
+ <request name="get_xdg_surface">
+ <description summary="create a shell surface from a surface">
+ This creates an xdg_surface for the given surface and gives it the
+ xdg_surface role. See the documentation of xdg_surface for more details.
+ </description>
+ <arg name="id" type="new_id" interface="xdg_surface"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+
+ <request name="get_xdg_popup">
+ <description summary="create a popup for a surface">
+ This creates an xdg_popup for the given surface and gives it the
+ xdg_popup role. See the documentation of xdg_popup for more details.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event.
+ </description>
+ <arg name="id" type="new_id" interface="xdg_popup"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="parent" type="object" interface="wl_surface"/>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ </request>
+
+ <event name="ping">
+ <description summary="check if the client is alive">
+ The ping event asks the client if it's still alive. Pass the
+ serial specified in the event back to the compositor by sending
+ a "pong" request back with the specified serial.
+
+ Compositors can use this to determine if the client is still
+ alive. It's unspecified what will happen if the client doesn't
+ respond to the ping request, or in what timeframe. Clients should
+ try to respond in a reasonable amount of time.
+ </description>
+ <arg name="serial" type="uint" summary="pass this to the pong request"/>
+ </event>
+
+ <request name="pong">
+ <description summary="respond to a ping event">
+ A client must respond to a ping event with a pong request or
+ the client may be deemed unresponsive.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the ping event"/>
+ </request>
+ </interface>
+
+ <interface name="xdg_surface" version="1">
+ <description summary="A desktop window">
+ An interface that may be implemented by a wl_surface, for
+ implementations that provide a desktop-style user interface.
+
+ It provides requests to treat surfaces like windows, allowing to set
+ properties like maximized, fullscreen, minimized, and to move and resize
+ them, and associate metadata like title and app id.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="Destroy the xdg_surface">
+ Unmap and destroy the window. The window will be effectively
+ hidden from the user's point of view, and all state like
+ maximization, fullscreen, and so on, will be lost.
+ </description>
+ </request>
+
+ <request name="set_parent">
+ <description summary="set the parent of this surface">
+ Set the "parent" of this surface. This window should be stacked
+ above a parent. The parent surface must be mapped as long as this
+ surface is mapped.
+
+ Parent windows should be set on dialogs, toolboxes, or other
+ "auxilliary" surfaces, so that the parent is raised when the dialog
+ is raised.
+ </description>
+ <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
+ </request>
+
+ <request name="set_title">
+ <description summary="set surface title">
+ Set a short title for the surface.
+
+ This string may be used to identify the surface in a task bar,
+ window list, or other user interface elements provided by the
+ compositor.
+
+ The string must be encoded in UTF-8.
+ </description>
+ <arg name="title" type="string"/>
+ </request>
+
+ <request name="set_app_id">
+ <description summary="set application ID">
+ Set an application identifier for the surface.
+
+ The app ID identifies the general class of applications to which
+ the surface belongs. The compositor can use this to group multiple
+ applications together, or to determine how to launch a new
+ application.
+
+ See the desktop-entry specification [0] for more details on
+ application identifiers and how they relate to well-known DBus
+ names and .desktop files.
+
+ [0] http://standards.freedesktop.org/desktop-entry-spec/
+ </description>
+ <arg name="app_id" type="string"/>
+ </request>
+
+ <request name="show_window_menu">
+ <description summary="show the window menu">
+ Clients implementing client-side decorations might want to show
+ a context menu when right-clicking on the decorations, giving the
+ user a menu that they can use to maximize or minimize the window.
+
+ This request asks the compositor to pop up such a window menu at
+ the given position, relative to the local surface coordinates of
+ the parent surface. There are no guarantees as to what menu items
+ the window menu contains.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event.
+ </description>
+
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
+ <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
+ </request>
+
+ <request name="move">
+ <description summary="start an interactive move">
+ Start an interactive, user-driven move of the surface.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event.
+
+ The server may ignore move requests depending on the state of
+ the surface (e.g. fullscreen or maximized).
+ </description>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ </request>
+
+ <enum name="resize_edge">
+ <description summary="edge values for resizing">
+ These values are used to indicate which edge of a surface
+ is being dragged in a resize operation. The server may
+ use this information to adapt its behavior, e.g. choose
+ an appropriate cursor image.
+ </description>
+ <entry name="none" value="0"/>
+ <entry name="top" value="1"/>
+ <entry name="bottom" value="2"/>
+ <entry name="left" value="4"/>
+ <entry name="top_left" value="5"/>
+ <entry name="bottom_left" value="6"/>
+ <entry name="right" value="8"/>
+ <entry name="top_right" value="9"/>
+ <entry name="bottom_right" value="10"/>
+ </enum>
+
+ <request name="resize">
+ <description summary="start an interactive resize">
+ Start a user-driven, interactive resize of the surface.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event.
+
+ The server may ignore resize requests depending on the state of
+ the surface (e.g. fullscreen or maximized).
+ </description>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
+ </request>
+
+ <enum name="state">
+ <description summary="types of state on the surface">
+ The different state values used on the surface. This is designed for
+ state values like maximized, fullscreen. It is paired with the
+ configure event to ensure that both the client and the compositor
+ setting the state can be synchronized.
+
+ States set in this way are double-buffered. They will get applied on
+ the next commit.
+
+ Desktop environments may extend this enum by taking up a range of
+ values and documenting the range they chose in this description.
+ They are not required to document the values for the range that they
+ chose. Ideally, any good extensions from a desktop environment should
+ make its way into standardization into this enum.
+
+ The current reserved ranges are:
+
+ 0x0000 - 0x0FFF: xdg-shell core values, documented below.
+ 0x1000 - 0x1FFF: GNOME
+ </description>
+ <entry name="maximized" value="1" summary="the surface is maximized">
+ The surface is maximized. The window geometry specified in the configure
+ event must be obeyed by the client.
+ </entry>
+ <entry name="fullscreen" value="2" summary="the surface is fullscreen">
+ The surface is fullscreen. The window geometry specified in the configure
+ event must be obeyed by the client.
+ </entry>
+ <entry name="resizing" value="3">
+ The surface is being resized. The window geometry specified in the
+ configure event is a maximum; the client cannot resize beyond it.
+ Clients that have aspect ratio or cell sizing configuration can use
+ a smaller size, however.
+ </entry>
+ <entry name="activated" value="4">
+ Client window decorations should be painted as if the window is
+ active. Do not assume this means that the window actually has
+ keyboard or pointer focus.
+ </entry>
+ </enum>
+
+ <event name="configure">
+ <description summary="suggest a surface change">
+ The configure event asks the client to resize its surface or to
+ change its state.
+
+ The width and height arguments specify a hint to the window
+ about how its surface should be resized in window geometry
+ coordinates.
+
+ The states listed in the event specify how the width/height
+ arguments should be interpreted, and possibly how it should be
+ drawn.
+
+ Clients should arrange their surface for the new size and
+ states, and then send a ack_configure request with the serial
+ sent in this configure event at some point before committing
+ the new surface.
+
+ If the client receives multiple configure events before it
+ can respond to one, it is free to discard all but the last
+ event it received.
+ </description>
+
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="states" type="array"/>
+ <arg name="serial" type="uint"/>
+ </event>
+
+ <request name="ack_configure">
+ <description summary="ack a configure event">
+ When a configure event is received, if a client commits the
+ surface in response to the configure event, then the client
+ must make a ack_configure request before the commit request,
+ passing along the serial of the configure event.
+
+ The compositor might use this information to move a surface
+ to the top left only when the client has drawn itself for
+ the maximized or fullscreen state.
+
+ If the client receives multiple configure events before it
+ can respond to one, it only has to ack the last configure event.
+ </description>
+ <arg name="serial" type="uint" summary="the serial from the configure event"/>
+ </request>
+
+ <request name="set_window_geometry">
+ <description summary="set the new window geometry">
+ The window geometry of a window is its "visible bounds" from the
+ user's perspective. Client-side decorations often have invisible
+ portions like drop-shadows which should be ignored for the
+ purposes of aligning, placing and constraining windows.
+
+ Once the window geometry of the surface is set once, it is not
+ possible to unset it, and it will remain the same until
+ set_window_geometry is called again, even if a new subsurface or
+ buffer is attached.
+
+ If never set, the value is the full bounds of the surface,
+ including any subsurfaces. This updates dynamically on every
+ commit. This unset mode is meant for extremely simple clients.
+
+ If responding to a configure event, the window geometry in here
+ must respect the sizing negotiations specified by the states in
+ the configure event.
+
+ The width and height must be greater than zero.
+ </description>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <request name="set_maximized" />
+ <request name="unset_maximized" />
+
+ <request name="set_fullscreen">
+ <description summary="set the window as fullscreen on a monitor">
+ Make the surface fullscreen.
+
+ You can specify an output that you would prefer to be fullscreen.
+ If this value is NULL, it's up to the compositor to choose which
+ display will be used to map this surface.
+ </description>
+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
+ </request>
+ <request name="unset_fullscreen" />
+
+ <request name="set_minimized">
+ <description summary="set the window as minimized">
+ Request that the compositor minimize your surface. There is no
+ way to know if the surface is currently minimized, nor is there
+ any way to unset minimization on this surface.
+
+ If you are looking to throttle redrawing when minimized, please
+ instead use the wl_surface.frame event for this, as this will
+ also work with live previews on windows in Alt-Tab, Expose or
+ similar compositor features.
+ </description>
+ </request>
+
+ <event name="close">
+ <description summary="surface wants to be closed">
+ The close event is sent by the compositor when the user
+ wants the surface to be closed. This should be equivalent to
+ the user clicking the close button in client-side decorations,
+ if your application has any...
+
+ This is only a request that the user intends to close your
+ window. The client may choose to ignore this request, or show
+ a dialog to ask the user to save their data...
+ </description>
+ </event>
+ </interface>
+
+ <interface name="xdg_popup" version="1">
+ <description summary="short-lived, popup surfaces for menus">
+ A popup surface is a short-lived, temporary surface that can be
+ used to implement menus. It takes an explicit grab on the surface
+ that will be dismissed when the user dismisses the popup. This can
+ be done by the user clicking outside the surface, using the keyboard,
+ or even locking the screen through closing the lid or a timeout.
+
+ When the popup is dismissed, a popup_done event will be sent out,
+ and at the same time the surface will be unmapped. The xdg_popup
+ object is now inert and cannot be reactivated, so clients should
+ destroy it. Explicitly destroying the xdg_popup object will also
+ dismiss the popup and unmap the surface.
+
+ Clients will receive events for all their surfaces during this
+ grab (which is an "owner-events" grab in X11 parlance). This is
+ done so that users can navigate through submenus and other
+ "nested" popup windows without having to dismiss the topmost
+ popup.
+
+ Clients that want to dismiss the popup when another surface of
+ their own is clicked should dismiss the popup using the destroy
+ request.
+
+ The parent surface must have either an xdg_surface or xdg_popup
+ role.
+
+ Specifying an xdg_popup for the parent means that the popups are
+ nested, with this popup now being the topmost popup. Nested
+ popups must be destroyed in the reverse order they were created
+ in, e.g. the only popup you are allowed to destroy at all times
+ is the topmost one.
+
+ If there is an existing popup when creating a new popup, the
+ parent must be the current topmost popup.
+
+ A parent surface must be mapped before the new popup is mapped.
+
+ When compositors choose to dismiss a popup, they will likely
+ dismiss every nested popup as well.
+
+ The x and y arguments specify where the top left of the popup
+ should be placed, relative to the local surface coordinates of the
+ parent surface.
+ </description>
+
+ <enum name="error">
+ <description summary="xdg_popup error values">
+ These errors can be emitted in response to xdg_popup requests.
+ </description>
+ <entry name="not_the_topmost_popup" value="0" summary="The client tried to map or destroy a non-topmost popup"/>
+ <entry name="invalid_parent" value="1" summary="The client specified an invalid parent surface"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="remove xdg_popup interface">
+ This destroys the popup. Explicitly destroying the xdg_popup
+ object will also dismiss the popup, and unmap the surface.
+
+ If this xdg_popup is not the "topmost" popup, a protocol error
+ will be sent.
+ </description>
+ </request>
+
+ <event name="popup_done">
+ <description summary="popup interaction is done">
+ The popup_done event is sent out when a popup is dismissed
+ by the compositor.
+ </description>
+ </event>
+
+ </interface>
+</protocol>
diff --git a/src/arg.h b/src/arg.h
new file mode 100644
index 0000000..4df77a7
--- /dev/null
+++ b/src/arg.h
@@ -0,0 +1,63 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef ARG_H__
+#define ARG_H__
+
+extern char *argv0;
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][1]\
+ && argv[0][0] == '-';\
+ argc--, argv++) {\
+ char argc_;\
+ char **argv_;\
+ int brk_;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (brk_ = 0, argv[0]++, argv_ = argv;\
+ argv[0][0] && !brk_;\
+ argv[0]++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][0];\
+ switch (argc_)
+
+/* Handles obsolete -NUM syntax */
+#define ARGNUM case '0':\
+ case '1':\
+ case '2':\
+ case '3':\
+ case '4':\
+ case '5':\
+ case '6':\
+ case '7':\
+ case '8':\
+ case '9'
+
+#define ARGEND }\
+ }
+
+#define ARGC() argc_
+
+#define ARGNUMF(base) (brk_ = 1, estrtol(argv[0], (base)))
+
+#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ ((x), abort(), (char *)0) :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#endif
diff --git a/st.c b/src/st.c
index 871b0de..ba550ce 100644
--- a/st.c
+++ b/src/st.c
@@ -32,7 +32,7 @@
#include <wchar.h>
#include "arg.h"
-#include "xdg-shell-client-protocol.h"
+#include "xdg-shell.h"
char *argv0;
diff --git a/src/wld/.gitignore b/src/wld/.gitignore
new file mode 100644
index 0000000..445ef3b
--- /dev/null
+++ b/src/wld/.gitignore
@@ -0,0 +1,11 @@
+*.o
+*.lo
+.*.sw*
+
+/.deps/
+/libwld.a
+/libwld.so*
+/wld.pc
+/protocol/wayland-drm-client-protocol.h
+/protocol/wayland-drm-protocol.c
+
diff --git a/src/wld/COPYING b/src/wld/COPYING
new file mode 100644
index 0000000..7da88e5
--- /dev/null
+++ b/src/wld/COPYING
@@ -0,0 +1,20 @@
+Copyright (c) 2013, 2014 Michael Forney
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/src/wld/Makefile b/src/wld/Makefile
new file mode 100644
index 0000000..b5db1c8
--- /dev/null
+++ b/src/wld/Makefile
@@ -0,0 +1,186 @@
+# wld: Makefile
+
+include config.mk
+
+#PREFIX ?= /usr/local
+#LIBDIR ?= $(PREFIX)/lib
+#INCLUDEDIR ?= $(PREFIX)/include
+#PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
+
+PKG_CONFIG ?= pkg-config
+WAYLAND_SCANNER ?= wayland-scanner
+
+VERSION_MAJOR := 0
+VERSION_MINOR := 0
+VERSION := $(VERSION_MAJOR).$(VERSION_MINOR)
+
+WLD_LIB_LINK := libwld.so
+WLD_LIB_SONAME := $(WLD_LIB_LINK).$(VERSION_MAJOR)
+WLD_LIB := $(WLD_LIB_LINK).$(VERSION)
+
+TARGETS := wld.pc
+CLEAN_FILES :=
+
+WLD_REQUIRES = fontconfig pixman-1
+WLD_REQUIRES_PRIVATE = freetype2
+WLD_SOURCES = \
+ buffer.c \
+ buffered_surface.c \
+ color.c \
+ context.c \
+ font.c \
+ renderer.c \
+ surface.c
+WLD_HEADERS = wld.h
+
+ifeq ($(ENABLE_DRM),1)
+ WLD_REQUIRES_PRIVATE += libdrm
+ WLD_SOURCES += drm.c dumb.c
+ WLD_HEADERS += drm.h
+
+ ifneq ($(findstring intel,$(DRM_DRIVERS)),)
+ WLD_REQUIRES_PRIVATE += libdrm_intel
+ WLD_SOURCES += intel.c intel/batch.c
+ WLD_CPPFLAGS += -DWITH_DRM_INTEL=1
+ endif
+
+ ifneq ($(findstring nouveau,$(DRM_DRIVERS)),)
+ WLD_REQUIRES_PRIVATE += libdrm_nouveau
+ WLD_SOURCES += nouveau.c
+ WLD_CPPFLAGS += -DWITH_DRM_NOUVEAU=1
+ endif
+endif
+
+ifeq ($(ENABLE_PIXMAN),1)
+ WLD_SOURCES += pixman.c
+ WLD_HEADERS += pixman.h
+endif
+
+ifeq ($(ENABLE_WAYLAND),1)
+ WLD_REQUIRES_PRIVATE += wayland-client
+ WLD_SOURCES += wayland.c
+ WLD_HEADERS += wayland.h
+
+ ifneq ($(findstring shm,$(WAYLAND_INTERFACES)),)
+ WLD_SOURCES += wayland-shm.c
+ WLD_CPPFLAGS += -DWITH_WAYLAND_SHM=1
+ endif
+
+ ifneq ($(findstring drm,$(WAYLAND_INTERFACES)),)
+ WLD_SOURCES += wayland-drm.c protocol/wayland-drm-protocol.c
+ WLD_CPPFLAGS += -DWITH_WAYLAND_DRM=1
+ endif
+endif
+
+ifeq ($(if $(V),$(V),0), 0)
+ define quiet
+ @echo " $1 $@"
+ @$(if $2,$2,$($1))
+ endef
+else
+ quiet = $(if $2,$2,$($1))
+endif
+
+WLD_STATIC_OBJECTS = $(WLD_SOURCES:%.c=%.o)
+WLD_SHARED_OBJECTS = $(WLD_SOURCES:%.c=%.lo)
+WLD_PACKAGES = $(WLD_REQUIRES) $(WLD_REQUIRES_PRIVATE)
+WLD_PACKAGE_CFLAGS ?= $(call pkgconfig,$(WLD_PACKAGES),cflags,CFLAGS)
+WLD_PACKAGE_LIBS ?= $(call pkgconfig,$(WLD_PACKAGES),libs,LIBS)
+
+FINAL_CFLAGS = $(CFLAGS) -fvisibility=hidden -std=c99
+FINAL_CPPFLAGS = $(CPPFLAGS) -D_XOPEN_SOURCE=700
+
+# Warning/error flags
+FINAL_CFLAGS += -Werror=implicit-function-declaration -Werror=implicit-int \
+ -Werror=pointer-sign -Werror=pointer-arith \
+ -Wall -Wno-missing-braces
+
+ifeq ($(ENABLE_DEBUG),1)
+ FINAL_CPPFLAGS += -DENABLE_DEBUG=1
+ FINAL_CFLAGS += -g
+else
+ FINAL_CPPFLAGS += -DNDEBUG
+endif
+
+ifeq ($(ENABLE_STATIC),1)
+ TARGETS += libwld.a
+ CLEAN_FILES += $(WLD_STATIC_OBJECTS)
+endif
+
+ifeq ($(ENABLE_SHARED),1)
+ TARGETS += $(WLD_LIB) $(WLD_LIB_LINK) $(WLD_LIB_SONAME)
+ CLEAN_FILES += $(WLD_SHARED_OBJECTS)
+endif
+
+CLEAN_FILES += $(TARGETS)
+
+compile = $(call quiet,CC) $(FINAL_CPPFLAGS) $(FINAL_CFLAGS) -c -o $@ $< \
+ -MMD -MP -MF .deps/$(basename $<).d -MT $(basename $@).o -MT $(basename $@).lo
+link = $(call quiet,CCLD,$(CC)) $(LDFLAGS) -o $@ $^
+pkgconfig = $(sort $(foreach pkg,$(1),$(if $($(pkg)_$(3)),$($(pkg)_$(3)), \
+ $(shell $(PKG_CONFIG) --$(2) $(pkg)))))
+
+.PHONY: all
+all: $(TARGETS)
+
+include $(foreach dir,intel protocol,$(dir)/local.mk)
+
+.deps:
+ @mkdir "$@"
+
+%.o: %.c | .deps
+ $(compile) $(WLD_CPPFLAGS) $(WLD_PACKAGE_CFLAGS)
+
+%.lo: %.c | .deps
+ $(compile) $(WLD_CPPFLAGS) $(WLD_PACKAGE_CFLAGS) -fPIC
+
+wayland-drm.o wayland-drm.lo: protocol/wayland-drm-client-protocol.h
+
+wld.pc: wld.pc.in
+ $(call quiet,GEN,sed) \
+ -e "s:@VERSION@:$(VERSION):" \
+ -e "s:@PREFIX@:$(PREFIX):" \
+ -e "s:@LIBDIR@:$(LIBDIR):" \
+ -e "s:@INCLUDEDIR@:$(INCLUDEDIR):" \
+ -e "s:@WLD_REQUIRES@:$(WLD_REQUIRES):" \
+ -e "s:@WLD_REQUIRES_PRIVATE@:$(WLD_REQUIRES_PRIVATE):" \
+ $< > $@
+
+libwld.a: $(WLD_STATIC_OBJECTS)
+ $(call quiet,AR) cr $@ $^
+
+$(WLD_LIB): $(WLD_SHARED_OBJECTS)
+ $(link) $(WLD_PACKAGE_LIBS) -shared -Wl,-soname,$(WLD_LIB_SONAME),-no-undefined
+
+$(WLD_LIB_SONAME) $(WLD_LIB_LINK): $(WLD_LIB)
+ $(call quiet,SYM,ln -sf) $< $@
+
+$(foreach dir,LIB PKGCONFIG,$(DESTDIR)$($(dir)DIR)) $(DESTDIR)$(INCLUDEDIR)/wld:
+ mkdir -p $@
+
+.PHONY: install-wld.pc
+install-wld.pc: wld.pc | $(DESTDIR)$(PKGCONFIGDIR)
+ install -m 644 $< $(DESTDIR)$(PKGCONFIGDIR)
+
+.PHONY: install-libwld.a
+install-libwld.a: libwld.a | $(DESTDIR)$(LIBDIR)
+ install -m 644 $< $(DESTDIR)$(LIBDIR)
+
+.PHONY: install-$(WLD_LIB)
+install-$(WLD_LIB): $(WLD_LIB) | $(DESTDIR)$(LIBDIR)
+ install -m 755 $< $(DESTDIR)$(LIBDIR)
+
+.PHONY: install-$(WLD_LIB_LINK) install-$(WLD_LIB_SONAME)
+install-$(WLD_LIB_LINK) install-$(WLD_LIB_SONAME): install-$(WLD_LIB) | $(DESTDIR)$(LIBDIR)
+ ln -sf $(WLD_LIB) $(DESTDIR)$(LIBDIR)/${@:install-%=%}
+
+.PHONY: install
+install: $(TARGETS:%=install-%) | $(foreach dir,LIB PKGCONFIG,$(DESTDIR)$($(dir)DIR)) $(DESTDIR)$(INCLUDEDIR)/wld
+ install -m 644 $(WLD_HEADERS) $(DESTDIR)$(INCLUDEDIR)/wld
+
+.PHONY: clean
+clean:
+ rm -rf $(CLEAN_FILES)
+
+-include .deps/*.d
+
diff --git a/src/wld/README.md b/src/wld/README.md
new file mode 100644
index 0000000..1326c25
--- /dev/null
+++ b/src/wld/README.md
@@ -0,0 +1,16 @@
+wld
+===
+wld is a drawing library that targets Wayland. The [swc Wayland compositor
+library](https://github.com/michaelforney/swc) uses wld.
+
+Installing
+==========
+To build and install wld, simply use:
+
+```Bash
+make
+make install
+```
+
+Various flags may be set in config.mk. You will likely want to compile
+using only intel or noveau, not both.
diff --git a/src/wld/TODO b/src/wld/TODO
new file mode 100644
index 0000000..9915589
--- /dev/null
+++ b/src/wld/TODO
@@ -0,0 +1,6 @@
+TODO
+====
+- Non-monochrome text rendering
+ - Probably requires 3d engine blending for intel backend
+- Add doxygen documentation
+
diff --git a/src/wld/buffer.c b/src/wld/buffer.c
new file mode 100644
index 0000000..46b1b3b
--- /dev/null
+++ b/src/wld/buffer.c
@@ -0,0 +1,137 @@
+/* wld: buffer.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wld-private.h"
+
+void buffer_initialize(struct buffer * buffer,
+ const struct wld_buffer_impl * impl,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ *((const struct wld_buffer_impl **) &buffer->base.impl) = impl;
+ buffer->base.width = width;
+ buffer->base.height = height;
+ buffer->base.format = format;
+ buffer->base.pitch = pitch;
+ buffer->base.map = NULL;
+ buffer->references = 1;
+ buffer->map_references = 0;
+ buffer->exporters = NULL;
+ buffer->destructors = NULL;
+ pixman_region32_init_rect(&buffer->base.damage, 0, 0, width, height);
+}
+
+EXPORT
+bool wld_map(struct wld_buffer * base)
+{
+ struct buffer * buffer = (void *) base;
+
+ if (buffer->map_references == 0 && !buffer->base.impl->map(buffer))
+ return false;
+
+ ++buffer->map_references;
+ return true;
+}
+
+EXPORT
+bool wld_unmap(struct wld_buffer * base)
+{
+ struct buffer * buffer = (void *) base;
+
+ if (buffer->map_references == 0
+ || (buffer->map_references == 1 && !buffer->base.impl->unmap(buffer)))
+ {
+ return false;
+ }
+
+ --buffer->map_references;
+ return true;
+}
+
+EXPORT
+bool wld_export(struct wld_buffer * base,
+ uint32_t type, union wld_object * object)
+{
+ struct buffer * buffer = (void *) base;
+ struct wld_exporter * exporter;
+
+ for (exporter = buffer->exporters; exporter; exporter = exporter->next)
+ {
+ if (exporter->export(exporter, &buffer->base, type, object))
+ return true;
+ }
+
+ return false;
+}
+
+EXPORT
+void wld_buffer_add_exporter(struct wld_buffer * base,
+ struct wld_exporter * exporter)
+{
+ struct buffer * buffer = (void *) base;
+
+ exporter->next = buffer->exporters;
+ buffer->exporters = exporter;
+}
+
+EXPORT
+void wld_buffer_add_destructor(struct wld_buffer * base,
+ struct wld_destructor * destructor)
+{
+ struct buffer * buffer = (void *) base;
+
+ destructor->next = buffer->destructors;
+ buffer->destructors = destructor;
+}
+
+EXPORT
+void wld_buffer_reference(struct wld_buffer * base)
+{
+ struct buffer * buffer = (void *) base;
+
+ ++buffer->references;
+}
+
+EXPORT
+void wld_buffer_unreference(struct wld_buffer * base)
+{
+ struct buffer * buffer = (void *) base;
+ struct wld_destructor * destructor, * next;
+
+ if (--buffer->references > 0)
+ return;
+
+ pixman_region32_fini(&buffer->base.damage);
+
+ for (destructor = buffer->destructors; destructor; destructor = next)
+ {
+ next = destructor->next;
+ destructor->destroy(destructor);
+ }
+
+ if (buffer->map_references > 0)
+ buffer->base.impl->unmap(buffer);
+
+ buffer->base.impl->destroy(buffer);
+}
+
diff --git a/src/wld/buffered_surface.c b/src/wld/buffered_surface.c
new file mode 100644
index 0000000..e3d9133
--- /dev/null
+++ b/src/wld/buffered_surface.c
@@ -0,0 +1,224 @@
+/* wld: buffered_surface.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wld-private.h"
+
+#include "interface/surface.h"
+IMPL(buffered_surface, wld_surface)
+
+struct buffer_entry
+{
+ struct buffer * buffer;
+ bool busy;
+};
+
+struct buffered_surface
+{
+ struct wld_surface base;
+
+ struct wld_context * context;
+ struct buffer_entry * entries, * back;
+ unsigned entries_size, entries_capacity;
+
+ struct buffer_socket * buffer_socket;
+
+ uint32_t width, height;
+ enum wld_format format;
+ uint32_t flags;
+};
+
+struct wld_surface * buffered_surface_create
+ (struct wld_context * context, uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags, struct buffer_socket * buffer_socket)
+{
+ struct buffered_surface * surface;
+
+ if (!(surface = malloc(sizeof *surface)))
+ return NULL;
+
+ surface_initialize(&surface->base, &wld_surface_impl);
+ surface->context = context;
+ surface->entries = NULL;
+ surface->back = NULL;
+ surface->entries_size = 0;
+ surface->entries_capacity = 0;
+ surface->buffer_socket = buffer_socket;
+ surface->width = width;
+ surface->height = height;
+ surface->format = format;
+ surface->flags = flags;
+
+ return &surface->base;
+}
+
+pixman_region32_t * surface_damage(struct wld_surface * base,
+ pixman_region32_t * new_damage)
+{
+ struct buffered_surface * surface = buffered_surface(base);
+ struct buffer * back_buffer;
+ unsigned index;
+
+ if (pixman_region32_not_empty(new_damage))
+ {
+ for (index = 0; index < surface->entries_size; ++index)
+ {
+ pixman_region32_union(&surface->entries[index].buffer->base.damage,
+ &surface->entries[index].buffer->base.damage,
+ new_damage);
+ }
+ }
+
+ if (!(back_buffer = surface_back(base)))
+ return NULL;
+
+ return &back_buffer->base.damage;
+}
+
+struct buffer * surface_back(struct wld_surface * base)
+{
+ struct buffered_surface * surface = buffered_surface(base);
+ unsigned index;
+
+ if (surface->back)
+ return surface->back->buffer;
+
+ /* The buffer socket may need to process any incoming buffer releases. */
+ if (surface->buffer_socket)
+ surface->buffer_socket->impl->process(surface->buffer_socket);
+
+ for (index = 0; index < surface->entries_size; ++index)
+ {
+ if (!surface->entries[index].busy)
+ {
+ surface->back = &surface->entries[index];
+ return surface->back->buffer;
+ }
+ }
+
+ /* If there are no free buffers, we need to allocate another one. */
+ struct buffer * buffer;
+
+ buffer = surface->context->impl->create_buffer
+ (surface->context, surface->width, surface->height,
+ surface->format, surface->flags);
+
+ if (!buffer)
+ goto error0;
+
+ if (surface->entries_size == surface->entries_capacity)
+ {
+ struct buffer_entry * new_entries;
+ size_t new_capacity = surface->entries_capacity * 2 + 1;
+
+ new_entries = realloc(surface->entries,
+ new_capacity * sizeof surface->entries[0]);
+
+ if (!new_entries)
+ goto error1;
+
+ surface->entries = new_entries;
+ surface->entries_capacity = new_capacity;
+ }
+
+ surface->back = &surface->entries[surface->entries_size++];
+ *surface->back = (struct buffer_entry) {
+ .buffer = buffer,
+ .busy = false
+ };
+
+ return buffer;
+
+ error1:
+ wld_buffer_unreference(&buffer->base);
+ error0:
+ return NULL;
+}
+
+struct buffer * surface_take(struct wld_surface * base)
+{
+ struct buffered_surface * surface = buffered_surface(base);
+ struct buffer * buffer;
+
+ if (!(buffer = surface_back(base)))
+ return NULL;
+
+ surface->back->busy = true;
+ surface->back = NULL;
+ pixman_region32_clear(&buffer->base.damage);
+
+ return buffer;
+}
+
+bool surface_release(struct wld_surface * base, struct buffer * buffer)
+{
+ struct buffered_surface * surface = buffered_surface(base);
+ unsigned index;
+
+ for (index = 0; index < surface->entries_size; ++index)
+ {
+ if (surface->entries[index].buffer == buffer)
+ {
+ surface->entries[index].busy = false;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool surface_swap(struct wld_surface * base)
+{
+ struct buffered_surface * surface = buffered_surface(base);
+ struct buffer * buffer;
+
+ if (!surface->buffer_socket)
+ return false;
+
+ if (!(buffer = surface_back(base)))
+ return false;
+
+ if (!surface->buffer_socket->impl->attach(surface->buffer_socket, buffer))
+ return false;
+
+ surface->back->busy = true;
+ surface->back = NULL;
+ pixman_region32_clear(&buffer->base.damage);
+
+ return true;
+}
+
+void surface_destroy(struct wld_surface * base)
+{
+ struct buffered_surface * surface = buffered_surface(base);
+ unsigned index;
+
+ if (surface->buffer_socket)
+ surface->buffer_socket->impl->destroy(surface->buffer_socket);
+
+ for (index = 0; index < surface->entries_size; ++index)
+ wld_buffer_unreference(&surface->entries[index].buffer->base);
+
+ free(surface->entries);
+ free(surface);
+}
+
diff --git a/src/wld/color.c b/src/wld/color.c
new file mode 100644
index 0000000..88e791a
--- /dev/null
+++ b/src/wld/color.c
@@ -0,0 +1,850 @@
+/* Adapted from xorg-server */
+
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#include "wld-private.h"
+
+#include <strings.h>
+
+struct named_color
+{
+ const char * name;
+ uint32_t color;
+};
+
+static const struct named_color named_colors[] = {
+ { "alice blue", 0xfff0f8ff },
+ { "AliceBlue", 0xfff0f8ff },
+ { "antique white", 0xfffaebd7 },
+ { "AntiqueWhite", 0xfffaebd7 },
+ { "AntiqueWhite1", 0xffffefdb },
+ { "AntiqueWhite2", 0xffeedfcc },
+ { "AntiqueWhite3", 0xffcdc0b0 },
+ { "AntiqueWhite4", 0xff8b8378 },
+ { "aquamarine", 0xff7fffd4 },
+ { "aquamarine1", 0xff7fffd4 },
+ { "aquamarine2", 0xff76eec6 },
+ { "aquamarine3", 0xff66cdaa },
+ { "aquamarine4", 0xff458b74 },
+ { "azure", 0xfff0ffff },
+ { "azure1", 0xfff0ffff },
+ { "azure2", 0xffe0eeee },
+ { "azure3", 0xffc1cdcd },
+ { "azure4", 0xff838b8b },
+ { "beige", 0xfff5f5dc },
+ { "bisque", 0xffffe4c4 },
+ { "bisque1", 0xffffe4c4 },
+ { "bisque2", 0xffeed5b7 },
+ { "bisque3", 0xffcdb79e },
+ { "bisque4", 0xff8b7d6b },
+ { "black", 0xff000000 },
+ { "blanched almond", 0xffffebcd },
+ { "BlanchedAlmond", 0xffffebcd },
+ { "blue", 0xff0000ff },
+ { "blue violet", 0xff8a2be2 },
+ { "blue1", 0xff0000ff },
+ { "blue2", 0xff0000ee },
+ { "blue3", 0xff0000cd },
+ { "blue4", 0xff00008b },
+ { "BlueViolet", 0xff8a2be2 },
+ { "brown", 0xffa52a2a },
+ { "brown1", 0xffff4040 },
+ { "brown2", 0xffee3b3b },
+ { "brown3", 0xffcd3333 },
+ { "brown4", 0xff8b2323 },
+ { "burlywood", 0xffdeb887 },
+ { "burlywood1", 0xffffd39b },
+ { "burlywood2", 0xffeec591 },
+ { "burlywood3", 0xffcdaa7d },
+ { "burlywood4", 0xff8b7355 },
+ { "cadet blue", 0xff5f9ea0 },
+ { "CadetBlue", 0xff5f9ea0 },
+ { "CadetBlue1", 0xff98f5ff },
+ { "CadetBlue2", 0xff8ee5ee },
+ { "CadetBlue3", 0xff7ac5cd },
+ { "CadetBlue4", 0xff53868b },
+ { "chartreuse", 0xff7fff00 },
+ { "chartreuse1", 0xff7fff00 },
+ { "chartreuse2", 0xff76ee00 },
+ { "chartreuse3", 0xff66cd00 },
+ { "chartreuse4", 0xff458b00 },
+ { "chocolate", 0xffd2691e },
+ { "chocolate1", 0xffff7f24 },
+ { "chocolate2", 0xffee7621 },
+ { "chocolate3", 0xffcd661d },
+ { "chocolate4", 0xff8b4513 },
+ { "coral", 0xffff7f50 },
+ { "coral1", 0xffff7256 },
+ { "coral2", 0xffee6a50 },
+ { "coral3", 0xffcd5b45 },
+ { "coral4", 0xff8b3e2f },
+ { "cornflower blue", 0xff6495ed },
+ { "CornflowerBlue", 0xff6495ed },
+ { "cornsilk", 0xfffff8dc },
+ { "cornsilk1", 0xfffff8dc },
+ { "cornsilk2", 0xffeee8cd },
+ { "cornsilk3", 0xffcdc8b1 },
+ { "cornsilk4", 0xff8b8878 },
+ { "cyan", 0xff00ffff },
+ { "cyan1", 0xff00ffff },
+ { "cyan2", 0xff00eeee },
+ { "cyan3", 0xff00cdcd },
+ { "cyan4", 0xff008b8b },
+ { "dark blue", 0xff00008b },
+ { "dark cyan", 0xff008b8b },
+ { "dark goldenrod", 0xffb8860b },
+ { "dark gray", 0xffa9a9a9 },
+ { "dark green", 0xff006400 },
+ { "dark grey", 0xffa9a9a9 },
+ { "dark khaki", 0xffbdb76b },
+ { "dark magenta", 0xff8b008b },
+ { "dark olive green", 0xff556b2f },
+ { "dark orange", 0xffff8c00 },
+ { "dark orchid", 0xff9932cc },
+ { "dark red", 0xff8b0000 },
+ { "dark salmon", 0xffe9967a },
+ { "dark sea green", 0xff8fbc8f },
+ { "dark slate blue", 0xff483d8b },
+ { "dark slate gray", 0xff2f4f4f },
+ { "dark slate grey", 0xff2f4f4f },
+ { "dark turquoise", 0xff00ced1 },
+ { "dark violet", 0xff9400d3 },
+ { "DarkBlue", 0xff00008b },
+ { "DarkCyan", 0xff008b8b },
+ { "DarkGoldenrod", 0xffb8860b },
+ { "DarkGoldenrod1", 0xffffb90f },
+ { "DarkGoldenrod2", 0xffeead0e },
+ { "DarkGoldenrod3", 0xffcd950c },
+ { "DarkGoldenrod4", 0xff8b6508 },
+ { "DarkGray", 0xffa9a9a9 },
+ { "DarkGreen", 0xff006400 },
+ { "DarkGrey", 0xffa9a9a9 },
+ { "DarkKhaki", 0xffbdb76b },
+ { "DarkMagenta", 0xff8b008b },
+ { "DarkOliveGreen", 0xff556b2f },
+ { "DarkOliveGreen1", 0xffcaff70 },
+ { "DarkOliveGreen2", 0xffbcee68 },
+ { "DarkOliveGreen3", 0xffa2cd5a },
+ { "DarkOliveGreen4", 0xff6e8b3d },
+ { "DarkOrange", 0xffff8c00 },
+ { "DarkOrange1", 0xffff7f00 },
+ { "DarkOrange2", 0xffee7600 },
+ { "DarkOrange3", 0xffcd6600 },
+ { "DarkOrange4", 0xff8b4500 },
+ { "DarkOrchid", 0xff9932cc },
+ { "DarkOrchid1", 0xffbf3eff },
+ { "DarkOrchid2", 0xffb23aee },
+ { "DarkOrchid3", 0xff9a32cd },
+ { "DarkOrchid4", 0xff68228b },
+ { "DarkRed", 0xff8b0000 },
+ { "DarkSalmon", 0xffe9967a },
+ { "DarkSeaGreen", 0xff8fbc8f },
+ { "DarkSeaGreen1", 0xffc1ffc1 },
+ { "DarkSeaGreen2", 0xffb4eeb4 },
+ { "DarkSeaGreen3", 0xff9bcd9b },
+ { "DarkSeaGreen4", 0xff698b69 },
+ { "DarkSlateBlue", 0xff483d8b },
+ { "DarkSlateGray", 0xff2f4f4f },
+ { "DarkSlateGray1", 0xff97ffff },
+ { "DarkSlateGray2", 0xff8deeee },
+ { "DarkSlateGray3", 0xff79cdcd },
+ { "DarkSlateGray4", 0xff528b8b },
+ { "DarkSlateGrey", 0xff2f4f4f },
+ { "DarkTurquoise", 0xff00ced1 },
+ { "DarkViolet", 0xff9400d3 },
+ { "deep pink", 0xffff1493 },
+ { "deep sky blue", 0xff00bfff },
+ { "DeepPink", 0xffff1493 },
+ { "DeepPink1", 0xffff1493 },
+ { "DeepPink2", 0xffee1289 },
+ { "DeepPink3", 0xffcd1076 },
+ { "DeepPink4", 0xff8b0a50 },
+ { "DeepSkyBlue", 0xff00bfff },
+ { "DeepSkyBlue1", 0xff00bfff },
+ { "DeepSkyBlue2", 0xff00b2ee },
+ { "DeepSkyBlue3", 0xff009acd },
+ { "DeepSkyBlue4", 0xff00688b },
+ { "dim gray", 0xff696969 },
+ { "dim grey", 0xff696969 },
+ { "DimGray", 0xff696969 },
+ { "DimGrey", 0xff696969 },
+ { "dodger blue", 0xff1e90ff },
+ { "DodgerBlue", 0xff1e90ff },
+ { "DodgerBlue1", 0xff1e90ff },
+ { "DodgerBlue2", 0xff1c86ee },
+ { "DodgerBlue3", 0xff1874cd },
+ { "DodgerBlue4", 0xff104e8b },
+ { "firebrick", 0xffb22222 },
+ { "firebrick1", 0xffff3030 },
+ { "firebrick2", 0xffee2c2c },
+ { "firebrick3", 0xffcd2626 },
+ { "firebrick4", 0xff8b1a1a },
+ { "floral white", 0xfffffaf0 },
+ { "FloralWhite", 0xfffffaf0 },
+ { "forest green", 0xff228b22 },
+ { "ForestGreen", 0xff228b22 },
+ { "gainsboro", 0xffdcdcdc },
+ { "ghost white", 0xfff8f8ff },
+ { "GhostWhite", 0xfff8f8ff },
+ { "gold", 0xffffd700 },
+ { "gold1", 0xffffd700 },
+ { "gold2", 0xffeec900 },
+ { "gold3", 0xffcdad00 },
+ { "gold4", 0xff8b7500 },
+ { "goldenrod", 0xffdaa520 },
+ { "goldenrod1", 0xffffc125 },
+ { "goldenrod2", 0xffeeb422 },
+ { "goldenrod3", 0xffcd9b1d },
+ { "goldenrod4", 0xff8b6914 },
+ { "gray", 0xffbebebe },
+ { "gray0", 0xff000000 },
+ { "gray1", 0xff030303 },
+ { "gray10", 0xff1a1a1a },
+ { "gray100", 0xffffffff },
+ { "gray11", 0xff1c1c1c },
+ { "gray12", 0xff1f1f1f },
+ { "gray13", 0xff212121 },
+ { "gray14", 0xff242424 },
+ { "gray15", 0xff262626 },
+ { "gray16", 0xff292929 },
+ { "gray17", 0xff2b2b2b },
+ { "gray18", 0xff2e2e2e },
+ { "gray19", 0xff303030 },
+ { "gray2", 0xff050505 },
+ { "gray20", 0xff333333 },
+ { "gray21", 0xff363636 },
+ { "gray22", 0xff383838 },
+ { "gray23", 0xff3b3b3b },
+ { "gray24", 0xff3d3d3d },
+ { "gray25", 0xff404040 },
+ { "gray26", 0xff424242 },
+ { "gray27", 0xff454545 },
+ { "gray28", 0xff474747 },
+ { "gray29", 0xff4a4a4a },
+ { "gray3", 0xff080808 },
+ { "gray30", 0xff4d4d4d },
+ { "gray31", 0xff4f4f4f },
+ { "gray32", 0xff525252 },
+ { "gray33", 0xff545454 },
+ { "gray34", 0xff575757 },
+ { "gray35", 0xff595959 },
+ { "gray36", 0xff5c5c5c },
+ { "gray37", 0xff5e5e5e },
+ { "gray38", 0xff616161 },
+ { "gray39", 0xff636363 },
+ { "gray4", 0xff0a0a0a },
+ { "gray40", 0xff666666 },
+ { "gray41", 0xff696969 },
+ { "gray42", 0xff6b6b6b },
+ { "gray43", 0xff6e6e6e },
+ { "gray44", 0xff707070 },
+ { "gray45", 0xff737373 },
+ { "gray46", 0xff757575 },
+ { "gray47", 0xff787878 },
+ { "gray48", 0xff7a7a7a },
+ { "gray49", 0xff7d7d7d },
+ { "gray5", 0xff0d0d0d },
+ { "gray50", 0xff7f7f7f },
+ { "gray51", 0xff828282 },
+ { "gray52", 0xff858585 },
+ { "gray53", 0xff878787 },
+ { "gray54", 0xff8a8a8a },
+ { "gray55", 0xff8c8c8c },
+ { "gray56", 0xff8f8f8f },
+ { "gray57", 0xff919191 },
+ { "gray58", 0xff949494 },
+ { "gray59", 0xff969696 },
+ { "gray6", 0xff0f0f0f },
+ { "gray60", 0xff999999 },
+ { "gray61", 0xff9c9c9c },
+ { "gray62", 0xff9e9e9e },
+ { "gray63", 0xffa1a1a1 },
+ { "gray64", 0xffa3a3a3 },
+ { "gray65", 0xffa6a6a6 },
+ { "gray66", 0xffa8a8a8 },
+ { "gray67", 0xffababab },
+ { "gray68", 0xffadadad },
+ { "gray69", 0xffb0b0b0 },
+ { "gray7", 0xff121212 },
+ { "gray70", 0xffb3b3b3 },
+ { "gray71", 0xffb5b5b5 },
+ { "gray72", 0xffb8b8b8 },
+ { "gray73", 0xffbababa },
+ { "gray74", 0xffbdbdbd },
+ { "gray75", 0xffbfbfbf },
+ { "gray76", 0xffc2c2c2 },
+ { "gray77", 0xffc4c4c4 },
+ { "gray78", 0xffc7c7c7 },
+ { "gray79", 0xffc9c9c9 },
+ { "gray8", 0xff141414 },
+ { "gray80", 0xffcccccc },
+ { "gray81", 0xffcfcfcf },
+ { "gray82", 0xffd1d1d1 },
+ { "gray83", 0xffd4d4d4 },
+ { "gray84", 0xffd6d6d6 },
+ { "gray85", 0xffd9d9d9 },
+ { "gray86", 0xffdbdbdb },
+ { "gray87", 0xffdedede },
+ { "gray88", 0xffe0e0e0 },
+ { "gray89", 0xffe3e3e3 },
+ { "gray9", 0xff171717 },
+ { "gray90", 0xffe5e5e5 },
+ { "gray91", 0xffe8e8e8 },
+ { "gray92", 0xffebebeb },
+ { "gray93", 0xffededed },
+ { "gray94", 0xfff0f0f0 },
+ { "gray95", 0xfff2f2f2 },
+ { "gray96", 0xfff5f5f5 },
+ { "gray97", 0xfff7f7f7 },
+ { "gray98", 0xfffafafa },
+ { "gray99", 0xfffcfcfc },
+ { "green", 0xff00ff00 },
+ { "green yellow", 0xffadff2f },
+ { "green1", 0xff00ff00 },
+ { "green2", 0xff00ee00 },
+ { "green3", 0xff00cd00 },
+ { "green4", 0xff008b00 },
+ { "GreenYellow", 0xffadff2f },
+ { "grey", 0xffbebebe },
+ { "grey0", 0xff000000 },
+ { "grey1", 0xff030303 },
+ { "grey10", 0xff1a1a1a },
+ { "grey100", 0xffffffff },
+ { "grey11", 0xff1c1c1c },
+ { "grey12", 0xff1f1f1f },
+ { "grey13", 0xff212121 },
+ { "grey14", 0xff242424 },
+ { "grey15", 0xff262626 },
+ { "grey16", 0xff292929 },
+ { "grey17", 0xff2b2b2b },
+ { "grey18", 0xff2e2e2e },
+ { "grey19", 0xff303030 },
+ { "grey2", 0xff050505 },
+ { "grey20", 0xff333333 },
+ { "grey21", 0xff363636 },
+ { "grey22", 0xff383838 },
+ { "grey23", 0xff3b3b3b },
+ { "grey24", 0xff3d3d3d },
+ { "grey25", 0xff404040 },
+ { "grey26", 0xff424242 },
+ { "grey27", 0xff454545 },
+ { "grey28", 0xff474747 },
+ { "grey29", 0xff4a4a4a },
+ { "grey3", 0xff080808 },
+ { "grey30", 0xff4d4d4d },
+ { "grey31", 0xff4f4f4f },
+ { "grey32", 0xff525252 },
+ { "grey33", 0xff545454 },
+ { "grey34", 0xff575757 },
+ { "grey35", 0xff595959 },
+ { "grey36", 0xff5c5c5c },
+ { "grey37", 0xff5e5e5e },
+ { "grey38", 0xff616161 },
+ { "grey39", 0xff636363 },
+ { "grey4", 0xff0a0a0a },
+ { "grey40", 0xff666666 },
+ { "grey41", 0xff696969 },
+ { "grey42", 0xff6b6b6b },
+ { "grey43", 0xff6e6e6e },
+ { "grey44", 0xff707070 },
+ { "grey45", 0xff737373 },
+ { "grey46", 0xff757575 },
+ { "grey47", 0xff787878 },
+ { "grey48", 0xff7a7a7a },
+ { "grey49", 0xff7d7d7d },
+ { "grey5", 0xff0d0d0d },
+ { "grey50", 0xff7f7f7f },
+ { "grey51", 0xff828282 },
+ { "grey52", 0xff858585 },
+ { "grey53", 0xff878787 },
+ { "grey54", 0xff8a8a8a },
+ { "grey55", 0xff8c8c8c },
+ { "grey56", 0xff8f8f8f },
+ { "grey57", 0xff919191 },
+ { "grey58", 0xff949494 },
+ { "grey59", 0xff969696 },
+ { "grey6", 0xff0f0f0f },
+ { "grey60", 0xff999999 },
+ { "grey61", 0xff9c9c9c },
+ { "grey62", 0xff9e9e9e },
+ { "grey63", 0xffa1a1a1 },
+ { "grey64", 0xffa3a3a3 },
+ { "grey65", 0xffa6a6a6 },
+ { "grey66", 0xffa8a8a8 },
+ { "grey67", 0xffababab },
+ { "grey68", 0xffadadad },
+ { "grey69", 0xffb0b0b0 },
+ { "grey7", 0xff121212 },
+ { "grey70", 0xffb3b3b3 },
+ { "grey71", 0xffb5b5b5 },
+ { "grey72", 0xffb8b8b8 },
+ { "grey73", 0xffbababa },
+ { "grey74", 0xffbdbdbd },
+ { "grey75", 0xffbfbfbf },
+ { "grey76", 0xffc2c2c2 },
+ { "grey77", 0xffc4c4c4 },
+ { "grey78", 0xffc7c7c7 },
+ { "grey79", 0xffc9c9c9 },
+ { "grey8", 0xff141414 },
+ { "grey80", 0xffcccccc },
+ { "grey81", 0xffcfcfcf },
+ { "grey82", 0xffd1d1d1 },
+ { "grey83", 0xffd4d4d4 },
+ { "grey84", 0xffd6d6d6 },
+ { "grey85", 0xffd9d9d9 },
+ { "grey86", 0xffdbdbdb },
+ { "grey87", 0xffdedede },
+ { "grey88", 0xffe0e0e0 },
+ { "grey89", 0xffe3e3e3 },
+ { "grey9", 0xff171717 },
+ { "grey90", 0xffe5e5e5 },
+ { "grey91", 0xffe8e8e8 },
+ { "grey92", 0xffebebeb },
+ { "grey93", 0xffededed },
+ { "grey94", 0xfff0f0f0 },
+ { "grey95", 0xfff2f2f2 },
+ { "grey96", 0xfff5f5f5 },
+ { "grey97", 0xfff7f7f7 },
+ { "grey98", 0xfffafafa },
+ { "grey99", 0xfffcfcfc },
+ { "honeydew", 0xfff0fff0 },
+ { "honeydew1", 0xfff0fff0 },
+ { "honeydew2", 0xffe0eee0 },
+ { "honeydew3", 0xffc1cdc1 },
+ { "honeydew4", 0xff838b83 },
+ { "hot pink", 0xffff69b4 },
+ { "HotPink", 0xffff69b4 },
+ { "HotPink1", 0xffff6eb4 },
+ { "HotPink2", 0xffee6aa7 },
+ { "HotPink3", 0xffcd6090 },
+ { "HotPink4", 0xff8b3a62 },
+ { "indian red", 0xffcd5c5c },
+ { "IndianRed", 0xffcd5c5c },
+ { "IndianRed1", 0xffff6a6a },
+ { "IndianRed2", 0xffee6363 },
+ { "IndianRed3", 0xffcd5555 },
+ { "IndianRed4", 0xff8b3a3a },
+ { "ivory", 0xfffffff0 },
+ { "ivory1", 0xfffffff0 },
+ { "ivory2", 0xffeeeee0 },
+ { "ivory3", 0xffcdcdc1 },
+ { "ivory4", 0xff8b8b83 },
+ { "khaki", 0xfff0e68c },
+ { "khaki1", 0xfffff68f },
+ { "khaki2", 0xffeee685 },
+ { "khaki3", 0xffcdc673 },
+ { "khaki4", 0xff8b864e },
+ { "lavender", 0xffe6e6fa },
+ { "lavender blush", 0xfffff0f5 },
+ { "LavenderBlush", 0xfffff0f5 },
+ { "LavenderBlush1", 0xfffff0f5 },
+ { "LavenderBlush2", 0xffeee0e5 },
+ { "LavenderBlush3", 0xffcdc1c5 },
+ { "LavenderBlush4", 0xff8b8386 },
+ { "lawn green", 0xff7cfc00 },
+ { "LawnGreen", 0xff7cfc00 },
+ { "lemon chiffon", 0xfffffacd },
+ { "LemonChiffon", 0xfffffacd },
+ { "LemonChiffon1", 0xfffffacd },
+ { "LemonChiffon2", 0xffeee9bf },
+ { "LemonChiffon3", 0xffcdc9a5 },
+ { "LemonChiffon4", 0xff8b8970 },
+ { "light blue", 0xffadd8e6 },
+ { "light coral", 0xfff08080 },
+ { "light cyan", 0xffe0ffff },
+ { "light goldenrod", 0xffeedd82 },
+ { "light goldenrod yellow", 0xfffafad2 },
+ { "light gray", 0xffd3d3d3 },
+ { "light green", 0xff90ee90 },
+ { "light grey", 0xffd3d3d3 },
+ { "light pink", 0xffffb6c1 },
+ { "light salmon", 0xffffa07a },
+ { "light sea green", 0xff20b2aa },
+ { "light sky blue", 0xff87cefa },
+ { "light slate blue", 0xff8470ff },
+ { "light slate gray", 0xff778899 },
+ { "light slate grey", 0xff778899 },
+ { "light steel blue", 0xffb0c4de },
+ { "light yellow", 0xffffffe0 },
+ { "LightBlue", 0xffadd8e6 },
+ { "LightBlue1", 0xffbfefff },
+ { "LightBlue2", 0xffb2dfee },
+ { "LightBlue3", 0xff9ac0cd },
+ { "LightBlue4", 0xff68838b },
+ { "LightCoral", 0xfff08080 },
+ { "LightCyan", 0xffe0ffff },
+ { "LightCyan1", 0xffe0ffff },
+ { "LightCyan2", 0xffd1eeee },
+ { "LightCyan3", 0xffb4cdcd },
+ { "LightCyan4", 0xff7a8b8b },
+ { "LightGoldenrod", 0xffeedd82 },
+ { "LightGoldenrod1", 0xffffec8b },
+ { "LightGoldenrod2", 0xffeedc82 },
+ { "LightGoldenrod3", 0xffcdbe70 },
+ { "LightGoldenrod4", 0xff8b814c },
+ { "LightGoldenrodYellow", 0xfffafad2 },
+ { "LightGray", 0xffd3d3d3 },
+ { "LightGreen", 0xff90ee90 },
+ { "LightGrey", 0xffd3d3d3 },
+ { "LightPink", 0xffffb6c1 },
+ { "LightPink1", 0xffffaeb9 },
+ { "LightPink2", 0xffeea2ad },
+ { "LightPink3", 0xffcd8c95 },
+ { "LightPink4", 0xff8b5f65 },
+ { "LightSalmon", 0xffffa07a },
+ { "LightSalmon1", 0xffffa07a },
+ { "LightSalmon2", 0xffee9572 },
+ { "LightSalmon3", 0xffcd8162 },
+ { "LightSalmon4", 0xff8b5742 },
+ { "LightSeaGreen", 0xff20b2aa },
+ { "LightSkyBlue", 0xff87cefa },
+ { "LightSkyBlue1", 0xffb0e2ff },
+ { "LightSkyBlue2", 0xffa4d3ee },
+ { "LightSkyBlue3", 0xff8db6cd },
+ { "LightSkyBlue4", 0xff607b8b },
+ { "LightSlateBlue", 0xff8470ff },
+ { "LightSlateGray", 0xff778899 },
+ { "LightSlateGrey", 0xff778899 },
+ { "LightSteelBlue", 0xffb0c4de },
+ { "LightSteelBlue1", 0xffcae1ff },
+ { "LightSteelBlue2", 0xffbcd2ee },
+ { "LightSteelBlue3", 0xffa2b5cd },
+ { "LightSteelBlue4", 0xff6e7b8b },
+ { "LightYellow", 0xffffffe0 },
+ { "LightYellow1", 0xffffffe0 },
+ { "LightYellow2", 0xffeeeed1 },
+ { "LightYellow3", 0xffcdcdb4 },
+ { "LightYellow4", 0xff8b8b7a },
+ { "lime green", 0xff32cd32 },
+ { "LimeGreen", 0xff32cd32 },
+ { "linen", 0xfffaf0e6 },
+ { "magenta", 0xffff00ff },
+ { "magenta1", 0xffff00ff },
+ { "magenta2", 0xffee00ee },
+ { "magenta3", 0xffcd00cd },
+ { "magenta4", 0xff8b008b },
+ { "maroon", 0xffb03060 },
+ { "maroon1", 0xffff34b3 },
+ { "maroon2", 0xffee30a7 },
+ { "maroon3", 0xffcd2990 },
+ { "maroon4", 0xff8b1c62 },
+ { "medium aquamarine", 0xff66cdaa },
+ { "medium blue", 0xff0000cd },
+ { "medium orchid", 0xffba55d3 },
+ { "medium purple", 0xff9370db },
+ { "medium sea green", 0xff3cb371 },
+ { "medium slate blue", 0xff7b68ee },
+ { "medium spring green", 0xff00fa9a },
+ { "medium turquoise", 0xff48d1cc },
+ { "medium violet red", 0xffc71585 },
+ { "MediumAquamarine", 0xff66cdaa },
+ { "MediumBlue", 0xff0000cd },
+ { "MediumOrchid", 0xffba55d3 },
+ { "MediumOrchid1", 0xffe066ff },
+ { "MediumOrchid2", 0xffd15fee },
+ { "MediumOrchid3", 0xffb452cd },
+ { "MediumOrchid4", 0xff7a378b },
+ { "MediumPurple", 0xff9370db },
+ { "MediumPurple1", 0xffab82ff },
+ { "MediumPurple2", 0xff9f79ee },
+ { "MediumPurple3", 0xff8968cd },
+ { "MediumPurple4", 0xff5d478b },
+ { "MediumSeaGreen", 0xff3cb371 },
+ { "MediumSlateBlue", 0xff7b68ee },
+ { "MediumSpringGreen", 0xff00fa9a },
+ { "MediumTurquoise", 0xff48d1cc },
+ { "MediumVioletRed", 0xffc71585 },
+ { "midnight blue", 0xff191970 },
+ { "MidnightBlue", 0xff191970 },
+ { "mint cream", 0xfff5fffa },
+ { "MintCream", 0xfff5fffa },
+ { "misty rose", 0xffffe4e1 },
+ { "MistyRose", 0xffffe4e1 },
+ { "MistyRose1", 0xffffe4e1 },
+ { "MistyRose2", 0xffeed5d2 },
+ { "MistyRose3", 0xffcdb7b5 },
+ { "MistyRose4", 0xff8b7d7b },
+ { "moccasin", 0xffffe4b5 },
+ { "navajo white", 0xffffdead },
+ { "NavajoWhite", 0xffffdead },
+ { "NavajoWhite1", 0xffffdead },
+ { "NavajoWhite2", 0xffeecfa1 },
+ { "NavajoWhite3", 0xffcdb38b },
+ { "NavajoWhite4", 0xff8b795e },
+ { "navy", 0xff000080 },
+ { "navy blue", 0xff000080 },
+ { "NavyBlue", 0xff000080 },
+ { "old lace", 0xfffdf5e6 },
+ { "OldLace", 0xfffdf5e6 },
+ { "olive drab", 0xff6b8e23 },
+ { "OliveDrab", 0xff6b8e23 },
+ { "OliveDrab1", 0xffc0ff3e },
+ { "OliveDrab2", 0xffb3ee3a },
+ { "OliveDrab3", 0xff9acd32 },
+ { "OliveDrab4", 0xff698b22 },
+ { "orange", 0xffffa500 },
+ { "orange red", 0xffff4500 },
+ { "orange1", 0xffffa500 },
+ { "orange2", 0xffee9a00 },
+ { "orange3", 0xffcd8500 },
+ { "orange4", 0xff8b5a00 },
+ { "OrangeRed", 0xffff4500 },
+ { "OrangeRed1", 0xffff4500 },
+ { "OrangeRed2", 0xffee4000 },
+ { "OrangeRed3", 0xffcd3700 },
+ { "OrangeRed4", 0xff8b2500 },
+ { "orchid", 0xffda70d6 },
+ { "orchid1", 0xffff83fa },
+ { "orchid2", 0xffee7ae9 },
+ { "orchid3", 0xffcd69c9 },
+ { "orchid4", 0xff8b4789 },
+ { "pale goldenrod", 0xffeee8aa },
+ { "pale green", 0xff98fb98 },
+ { "pale turquoise", 0xffafeeee },
+ { "pale violet red", 0xffdb7093 },
+ { "PaleGoldenrod", 0xffeee8aa },
+ { "PaleGreen", 0xff98fb98 },
+ { "PaleGreen1", 0xff9aff9a },
+ { "PaleGreen2", 0xff90ee90 },
+ { "PaleGreen3", 0xff7ccd7c },
+ { "PaleGreen4", 0xff548b54 },
+ { "PaleTurquoise", 0xffafeeee },
+ { "PaleTurquoise1", 0xffbbffff },
+ { "PaleTurquoise2", 0xffaeeeee },
+ { "PaleTurquoise3", 0xff96cdcd },
+ { "PaleTurquoise4", 0xff668b8b },
+ { "PaleVioletRed", 0xffdb7093 },
+ { "PaleVioletRed1", 0xffff82ab },
+ { "PaleVioletRed2", 0xffee799f },
+ { "PaleVioletRed3", 0xffcd6889 },
+ { "PaleVioletRed4", 0xff8b475d },
+ { "papaya whip", 0xffffefd5 },
+ { "PapayaWhip", 0xffffefd5 },
+ { "peach puff", 0xffffdab9 },
+ { "PeachPuff", 0xffffdab9 },
+ { "PeachPuff1", 0xffffdab9 },
+ { "PeachPuff2", 0xffeecbad },
+ { "PeachPuff3", 0xffcdaf95 },
+ { "PeachPuff4", 0xff8b7765 },
+ { "peru", 0xffcd853f },
+ { "pink", 0xffffc0cb },
+ { "pink1", 0xffffb5c5 },
+ { "pink2", 0xffeea9b8 },
+ { "pink3", 0xffcd919e },
+ { "pink4", 0xff8b636c },
+ { "plum", 0xffdda0dd },
+ { "plum1", 0xffffbbff },
+ { "plum2", 0xffeeaeee },
+ { "plum3", 0xffcd96cd },
+ { "plum4", 0xff8b668b },
+ { "powder blue", 0xffb0e0e6 },
+ { "PowderBlue", 0xffb0e0e6 },
+ { "purple", 0xffa020f0 },
+ { "purple1", 0xff9b30ff },
+ { "purple2", 0xff912cee },
+ { "purple3", 0xff7d26cd },
+ { "purple4", 0xff551a8b },
+ { "red", 0xffff0000 },
+ { "red1", 0xffff0000 },
+ { "red2", 0xffee0000 },
+ { "red3", 0xffcd0000 },
+ { "red4", 0xff8b0000 },
+ { "rosy brown", 0xffbc8f8f },
+ { "RosyBrown", 0xffbc8f8f },
+ { "RosyBrown1", 0xffffc1c1 },
+ { "RosyBrown2", 0xffeeb4b4 },
+ { "RosyBrown3", 0xffcd9b9b },
+ { "RosyBrown4", 0xff8b6969 },
+ { "royal blue", 0xff4169e1 },
+ { "RoyalBlue", 0xff4169e1 },
+ { "RoyalBlue1", 0xff4876ff },
+ { "RoyalBlue2", 0xff436eee },
+ { "RoyalBlue3", 0xff3a5fcd },
+ { "RoyalBlue4", 0xff27408b },
+ { "saddle brown", 0xff8b4513 },
+ { "SaddleBrown", 0xff8b4513 },
+ { "salmon", 0xfffa8072 },
+ { "salmon1", 0xffff8c69 },
+ { "salmon2", 0xffee8262 },
+ { "salmon3", 0xffcd7054 },
+ { "salmon4", 0xff8b4c39 },
+ { "sandy brown", 0xfff4a460 },
+ { "SandyBrown", 0xfff4a460 },
+ { "sea green", 0xff2e8b57 },
+ { "SeaGreen", 0xff2e8b57 },
+ { "SeaGreen1", 0xff54ff9f },
+ { "SeaGreen2", 0xff4eee94 },
+ { "SeaGreen3", 0xff43cd80 },
+ { "SeaGreen4", 0xff2e8b57 },
+ { "seashell", 0xfffff5ee },
+ { "seashell1", 0xfffff5ee },
+ { "seashell2", 0xffeee5de },
+ { "seashell3", 0xffcdc5bf },
+ { "seashell4", 0xff8b8682 },
+ { "sienna", 0xffa0522d },
+ { "sienna1", 0xffff8247 },
+ { "sienna2", 0xffee7942 },
+ { "sienna3", 0xffcd6839 },
+ { "sienna4", 0xff8b4726 },
+ { "sky blue", 0xff87ceeb },
+ { "SkyBlue", 0xff87ceeb },
+ { "SkyBlue1", 0xff87ceff },
+ { "SkyBlue2", 0xff7ec0ee },
+ { "SkyBlue3", 0xff6ca6cd },
+ { "SkyBlue4", 0xff4a708b },
+ { "slate blue", 0xff6a5acd },
+ { "slate gray", 0xff708090 },
+ { "slate grey", 0xff708090 },
+ { "SlateBlue", 0xff6a5acd },
+ { "SlateBlue1", 0xff836fff },
+ { "SlateBlue2", 0xff7a67ee },
+ { "SlateBlue3", 0xff6959cd },
+ { "SlateBlue4", 0xff473c8b },
+ { "SlateGray", 0xff708090 },
+ { "SlateGray1", 0xffc6e2ff },
+ { "SlateGray2", 0xffb9d3ee },
+ { "SlateGray3", 0xff9fb6cd },
+ { "SlateGray4", 0xff6c7b8b },
+ { "SlateGrey", 0xff708090 },
+ { "snow", 0xfffffafa },
+ { "snow1", 0xfffffafa },
+ { "snow2", 0xffeee9e9 },
+ { "snow3", 0xffcdc9c9 },
+ { "snow4", 0xff8b8989 },
+ { "spring green", 0xff00ff7f },
+ { "SpringGreen", 0xff00ff7f },
+ { "SpringGreen1", 0xff00ff7f },
+ { "SpringGreen2", 0xff00ee76 },
+ { "SpringGreen3", 0xff00cd66 },
+ { "SpringGreen4", 0xff008b45 },
+ { "steel blue", 0xff4682b4 },
+ { "SteelBlue", 0xff4682b4 },
+ { "SteelBlue1", 0xff63b8ff },
+ { "SteelBlue2", 0xff5cacee },
+ { "SteelBlue3", 0xff4f94cd },
+ { "SteelBlue4", 0xff36648b },
+ { "tan", 0xffd2b48c },
+ { "tan1", 0xffffa54f },
+ { "tan2", 0xffee9a49 },
+ { "tan3", 0xffcd853f },
+ { "tan4", 0xff8b5a2b },
+ { "thistle", 0xffd8bfd8 },
+ { "thistle1", 0xffffe1ff },
+ { "thistle2", 0xffeed2ee },
+ { "thistle3", 0xffcdb5cd },
+ { "thistle4", 0xff8b7b8b },
+ { "tomato", 0xffff6347 },
+ { "tomato1", 0xffff6347 },
+ { "tomato2", 0xffee5c42 },
+ { "tomato3", 0xffcd4f39 },
+ { "tomato4", 0xff8b3626 },
+ { "turquoise", 0xff40e0d0 },
+ { "turquoise1", 0xff00f5ff },
+ { "turquoise2", 0xff00e5ee },
+ { "turquoise3", 0xff00c5cd },
+ { "turquoise4", 0xff00868b },
+ { "violet", 0xffee82ee },
+ { "violet red", 0xffd02090 },
+ { "VioletRed", 0xffd02090 },
+ { "VioletRed1", 0xffff3e96 },
+ { "VioletRed2", 0xffee3a8c },
+ { "VioletRed3", 0xffcd3278 },
+ { "VioletRed4", 0xff8b2252 },
+ { "wheat", 0xfff5deb3 },
+ { "wheat1", 0xffffe7ba },
+ { "wheat2", 0xffeed8ae },
+ { "wheat3", 0xffcdba96 },
+ { "wheat4", 0xff8b7e66 },
+ { "white", 0xffffffff },
+ { "white smoke", 0xfff5f5f5 },
+ { "WhiteSmoke", 0xfff5f5f5 },
+ { "yellow", 0xffffff00 },
+ { "yellow green", 0xff9acd32 },
+ { "yellow1", 0xffffff00 },
+ { "yellow2", 0xffeeee00 },
+ { "yellow3", 0xffcdcd00 },
+ { "yellow4", 0xff8b8b00 },
+ { "YellowGreen", 0xff9acd32 }
+};
+
+EXPORT
+bool wld_lookup_named_color(const char * name, uint32_t * color)
+{
+ char * end;
+ int low = 0, mid, high = ARRAY_LENGTH(named_colors);
+ int r;
+
+ if (name[0] == '#' && name[1] != '\0')
+ {
+ *color = strtoul(name + 1, &end, 16);
+
+ /* Set alpha channel to opaque. */
+ *color |= 0xff << 24;
+
+ if (*end == '\0')
+ return true;
+ }
+
+ while (low <= high)
+ {
+ mid = (low + high) / 2;
+ r = strcasecmp(named_colors[mid].name, name);
+
+ if (r == 0)
+ {
+ *color = named_colors[mid].color;
+ return true;
+ }
+ if (r < 0)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+
+ return false;
+}
+
diff --git a/src/wld/common.mk b/src/wld/common.mk
new file mode 100644
index 0000000..480ec90
--- /dev/null
+++ b/src/wld/common.mk
@@ -0,0 +1,11 @@
+# wld: common.mk
+
+.deps/$(dir): | .deps
+ @mkdir "$@"
+
+$(dir)/%.o: $(dir)/%.c | .deps/$(dir)
+ $(compile) $(WLD_PACKAGE_CFLAGS)
+
+$(dir)/%.lo: $(dir)/%.c | .deps/$(dir)
+ $(compile) $(WLD_PACKAGE_CFLAGS) -fPIC
+
diff --git a/src/wld/config.mk b/src/wld/config.mk
new file mode 100644
index 0000000..8f3ee29
--- /dev/null
+++ b/src/wld/config.mk
@@ -0,0 +1,20 @@
+# wld: config.mk
+
+CC = gcc
+CFLAGS = -pipe
+
+ENABLE_DEBUG = 1
+ENABLE_STATIC = 1
+ENABLE_SHARED = 0
+
+ENABLE_PIXMAN = 1
+ENABLE_DRM = 1
+ENABLE_WAYLAND = 1
+
+DRM_DRIVERS = intel nouveau
+WAYLAND_INTERFACES = shm
+
+ifeq ($(ENABLE_DRM),1)
+ WAYLAND_INTERFACES += drm
+endif
+
diff --git a/src/wld/context.c b/src/wld/context.c
new file mode 100644
index 0000000..a735d40
--- /dev/null
+++ b/src/wld/context.c
@@ -0,0 +1,70 @@
+/* wld: context.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wld-private.h"
+
+void context_initialize(struct wld_context * context,
+ const struct wld_context_impl * impl)
+{
+ *((const struct wld_context_impl **) &context->impl) = impl;
+}
+
+EXPORT
+struct wld_renderer * wld_create_renderer(struct wld_context * context)
+{
+ return context->impl->create_renderer(context);
+}
+
+EXPORT
+struct wld_buffer * wld_create_buffer(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ return &context->impl->create_buffer(context, width, height,
+ format, flags)->base;
+}
+
+EXPORT
+struct wld_buffer * wld_import_buffer(struct wld_context * context,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ return &context->impl->import_buffer(context, type, object,
+ width, height, format, pitch)->base;
+}
+
+EXPORT
+struct wld_surface * wld_create_surface(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ return context->impl->create_surface(context, width, height, format, flags);
+}
+
+EXPORT
+void wld_destroy_context(struct wld_context * context)
+{
+ context->impl->destroy(context);
+}
+
diff --git a/src/wld/drm-private.h b/src/wld/drm-private.h
new file mode 100644
index 0000000..6c36088
--- /dev/null
+++ b/src/wld/drm-private.h
@@ -0,0 +1,46 @@
+/* wld: drm-private.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_DRM_PRIVATE_H
+#define WLD_DRM_PRIVATE_H
+
+#include "wld-private.h"
+
+struct drm_driver
+{
+ const char * name;
+ bool (* device_supported)(uint32_t vendor_id, uint32_t device_id);
+ struct wld_context * (* create_context)(int drm_fd);
+};
+
+#if WITH_DRM_INTEL
+extern const struct drm_driver intel_drm_driver;
+#endif
+#if WITH_DRM_NOUVEAU
+extern const struct drm_driver nouveau_drm_driver;
+#endif
+extern const struct drm_driver dumb_drm_driver;
+extern const struct wld_context_impl * dumb_context_impl;
+
+#endif
+
diff --git a/src/wld/drm.c b/src/wld/drm.c
new file mode 100644
index 0000000..2768640
--- /dev/null
+++ b/src/wld/drm.c
@@ -0,0 +1,98 @@
+/* wld: drm.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "drm.h"
+#include "drm-private.h"
+
+#include <sys/sysmacros.h>
+
+const static struct drm_driver * drivers[] = {
+#if WITH_DRM_INTEL
+ &intel_drm_driver,
+#endif
+#if WITH_DRM_NOUVEAU
+ &nouveau_drm_driver,
+#endif
+ &dumb_drm_driver
+};
+
+static const struct drm_driver * find_driver(int fd)
+{
+ char path[64], id[32];
+ uint32_t vendor_id, device_id;
+ char * path_part;
+ struct stat st;
+ FILE * file;
+ uint32_t index;
+
+ if (fstat(fd, &st) == -1)
+ return NULL;
+
+ path_part = path + snprintf(path, sizeof path,
+ "/sys/dev/char/%u:%u/device/",
+ major(st.st_rdev), minor(st.st_rdev));
+
+ strcpy(path_part, "vendor");
+ file = fopen(path, "r");
+ fgets(id, sizeof id, file);
+ fclose(file);
+ vendor_id = strtoul(id, NULL, 0);
+
+ strcpy(path_part, "device");
+ file = fopen(path, "r");
+ fgets(id, sizeof id, file);
+ fclose(file);
+ device_id = strtoul(id, NULL, 0);
+
+ if (getenv("WLD_DRM_DUMB"))
+ return &dumb_drm_driver;
+
+ for (index = 0; index < ARRAY_LENGTH(drivers); ++index)
+ {
+ DEBUG("Trying DRM driver `%s'\n", drivers[index]->name);
+ if (drivers[index]->device_supported(vendor_id, device_id))
+ return drivers[index];
+ }
+
+ DEBUG("No DRM driver supports device 0x%x:0x%x\n", vendor_id, device_id);
+
+ return NULL;
+}
+
+EXPORT
+struct wld_context * wld_drm_create_context(int fd)
+{
+ const struct drm_driver * driver;
+
+ if (!(driver = find_driver(fd)))
+ return NULL;
+
+ return driver->create_context(fd);
+}
+
+EXPORT
+bool wld_drm_is_dumb(struct wld_context * context)
+{
+ return context->impl == dumb_context_impl;
+}
+
diff --git a/src/wld/drm.h b/src/wld/drm.h
new file mode 100644
index 0000000..20ee3e8
--- /dev/null
+++ b/src/wld/drm.h
@@ -0,0 +1,52 @@
+/* wld: drm.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_DRM_H
+#define WLD_DRM_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define WLD_DRM_ID (0x02 << 24)
+
+enum wld_drm_object_type
+{
+ WLD_DRM_OBJECT_HANDLE = WLD_DRM_ID,
+ WLD_DRM_OBJECT_PRIME_FD,
+};
+
+enum wld_drm_flags
+{
+ WLD_DRM_FLAG_SCANOUT = 0x1,
+ WLD_DRM_FLAG_TILED = 0x2
+};
+
+/**
+ * Create a new WLD context from an opened DRM device file descriptor.
+ */
+struct wld_context * wld_drm_create_context(int fd);
+
+bool wld_drm_is_dumb(struct wld_context * context);
+
+#endif
+
diff --git a/src/wld/dumb.c b/src/wld/dumb.c
new file mode 100644
index 0000000..b08d098
--- /dev/null
+++ b/src/wld/dumb.c
@@ -0,0 +1,235 @@
+/* wld: dumb.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "drm-private.h"
+#include "drm.h"
+#include "pixman.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include <errno.h>
+
+struct dumb_context
+{
+ struct wld_context base;
+ int fd;
+};
+
+struct dumb_buffer
+{
+ struct buffer base;
+ struct wld_exporter exporter;
+ struct dumb_context * context;
+ uint32_t handle;
+};
+
+#include "interface/context.h"
+#include "interface/buffer.h"
+#define DRM_DRIVER_NAME dumb
+#include "interface/drm.h"
+IMPL(dumb_context, wld_context)
+IMPL(dumb_buffer, wld_buffer)
+
+const struct wld_context_impl * dumb_context_impl = &wld_context_impl;
+
+bool driver_device_supported(uint32_t vendor_id, uint32_t device_id)
+{
+ return true;
+}
+
+struct wld_context * driver_create_context(int drm_fd)
+{
+ struct dumb_context * context;
+
+ if (!(context = malloc(sizeof *context)))
+ return NULL;
+
+ context_initialize(&context->base, &wld_context_impl);
+ context->fd = drm_fd;
+
+ return &context->base;
+}
+
+struct wld_renderer * context_create_renderer(struct wld_context * context)
+{
+ return wld_create_renderer(wld_pixman_context);
+}
+
+static bool export(struct wld_exporter * exporter, struct wld_buffer * base,
+ uint32_t type, union wld_object * object)
+{
+ struct dumb_buffer * buffer = dumb_buffer(base);
+
+ switch (type)
+ {
+ case WLD_DRM_OBJECT_HANDLE:
+ object->u32 = buffer->handle;
+ return true;
+ case WLD_DRM_OBJECT_PRIME_FD:
+ if (drmPrimeHandleToFD(buffer->context->fd, buffer->handle,
+ DRM_CLOEXEC, &object->i) != 0)
+ {
+ return false;
+ }
+
+ return true;
+ default:
+ return false;
+ }
+}
+
+static struct buffer * new_buffer(struct dumb_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t handle,
+ unsigned long pitch)
+{
+ struct dumb_buffer * buffer;
+
+ if (!(buffer = malloc(sizeof *buffer)))
+ return NULL;
+
+ buffer_initialize(&buffer->base, &wld_buffer_impl,
+ width, height, format, pitch);
+ buffer->context = context;
+ buffer->handle = handle;
+ buffer->exporter.export = &export;
+ wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter);
+
+ return &buffer->base;
+}
+
+struct buffer * context_create_buffer(struct wld_context * base,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ struct dumb_context * context = dumb_context(base);
+ struct buffer * buffer;
+ struct drm_mode_create_dumb create_dumb = {
+ .height = height, .width = width,
+ .bpp = format_bytes_per_pixel(format) * 8,
+ };
+
+ if (drmIoctl(context->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb) != 0)
+ goto error0;
+
+ buffer = new_buffer(context, width, height, format,
+ create_dumb.handle, create_dumb.pitch);
+
+ if (!buffer)
+ goto error1;
+
+ return buffer;
+
+ error1:
+ {
+ struct drm_mode_destroy_dumb destroy_dumb = {
+ .handle = create_dumb.handle
+ };
+
+ drmIoctl(context->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
+ }
+ error0:
+ return NULL;
+}
+
+struct buffer * context_import_buffer(struct wld_context * base,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ struct dumb_context * context = dumb_context(base);
+ uint32_t handle;
+
+ switch (type)
+ {
+ case WLD_DRM_OBJECT_PRIME_FD:
+ if (drmPrimeFDToHandle(context->fd, object.i, &handle) != 0)
+ return NULL;
+ break;
+ default: return NULL;
+ }
+
+ return new_buffer(context, width, height, format, handle, pitch);
+}
+
+void context_destroy(struct wld_context * base)
+{
+ struct dumb_context * context = dumb_context(base);
+
+ close(context->fd);
+ free(context);
+}
+
+/**** Buffer ****/
+
+bool buffer_map(struct buffer * base)
+{
+ struct dumb_buffer * buffer = dumb_buffer(&base->base);
+ struct drm_mode_map_dumb map_dumb = { .handle = buffer->handle };
+ void * data;
+
+ if (drmIoctl(buffer->context->fd, DRM_IOCTL_MODE_MAP_DUMB,
+ &map_dumb) != 0)
+ {
+ return false;
+ }
+
+ data = mmap(NULL, buffer->base.base.pitch * buffer->base.base.height,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buffer->context->fd, map_dumb.offset);
+
+ if (data == MAP_FAILED)
+ return false;
+
+ buffer->base.base.map = data;
+
+ return true;
+}
+
+bool buffer_unmap(struct buffer * buffer)
+{
+ if (munmap(buffer->base.map,
+ buffer->base.pitch * buffer->base.height) == -1)
+ {
+ return false;
+ }
+
+ buffer->base.map = NULL;
+
+ return true;
+}
+
+void buffer_destroy(struct buffer * base)
+{
+ struct dumb_buffer * buffer = dumb_buffer(&base->base);
+ struct drm_mode_destroy_dumb destroy_dumb = {
+ .handle = buffer->handle
+ };
+
+ drmIoctl(buffer->context->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
+ free(buffer);
+}
+
diff --git a/src/wld/font.c b/src/wld/font.c
new file mode 100644
index 0000000..36b8a07
--- /dev/null
+++ b/src/wld/font.c
@@ -0,0 +1,235 @@
+/* wld: font.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wld-private.h"
+
+#include <fontconfig/fcfreetype.h>
+
+EXPORT
+struct wld_font_context * wld_font_create_context()
+{
+ struct wld_font_context * context;
+
+ context = malloc(sizeof *context);
+
+ if (!context)
+ goto error0;
+
+ if (FT_Init_FreeType(&context->library) != 0)
+ {
+ DEBUG("Failed to initialize FreeType library\n");
+
+ goto error1;
+ }
+
+ return context;
+
+ error1:
+ free(context);
+ error0:
+ return NULL;
+}
+
+EXPORT
+void wld_font_destroy_context(struct wld_font_context * context)
+{
+ FT_Done_FreeType(context->library);
+ free(context);
+}
+
+EXPORT
+struct wld_font * wld_font_open_name(struct wld_font_context * context,
+ const char * name)
+{
+ FcPattern * pattern, * match;
+ FcResult result;
+
+ DEBUG("Opening font with name: %s\n", name);
+
+ pattern = FcNameParse((const FcChar8 *) name);
+ FcConfigSubstitute(NULL, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ match = FcFontMatch(NULL, pattern, &result);
+
+ if (!match)
+ return NULL;
+
+ return wld_font_open_pattern(context, match);
+}
+
+EXPORT
+struct wld_font * wld_font_open_pattern(struct wld_font_context * context,
+ FcPattern * match)
+{
+ char * filename;
+ struct font * font;
+ FcResult result;
+ double pixel_size, aspect;
+
+ font = malloc(sizeof *font);
+
+ if (!font)
+ goto error0;
+
+ font->context = context;
+
+ result = FcPatternGetString(match, FC_FILE, 0, (FcChar8 **) &filename);
+
+ if (result == FcResultMatch)
+ {
+ FT_Error error;
+
+ DEBUG("Loading font file: %s\n", filename);
+
+ error = FT_New_Face(context->library, filename, 0, &font->face);
+
+ if (error == 0)
+ goto load_face;
+ }
+
+ result = FcPatternGetFTFace(match, FC_FT_FACE, 0, &font->face);
+
+ if (result != FcResultMatch)
+ {
+ DEBUG("Couldn't determine font filename or FreeType face\n");
+ goto error1;
+ }
+
+ load_face:
+ result = FcPatternGetDouble(match, FC_PIXEL_SIZE, 0, &pixel_size);
+
+ result = FcPatternGetDouble(match, FC_ASPECT, 0, &aspect);
+
+ if (result == FcResultNoMatch)
+ aspect = 1.0;
+
+ if (font->face->face_flags & FT_FACE_FLAG_SCALABLE)
+ {
+ FT_F26Dot6 width, height;
+
+ width = ((unsigned int) pixel_size) << 6;
+ height = ((unsigned int) (pixel_size * aspect)) << 6;
+
+ FT_Set_Char_Size(font->face, width, height, 0, 0);
+ }
+ else
+ {
+ FT_Set_Pixel_Sizes(font->face, (unsigned int) pixel_size,
+ (unsigned int) (pixel_size * aspect));
+ }
+
+ font->base.ascent = font->face->size->metrics.ascender >> 6;
+ font->base.descent = -font->face->size->metrics.descender >> 6;
+ font->base.height = font->base.ascent + font->base.descent;
+ font->base.max_advance = font->face->size->metrics.max_advance >> 6;
+
+ font->glyphs = calloc(font->face->num_glyphs, sizeof(struct glyph *));
+
+ return &font->base;
+
+ error1:
+ free(font);
+ error0:
+ return NULL;
+}
+
+EXPORT
+void wld_font_close(struct wld_font * font_base)
+{
+ struct font * font = (void *) font_base;
+
+ FT_Done_Face(font->face);
+ free(font);
+}
+
+bool font_ensure_glyph(struct font * font, FT_UInt glyph_index)
+{
+ if (glyph_index)
+ {
+ if (!font->glyphs[glyph_index])
+ {
+ struct glyph * glyph;
+
+ glyph = malloc(sizeof *glyph);
+
+ if (!glyph)
+ return false;
+
+ FT_Load_Glyph(font->face, glyph_index, FT_LOAD_RENDER
+ | FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO);
+
+ FT_Bitmap_New(&glyph->bitmap);
+
+ FT_Bitmap_Copy(font->context->library,
+ &font->face->glyph->bitmap, &glyph->bitmap);
+
+ glyph->advance = font->face->glyph->metrics.horiAdvance >> 6;
+ glyph->x = font->face->glyph->bitmap_left;
+ glyph->y = -font->face->glyph->bitmap_top;
+
+ font->glyphs[glyph_index] = glyph;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+EXPORT
+bool wld_font_ensure_char(struct wld_font * font_base, uint32_t character)
+{
+ struct font * font = (void *) font_base;
+ FT_UInt glyph_index;
+
+ glyph_index = FT_Get_Char_Index(font->face, character);
+
+ return font_ensure_glyph(font, glyph_index);
+}
+
+EXPORT
+void wld_font_text_extents_n(struct wld_font * font_base,
+ const char * text, int32_t length,
+ struct wld_extents * extents)
+{
+ struct font * font = (void *) font_base;
+ int ret;
+ uint32_t c;
+ FT_UInt glyph_index;
+
+ extents->advance = 0;
+
+ while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length) > 0) && c != '\0')
+ {
+ length -= ret;
+ text += ret;
+ glyph_index = FT_Get_Char_Index(font->face, c);
+
+ if (!font_ensure_glyph(font, glyph_index))
+ continue;
+
+ extents->advance += font->glyphs[glyph_index]->advance;
+ }
+}
+
diff --git a/src/wld/intel.c b/src/wld/intel.c
new file mode 100644
index 0000000..78c3c0f
--- /dev/null
+++ b/src/wld/intel.c
@@ -0,0 +1,390 @@
+/* wld: intel.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "drm-private.h"
+#include "drm.h"
+#include "intel/batch.h"
+#include "intel/blt.h"
+#include "wld-private.h"
+
+#include <unistd.h>
+#include <intel_bufmgr.h>
+#include <i915_drm.h>
+
+struct intel_context
+{
+ struct wld_context base;
+ drm_intel_bufmgr * bufmgr;
+};
+
+struct intel_renderer
+{
+ struct wld_renderer base;
+ struct intel_batch batch;
+ struct intel_buffer * target;
+};
+
+struct intel_buffer
+{
+ struct buffer base;
+ struct wld_exporter exporter;
+ drm_intel_bo * bo;
+};
+
+#include "interface/context.h"
+#include "interface/renderer.h"
+#include "interface/buffer.h"
+#define DRM_DRIVER_NAME intel
+#include "interface/drm.h"
+IMPL(intel_context, wld_context)
+IMPL(intel_renderer, wld_renderer)
+IMPL(intel_buffer, wld_buffer)
+
+/**** DRM driver ****/
+bool driver_device_supported(uint32_t vendor_id, uint32_t device_id)
+{
+ return vendor_id == 0x8086;
+}
+
+struct wld_context * driver_create_context(int drm_fd)
+{
+ struct intel_context * context;
+
+ context = malloc(sizeof *context);
+
+ if (!context)
+ goto error0;
+
+ context_initialize(&context->base, &wld_context_impl);
+ context->bufmgr = drm_intel_bufmgr_gem_init(drm_fd, INTEL_BATCH_SIZE);
+
+ if (!context->bufmgr)
+ goto error1;
+
+ return &context->base;
+
+ error1:
+ free(context);
+ error0:
+ return NULL;
+}
+
+/**** Context ****/
+struct wld_renderer * context_create_renderer(struct wld_context * base)
+{
+ struct intel_context * context = intel_context(base);
+ struct intel_renderer * renderer;
+
+ if (!(renderer = malloc(sizeof *renderer)))
+ goto error0;
+
+ if (!(intel_batch_initialize(&renderer->batch, context->bufmgr)))
+ goto error1;
+
+ renderer_initialize(&renderer->base, &wld_renderer_impl);
+
+ return &renderer->base;
+
+ error1:
+ free(renderer);
+ error0:
+ return NULL;
+}
+
+static bool export(struct wld_exporter * exporter, struct wld_buffer * base,
+ uint32_t type, union wld_object * object)
+{
+ struct intel_buffer * buffer = intel_buffer(base);
+
+ switch (type)
+ {
+ case WLD_DRM_OBJECT_HANDLE:
+ object->u32 = buffer->bo->handle;
+ return true;
+ case WLD_DRM_OBJECT_PRIME_FD:
+ if (drm_intel_bo_gem_export_to_prime(buffer->bo, &object->i) != 0)
+ return false;
+ return true;
+ default:
+ return false;
+ }
+}
+
+static struct buffer * new_buffer(uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch,
+ drm_intel_bo * bo)
+{
+ struct intel_buffer * buffer;
+
+ if (!(buffer = malloc(sizeof *buffer)))
+ return NULL;
+
+ buffer_initialize(&buffer->base, &wld_buffer_impl,
+ width, height, format, pitch);
+ buffer->bo = bo;
+ buffer->exporter.export = &export;
+ wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter);
+
+ return &buffer->base;
+}
+
+struct buffer * context_create_buffer(struct wld_context * base,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ struct intel_context * context = intel_context(base);
+ struct buffer * buffer;
+ drm_intel_bo * bo;
+ uint32_t tiling_mode = width >= 128 ? I915_TILING_X : I915_TILING_NONE;
+ unsigned long pitch;
+
+ bo = drm_intel_bo_alloc_tiled(context->bufmgr, "buffer", width, height, 4,
+ &tiling_mode, &pitch, 0);
+
+ if (!bo)
+ goto error0;
+
+ if (!(buffer = new_buffer(width, height, format, pitch, bo)))
+ goto error1;
+
+ return buffer;
+
+ error1:
+ drm_intel_bo_unreference(bo);
+ error0:
+ return NULL;
+}
+
+struct buffer * context_import_buffer(struct wld_context * base,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ struct intel_context * context = intel_context(base);
+ struct buffer * buffer;
+ drm_intel_bo * bo;
+
+ switch (type)
+ {
+ case WLD_DRM_OBJECT_PRIME_FD:
+ {
+ uint32_t size = width * height * format_bytes_per_pixel(format);
+ bo = drm_intel_bo_gem_create_from_prime(context->bufmgr,
+ object.i, size);
+ break;
+ }
+ default: bo = NULL;
+ };
+
+ if (!bo)
+ goto error0;
+
+ if (!(buffer = new_buffer(width, height, format, pitch, bo)))
+ goto error1;
+
+ return buffer;
+
+ error1:
+ drm_intel_bo_unreference(bo);
+ error0:
+ return NULL;
+}
+
+void context_destroy(struct wld_context * base)
+{
+ struct intel_context * context = intel_context(base);
+
+ drm_intel_bufmgr_destroy(context->bufmgr);
+ free(context);
+}
+
+/**** Renderer ****/
+uint32_t renderer_capabilities(struct wld_renderer * renderer,
+ struct buffer * buffer)
+{
+ if (buffer->base.impl == &wld_buffer_impl)
+ return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
+
+ return 0;
+}
+
+bool renderer_set_target(struct wld_renderer * base, struct buffer * buffer)
+{
+ struct intel_renderer * renderer = intel_renderer(base);
+
+ if (buffer && buffer->base.impl != &wld_buffer_impl)
+ return false;
+
+ renderer->target = buffer ? intel_buffer(&buffer->base) : NULL;
+
+ return true;
+}
+
+void renderer_fill_rectangle(struct wld_renderer * base, uint32_t color,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct intel_renderer * renderer = intel_renderer(base);
+ struct intel_buffer * dst = renderer->target;
+
+ xy_color_blt(&renderer->batch, dst->bo, dst->base.base.pitch,
+ x, y, x + width, y + height, color);
+}
+
+void renderer_copy_rectangle(struct wld_renderer * base,
+ struct buffer * buffer_base,
+ int32_t dst_x, int32_t dst_y,
+ int32_t src_x, int32_t src_y,
+ uint32_t width, uint32_t height)
+{
+ struct intel_renderer * renderer = intel_renderer(base);
+
+ if (buffer_base->base.impl != &wld_buffer_impl)
+ return;
+
+ struct intel_buffer * src = intel_buffer(&buffer_base->base),
+ * dst = renderer->target;
+
+ xy_src_copy_blt(&renderer->batch,
+ src->bo, src->base.base.pitch, src_x, src_y,
+ dst->bo, dst->base.base.pitch, dst_x, dst_y, width, height);
+}
+
+void renderer_draw_text(struct wld_renderer * base,
+ struct font * font, uint32_t color,
+ int32_t x, int32_t y, const char * text,
+ uint32_t length, struct wld_extents * extents)
+{
+ struct intel_renderer * renderer = intel_renderer(base);
+ struct intel_buffer * dst = renderer->target;
+ int ret;
+ struct glyph * glyph;
+ uint32_t row;
+ FT_UInt glyph_index;
+ uint32_t c;
+ uint8_t immediate[512];
+ uint8_t * byte;
+ int32_t origin_x = x;
+
+ xy_setup_blt(&renderer->batch, true, BLT_RASTER_OPERATION_SRC,
+ 0, color, dst->bo, dst->base.base.pitch);
+
+ if (length == -1)
+ length = strlen(text);
+
+ while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length)) > 0 && c != '\0')
+ {
+ text += ret;
+ length -= ret;
+ glyph_index = FT_Get_Char_Index(font->face, c);
+
+ if (!font_ensure_glyph(font, glyph_index))
+ continue;
+
+ glyph = font->glyphs[glyph_index];
+
+ if (glyph->bitmap.width == 0 || glyph->bitmap.rows == 0)
+ goto advance;
+
+ byte = immediate;
+
+ /* XY_TEXT_IMMEDIATE requires a pitch with no extra bytes */
+ for (row = 0; row < glyph->bitmap.rows; ++row)
+ {
+ memcpy(byte, glyph->bitmap.buffer + (row * glyph->bitmap.pitch),
+ (glyph->bitmap.width + 7) / 8);
+ byte += (glyph->bitmap.width + 7) / 8;
+ }
+
+ retry:
+ ret = xy_text_immediate_blt(&renderer->batch, dst->bo,
+ origin_x + glyph->x, y + glyph->y,
+ origin_x + glyph->x + glyph->bitmap.width,
+ y + glyph->y + glyph->bitmap.rows,
+ (byte - immediate + 3) / 4,
+ (uint32_t *) immediate);
+
+ if (ret == INTEL_BATCH_NO_SPACE)
+ {
+ intel_batch_flush(&renderer->batch);
+ xy_setup_blt(&renderer->batch, true, BLT_RASTER_OPERATION_SRC,
+ 0, color, dst->bo, dst->base.base.pitch);
+ goto retry;
+ }
+
+ advance:
+ origin_x += glyph->advance;
+ }
+
+ if (extents)
+ extents->advance = origin_x - x;
+}
+
+void renderer_flush(struct wld_renderer * base)
+{
+ struct intel_renderer * renderer = intel_renderer(base);
+
+ intel_batch_flush(&renderer->batch);
+}
+
+void renderer_destroy(struct wld_renderer * base)
+{
+ struct intel_renderer * renderer = intel_renderer(base);
+
+ intel_batch_finalize(&renderer->batch);
+ free(renderer);
+}
+
+/**** Buffer ****/
+bool buffer_map(struct buffer * base)
+{
+ struct intel_buffer * buffer = intel_buffer(&base->base);
+
+ if (drm_intel_gem_bo_map_gtt(buffer->bo) != 0)
+ return false;
+
+ buffer->base.base.map = buffer->bo->virtual;
+
+ return true;
+}
+
+bool buffer_unmap(struct buffer * base)
+{
+ struct intel_buffer * buffer = intel_buffer(&base->base);
+
+ if (drm_intel_gem_bo_unmap_gtt(buffer->bo) != 0)
+ return false;
+
+ buffer->base.base.map = NULL;
+
+ return true;
+}
+
+void buffer_destroy(struct buffer * base)
+{
+ struct intel_buffer * buffer = intel_buffer(&base->base);
+
+ drm_intel_bo_unreference(buffer->bo);
+ free(buffer);
+}
+
diff --git a/src/wld/intel/batch.c b/src/wld/intel/batch.c
new file mode 100644
index 0000000..61d9ecf
--- /dev/null
+++ b/src/wld/intel/batch.c
@@ -0,0 +1,99 @@
+/* wld: intel/batch.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "batch.h"
+#include "mi.h"
+
+#include <i915_drm.h>
+#include <stdlib.h>
+
+static const struct intel_device_info device_info_i965 = { .gen = 4 };
+static const struct intel_device_info device_info_g4x = { .gen = 4 };
+static const struct intel_device_info device_info_ilk = { .gen = 5 };
+static const struct intel_device_info device_info_snb_gt1 = { .gen = 6 };
+static const struct intel_device_info device_info_snb_gt2 = { .gen = 6 };
+static const struct intel_device_info device_info_ivb_gt1 = { .gen = 7 };
+static const struct intel_device_info device_info_ivb_gt2 = { .gen = 7 };
+static const struct intel_device_info device_info_byt = { .gen = 7 };
+static const struct intel_device_info device_info_hsw_gt1 = { .gen = 7 };
+static const struct intel_device_info device_info_hsw_gt2 = { .gen = 7 };
+static const struct intel_device_info device_info_hsw_gt3 = { .gen = 7 };
+
+static const struct intel_device_info * device_info(int device_id)
+{
+ switch (device_id)
+ {
+#define CHIPSET(device_id, type, name) \
+ case device_id: return &device_info_ ## type;
+#include "i965_pci_ids.h"
+#undef CHIPSET
+ default: return NULL;
+ }
+}
+
+bool intel_batch_initialize(struct intel_batch * batch,
+ drm_intel_bufmgr * bufmgr)
+{
+ int device_id = drm_intel_bufmgr_gem_get_devid(bufmgr);
+
+ batch->command_count = 0;
+ batch->device_info = device_info(device_id);
+
+ if (!batch->device_info)
+ return false;
+
+ /* Alignment argument (4096) is not used */
+ batch->bo = drm_intel_bo_alloc(bufmgr, "batchbuffer",
+ sizeof batch->commands, 4096);
+
+ if (!batch->bo)
+ return false;
+
+ return true;
+}
+
+void intel_batch_finalize(struct intel_batch * batch)
+{
+ drm_intel_bo_unreference(batch->bo);
+}
+
+void intel_batch_flush(struct intel_batch * batch)
+{
+ if (batch->command_count == 0)
+ return;
+
+ intel_batch_add_dword(batch, MI_BATCH_BUFFER_END);
+
+ /* Pad the batch buffer to the next quad-word. */
+ if (batch->command_count & 1)
+ intel_batch_add_dword(batch, MI_NOOP);
+
+ drm_intel_bo_subdata(batch->bo, 0, batch->command_count << 2,
+ batch->commands);
+ drm_intel_bo_mrb_exec(batch->bo, batch->command_count << 2, NULL, 0, 0,
+ batch->device_info->gen >= 6 ? I915_EXEC_BLT
+ : I915_EXEC_DEFAULT);
+ drm_intel_gem_bo_clear_relocs(batch->bo, 0);
+ batch->command_count = 0;
+}
+
diff --git a/src/wld/intel/batch.h b/src/wld/intel/batch.h
new file mode 100644
index 0000000..d09eb27
--- /dev/null
+++ b/src/wld/intel/batch.h
@@ -0,0 +1,104 @@
+/* wld: intel/batch.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_INTEL_BATCH_H
+#define WLD_INTEL_BATCH_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <intel_bufmgr.h>
+
+#define INTEL_BATCH_MAX_COMMANDS (1 << 13)
+#define INTEL_BATCH_RESERVED_COMMANDS 2
+#define INTEL_BATCH_SIZE (INTEL_BATCH_MAX_COMMANDS << 2)
+
+enum intel_batch_result
+{
+ INTEL_BATCH_SUCCESS,
+ INTEL_BATCH_NO_SPACE
+};
+
+struct intel_device_info
+{
+ int gen;
+};
+
+struct intel_batch
+{
+ const struct intel_device_info * device_info;
+ drm_intel_bo * bo;
+ uint32_t commands[INTEL_BATCH_MAX_COMMANDS];
+ uint32_t command_count;
+};
+
+bool intel_batch_initialize(struct intel_batch * batch,
+ drm_intel_bufmgr * bufmgr);
+
+void intel_batch_finalize(struct intel_batch * batch);
+
+void intel_batch_flush(struct intel_batch * batch);
+
+static inline uint32_t intel_batch_check_space(struct intel_batch * batch,
+ uint32_t size)
+{
+ return (INTEL_BATCH_MAX_COMMANDS - INTEL_BATCH_RESERVED_COMMANDS
+ - batch->command_count) >= size;
+}
+
+static inline void intel_batch_ensure_space(struct intel_batch * batch, uint32_t size)
+{
+ if (!intel_batch_check_space(batch, size))
+ intel_batch_flush(batch);
+}
+
+static inline void intel_batch_add_dword(struct intel_batch * batch,
+ uint32_t dword)
+{
+ batch->commands[batch->command_count++] = dword;
+}
+
+static inline void intel_batch_add_dwords_va(struct intel_batch * batch,
+ uint32_t count, va_list dwords)
+{
+ while (count--)
+ intel_batch_add_dword(batch, va_arg(dwords, uint32_t));
+}
+
+static inline void intel_batch_add_dwords(struct intel_batch * batch,
+ uint32_t count, ...)
+{
+ va_list dwords;
+ va_start(dwords, count);
+ intel_batch_add_dwords_va(batch, count, dwords);
+ va_end(dwords);
+}
+
+static inline uint32_t intel_batch_offset(struct intel_batch * batch,
+ uint32_t command_index)
+{
+ return (batch->command_count + command_index) << 2;
+}
+
+#endif
+
diff --git a/src/wld/intel/blt.h b/src/wld/intel/blt.h
new file mode 100644
index 0000000..a90c921
--- /dev/null
+++ b/src/wld/intel/blt.h
@@ -0,0 +1,347 @@
+/* wld: intel/blt.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_INTEL_BLT_H
+#define WLD_INTEL_BLT_H
+
+#include <i915_drm.h>
+#include <intel_bufmgr.h>
+
+#define INTEL_CLIENT_BLT 0x2
+
+enum blt_op
+{
+ BLT_OP_XY_SETUP_BLT = 0x01,
+ BLT_OP_XY_TEXT_BLT = 0x26,
+ BLT_OP_XY_TEXT_IMMEDIATE_BLT = 0x31,
+ BLT_OP_XY_COLOR_BLT = 0x50,
+ BLT_OP_XY_SRC_COPY_BLT = 0x53
+};
+
+enum blt_32bpp_mask
+{
+ BLT_32BPP_MASK_ALPHA = (1 << 0),
+ BLT_32BPP_MASK_RGB = (1 << 1)
+};
+
+enum blt_packing
+{
+ BLT_PACKING_BIT = 0,
+ BLT_PACKING_BYTE = 1
+};
+
+enum blt_color_depth
+{
+ BLT_COLOR_DEPTH_8BIT = 0x0,
+ BLT_COLOR_DEPTH_16BIT_565 = 0x1,
+ BLT_COLOR_DEPTH_16BIT_1555 = 0x2,
+ BLT_COLOR_DEPTH_32BIT = 0x3
+};
+
+enum blt_raster_operation
+{
+ BLT_RASTER_OPERATION_SRC = 0xcc,
+ BLT_RASTER_OPERATION_PAT = 0xf0
+};
+
+/* BR00 : BLT Opcode & Control */
+#define BLT_BR00_CLIENT(x) ((x) << 29) /* 31:29 */
+#define BLT_BR00_OP(x) ((x) << 22) /* 28:22 */
+#define BLT_BR00_32BPP_MASK(x) ((x) << 20) /* 21:20 */
+ /* 19:17 */
+#define BLT_BR00_PACKING(x) ((x) << 16) /* 16 */
+#define BLT_BR00_SRC_TILING_ENABLE(x) ((x) << 15) /* 15 */
+ /* 14:12 */
+#define BLT_BR00_DST_TILING_ENABLE(x) ((x) << 11) /* 11 */
+#define BLT_BR00_DWORD_LENGTH(x) ((x) << 0) /* 7:0 */
+
+/* BR01 : Setup BLT Raster OP, Control, and Destination Offset */
+#define BLT_BR01_SOLID_PATTERN(x) ((x) << 31) /* 31 */
+#define BLT_BR01_CLIPPING_ENABLE(x) ((x) << 30) /* 30 */
+#define BLT_BR01_MONO_SRC_TRANSPARENCY(x) ((x) << 29) /* 29 */
+#define BLT_BR01_MONO_PAT_TRANSPARENCY(x) ((x) << 28) /* 28 */
+#define BLT_BR01_COLOR_DEPTH(x) ((x) << 24) /* 25:24 */
+#define BLT_BR01_RASTER_OPERATION(x) ((x) << 16) /* 23:16 */
+#define BLT_BR01_DST_PITCH(x) ((x) << 0) /* 15:0 */
+
+/* BR05 : Setup Expansion Background Color */
+#define BLT_BR05_BACKGROUND_COLOR(x) ((x) << 0) /* 31:0 */
+
+/* BR06 : Setup Expansion Foreground Color */
+#define BLT_BR06_FOREGROUND_COLOR(x) ((x) << 0) /* 31:0 */
+
+/* BR07 : Setup Blit Color Pattern Address */
+ /* 31:29 */
+#define BLT_BR07_PAT_ADDRESS(x) ((x) << 6) /* 28:6 */
+ /* 5:0 */
+
+/* BR09 : Destination Address */
+ /* 31:29 */
+#define BLT_BR09_DST_ADDRESS(x) ((x) << 0) /* 28:0 */
+
+/* BR11 : Source Pitch */
+ /* 31:16 */
+#define BLT_BR11_SRC_PITCH(x) ((x) << 0) /* 15:0 */
+
+/* BR12 : Source Address */
+ /* 31:29 */
+#define BLT_BR12_SRC_ADDRESS(x) ((x) << 0) /* 28:0 */
+
+/* BR13 : BLT Raster OP, Control, and Destination Pitch */
+#define BLT_BR13_SOLID_PATTERN(x) ((x) << 31) /* 31 */
+#define BLT_BR13_CLIPPING_ENABLE(x) ((x) << 30) /* 30 */
+#define BLT_BR13_MONO_SRC_TRANSPARENT(x) ((x) << 29) /* 29 */
+#define BLT_BR13_MONO_PAT_TRANSPARENT(x) ((x) << 28) /* 28 */
+#define BLT_BR13_COLOR_DEPTH(x) ((x) << 24) /* 25:24 */
+#define BLT_BR13_RASTER_OPERATION(x) ((x) << 16) /* 23:16 */
+#define BLT_BR13_DST_PITCH(x) ((x) << 0) /* 15:0 */
+
+/* BR16 : Pattern Expansion Background & Solid Pattern Color */
+#define BLT_BR16_COLOR(x) ((x) << 0) /* 31 : 0 */
+
+/* BR22 : Destination Top Left */
+#define BLT_BR22_DST_Y1(x) ((x) << 16) /* 31:16 */
+#define BLT_BR22_DST_X1(x) ((x) << 0) /* 16:0 */
+
+/* BR23 : Destination Bottom Right */
+#define BLT_BR23_DST_Y2(x) ((x) << 16) /* 31:16 */
+#define BLT_BR23_DST_X2(x) ((x) << 0) /* 16:0 */
+
+/* BR24 : Clip Rectangle Top Left */
+ /* 31 */
+#define BLT_BR24_CLP_Y1(x) ((x) << 16) /* 30:16 */
+ /* 15 */
+#define BLT_BR24_CLP_X1(x) ((x) << 0) /* 14:0 */
+
+/* BR25 : Clip Rectangle Bottom Right */
+ /* 31 */
+#define BLT_BR25_CLP_Y2(x) ((x) << 16) /* 30:16 */
+ /* 15 */
+#define BLT_BR25_CLP_X2(x) ((x) << 0) /* 14:0 */
+
+/* BR26 : Source Top Left */
+#define BLT_BR26_SRC_Y1(x) ((x) << 16) /* 31:16 */
+#define BLT_BR26_SRC_X1(x) ((x) << 0) /* 15:0 */
+
+static inline void xy_setup_blt(struct intel_batch * batch,
+ bool monochrome_source_transparency,
+ uint8_t raster_operation,
+ uint32_t background_color,
+ uint32_t foreground_color,
+ drm_intel_bo * dst, uint16_t dst_pitch)
+{
+ uint32_t tiling_mode, swizzle_mode;
+
+ intel_batch_ensure_space(batch, 8);
+
+ drm_intel_bo_get_tiling(dst, &tiling_mode, &swizzle_mode);
+ drm_intel_bo_emit_reloc_fence
+ (batch->bo, intel_batch_offset(batch, 4), dst, 0,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+
+ intel_batch_add_dwords(batch, 8,
+ BLT_BR00_CLIENT(INTEL_CLIENT_BLT)
+ | BLT_BR00_OP(BLT_OP_XY_SETUP_BLT)
+ | BLT_BR00_32BPP_MASK(BLT_32BPP_MASK_ALPHA | BLT_32BPP_MASK_RGB)
+ | BLT_BR00_DST_TILING_ENABLE(tiling_mode != I915_TILING_NONE)
+ | BLT_BR00_DWORD_LENGTH(6),
+
+ BLT_BR01_CLIPPING_ENABLE(false)
+ | BLT_BR01_MONO_SRC_TRANSPARENCY(monochrome_source_transparency)
+ | BLT_BR01_COLOR_DEPTH(BLT_COLOR_DEPTH_32BIT)
+ | BLT_BR01_RASTER_OPERATION(raster_operation)
+ | BLT_BR01_DST_PITCH(tiling_mode == I915_TILING_NONE
+ ? dst_pitch : dst_pitch >> 2),
+
+ /* XXX: No clipping yet */
+ BLT_BR24_CLP_Y1(0)
+ | BLT_BR24_CLP_X1(0),
+
+ BLT_BR25_CLP_Y2(0)
+ | BLT_BR25_CLP_X2(0),
+
+ BLT_BR09_DST_ADDRESS(dst->offset),
+ BLT_BR05_BACKGROUND_COLOR(background_color),
+ BLT_BR06_FOREGROUND_COLOR(foreground_color),
+ BLT_BR07_PAT_ADDRESS(0)
+ );
+}
+
+static inline int xy_text_blt(struct intel_batch * batch,
+ drm_intel_bo * src, uint32_t src_offset,
+ drm_intel_bo * dst,
+ int16_t dst_x1, int16_t dst_y1,
+ int16_t dst_x2, int16_t dst_y2)
+{
+ uint32_t tiling_mode, swizzle_mode;
+
+ if (!intel_batch_check_space(batch, 4))
+ return INTEL_BATCH_NO_SPACE;
+
+ drm_intel_bo_get_tiling(dst, &tiling_mode, &swizzle_mode);
+
+ drm_intel_bo_emit_reloc_fence
+ (batch->bo, intel_batch_offset(batch, 3), src, src_offset,
+ I915_GEM_DOMAIN_RENDER, 0);
+
+ intel_batch_add_dwords(batch, 4,
+ BLT_BR00_CLIENT(INTEL_CLIENT_BLT)
+ | BLT_BR00_OP(BLT_OP_XY_TEXT_BLT)
+ | BLT_BR00_PACKING(BLT_PACKING_BYTE)
+ | BLT_BR00_DST_TILING_ENABLE(tiling_mode != I915_TILING_NONE)
+ | BLT_BR00_DWORD_LENGTH(2),
+
+ BLT_BR22_DST_Y1(dst_y1) | BLT_BR22_DST_X1(dst_x1),
+ BLT_BR23_DST_Y2(dst_y2) | BLT_BR23_DST_X2(dst_x2),
+ BLT_BR12_SRC_ADDRESS(src->offset + src_offset)
+ );
+
+ return INTEL_BATCH_SUCCESS;
+}
+
+static inline int xy_text_immediate_blt(struct intel_batch * batch,
+ drm_intel_bo * dst,
+ int16_t dst_x1, int16_t dst_y1,
+ int16_t dst_x2, int16_t dst_y2,
+ uint16_t count, uint32_t * immediates)
+{
+ /* Round up to the next even number. */
+ uint8_t dwords = (count + 1) & ~1;
+ uint32_t index;
+ uint32_t tiling_mode, swizzle_mode;
+
+ if (!intel_batch_check_space(batch, 3 + dwords))
+ return INTEL_BATCH_NO_SPACE;
+
+ drm_intel_bo_get_tiling(dst, &tiling_mode, &swizzle_mode);
+
+ intel_batch_add_dwords(batch, 3,
+ BLT_BR00_CLIENT(INTEL_CLIENT_BLT)
+ | BLT_BR00_OP(BLT_OP_XY_TEXT_IMMEDIATE_BLT)
+ | BLT_BR00_PACKING(BLT_PACKING_BYTE)
+ | BLT_BR00_DST_TILING_ENABLE(tiling_mode != I915_TILING_NONE)
+ | BLT_BR00_DWORD_LENGTH(1 + dwords),
+
+ BLT_BR22_DST_Y1(dst_y1) | BLT_BR22_DST_X1(dst_x1),
+ BLT_BR23_DST_Y2(dst_y2) | BLT_BR23_DST_X2(dst_x2)
+ );
+
+ for (index = 0; index < count; ++index)
+ intel_batch_add_dword(batch, *immediates++);
+
+ /* From BLT engine documentation:
+ *
+ * The IMMEDIATE_BLT data MUST transfer an even number of doublewords. The
+ * BLT engine will hang if it does not get an even number of doublewords. */
+ if (count & 1)
+ intel_batch_add_dword(batch, 0);
+
+ return INTEL_BATCH_SUCCESS;
+}
+
+static inline void xy_src_copy_blt(struct intel_batch * batch,
+ drm_intel_bo * src, uint16_t src_pitch,
+ uint16_t src_x, uint16_t src_y,
+ drm_intel_bo * dst, uint16_t dst_pitch,
+ uint16_t dst_x, uint16_t dst_y,
+ uint16_t width, uint16_t height)
+{
+ uint32_t src_tiling_mode, dst_tiling_mode, swizzle;
+
+ intel_batch_ensure_space(batch, 8);
+
+ drm_intel_bo_get_tiling(dst, &dst_tiling_mode, &swizzle);
+ drm_intel_bo_get_tiling(src, &src_tiling_mode, &swizzle);
+
+ drm_intel_bo_emit_reloc_fence
+ (batch->bo, intel_batch_offset(batch, 4), dst, 0,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ drm_intel_bo_emit_reloc_fence
+ (batch->bo, intel_batch_offset(batch, 7), src, 0,
+ I915_GEM_DOMAIN_RENDER, 0);
+
+ intel_batch_add_dwords(batch, 8,
+ BLT_BR00_CLIENT(INTEL_CLIENT_BLT)
+ | BLT_BR00_OP(BLT_OP_XY_SRC_COPY_BLT)
+ | BLT_BR00_32BPP_MASK(BLT_32BPP_MASK_ALPHA | BLT_32BPP_MASK_RGB)
+ | BLT_BR00_SRC_TILING_ENABLE(src_tiling_mode != I915_TILING_NONE)
+ | BLT_BR00_DST_TILING_ENABLE(dst_tiling_mode != I915_TILING_NONE)
+ | BLT_BR00_DWORD_LENGTH(6),
+
+ BLT_BR13_CLIPPING_ENABLE(false)
+ | BLT_BR13_COLOR_DEPTH(BLT_COLOR_DEPTH_32BIT)
+ | BLT_BR13_RASTER_OPERATION(BLT_RASTER_OPERATION_SRC)
+ | BLT_BR13_DST_PITCH(dst_tiling_mode == I915_TILING_NONE
+ ? dst_pitch : dst_pitch >> 2),
+
+ BLT_BR22_DST_Y1(dst_y) | BLT_BR22_DST_X1(dst_x),
+
+ BLT_BR23_DST_Y2(dst_y + height)
+ | BLT_BR23_DST_X2(dst_x + width),
+
+ BLT_BR09_DST_ADDRESS(dst->offset),
+ BLT_BR26_SRC_Y1(src_y) | BLT_BR26_SRC_X1(src_x),
+ BLT_BR11_SRC_PITCH(src_tiling_mode == I915_TILING_NONE
+ ? src_pitch : src_pitch >> 2),
+ BLT_BR12_SRC_ADDRESS(src->offset)
+ );
+}
+
+static inline void xy_color_blt(struct intel_batch * batch,
+ drm_intel_bo * dst, uint16_t dst_pitch,
+ uint16_t dst_x1, uint16_t dst_y1,
+ uint16_t dst_x2, uint16_t dst_y2,
+ uint32_t color)
+{
+ uint32_t tiling_mode, swizzle_mode;
+
+ intel_batch_ensure_space(batch, 6);
+
+ drm_intel_bo_get_tiling(dst, &tiling_mode, &swizzle_mode);
+
+ drm_intel_bo_emit_reloc_fence
+ (batch->bo, intel_batch_offset(batch, 4), dst, 0,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+
+ intel_batch_add_dwords(batch, 6,
+ BLT_BR00_CLIENT(INTEL_CLIENT_BLT)
+ | BLT_BR00_OP(BLT_OP_XY_COLOR_BLT)
+ | BLT_BR00_32BPP_MASK(BLT_32BPP_MASK_ALPHA | BLT_32BPP_MASK_RGB)
+ | BLT_BR00_DST_TILING_ENABLE(tiling_mode != I915_TILING_NONE)
+ | BLT_BR00_DWORD_LENGTH(4),
+
+ BLT_BR13_CLIPPING_ENABLE(false)
+ | BLT_BR13_COLOR_DEPTH(BLT_COLOR_DEPTH_32BIT)
+ | BLT_BR13_RASTER_OPERATION(BLT_RASTER_OPERATION_PAT)
+ | BLT_BR13_DST_PITCH(tiling_mode == I915_TILING_NONE
+ ? dst_pitch : dst_pitch >> 2),
+
+ BLT_BR22_DST_Y1(dst_y1) | BLT_BR22_DST_X1(dst_x1),
+ BLT_BR23_DST_Y2(dst_y2) | BLT_BR23_DST_X2(dst_x2),
+ BLT_BR09_DST_ADDRESS(dst->offset),
+ BLT_BR16_COLOR(color)
+ );
+}
+
+#endif
+
diff --git a/src/wld/intel/i965_pci_ids.h b/src/wld/intel/i965_pci_ids.h
new file mode 100644
index 0000000..9d38a4a
--- /dev/null
+++ b/src/wld/intel/i965_pci_ids.h
@@ -0,0 +1,93 @@
+CHIPSET(0x29A2, i965, "Intel(R) 965G")
+CHIPSET(0x2992, i965, "Intel(R) 965Q")
+CHIPSET(0x2982, i965, "Intel(R) 965G")
+CHIPSET(0x2972, i965, "Intel(R) 946GZ")
+CHIPSET(0x2A02, i965, "Intel(R) 965GM")
+CHIPSET(0x2A12, i965, "Intel(R) 965GME/GLE")
+CHIPSET(0x2A42, g4x, "Mobile Intel® GM45 Express Chipset")
+CHIPSET(0x2E02, g4x, "Intel(R) Integrated Graphics Device")
+CHIPSET(0x2E12, g4x, "Intel(R) Q45/Q43")
+CHIPSET(0x2E22, g4x, "Intel(R) G45/G43")
+CHIPSET(0x2E32, g4x, "Intel(R) G41")
+CHIPSET(0x2E42, g4x, "Intel(R) B43")
+CHIPSET(0x2E92, g4x, "Intel(R) B43")
+CHIPSET(0x0042, ilk, "Intel(R) Ironlake Desktop")
+CHIPSET(0x0046, ilk, "Intel(R) Ironlake Mobile")
+CHIPSET(0x0102, snb_gt1, "Intel(R) Sandybridge Desktop")
+CHIPSET(0x0112, snb_gt2, "Intel(R) Sandybridge Desktop")
+CHIPSET(0x0122, snb_gt2, "Intel(R) Sandybridge Desktop")
+CHIPSET(0x0106, snb_gt1, "Intel(R) Sandybridge Mobile")
+CHIPSET(0x0116, snb_gt2, "Intel(R) Sandybridge Mobile")
+CHIPSET(0x0126, snb_gt2, "Intel(R) Sandybridge Mobile")
+CHIPSET(0x010A, snb_gt1, "Intel(R) Sandybridge Server")
+CHIPSET(0x0152, ivb_gt1, "Intel(R) Ivybridge Desktop")
+CHIPSET(0x0162, ivb_gt2, "Intel(R) Ivybridge Desktop")
+CHIPSET(0x0156, ivb_gt1, "Intel(R) Ivybridge Mobile")
+CHIPSET(0x0166, ivb_gt2, "Intel(R) Ivybridge Mobile")
+CHIPSET(0x015a, ivb_gt1, "Intel(R) Ivybridge Server")
+CHIPSET(0x016a, ivb_gt2, "Intel(R) Ivybridge Server")
+CHIPSET(0x0402, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0412, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0422, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0406, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0416, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0426, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x040A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x041A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x042A, hsw_gt3, "Intel(R) Haswell Server")
+CHIPSET(0x040B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x041B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x042B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x040E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x041E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x042E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0C02, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0C12, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0C22, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0C06, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0C16, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0C26, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x0C0A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x0C1A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x0C2A, hsw_gt3, "Intel(R) Haswell Server")
+CHIPSET(0x0C0B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0C1B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0C2B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0C0E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0C1E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0C2E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0A02, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0A12, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0A22, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0A06, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0A16, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0A26, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x0A0A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x0A1A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x0A2A, hsw_gt3, "Intel(R) Haswell Server")
+CHIPSET(0x0A0B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0A1B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0A2B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0A0E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0A1E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0A2E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0D02, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0D12, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0D22, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0D06, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0D16, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0D26, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x0D0A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x0D1A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x0D2A, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0D0B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0D1B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0D2B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0D0E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0D1E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0D2E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0F31, byt, "Intel(R) Bay Trail")
+CHIPSET(0x0F32, byt, "Intel(R) Bay Trail")
+CHIPSET(0x0F33, byt, "Intel(R) Bay Trail")
+CHIPSET(0x0157, byt, "Intel(R) Bay Trail")
+CHIPSET(0x0155, byt, "Intel(R) Bay Trail")
diff --git a/src/wld/intel/local.mk b/src/wld/intel/local.mk
new file mode 100644
index 0000000..f1ac032
--- /dev/null
+++ b/src/wld/intel/local.mk
@@ -0,0 +1,6 @@
+# wld: intel/local.mk
+
+dir := intel
+
+include common.mk
+
diff --git a/src/wld/intel/mi.h b/src/wld/intel/mi.h
new file mode 100644
index 0000000..5c830c7
--- /dev/null
+++ b/src/wld/intel/mi.h
@@ -0,0 +1,50 @@
+/* wld: intel/mi.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_INTEL_MI_H
+#define WLD_INTEL_MI_H
+
+#define INTEL_CLIENT_MI 0x0
+
+#define MI_OP(opcode) ( \
+ INTEL_CLIENT_MI << 29 /* 31:29 */ \
+ | opcode << 23 /* 28:23 */ \
+)
+
+#define MI_NOOP MI_OP(0x00)
+#define MI_FLUSH MI_OP(0x04)
+#define MI_BATCH_BUFFER_END MI_OP(0x0A)
+
+/* MI_NOOP */
+#define MI_NOOP_IDENTIFICATION_NUMBER(number) (1 << 22 | number)
+
+/* MI_FLUSH */
+#define MI_FLUSH_ENABLE_PROTECTED_MEMORY (1 << 6)
+#define MI_FLUSH_DISABLE_INDIRECT_STATE_POINTERS (1 << 5)
+#define MI_FLUSH_CLEAR_GENERIC_MEDIA_STATE (1 << 4)
+#define MI_FLUSH_RESET_GLOBAL_SNAPSHOT_COUNT (1 << 3)
+#define MI_FLUSH_INHIBIT_RENDER_CACHE_FLUSH (1 << 2)
+#define MI_FLUSH_INVALIDATE_STATE_INSTRUCTION_CACHE (1 << 1)
+
+#endif
+
diff --git a/src/wld/interface/buffer.h b/src/wld/interface/buffer.h
new file mode 100644
index 0000000..03c6ffc
--- /dev/null
+++ b/src/wld/interface/buffer.h
@@ -0,0 +1,33 @@
+/* wld: interface/buffer.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+static bool buffer_map(struct buffer * drawable);
+static bool buffer_unmap(struct buffer * drawable);
+static void buffer_destroy(struct buffer * drawable);
+
+static const struct wld_buffer_impl wld_buffer_impl = {
+ .map = &buffer_map,
+ .unmap = &buffer_unmap,
+ .destroy = &buffer_destroy
+};
+
diff --git a/src/wld/interface/context.h b/src/wld/interface/context.h
new file mode 100644
index 0000000..a40dac1
--- /dev/null
+++ b/src/wld/interface/context.h
@@ -0,0 +1,50 @@
+/* wld: interface/context.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+static struct wld_renderer * context_create_renderer
+ (struct wld_context * context);
+static struct buffer * context_create_buffer
+ (struct wld_context * context,
+ uint32_t width, uint32_t height, uint32_t format, uint32_t flags);
+static struct buffer * context_import_buffer
+ (struct wld_context * context, uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height, uint32_t format, uint32_t pitch);
+#ifdef CONTEXT_IMPLEMENTS_CREATE_SURFACE
+static struct wld_surface * context_create_surface
+ (struct wld_context * context,
+ uint32_t width, uint32_t height, uint32_t format, uint32_t flags);
+#endif
+static void context_destroy(struct wld_context * context);
+
+static const struct wld_context_impl wld_context_impl = {
+ .create_renderer = &context_create_renderer,
+ .create_buffer = &context_create_buffer,
+ .import_buffer = &context_import_buffer,
+#ifdef CONTEXT_IMPLEMENTS_CREATE_SURFACE
+ .create_surface = &context_create_surface,
+#else
+ .create_surface = &default_create_surface,
+#endif
+ .destroy = &context_destroy
+};
+
diff --git a/src/wld/interface/drm.h b/src/wld/interface/drm.h
new file mode 100644
index 0000000..6f815ad
--- /dev/null
+++ b/src/wld/interface/drm.h
@@ -0,0 +1,43 @@
+/* wld: interface/drm.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef DRM_DRIVER_NAME
+# error "You must define DRM_DRIVER_NAME before including interface/drm.h"
+#endif
+
+/* DRM driver */
+static bool driver_device_supported(uint32_t vendor_id, uint32_t device_id);
+static struct wld_context * driver_create_context(int drm_fd);
+
+#define EXPAND(f, x) f(x)
+#define VAR(name) name ## _drm_driver
+#define STRING(name) # name
+const struct drm_driver EXPAND(VAR, DRM_DRIVER_NAME) = {
+ .name = EXPAND(STRING, DRM_DRIVER_NAME),
+ .device_supported = &driver_device_supported,
+ .create_context = &driver_create_context,
+};
+#undef VAR
+#undef STRING
+#undef EXPAND
+
diff --git a/src/wld/interface/renderer.h b/src/wld/interface/renderer.h
new file mode 100644
index 0000000..557b693
--- /dev/null
+++ b/src/wld/interface/renderer.h
@@ -0,0 +1,68 @@
+/* wld: interface/drawable.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+static uint32_t renderer_capabilities(struct wld_renderer * renderer,
+ struct buffer * buffer);
+static bool renderer_set_target(struct wld_renderer * renderer,
+ struct buffer * buffer);
+static void renderer_fill_rectangle(struct wld_renderer * renderer,
+ uint32_t color, int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+static void renderer_copy_rectangle(struct wld_renderer * renderer,
+ struct buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ int32_t src_x, int32_t src_y,
+ uint32_t width, uint32_t height);
+#ifdef RENDERER_IMPLEMENTS_REGION
+static void renderer_fill_region(struct wld_renderer * base, uint32_t color,
+ pixman_region32_t * region);
+static void renderer_copy_region(struct wld_renderer * base,
+ struct buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ pixman_region32_t * region);
+#endif
+static void renderer_draw_text(struct wld_renderer * renderer,
+ struct font * font, uint32_t color,
+ int32_t x, int32_t y,
+ const char * text, uint32_t length,
+ struct wld_extents * extents);
+static void renderer_flush(struct wld_renderer * renderer);
+static void renderer_destroy(struct wld_renderer * renderer);
+
+static const struct wld_renderer_impl wld_renderer_impl = {
+ .capabilities = &renderer_capabilities,
+ .set_target = &renderer_set_target,
+ .fill_rectangle = &renderer_fill_rectangle,
+ .copy_rectangle = &renderer_copy_rectangle,
+#ifdef RENDERER_IMPLEMENTS_REGION
+ .fill_region = &renderer_fill_region,
+ .copy_region = &renderer_copy_region,
+#else
+ .fill_region = &default_fill_region,
+ .copy_region = &default_copy_region,
+#endif
+ .draw_text = &renderer_draw_text,
+ .flush = &renderer_flush,
+ .destroy = &renderer_destroy
+};
+
diff --git a/src/wld/interface/surface.h b/src/wld/interface/surface.h
new file mode 100644
index 0000000..5e10ada
--- /dev/null
+++ b/src/wld/interface/surface.h
@@ -0,0 +1,41 @@
+/* wld: interface/surface.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+static pixman_region32_t * surface_damage(struct wld_surface * surface,
+ pixman_region32_t * new_damage);
+static struct buffer * surface_back(struct wld_surface * surface);
+static struct buffer * surface_take(struct wld_surface * surface);
+static bool surface_release(struct wld_surface * surface,
+ struct buffer * buffer);
+static bool surface_swap(struct wld_surface * surface);
+static void surface_destroy(struct wld_surface * surface);
+
+static const struct wld_surface_impl wld_surface_impl = {
+ .damage = &surface_damage,
+ .back = &surface_back,
+ .take = &surface_take,
+ .release = &surface_release,
+ .swap = &surface_swap,
+ .destroy = &surface_destroy
+};
+
diff --git a/src/wld/interface/wayland.h b/src/wld/interface/wayland.h
new file mode 100644
index 0000000..f457932
--- /dev/null
+++ b/src/wld/interface/wayland.h
@@ -0,0 +1,41 @@
+/* wld: interface/wayland.h
+ *
+ * Copyright (c) 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WAYLAND_IMPL_NAME
+# error you must define WAYLAND_IMPL_NAME before including interface/wayland.h
+#endif
+
+static struct wayland_context * wayland_create_context
+ (struct wl_display * display, struct wl_event_queue * queue);
+static bool wayland_has_format(struct wld_context * context, uint32_t format);
+
+#define EXPAND(f, x) f(x)
+#define VAR(name) name ## _wayland_impl
+const struct wayland_impl EXPAND(VAR, WAYLAND_IMPL_NAME) = {
+ .create_context = &wayland_create_context,
+ .has_format = &wayland_has_format,
+ //.create_surface = &wayland_create_surface,
+};
+#undef VAR
+#undef EXPAND
+
diff --git a/src/wld/nouveau/g80_2d.xml.h b/src/wld/nouveau/g80_2d.xml.h
new file mode 100644
index 0000000..9ac44a3
--- /dev/null
+++ b/src/wld/nouveau/g80_2d.xml.h
@@ -0,0 +1,547 @@
+#ifndef G80_2D_XML
+#define G80_2D_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/envytools/envytools/
+git clone https://github.com/envytools/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/michael/src/envytools/rnndb/root.xml ( 514 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/copyright.xml ( 6452 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv_mmio.xml ( 7175 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/nvchipsets.xml ( 2759 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/bus/pmc.xml ( 11361 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pbus.xml ( 19778 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/g80_defs.xml ( 18175 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/g80_vm.xml ( 9832 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv_vga.xml ( 13101 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pci.xml ( 17513 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv1_pfifo.xml ( 10542 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv4_pfifo.xml ( 24010 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/g80_pfifo.xml ( 23184 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/gf100_pfifo.xml ( 26735 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_vm.xml ( 8722 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/nv40_pclock.xml ( 1166 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/g80_pclock.xml ( 16434 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/gt215_pclock.xml ( 4960 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/nv10_pvideo.xml ( 2468 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/ptimer.xml ( 2285 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv10_pcounter.xml ( 5914 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv40_pcounter.xml ( 9663 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pmpeg.xml ( 12735 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pvpe.xml ( 703 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/mpeg_fifo.xml ( 2614 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/nv_object.xml ( 15326 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pme.xml ( 5105 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/nv17_ptv.xml ( 457 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pnvio.xml ( 31893 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pvp1.xml ( 2108 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pvp2.xml ( 1615 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/xtensa.xml ( 5390 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/ptherm.xml ( 34788 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/bus/pfuse.xml ( 1158 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/punits.xml ( 4661 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp3/pvld.xml ( 13271 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/falcon.xml ( 17092 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/falcon_crypt.xml ( 3446 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp3/ppdec.xml ( 14150 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp3/pppp.xml ( 8842 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/nv_defs.xml ( 4399 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp3/psec.xml ( 993 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/g84_punk089.xml ( 448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_prmvio.xml ( 651 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv1_pdma.xml ( 5339 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv3_pfb.xml ( 4493 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv10_pfb.xml ( 18821 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv_pfb.xml ( 1135 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/g80_pfb.xml ( 11139 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pffb.xml ( 2712 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pstraps.xml ( 8118 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pcipher.xml ( 3572 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pbsp.xml ( 10610 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/pcopy.xml ( 7877 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/gt215_pcodec.xml ( 449 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/gt215_pkfuse.xml ( 448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/pdaemon.xml ( 19259 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/10e000.xml ( 1185 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/memory/gf100_pbfb.xml ( 3917 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pibus.xml ( 8545 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/gf100_pclock.xml ( 7338 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/memory/gf100_pp2p.xml ( 1949 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pxbar.xml ( 1516 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pmfb.xml ( 3646 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/gf100_pcounter.xml ( 12713 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/pvcomp.xml ( 8687 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/pvenc.xml ( 1416 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/gf119_punk1c3.xml ( 981 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pmedia.xml ( 432 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv1_paudio.xml ( 1862 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/extdev/ad1848.xml ( 5260 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv1_pgraph.xml ( 14207 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv1_2d.xml ( 36532 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_pgraph.xml ( 4004 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_pgraph.xml ( 11327 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/pgraph.xml ( 31568 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/tpc.xml ( 6832 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/mpc.xml ( 6373 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/mp.xml ( 16762 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/pgraph.xml ( 26735 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/hw_blk.xml ( 760 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/ctxctl.xml ( 13155 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/gpc.xml ( 13114 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/tpc.xml ( 22154 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/ppc.xml ( 2131 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/rop.xml ( 5134 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_pdma.xml ( 2290 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv1_pfb.xml ( 4030 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_pcrtc.xml ( 1108 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv1_pram.xml ( 1235 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pchipid.xml ( 493 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv1_pdac.xml ( 4628 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/peeprom.xml ( 702 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_pramdac.xml ( 4419 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/g80_pdisplay.xml ( 39075 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/prm.xml ( 5094 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv_evo.xml ( 10448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv_objects.xml ( 1053 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv_m2mf.xml ( 2691 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_m2mf.xml ( 2783 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_dvd.xml ( 2994 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_3d.xml ( 5197 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_3d.xml ( 17716 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv_3ddefs.xml ( 16390 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv10_3d.xml ( 18416 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv20_3d.xml ( 21096 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv30-40_3d.xml ( 32451 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_2d.xml ( 11440 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_3d.xml ( 65900 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_compute.xml ( 14027 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_3d.xml ( 59845 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gk104_p2mf.xml ( 2376 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_compute.xml ( 11143 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gk104_compute.xml ( 10182 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/me_fifo.xml ( 1685 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/vp1_fifo.xml ( 670 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/cipher_fifo.xml ( 2071 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/gk104_copy.xml ( 3938 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_texture.xml ( 8881 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_shaders.xml ( 9244 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/mpeg_cmd.xml ( 7682 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/extdev/adt7473.xml ( 11411 bytes, from 2014-11-02 20:39:42)
+
+Copyright (C) 2006-2014 by the following authors:
+- Artur Huillet <arthur.huillet@free.fr> (ahuillet)
+- Ben Skeggs (darktama, darktama_)
+- B. R. <koala_br@users.sourceforge.net> (koala_br)
+- Carlos Martin <carlosmn@users.sf.net> (carlosmn)
+- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr)
+- Dawid Gajownik <gajownik@users.sf.net> (gajownik)
+- Dmitry Baryshkov
+- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag)
+- EdB <edb_@users.sf.net> (edb_)
+- Erik Waling <erikwailing@users.sf.net> (erikwaling)
+- Francisco Jerez <currojerez@riseup.net> (curro)
+- imirkin <imirkin@users.sf.net> (imirkin)
+- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome)
+- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy)
+- Laurent Carlier <lordheavym@gmail.com> (lordheavy)
+- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1)
+- Maarten Maathuis <madman2003@gmail.com> (stillunknown)
+- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin)
+- Mark Carey <mark.carey@gmail.com> (careym)
+- Matthieu Castet <matthieu.castet@parrot.com> (mat-c)
+- nvidiaman <nvidiaman@users.sf.net> (nvidiaman)
+- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata)
+- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen)
+- Peter Popov <ironpeter@users.sf.net> (ironpeter)
+- Richard Hughes <hughsient@users.sf.net> (hughsient)
+- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar)
+- Serge Martin
+- Simon Raffeiner
+- Stephane Loeuillet <leroutier@users.sf.net> (leroutier)
+- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu)
+- sturmflut <sturmflut@users.sf.net> (sturmflut)
+- Sylvain Munaut <tnt@246tNt.com>
+- Victor Stinner <victor.stinner@haypocalc.com> (haypo)
+- Wladmir van der Laan <laanwj@gmail.com> (miathan6)
+- Younes Manton <younes.m@gmail.com> (ymanton)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+
+
+#define G80_2D_DMA_NOTIFY 0x00000180
+
+#define G80_2D_DMA_DST 0x00000184
+
+#define G80_2D_DMA_SRC 0x00000188
+
+#define G80_2D_DMA_COND 0x0000018c
+
+#define G80_2D_DST_FORMAT 0x00000200
+
+#define G80_2D_DST_LINEAR 0x00000204
+
+#define G80_2D_DST_TILE_MODE 0x00000208
+
+#define G80_2D_DST_DEPTH 0x0000020c
+
+#define G80_2D_DST_LAYER 0x00000210
+
+#define G80_2D_DST_PITCH 0x00000214
+
+#define G80_2D_DST_WIDTH 0x00000218
+
+#define G80_2D_DST_HEIGHT 0x0000021c
+
+#define G80_2D_DST_ADDRESS_HIGH 0x00000220
+
+#define G80_2D_DST_ADDRESS_LOW 0x00000224
+
+#define G80_2D_UNK228 0x00000228
+
+#define GF100_2D_UNK228 0x00000228
+
+#define GF100_2D_UNK22C 0x0000022c
+
+#define G80_2D_SRC_FORMAT 0x00000230
+
+#define G80_2D_SRC_LINEAR 0x00000234
+
+#define G80_2D_SRC_TILE_MODE 0x00000238
+
+#define G80_2D_SRC_DEPTH 0x0000023c
+
+#define G80_2D_SRC_LAYER 0x00000240
+
+#define GF100_2D_UNK0240 0x00000240
+
+#define G80_2D_SRC_PITCH 0x00000244
+#define G80_2D_SRC_PITCH__MAX 0x00040000
+
+#define G80_2D_SRC_WIDTH 0x00000248
+#define G80_2D_SRC_WIDTH__MAX 0x00010000
+
+#define G80_2D_SRC_HEIGHT 0x0000024c
+#define G80_2D_SRC_HEIGHT__MAX 0x00010000
+
+#define G80_2D_SRC_ADDRESS_HIGH 0x00000250
+
+#define G80_2D_SRC_ADDRESS_LOW 0x00000254
+
+#define G80_2D_UNK258 0x00000258
+
+#define GF100_2D_UNK25C 0x0000025c
+
+#define G80_2D_UNK260 0x00000260
+
+#define GF100_2D_SINGLE_GPC 0x00000260
+
+#define G80_2D_COND_ADDRESS_HIGH 0x00000264
+
+#define G80_2D_COND_ADDRESS_LOW 0x00000268
+
+#define G80_2D_COND_MODE 0x0000026c
+#define G80_2D_COND_MODE_NEVER 0x00000000
+#define G80_2D_COND_MODE_ALWAYS 0x00000001
+#define G80_2D_COND_MODE_RES_NON_ZERO 0x00000002
+#define G80_2D_COND_MODE_EQUAL 0x00000003
+#define G80_2D_COND_MODE_NOT_EQUAL 0x00000004
+
+#define GF100_2D_UNK0270(i0) (0x00000270 + 0x4*(i0))
+#define GF100_2D_UNK0270__ESIZE 0x00000004
+#define GF100_2D_UNK0270__LEN 0x00000004
+
+#define G80_2D_CLIP_X 0x00000280
+
+#define G80_2D_CLIP_Y 0x00000284
+
+#define G80_2D_CLIP_W 0x00000288
+
+#define G80_2D_CLIP_H 0x0000028c
+
+#define G80_2D_CLIP_ENABLE 0x00000290
+
+#define G80_2D_COLOR_KEY_FORMAT 0x00000294
+#define G80_2D_COLOR_KEY_FORMAT_16BPP 0x00000000
+#define G80_2D_COLOR_KEY_FORMAT_15BPP 0x00000001
+#define G80_2D_COLOR_KEY_FORMAT_24BPP 0x00000002
+#define G80_2D_COLOR_KEY_FORMAT_30BPP 0x00000003
+#define G80_2D_COLOR_KEY_FORMAT_8BPP 0x00000004
+#define G80_2D_COLOR_KEY_FORMAT_16BPP2 0x00000005
+#define G80_2D_COLOR_KEY_FORMAT_32BPP 0x00000006
+
+#define G80_2D_COLOR_KEY 0x00000298
+
+#define G80_2D_COLOR_KEY_ENABLE 0x0000029c
+
+#define G80_2D_ROP 0x000002a0
+
+#define G80_2D_BETA1 0x000002a4
+#define G80_2D_BETA1_BETA1__MASK 0x7f800000
+#define G80_2D_BETA1_BETA1__SHIFT 23
+
+#define G80_2D_BETA4 0x000002a8
+#define G80_2D_BETA4_B__MASK 0x000000ff
+#define G80_2D_BETA4_B__SHIFT 0
+#define G80_2D_BETA4_G__MASK 0x0000ff00
+#define G80_2D_BETA4_G__SHIFT 8
+#define G80_2D_BETA4_R__MASK 0x00ff0000
+#define G80_2D_BETA4_R__SHIFT 16
+#define G80_2D_BETA4_A__MASK 0xff000000
+#define G80_2D_BETA4_A__SHIFT 24
+
+#define G80_2D_OPERATION 0x000002ac
+#define G80_2D_OPERATION_SRCCOPY_AND 0x00000000
+#define G80_2D_OPERATION_ROP_AND 0x00000001
+#define G80_2D_OPERATION_BLEND 0x00000002
+#define G80_2D_OPERATION_SRCCOPY 0x00000003
+#define G80_2D_OPERATION_ROP 0x00000004
+#define G80_2D_OPERATION_SRCCOPY_PREMULT 0x00000005
+#define G80_2D_OPERATION_BLEND_PREMULT 0x00000006
+
+#define G80_2D_PATTERN_OFFSET 0x000002b0
+#define G80_2D_PATTERN_OFFSET_X__MASK 0x0000003f
+#define G80_2D_PATTERN_OFFSET_X__SHIFT 0
+#define G80_2D_PATTERN_OFFSET_Y__MASK 0x00003f00
+#define G80_2D_PATTERN_OFFSET_Y__SHIFT 8
+
+#define G80_2D_PATTERN_SELECT 0x000002b4
+#define G80_2D_PATTERN_SELECT_BITMAP_8X8 0x00000000
+#define G80_2D_PATTERN_SELECT_BITMAP_64X1 0x00000001
+#define G80_2D_PATTERN_SELECT_BITMAP_1X64 0x00000002
+#define G80_2D_PATTERN_SELECT_COLOR 0x00000003
+
+#define GF100_2D_UNK02B8(i0) (0x000002b8 + 0x4*(i0))
+#define GF100_2D_UNK02B8__ESIZE 0x00000004
+#define GF100_2D_UNK02B8__LEN 0x00000009
+
+#define GF100_2D_UNK2DC 0x000002dc
+
+#define GF100_2D_UNK2E0 0x000002e0
+
+#define GF100_2D_UNK02E4 0x000002e4
+
+#define G80_2D_PATTERN_COLOR_FORMAT 0x000002e8
+#define G80_2D_PATTERN_COLOR_FORMAT_A16R5G6B5 0x00000000
+#define G80_2D_PATTERN_COLOR_FORMAT_X16A1R5G5B5 0x00000001
+#define G80_2D_PATTERN_COLOR_FORMAT_A8R8G8B8 0x00000002
+#define G80_2D_PATTERN_COLOR_FORMAT_X16A8Y8 0x00000003
+#define G80_2D_PATTERN_COLOR_FORMAT_UNK4 0x00000004
+#define G80_2D_PATTERN_COLOR_FORMAT_UNK5 0x00000005
+
+#define G80_2D_PATTERN_BITMAP_FORMAT 0x000002ec
+#define G80_2D_PATTERN_BITMAP_FORMAT_CGA6 0x00000000
+#define G80_2D_PATTERN_BITMAP_FORMAT_LE 0x00000001
+
+#define G80_2D_PATTERN_BITMAP_COLOR(i0) (0x000002f0 + 0x4*(i0))
+#define G80_2D_PATTERN_BITMAP_COLOR__ESIZE 0x00000004
+#define G80_2D_PATTERN_BITMAP_COLOR__LEN 0x00000002
+
+#define G80_2D_PATTERN_BITMAP(i0) (0x000002f8 + 0x4*(i0))
+#define G80_2D_PATTERN_BITMAP__ESIZE 0x00000004
+#define G80_2D_PATTERN_BITMAP__LEN 0x00000002
+
+#define G80_2D_PATTERN_X8R8G8B8(i0) (0x00000300 + 0x4*(i0))
+#define G80_2D_PATTERN_X8R8G8B8__ESIZE 0x00000004
+#define G80_2D_PATTERN_X8R8G8B8__LEN 0x00000040
+#define G80_2D_PATTERN_X8R8G8B8_B__MASK 0x000000ff
+#define G80_2D_PATTERN_X8R8G8B8_B__SHIFT 0
+#define G80_2D_PATTERN_X8R8G8B8_G__MASK 0x0000ff00
+#define G80_2D_PATTERN_X8R8G8B8_G__SHIFT 8
+#define G80_2D_PATTERN_X8R8G8B8_R__MASK 0x00ff0000
+#define G80_2D_PATTERN_X8R8G8B8_R__SHIFT 16
+
+#define G80_2D_PATTERN_R5G6B5(i0) (0x00000400 + 0x4*(i0))
+#define G80_2D_PATTERN_R5G6B5__ESIZE 0x00000004
+#define G80_2D_PATTERN_R5G6B5__LEN 0x00000020
+#define G80_2D_PATTERN_R5G6B5_B0__MASK 0x0000001f
+#define G80_2D_PATTERN_R5G6B5_B0__SHIFT 0
+#define G80_2D_PATTERN_R5G6B5_G0__MASK 0x000007e0
+#define G80_2D_PATTERN_R5G6B5_G0__SHIFT 5
+#define G80_2D_PATTERN_R5G6B5_R0__MASK 0x0000f800
+#define G80_2D_PATTERN_R5G6B5_R0__SHIFT 11
+#define G80_2D_PATTERN_R5G6B5_B1__MASK 0x001f0000
+#define G80_2D_PATTERN_R5G6B5_B1__SHIFT 16
+#define G80_2D_PATTERN_R5G6B5_G1__MASK 0x07e00000
+#define G80_2D_PATTERN_R5G6B5_G1__SHIFT 21
+#define G80_2D_PATTERN_R5G6B5_R1__MASK 0xf8000000
+#define G80_2D_PATTERN_R5G6B5_R1__SHIFT 27
+
+#define G80_2D_PATTERN_X1R5G5B5(i0) (0x00000480 + 0x4*(i0))
+#define G80_2D_PATTERN_X1R5G5B5__ESIZE 0x00000004
+#define G80_2D_PATTERN_X1R5G5B5__LEN 0x00000020
+#define G80_2D_PATTERN_X1R5G5B5_B0__MASK 0x0000001f
+#define G80_2D_PATTERN_X1R5G5B5_B0__SHIFT 0
+#define G80_2D_PATTERN_X1R5G5B5_G0__MASK 0x000003e0
+#define G80_2D_PATTERN_X1R5G5B5_G0__SHIFT 5
+#define G80_2D_PATTERN_X1R5G5B5_R0__MASK 0x00007c00
+#define G80_2D_PATTERN_X1R5G5B5_R0__SHIFT 10
+#define G80_2D_PATTERN_X1R5G5B5_B1__MASK 0x001f0000
+#define G80_2D_PATTERN_X1R5G5B5_B1__SHIFT 16
+#define G80_2D_PATTERN_X1R5G5B5_G1__MASK 0x03e00000
+#define G80_2D_PATTERN_X1R5G5B5_G1__SHIFT 21
+#define G80_2D_PATTERN_X1R5G5B5_R1__MASK 0x7c000000
+#define G80_2D_PATTERN_X1R5G5B5_R1__SHIFT 26
+
+#define G80_2D_PATTERN_Y8(i0) (0x00000500 + 0x4*(i0))
+#define G80_2D_PATTERN_Y8__ESIZE 0x00000004
+#define G80_2D_PATTERN_Y8__LEN 0x00000010
+#define G80_2D_PATTERN_Y8_Y0__MASK 0x000000ff
+#define G80_2D_PATTERN_Y8_Y0__SHIFT 0
+#define G80_2D_PATTERN_Y8_Y1__MASK 0x0000ff00
+#define G80_2D_PATTERN_Y8_Y1__SHIFT 8
+#define G80_2D_PATTERN_Y8_Y2__MASK 0x00ff0000
+#define G80_2D_PATTERN_Y8_Y2__SHIFT 16
+#define G80_2D_PATTERN_Y8_Y3__MASK 0xff000000
+#define G80_2D_PATTERN_Y8_Y3__SHIFT 24
+
+#define GF100_2D_DRAW_COLOR_LONG(i0) (0x00000540 + 0x4*(i0))
+#define GF100_2D_DRAW_COLOR_LONG__ESIZE 0x00000004
+#define GF100_2D_DRAW_COLOR_LONG__LEN 0x00000004
+
+#define G80_2D_DRAW_SHAPE 0x00000580
+#define G80_2D_DRAW_SHAPE_POINTS 0x00000000
+#define G80_2D_DRAW_SHAPE_LINES 0x00000001
+#define G80_2D_DRAW_SHAPE_LINE_STRIP 0x00000002
+#define G80_2D_DRAW_SHAPE_TRIANGLES 0x00000003
+#define G80_2D_DRAW_SHAPE_RECTANGLES 0x00000004
+
+#define G80_2D_DRAW_COLOR_FORMAT 0x00000584
+
+#define G80_2D_DRAW_COLOR 0x00000588
+
+#define G80_2D_UNK58C 0x0000058c
+#define G80_2D_UNK58C_0 0x00000001
+#define G80_2D_UNK58C_1 0x00000010
+#define G80_2D_UNK58C_2 0x00000100
+#define G80_2D_UNK58C_3 0x00001000
+
+#define G80_2D_DRAW_POINT16 0x000005e0
+#define G80_2D_DRAW_POINT16_X__MASK 0x0000ffff
+#define G80_2D_DRAW_POINT16_X__SHIFT 0
+#define G80_2D_DRAW_POINT16_Y__MASK 0xffff0000
+#define G80_2D_DRAW_POINT16_Y__SHIFT 16
+
+#define G80_2D_DRAW_POINT32_X(i0) (0x00000600 + 0x8*(i0))
+#define G80_2D_DRAW_POINT32_X__ESIZE 0x00000008
+#define G80_2D_DRAW_POINT32_X__LEN 0x00000040
+
+#define G80_2D_DRAW_POINT32_Y(i0) (0x00000604 + 0x8*(i0))
+#define G80_2D_DRAW_POINT32_Y__ESIZE 0x00000008
+#define G80_2D_DRAW_POINT32_Y__LEN 0x00000040
+
+#define G80_2D_SIFC_BITMAP_ENABLE 0x00000800
+
+#define G80_2D_SIFC_FORMAT 0x00000804
+
+#define G80_2D_SIFC_BITMAP_FORMAT 0x00000808
+#define G80_2D_SIFC_BITMAP_FORMAT_I1 0x00000000
+#define G80_2D_SIFC_BITMAP_FORMAT_I4 0x00000001
+#define G80_2D_SIFC_BITMAP_FORMAT_I8 0x00000002
+
+#define G80_2D_SIFC_BITMAP_LSB_FIRST 0x0000080c
+
+#define G80_2D_SIFC_BITMAP_LINE_PACK_MODE 0x00000810
+#define G80_2D_SIFC_BITMAP_LINE_PACK_MODE_PACKED 0x00000000
+#define G80_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_BYTE 0x00000001
+#define G80_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_WORD 0x00000002
+
+#define G80_2D_SIFC_BITMAP_COLOR_BIT0 0x00000814
+
+#define G80_2D_SIFC_BITMAP_COLOR_BIT1 0x00000818
+
+#define G80_2D_SIFC_BITMAP_WRITE_BIT0_ENABLE 0x0000081c
+
+#define G80_2D_SIFC_WIDTH 0x00000838
+
+#define G80_2D_SIFC_HEIGHT 0x0000083c
+
+#define G80_2D_SIFC_DX_DU_FRACT 0x00000840
+
+#define G80_2D_SIFC_DX_DU_INT 0x00000844
+
+#define G80_2D_SIFC_DY_DV_FRACT 0x00000848
+
+#define G80_2D_SIFC_DY_DV_INT 0x0000084c
+
+#define G80_2D_SIFC_DST_X_FRACT 0x00000850
+
+#define G80_2D_SIFC_DST_X_INT 0x00000854
+
+#define G80_2D_SIFC_DST_Y_FRACT 0x00000858
+
+#define G80_2D_SIFC_DST_Y_INT 0x0000085c
+
+#define G80_2D_SIFC_DATA 0x00000860
+
+#define G80_2D_UNK0870 0x00000870
+
+#define G80_2D_UNK0880 0x00000880
+
+#define G80_2D_UNK0884 0x00000884
+
+#define G80_2D_UNK0888 0x00000888
+
+#define G80_2D_BLIT_CONTROL 0x0000088c
+#define G80_2D_BLIT_CONTROL_ORIGIN__MASK 0x00000001
+#define G80_2D_BLIT_CONTROL_ORIGIN__SHIFT 0
+#define G80_2D_BLIT_CONTROL_ORIGIN_CENTER 0x00000000
+#define G80_2D_BLIT_CONTROL_ORIGIN_CORNER 0x00000001
+#define G80_2D_BLIT_CONTROL_FILTER__MASK 0x00000010
+#define G80_2D_BLIT_CONTROL_FILTER__SHIFT 4
+#define G80_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE 0x00000000
+#define G80_2D_BLIT_CONTROL_FILTER_BILINEAR 0x00000010
+
+#define G80_2D_BLIT_DST_X 0x000008b0
+
+#define G80_2D_BLIT_DST_Y 0x000008b4
+
+#define G80_2D_BLIT_DST_W 0x000008b8
+
+#define G80_2D_BLIT_DST_H 0x000008bc
+
+#define G80_2D_BLIT_DU_DX_FRACT 0x000008c0
+
+#define G80_2D_BLIT_DU_DX_INT 0x000008c4
+
+#define G80_2D_BLIT_DV_DY_FRACT 0x000008c8
+
+#define G80_2D_BLIT_DV_DY_INT 0x000008cc
+
+#define G80_2D_BLIT_SRC_X_FRACT 0x000008d0
+
+#define G80_2D_BLIT_SRC_X_INT 0x000008d4
+
+#define G80_2D_BLIT_SRC_Y_FRACT 0x000008d8
+
+#define G80_2D_BLIT_SRC_Y_INT 0x000008dc
+
+#define GF100_2D_FIRMWARE(i0) (0x000008e0 + 0x4*(i0))
+#define GF100_2D_FIRMWARE__ESIZE 0x00000004
+#define GF100_2D_FIRMWARE__LEN 0x00000020
+
+
+#endif /* G80_2D_XML */
diff --git a/src/wld/nouveau/g80_defs.xml.h b/src/wld/nouveau/g80_defs.xml.h
new file mode 100644
index 0000000..ba7df43
--- /dev/null
+++ b/src/wld/nouveau/g80_defs.xml.h
@@ -0,0 +1,382 @@
+#ifndef G80_DEFS_XML
+#define G80_DEFS_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/envytools/envytools/
+git clone https://github.com/envytools/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/michael/src/envytools/rnndb/root.xml ( 514 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/copyright.xml ( 6452 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv_mmio.xml ( 7175 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/nvchipsets.xml ( 2759 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/bus/pmc.xml ( 11361 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pbus.xml ( 19778 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/g80_defs.xml ( 18175 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/g80_vm.xml ( 9832 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv_vga.xml ( 13101 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pci.xml ( 17513 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv1_pfifo.xml ( 10542 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv4_pfifo.xml ( 24010 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/g80_pfifo.xml ( 23184 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/gf100_pfifo.xml ( 26735 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_vm.xml ( 8722 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/nv40_pclock.xml ( 1166 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/g80_pclock.xml ( 16434 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/gt215_pclock.xml ( 4960 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/nv10_pvideo.xml ( 2468 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/ptimer.xml ( 2285 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv10_pcounter.xml ( 5914 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv40_pcounter.xml ( 9663 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pmpeg.xml ( 12735 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pvpe.xml ( 703 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/mpeg_fifo.xml ( 2614 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/nv_object.xml ( 15326 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pme.xml ( 5105 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/nv17_ptv.xml ( 457 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pnvio.xml ( 31893 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pvp1.xml ( 2108 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pvp2.xml ( 1615 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/xtensa.xml ( 5390 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/ptherm.xml ( 34788 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/bus/pfuse.xml ( 1158 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/punits.xml ( 4661 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp3/pvld.xml ( 13271 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/falcon.xml ( 17092 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/falcon_crypt.xml ( 3446 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp3/ppdec.xml ( 14150 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp3/pppp.xml ( 8842 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/nv_defs.xml ( 4399 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp3/psec.xml ( 993 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/g84_punk089.xml ( 448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_prmvio.xml ( 651 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv1_pdma.xml ( 5339 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv3_pfb.xml ( 4493 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv10_pfb.xml ( 18821 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv_pfb.xml ( 1135 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/g80_pfb.xml ( 11139 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pffb.xml ( 2712 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pstraps.xml ( 8118 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pcipher.xml ( 3572 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pbsp.xml ( 10610 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/pcopy.xml ( 7877 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/gt215_pcodec.xml ( 449 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/gt215_pkfuse.xml ( 448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/pdaemon.xml ( 19259 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/10e000.xml ( 1185 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/memory/gf100_pbfb.xml ( 3917 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pibus.xml ( 8545 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/gf100_pclock.xml ( 7338 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/memory/gf100_pp2p.xml ( 1949 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pxbar.xml ( 1516 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pmfb.xml ( 3646 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/gf100_pcounter.xml ( 12713 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/pvcomp.xml ( 8687 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/pvenc.xml ( 1416 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/gf119_punk1c3.xml ( 981 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pmedia.xml ( 432 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv1_paudio.xml ( 1862 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/extdev/ad1848.xml ( 5260 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv1_pgraph.xml ( 14207 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv1_2d.xml ( 36532 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_pgraph.xml ( 4004 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_pgraph.xml ( 11327 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/pgraph.xml ( 31568 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/tpc.xml ( 6832 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/mpc.xml ( 6373 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/mp.xml ( 16762 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/pgraph.xml ( 26735 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/hw_blk.xml ( 760 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/ctxctl.xml ( 13155 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/gpc.xml ( 13114 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/tpc.xml ( 22154 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/ppc.xml ( 2131 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/rop.xml ( 5134 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_pdma.xml ( 2290 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv1_pfb.xml ( 4030 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_pcrtc.xml ( 1108 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv1_pram.xml ( 1235 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pchipid.xml ( 493 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv1_pdac.xml ( 4628 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/peeprom.xml ( 702 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_pramdac.xml ( 4419 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/g80_pdisplay.xml ( 39075 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/prm.xml ( 5094 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv_evo.xml ( 10448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv_objects.xml ( 1053 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv_m2mf.xml ( 2691 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_m2mf.xml ( 2783 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_dvd.xml ( 2994 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_3d.xml ( 5197 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_3d.xml ( 17716 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv_3ddefs.xml ( 16390 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv10_3d.xml ( 18416 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv20_3d.xml ( 21096 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv30-40_3d.xml ( 32451 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_2d.xml ( 11440 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_3d.xml ( 65900 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_compute.xml ( 14027 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_3d.xml ( 59845 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gk104_p2mf.xml ( 2376 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_compute.xml ( 11143 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gk104_compute.xml ( 10182 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/me_fifo.xml ( 1685 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/vp1_fifo.xml ( 670 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/cipher_fifo.xml ( 2071 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/gk104_copy.xml ( 3938 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_texture.xml ( 8881 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_shaders.xml ( 9244 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/mpeg_cmd.xml ( 7682 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/extdev/adt7473.xml ( 11411 bytes, from 2014-11-02 20:39:42)
+
+Copyright (C) 2006-2014 by the following authors:
+- Artur Huillet <arthur.huillet@free.fr> (ahuillet)
+- Ben Skeggs (darktama, darktama_)
+- B. R. <koala_br@users.sourceforge.net> (koala_br)
+- Carlos Martin <carlosmn@users.sf.net> (carlosmn)
+- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr)
+- Dawid Gajownik <gajownik@users.sf.net> (gajownik)
+- Dmitry Baryshkov
+- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag)
+- EdB <edb_@users.sf.net> (edb_)
+- Erik Waling <erikwailing@users.sf.net> (erikwaling)
+- Francisco Jerez <currojerez@riseup.net> (curro)
+- imirkin <imirkin@users.sf.net> (imirkin)
+- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome)
+- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy)
+- Laurent Carlier <lordheavym@gmail.com> (lordheavy)
+- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1)
+- Maarten Maathuis <madman2003@gmail.com> (stillunknown)
+- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin)
+- Mark Carey <mark.carey@gmail.com> (careym)
+- Matthieu Castet <matthieu.castet@parrot.com> (mat-c)
+- nvidiaman <nvidiaman@users.sf.net> (nvidiaman)
+- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata)
+- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen)
+- Peter Popov <ironpeter@users.sf.net> (ironpeter)
+- Richard Hughes <hughsient@users.sf.net> (hughsient)
+- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar)
+- Serge Martin
+- Simon Raffeiner
+- Stephane Loeuillet <leroutier@users.sf.net> (leroutier)
+- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu)
+- sturmflut <sturmflut@users.sf.net> (sturmflut)
+- Sylvain Munaut <tnt@246tNt.com>
+- Victor Stinner <victor.stinner@haypocalc.com> (haypo)
+- Wladmir van der Laan <laanwj@gmail.com> (miathan6)
+- Younes Manton <younes.m@gmail.com> (ymanton)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#define G80_VSTATUS_IDLE 0x00000000
+#define G80_VSTATUS_BUSY 0x00000001
+#define G80_VSTATUS_UNK2 0x00000002
+#define G80_VSTATUS_WAITING 0x00000003
+#define G80_VSTATUS_BLOCKED 0x00000005
+#define G80_VSTATUS_FAULTED 0x00000006
+#define G80_VSTATUS_PAUSED 0x00000007
+#define G80_SURFACE_FORMAT_BITMAP 0x0000001c
+#define G80_SURFACE_FORMAT_UNK1D 0x0000001d
+#define G80_SURFACE_FORMAT_RGBA32_FLOAT 0x000000c0
+#define G80_SURFACE_FORMAT_RGBA32_SINT 0x000000c1
+#define G80_SURFACE_FORMAT_RGBA32_UINT 0x000000c2
+#define G80_SURFACE_FORMAT_RGBX32_FLOAT 0x000000c3
+#define G80_SURFACE_FORMAT_RGBX32_SINT 0x000000c4
+#define G80_SURFACE_FORMAT_RGBX32_UINT 0x000000c5
+#define G80_SURFACE_FORMAT_RGBA16_UNORM 0x000000c6
+#define G80_SURFACE_FORMAT_RGBA16_SNORM 0x000000c7
+#define G80_SURFACE_FORMAT_RGBA16_SINT 0x000000c8
+#define G80_SURFACE_FORMAT_RGBA16_UINT 0x000000c9
+#define G80_SURFACE_FORMAT_RGBA16_FLOAT 0x000000ca
+#define G80_SURFACE_FORMAT_RG32_FLOAT 0x000000cb
+#define G80_SURFACE_FORMAT_RG32_SINT 0x000000cc
+#define G80_SURFACE_FORMAT_RG32_UINT 0x000000cd
+#define G80_SURFACE_FORMAT_RGBX16_FLOAT 0x000000ce
+#define G80_SURFACE_FORMAT_BGRA8_UNORM 0x000000cf
+#define G80_SURFACE_FORMAT_BGRA8_SRGB 0x000000d0
+#define G80_SURFACE_FORMAT_RGB10_A2_UNORM 0x000000d1
+#define G80_SURFACE_FORMAT_RGB10_A2_UINT 0x000000d2
+#define G80_SURFACE_FORMAT_RGBA8_UNORM 0x000000d5
+#define G80_SURFACE_FORMAT_RGBA8_SRGB 0x000000d6
+#define G80_SURFACE_FORMAT_RGBA8_SNORM 0x000000d7
+#define G80_SURFACE_FORMAT_RGBA8_SINT 0x000000d8
+#define G80_SURFACE_FORMAT_RGBA8_UINT 0x000000d9
+#define G80_SURFACE_FORMAT_RG16_UNORM 0x000000da
+#define G80_SURFACE_FORMAT_RG16_SNORM 0x000000db
+#define G80_SURFACE_FORMAT_RG16_SINT 0x000000dc
+#define G80_SURFACE_FORMAT_RG16_UINT 0x000000dd
+#define G80_SURFACE_FORMAT_RG16_FLOAT 0x000000de
+#define G80_SURFACE_FORMAT_BGR10_A2_UNORM 0x000000df
+#define G80_SURFACE_FORMAT_R11G11B10_FLOAT 0x000000e0
+#define G80_SURFACE_FORMAT_R32_SINT 0x000000e3
+#define G80_SURFACE_FORMAT_R32_UINT 0x000000e4
+#define G80_SURFACE_FORMAT_R32_FLOAT 0x000000e5
+#define G80_SURFACE_FORMAT_BGRX8_UNORM 0x000000e6
+#define G80_SURFACE_FORMAT_BGRX8_SRGB 0x000000e7
+#define G80_SURFACE_FORMAT_B5G6R5_UNORM 0x000000e8
+#define G80_SURFACE_FORMAT_BGR5_A1_UNORM 0x000000e9
+#define G80_SURFACE_FORMAT_RG8_UNORM 0x000000ea
+#define G80_SURFACE_FORMAT_RG8_SNORM 0x000000eb
+#define G80_SURFACE_FORMAT_RG8_SINT 0x000000ec
+#define G80_SURFACE_FORMAT_RG8_UINT 0x000000ed
+#define G80_SURFACE_FORMAT_R16_UNORM 0x000000ee
+#define G80_SURFACE_FORMAT_R16_SNORM 0x000000ef
+#define G80_SURFACE_FORMAT_R16_SINT 0x000000f0
+#define G80_SURFACE_FORMAT_R16_UINT 0x000000f1
+#define G80_SURFACE_FORMAT_R16_FLOAT 0x000000f2
+#define G80_SURFACE_FORMAT_R8_UNORM 0x000000f3
+#define G80_SURFACE_FORMAT_R8_SNORM 0x000000f4
+#define G80_SURFACE_FORMAT_R8_SINT 0x000000f5
+#define G80_SURFACE_FORMAT_R8_UINT 0x000000f6
+#define G80_SURFACE_FORMAT_A8_UNORM 0x000000f7
+#define G80_SURFACE_FORMAT_BGR5_X1_UNORM 0x000000f8
+#define G80_SURFACE_FORMAT_RGBX8_UNORM 0x000000f9
+#define G80_SURFACE_FORMAT_RGBX8_SRGB 0x000000fa
+#define G80_SURFACE_FORMAT_BGR5_X1_UNORM_UNKFB 0x000000fb
+#define G80_SURFACE_FORMAT_BGR5_X1_UNORM_UNKFC 0x000000fc
+#define G80_SURFACE_FORMAT_BGRX8_UNORM_UNKFD 0x000000fd
+#define G80_SURFACE_FORMAT_BGRX8_UNORM_UNKFE 0x000000fe
+#define G80_SURFACE_FORMAT_Y32_UINT_UNKFF 0x000000ff
+#define G80_ZETA_FORMAT_Z32_FLOAT 0x0000000a
+#define G80_ZETA_FORMAT_Z16_UNORM 0x00000013
+#define G80_ZETA_FORMAT_S8_Z24_UNORM 0x00000014
+#define G80_ZETA_FORMAT_Z24_X8_UNORM 0x00000015
+#define G80_ZETA_FORMAT_Z24_S8_UNORM 0x00000016
+#define G80_ZETA_FORMAT_Z24_C8_UNORM 0x00000018
+#define G80_ZETA_FORMAT_Z32_S8_X24_FLOAT 0x00000019
+#define G80_ZETA_FORMAT_Z24_X8_S8_C8_X16_UNORM 0x0000001d
+#define G80_ZETA_FORMAT_Z32_X8_C8_X16_FLOAT 0x0000001e
+#define G80_ZETA_FORMAT_Z32_S8_C8_X16_FLOAT 0x0000001f
+#define GK104_IMAGE_FORMAT_RGBA32_FLOAT 0x00000002
+#define GK104_IMAGE_FORMAT_RGBA32_SINT 0x00000003
+#define GK104_IMAGE_FORMAT_RGBA32_UINT 0x00000004
+#define GK104_IMAGE_FORMAT_RGBA16_UNORM 0x00000008
+#define GK104_IMAGE_FORMAT_RGBA16_SNORM 0x00000009
+#define GK104_IMAGE_FORMAT_RGBA16_SINT 0x0000000a
+#define GK104_IMAGE_FORMAT_RGBA16_UINT 0x0000000b
+#define GK104_IMAGE_FORMAT_RGBA16_FLOAT 0x0000000c
+#define GK104_IMAGE_FORMAT_RG32_FLOAT 0x0000000d
+#define GK104_IMAGE_FORMAT_RG32_SINT 0x0000000e
+#define GK104_IMAGE_FORMAT_RG32_UINT 0x0000000f
+#define GK104_IMAGE_FORMAT_RGB10_A2_UNORM 0x00000013
+#define GK104_IMAGE_FORMAT_RGB10_A2_UINT 0x00000015
+#define GK104_IMAGE_FORMAT_RGBA8_UNORM 0x00000018
+#define GK104_IMAGE_FORMAT_RGBA8_SNORM 0x0000001a
+#define GK104_IMAGE_FORMAT_RGBA8_SINT 0x0000001b
+#define GK104_IMAGE_FORMAT_RGBA8_UINT 0x0000001c
+#define GK104_IMAGE_FORMAT_RG16_UNORM 0x0000001d
+#define GK104_IMAGE_FORMAT_RG16_SNORM 0x0000001e
+#define GK104_IMAGE_FORMAT_RG16_SINT 0x0000001f
+#define GK104_IMAGE_FORMAT_RG16_UINT 0x00000020
+#define GK104_IMAGE_FORMAT_RG16_FLOAT 0x00000021
+#define GK104_IMAGE_FORMAT_R11G11B10_FLOAT 0x00000024
+#define GK104_IMAGE_FORMAT_R32_SINT 0x00000027
+#define GK104_IMAGE_FORMAT_R32_UINT 0x00000028
+#define GK104_IMAGE_FORMAT_R32_FLOAT 0x00000029
+#define GK104_IMAGE_FORMAT_RG8_UNORM 0x0000002e
+#define GK104_IMAGE_FORMAT_RG8_SNORM 0x0000002f
+#define GK104_IMAGE_FORMAT_RG8_SINT 0x00000030
+#define GK104_IMAGE_FORMAT_RG8_UINT 0x00000031
+#define GK104_IMAGE_FORMAT_R16_UNORM 0x00000032
+#define GK104_IMAGE_FORMAT_R16_SNORM 0x00000033
+#define GK104_IMAGE_FORMAT_R16_SINT 0x00000034
+#define GK104_IMAGE_FORMAT_R16_UINT 0x00000035
+#define GK104_IMAGE_FORMAT_R16_FLOAT 0x00000036
+#define GK104_IMAGE_FORMAT_R8_UNORM 0x00000037
+#define GK104_IMAGE_FORMAT_R8_SNORM 0x00000038
+#define GK104_IMAGE_FORMAT_R8_SINT 0x00000039
+#define GK104_IMAGE_FORMAT_R8_UINT 0x0000003a
+#define G80_PGRAPH_DATA_ERROR_INVALID_OPERATION 0x00000003
+#define G80_PGRAPH_DATA_ERROR_INVALID_VALUE 0x00000004
+#define G80_PGRAPH_DATA_ERROR_INVALID_ENUM 0x00000005
+#define G80_PGRAPH_DATA_ERROR_INVALID_OBJECT 0x00000008
+#define G80_PGRAPH_DATA_ERROR_READ_ONLY_OBJECT 0x00000009
+#define G80_PGRAPH_DATA_ERROR_SUPERVISOR_OBJECT 0x0000000a
+#define G80_PGRAPH_DATA_ERROR_INVALID_ADDRESS_ALIGNMENT 0x0000000b
+#define G80_PGRAPH_DATA_ERROR_INVALID_BITFIELD 0x0000000c
+#define G80_PGRAPH_DATA_ERROR_BEGIN_END_ACTIVE 0x0000000d
+#define G80_PGRAPH_DATA_ERROR_SEMANTIC_COLOR_BACK_OVER_LIMIT 0x0000000e
+#define G80_PGRAPH_DATA_ERROR_VIEWPORT_ID_NEEDS_GP 0x0000000f
+#define G80_PGRAPH_DATA_ERROR_RT_DOUBLE_BIND 0x00000010
+#define G80_PGRAPH_DATA_ERROR_RT_TYPES_MISMATCH 0x00000011
+#define G80_PGRAPH_DATA_ERROR_RT_LINEAR_WITH_ZETA 0x00000012
+#define G80_PGRAPH_DATA_ERROR_FP_TOO_FEW_REGS 0x00000015
+#define G80_PGRAPH_DATA_ERROR_ZETA_FORMAT_CSAA_MISMATCH 0x00000016
+#define G80_PGRAPH_DATA_ERROR_RT_LINEAR_WITH_MSAA 0x00000017
+#define G80_PGRAPH_DATA_ERROR_FP_INTERPOLANT_START_OVER_LIMIT 0x00000018
+#define G80_PGRAPH_DATA_ERROR_SEMANTIC_LAYER_OVER_LIMIT 0x00000019
+#define G80_PGRAPH_DATA_ERROR_RT_INVALID_ALIGNMENT 0x0000001a
+#define G80_PGRAPH_DATA_ERROR_SAMPLER_OVER_LIMIT 0x0000001b
+#define G80_PGRAPH_DATA_ERROR_TEXTURE_OVER_LIMIT 0x0000001c
+#define G80_PGRAPH_DATA_ERROR_GP_TOO_MANY_OUTPUTS 0x0000001e
+#define G80_PGRAPH_DATA_ERROR_RT_BPP128_WITH_MS8 0x0000001f
+#define G80_PGRAPH_DATA_ERROR_Z_OUT_OF_BOUNDS 0x00000021
+#define G80_PGRAPH_DATA_ERROR_XY_OUT_OF_BOUNDS 0x00000023
+#define G80_PGRAPH_DATA_ERROR_VP_ZERO_INPUTS 0x00000024
+#define G80_PGRAPH_DATA_ERROR_CP_MORE_PARAMS_THAN_SHARED 0x00000027
+#define G80_PGRAPH_DATA_ERROR_CP_NO_REG_SPACE_STRIPED 0x00000028
+#define G80_PGRAPH_DATA_ERROR_CP_NO_REG_SPACE_PACKED 0x00000029
+#define G80_PGRAPH_DATA_ERROR_CP_NOT_ENOUGH_WARPS 0x0000002a
+#define G80_PGRAPH_DATA_ERROR_CP_BLOCK_SIZE_MISMATCH 0x0000002b
+#define G80_PGRAPH_DATA_ERROR_CP_NOT_ENOUGH_LOCAL_WARPS 0x0000002c
+#define G80_PGRAPH_DATA_ERROR_CP_NOT_ENOUGH_STACK_WARPS 0x0000002d
+#define G80_PGRAPH_DATA_ERROR_CP_NO_BLOCKDIM_LATCH 0x0000002e
+#define G80_PGRAPH_DATA_ERROR_ENG2D_FORMAT_MISMATCH 0x00000031
+#define G80_PGRAPH_DATA_ERROR_ENG2D_OPERATION_ILLEGAL_FOR_DST_FORMAT 0x00000033
+#define G80_PGRAPH_DATA_ERROR_ENG2D_FORMAT_MISMATCH_B 0x00000034
+#define G80_PGRAPH_DATA_ERROR_PRIMITIVE_ID_NEEDS_GP 0x0000003f
+#define G80_PGRAPH_DATA_ERROR_SEMANTIC_VIEWPORT_OVER_LIMIT 0x00000044
+#define G80_PGRAPH_DATA_ERROR_SEMANTIC_COLOR_FRONT_OVER_LIMIT 0x00000045
+#define G80_PGRAPH_DATA_ERROR_LAYER_ID_NEEDS_GP 0x00000046
+#define G80_PGRAPH_DATA_ERROR_SEMANTIC_CLIP_OVER_LIMIT 0x00000047
+#define G80_PGRAPH_DATA_ERROR_SEMANTIC_PTSZ_OVER_LIMIT 0x00000048
+#define G80_PGRAPH_DATA_ERROR_M2MF_LINE_LENGTH_EXCEEDS_PITCH_IN 0x00000051
+#define G80_PGRAPH_DATA_ERROR_M2MF_LINE_LENGTH_EXCEEDS_PITCH_OUT 0x00000053
+#define G80_PGRAPH_DATA_ERROR_RT_LINEAR_WITH_ZETA_GF100 0x00000098
+#define G80_PGRAPH_DATA_ERROR_ENG2D_UNALIGNED_PITCH_GF100 0x000000a5
+#define G80_CG_IDLE_TIMEOUT__MASK 0x0000003f
+#define G80_CG_IDLE_TIMEOUT__SHIFT 0
+#define G80_CG_IDLE_TIMEOUT_ENABLE 0x00000040
+#define G80_CG_INTERFACE_REENABLE_TIME__MASK 0x000f0000
+#define G80_CG_INTERFACE_REENABLE_TIME__SHIFT 16
+#define G80_CG_THROTTLE_DUTY_M1__MASK 0x00f00000
+#define G80_CG_THROTTLE_DUTY_M1__SHIFT 20
+#define G80_CG_DELAY__MASK 0x0f000000
+#define G80_CG_DELAY__SHIFT 24
+#define G80_CG_CLOCK_THROTTLE_ENABLE 0x10000000
+#define G80_CG_THROTTLE_MODE__MASK 0x20000000
+#define G80_CG_THROTTLE_MODE__SHIFT 29
+#define G80_CG_THROTTLE_MODE_AUTO 0x00000000
+#define G80_CG_THROTTLE_MODE_MANUAL 0x20000000
+#define G80_CG_INTERFACE_THROTTLE_ENABLE 0x40000000
+#define G80_QUERY__SIZE 0x00000010
+#define G80_QUERY_COUNTER 0x00000000
+
+#define G80_QUERY_RES 0x00000004
+
+#define G80_QUERY_TIME 0x00000008
+
+
+#endif /* G80_DEFS_XML */
diff --git a/src/wld/nouveau/nouveau.c b/src/wld/nouveau/nouveau.c
new file mode 100644
index 0000000..34829eb
--- /dev/null
+++ b/src/wld/nouveau/nouveau.c
@@ -0,0 +1,678 @@
+/* wld: nouveau.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Based in part upon nvc0_exa.c from xf86-video-nouveau, which is:
+ *
+ * Copyright 2007 NVIDIA, Corporation
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "drm-private.h"
+#include "drm.h"
+#include "pixman.h"
+#include "nv_object.xml.h"
+#include "g80_2d.xml.h"
+#include "g80_defs.xml.h"
+
+#include <nouveau.h>
+#include <sys/mman.h>
+
+enum nv_architecture
+{
+ NV_ARCH_50 = 0x50,
+ NV_ARCH_C0 = 0xc0,
+ NV_ARCH_E0 = 0xe0
+};
+
+struct nouveau_context
+{
+ struct wld_context base;
+ struct nouveau_device * device;
+ struct nouveau_client * client;
+ enum nv_architecture architecture;
+};
+
+struct nouveau_renderer
+{
+ struct wld_renderer base;
+ struct nouveau_object * channel;
+ struct nouveau_pushbuf * pushbuf;
+ struct nouveau_bufctx * bufctx;
+ struct nouveau_object * nvc0_2d;
+
+ struct nouveau_buffer * target;
+};
+
+struct nouveau_buffer
+{
+ struct buffer base;
+ struct wld_exporter exporter;
+ struct nouveau_context * context;
+ struct nouveau_bo * bo;
+};
+
+#include "interface/context.h"
+#include "interface/renderer.h"
+#include "interface/buffer.h"
+#define DRM_DRIVER_NAME nouveau
+#include "interface/drm.h"
+IMPL(nouveau_context, wld_context)
+IMPL(nouveau_renderer, wld_renderer)
+IMPL(nouveau_buffer, wld_buffer)
+
+/**** DRM driver ****/
+bool driver_device_supported(uint32_t vendor_id, uint32_t device_id)
+{
+ return vendor_id == 0x10de;
+}
+
+struct wld_context * driver_create_context(int drm_fd)
+{
+ struct nouveau_context * context;
+
+ if (!(context = malloc(sizeof *context)))
+ goto error0;
+
+ if (nouveau_device_wrap(drm_fd, 0, &context->device) != 0)
+ goto error1;
+
+ switch (context->device->chipset & ~0xf)
+ {
+ /* TODO: Support NV50
+ case 0x50:
+ case 0x80:
+ case 0x90:
+ case 0xa0:
+ context->architecture = NV_ARCH_50;
+ break;
+ */
+ case 0xc0:
+ case 0xd0:
+ context->architecture = NV_ARCH_C0;
+ break;
+ /* TODO: Support NVE0
+ case 0xe0:
+ case 0xf0:
+ case 0x100:
+ context->architecture = NV_ARCH_E0;
+ break;
+ */
+ default:
+ return NULL;
+ }
+
+ if (nouveau_client_new(context->device, &context->client) != 0)
+ goto error2;
+
+ context_initialize(&context->base, &wld_context_impl);
+
+ return &context->base;
+
+ error2:
+ nouveau_device_del(&context->device);
+ error1:
+ free(context);
+ error0:
+ return NULL;
+}
+
+/**** Context ****/
+static inline bool ensure_space(struct nouveau_pushbuf * push, uint32_t count)
+{
+ if (push->end - push->cur > count)
+ return true;
+
+ return nouveau_pushbuf_space(push, count, 0, 0) == 0;
+}
+
+static inline void nv_add_dword(struct nouveau_pushbuf * push, uint32_t dword)
+{
+ *push->cur++ = dword;
+}
+
+static inline void nv_add_dwords_va(struct nouveau_pushbuf * push,
+ uint16_t count, va_list dwords)
+{
+ while (count--)
+ nv_add_dword(push, va_arg(dwords, uint32_t));
+}
+
+static inline void nv_add_data(struct nouveau_pushbuf * push,
+ void * data, uint32_t count)
+{
+ memcpy(push->cur, data, count * 4);
+ push->cur += count;
+}
+
+static inline uint32_t nvc0_format(uint32_t format)
+{
+ switch (format)
+ {
+ case WLD_FORMAT_XRGB8888:
+ return G80_SURFACE_FORMAT_BGRX8_UNORM;
+ case WLD_FORMAT_ARGB8888:
+ return G80_SURFACE_FORMAT_BGRA8_UNORM;
+ }
+
+ return 0;
+}
+
+enum
+{
+ GF100_COMMAND_TYPE_INCREASING = 1,
+ GF100_COMMAND_TYPE_NON_INCREASING = 3,
+ GF100_COMMAND_TYPE_INLINE = 4
+};
+
+enum
+{
+ GF100_SUBCHANNEL_2D = 3,
+};
+
+static inline uint32_t nvc0_command(uint8_t type, uint8_t subchannel,
+ uint16_t method, uint16_t count_or_value)
+{
+ return type << 29 | count_or_value << 16 | subchannel << 13 | method >> 2;
+}
+
+static inline void nvc0_inline(struct nouveau_pushbuf * push,
+ uint8_t subchannel, uint16_t method,
+ uint16_t value)
+{
+ nv_add_dword(push, nvc0_command(GF100_COMMAND_TYPE_INLINE,
+ subchannel, method, value));
+}
+
+static inline void nvc0_methods(struct nouveau_pushbuf * push,
+ uint8_t subchannel, uint16_t start_method,
+ uint16_t count, ...)
+{
+ va_list dwords;
+ nv_add_dword(push, nvc0_command(GF100_COMMAND_TYPE_INCREASING,
+ subchannel, start_method, count));
+ va_start(dwords, count);
+ nv_add_dwords_va(push, count, dwords);
+ va_end(dwords);
+}
+
+#define nvc0_2d(push, method, count, ...) \
+ nvc0_methods(push, GF100_SUBCHANNEL_2D, method, count, __VA_ARGS__)
+#define nvc0_2d_inline(push, method, value) \
+ nvc0_inline(push, GF100_SUBCHANNEL_2D, method, value)
+
+static bool nvc0_2d_initialize(struct nouveau_renderer * renderer)
+{
+ int ret;
+
+ ret = nouveau_object_new(renderer->channel, GF100_2D, GF100_2D, NULL, 0,
+ &renderer->nvc0_2d);
+
+ if (ret != 0)
+ goto error0;
+
+ if (!ensure_space(renderer->pushbuf, 5))
+ goto error1;
+
+ nvc0_2d(renderer->pushbuf, NV1_SUBCHAN_OBJECT, 1,
+ renderer->nvc0_2d->handle);
+ nvc0_2d_inline(renderer->pushbuf, G80_2D_OPERATION,
+ G80_2D_OPERATION_SRCCOPY_AND);
+ nvc0_2d_inline(renderer->pushbuf, G80_2D_UNK0884, 0x3f);
+ nvc0_2d_inline(renderer->pushbuf, G80_2D_UNK0888, 1);
+
+ return true;
+
+ error1:
+ nouveau_object_del(&renderer->nvc0_2d);
+ error0:
+ return false;
+}
+
+static void nvc0_2d_finalize(struct nouveau_renderer * renderer)
+{
+ nouveau_object_del(&renderer->nvc0_2d);
+}
+
+struct wld_renderer * context_create_renderer(struct wld_context * base)
+{
+ struct nouveau_context * context = nouveau_context(base);
+ struct nouveau_renderer * renderer;
+ struct nvc0_fifo fifo = { };
+ int ret;
+
+ if (!(renderer = malloc(sizeof *renderer)))
+ goto error0;
+
+ ret = nouveau_object_new(&context->device->object, 0,
+ NOUVEAU_FIFO_CHANNEL_CLASS, &fifo, sizeof fifo,
+ &renderer->channel);
+
+ if (ret != 0)
+ goto error1;
+
+ ret = nouveau_pushbuf_new(context->client, renderer->channel, 4, 32 * 1024,
+ true, &renderer->pushbuf);
+
+ if (ret != 0)
+ goto error2;
+
+ if (nouveau_bufctx_new(context->client, 1, &renderer->bufctx) != 0)
+ goto error3;
+
+ if (!nvc0_2d_initialize(renderer))
+ goto error4;
+
+ renderer_initialize(&renderer->base, &wld_renderer_impl);
+ renderer->target = NULL;
+
+ return &renderer->base;
+
+ error4:
+ nouveau_bufctx_del(&renderer->bufctx);
+ error3:
+ nouveau_pushbuf_del(&renderer->pushbuf);
+ error2:
+ nouveau_object_del(&renderer->channel);
+ error1:
+ free(renderer);
+ error0:
+ return NULL;
+}
+
+static bool export(struct wld_exporter * exporter, struct wld_buffer * base,
+ uint32_t type, union wld_object * object)
+{
+ struct nouveau_buffer * buffer = nouveau_buffer(base);
+
+ switch (type)
+ {
+ case WLD_DRM_OBJECT_HANDLE:
+ object->u32 = buffer->bo->handle;
+ return true;
+ case WLD_DRM_OBJECT_PRIME_FD:
+ if (nouveau_bo_set_prime(buffer->bo, &object->i) != 0)
+ return false;
+ return true;
+ default:
+ return false;
+ }
+}
+
+static struct nouveau_buffer * new_buffer(struct nouveau_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ struct nouveau_buffer * buffer;
+
+ if (!(buffer = malloc(sizeof *buffer)))
+ return NULL;
+
+ buffer_initialize(&buffer->base, &wld_buffer_impl,
+ width, height, format, pitch);
+ buffer->context = context;
+ buffer->exporter.export = &export;
+ wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter);
+
+ return buffer;
+}
+
+static inline uint32_t roundup(uint32_t value, uint32_t alignment)
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+struct buffer * context_create_buffer(struct wld_context * base,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ struct nouveau_context * context = nouveau_context(base);
+ struct nouveau_buffer * buffer;
+ uint32_t bpp = format_bytes_per_pixel(format),
+ pitch = roundup(width * bpp, 64), bo_flags;
+ union nouveau_bo_config config = { };
+
+ if (!(buffer = new_buffer(context, width, height, format, pitch)))
+ goto error0;
+
+ bo_flags = NOUVEAU_BO_VRAM;
+
+ if (flags & WLD_DRM_FLAG_SCANOUT)
+ bo_flags |= NOUVEAU_BO_CONTIG;
+
+ if (height > 0x40 && !(flags & WLD_FLAG_MAP))
+ {
+ config.nvc0.tile_mode = 0x40;
+ config.nvc0.memtype = 0xfe;
+ height = roundup(height, 0x80);
+ }
+ else
+ bo_flags |= NOUVEAU_BO_MAP;
+
+ if (nouveau_bo_new(context->device, bo_flags, 0, pitch * height,
+ &config, &buffer->bo) != 0)
+ {
+ goto error1;
+ }
+
+ return &buffer->base;
+
+ error1:
+ free(buffer);
+ error0:
+ return NULL;
+}
+
+struct buffer * context_import_buffer(struct wld_context * base,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ struct nouveau_context * context = (void *) base;
+ struct nouveau_buffer * buffer;
+ struct nouveau_bo * bo = NULL;
+
+ switch (type)
+ {
+ case WLD_DRM_OBJECT_PRIME_FD:
+ if (nouveau_bo_prime_handle_ref(context->device,
+ object.i, &bo) != 0)
+ {
+ goto error0;
+ }
+ break;
+ default: goto error0;
+ }
+
+ if (!(buffer = new_buffer(context, width, height, format, pitch)))
+ goto error1;
+
+ buffer->bo = bo;
+
+ return &buffer->base;
+
+ error1:
+ nouveau_bo_ref(NULL, &buffer->bo);
+ error0:
+ return NULL;
+}
+
+void context_destroy(struct wld_context * base)
+{
+ struct nouveau_context * context = nouveau_context(base);
+
+ nouveau_client_del(&context->client);
+ nouveau_device_del(&context->device);
+ free(context);
+}
+
+/**** Renderer ****/
+uint32_t renderer_capabilities(struct wld_renderer * renderer,
+ struct buffer * buffer)
+{
+ if (buffer->base.impl == &wld_buffer_impl)
+ return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
+
+ return 0;
+}
+
+bool renderer_set_target(struct wld_renderer * base, struct buffer * buffer)
+{
+ struct nouveau_renderer * renderer = nouveau_renderer(base);
+
+ if (buffer && buffer->base.impl != &wld_buffer_impl)
+ return false;
+
+ renderer->target = buffer ? nouveau_buffer(&buffer->base) : NULL;
+
+ return true;
+}
+
+static inline void nvc0_2d_use_buffer(struct nouveau_renderer * renderer,
+ struct nouveau_buffer * buffer,
+ uint16_t format_method, uint16_t format)
+{
+ uint32_t access = format == G80_2D_SRC_FORMAT ? NOUVEAU_BO_RD
+ : NOUVEAU_BO_WR;
+
+ nvc0_2d_inline(renderer->pushbuf, format_method, format);
+
+ if (buffer->bo->config.nvc0.memtype)
+ {
+ nvc0_2d(renderer->pushbuf, format_method + 0x04, 2,
+ 0, buffer->bo->config.nvc0.tile_mode);
+ }
+ else
+ {
+ nvc0_2d_inline(renderer->pushbuf, format_method + 0x04, 1);
+ nvc0_2d(renderer->pushbuf, format_method + 0x14, 1,
+ buffer->base.base.pitch);
+ }
+
+ nvc0_2d(renderer->pushbuf, format_method + 0x18, 4,
+ buffer->base.base.width, buffer->base.base.height,
+ buffer->bo->offset >> 32, buffer->bo->offset);
+ nouveau_bufctx_refn(renderer->bufctx, 0, buffer->bo,
+ NOUVEAU_BO_VRAM | access);
+}
+
+void renderer_fill_rectangle(struct wld_renderer * base, uint32_t color,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct nouveau_renderer * renderer = nouveau_renderer(base);
+ struct nouveau_buffer * dst = renderer->target;
+ uint32_t format;
+
+ if (!ensure_space(renderer->pushbuf, 18))
+ return;
+
+ format = nvc0_format(dst->base.base.format);
+
+ nouveau_bufctx_reset(renderer->bufctx, 0);
+ nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, format);
+ nvc0_2d(renderer->pushbuf, G80_2D_DRAW_SHAPE, 3,
+ G80_2D_DRAW_SHAPE_RECTANGLES, format, color);
+ nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx);
+
+ if (nouveau_pushbuf_validate(renderer->pushbuf) != 0)
+ return;
+
+ nvc0_2d(renderer->pushbuf, G80_2D_DRAW_POINT32_X(0), 4,
+ x, y, x + width, y + height);
+}
+
+void renderer_copy_rectangle(struct wld_renderer * base,
+ struct buffer * buffer_base,
+ int32_t dst_x, int32_t dst_y,
+ int32_t src_x, int32_t src_y,
+ uint32_t width, uint32_t height)
+{
+ struct nouveau_renderer * renderer = nouveau_renderer(base);
+
+ if (buffer_base->base.impl != &wld_buffer_impl)
+ return;
+
+ struct nouveau_buffer * src = nouveau_buffer(&buffer_base->base),
+ * dst = renderer->target;
+ uint32_t src_format, dst_format;
+
+ if (!ensure_space(renderer->pushbuf, 33))
+ return;
+
+ src_format = nvc0_format(src->base.base.format);
+ dst_format = nvc0_format(dst->base.base.format);
+
+ nouveau_bufctx_reset(renderer->bufctx, 0);
+ nvc0_2d_use_buffer(renderer, src, G80_2D_SRC_FORMAT, src_format);
+ nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, dst_format);
+ nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx);
+
+ if (nouveau_pushbuf_validate(renderer->pushbuf) != 0)
+ return;
+
+ nvc0_2d_inline(renderer->pushbuf, G80_GRAPH_SERIALIZE, 0);
+ nvc0_2d_inline(renderer->pushbuf, G80_2D_BLIT_CONTROL,
+ G80_2D_BLIT_CONTROL_ORIGIN_CENTER
+ | G80_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE);
+ nvc0_2d(renderer->pushbuf, G80_2D_BLIT_DST_X, 12,
+ dst_x, dst_y, width, height, 0, 1, 0, 1, 0, src_x, 0, src_y);
+
+ renderer_flush(base);
+}
+
+void renderer_draw_text(struct wld_renderer * base,
+ struct font * font, uint32_t color,
+ int32_t x, int32_t y, const char * text,
+ uint32_t length, struct wld_extents * extents)
+{
+ struct nouveau_renderer * renderer = nouveau_renderer(base);
+ struct nouveau_buffer * dst = renderer->target;
+ uint32_t format;
+ int ret;
+ struct glyph * glyph;
+ FT_UInt glyph_index;
+ uint32_t c, count;
+ int32_t origin_x = x;
+
+ if (!ensure_space(renderer->pushbuf, 17))
+ return;
+
+ format = nvc0_format(dst->base.base.format);
+
+ nouveau_bufctx_reset(renderer->bufctx, 0);
+ nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, format);
+ nvc0_2d_inline(renderer->pushbuf, G80_2D_SIFC_BITMAP_ENABLE, 1);
+ nvc0_2d(renderer->pushbuf, G80_2D_SIFC_BITMAP_FORMAT, 6,
+ G80_2D_SIFC_BITMAP_FORMAT_I1,
+ 0, /* SIFC_FORMAT */
+ G80_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_BYTE,
+ 0, color, /* SIFC_BITMAP_COLOR_BIT0, SIFC_BITMAP_COLOR_BIT1 */
+ 0 /* SIFC_BITMAP_WRITE_BIT0_ENABLE */
+ );
+ nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx);
+
+ if (nouveau_pushbuf_validate(renderer->pushbuf) != 0)
+ return;
+
+ if (length == -1)
+ length = strlen(text);
+
+ while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length)) > 0 && c != '\0')
+ {
+ text += ret;
+ length -= ret;
+ glyph_index = FT_Get_Char_Index(font->face, c);
+
+ if (!font_ensure_glyph(font, glyph_index))
+ continue;
+
+ glyph = font->glyphs[glyph_index];
+
+ if (glyph->bitmap.width == 0 || glyph->bitmap.rows == 0)
+ goto advance;
+
+ count = (glyph->bitmap.pitch * glyph->bitmap.rows + 3) / 4;
+
+ if (!ensure_space(renderer->pushbuf, 12 + count))
+ return;
+
+ nvc0_2d(renderer->pushbuf, G80_2D_SIFC_WIDTH, 10,
+ /* Use the pitch instead of width to ensure the correct
+ * alignment is used. */
+ glyph->bitmap.pitch * 8, glyph->bitmap.rows,
+ 0, 1, 0, 1,
+ 0, origin_x + glyph->x, 0, y + glyph->y);
+ nv_add_dword(renderer->pushbuf,
+ nvc0_command(GF100_COMMAND_TYPE_NON_INCREASING,
+ GF100_SUBCHANNEL_2D,
+ G80_2D_SIFC_DATA, count));
+ nv_add_data(renderer->pushbuf, glyph->bitmap.buffer, count);
+
+ advance:
+ origin_x += glyph->advance;
+ }
+
+ if (extents)
+ extents->advance = origin_x - x;
+}
+
+void renderer_flush(struct wld_renderer * base)
+{
+ struct nouveau_renderer * renderer = nouveau_renderer(base);
+
+ nouveau_pushbuf_kick(renderer->pushbuf, renderer->channel);
+ nouveau_pushbuf_bufctx(renderer->pushbuf, NULL);
+}
+
+void renderer_destroy(struct wld_renderer * base)
+{
+ struct nouveau_renderer * renderer = nouveau_renderer(base);
+
+ nvc0_2d_finalize(renderer);
+ nouveau_bufctx_del(&renderer->bufctx);
+ nouveau_pushbuf_del(&renderer->pushbuf);
+ nouveau_object_del(&renderer->channel);
+ free(renderer);
+}
+
+/**** Buffer ****/
+bool buffer_map(struct buffer * base)
+{
+ struct nouveau_buffer * buffer = nouveau_buffer(&base->base);
+
+ /* If the buffer is tiled, it cannot be mapped into virtual memory in order
+ * to appear linear like intel can do with map_gtt. */
+ if (buffer->bo->config.nvc0.tile_mode)
+ return false;
+
+ if (nouveau_bo_map(buffer->bo, NOUVEAU_BO_WR,
+ buffer->context->client) != 0)
+ {
+ return false;
+ }
+
+ buffer->base.base.map = buffer->bo->map;
+
+ return true;
+}
+
+bool buffer_unmap(struct buffer * base)
+{
+ struct nouveau_buffer * buffer = nouveau_buffer(&base->base);
+
+ if (munmap(buffer->bo->map, buffer->bo->size) == -1)
+ return false;
+
+ buffer->bo->map = NULL;
+ base->base.map = NULL;
+
+ return true;
+}
+
+void buffer_destroy(struct buffer * base)
+{
+ struct nouveau_buffer * buffer = nouveau_buffer(&base->base);
+
+ nouveau_bo_ref(NULL, &buffer->bo);
+ free(buffer);
+}
+
diff --git a/src/wld/nouveau/nv_object.xml.h b/src/wld/nouveau/nv_object.xml.h
new file mode 100644
index 0000000..0a12a19
--- /dev/null
+++ b/src/wld/nouveau/nv_object.xml.h
@@ -0,0 +1,452 @@
+#ifndef NV_OBJECT_XML
+#define NV_OBJECT_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/envytools/envytools/
+git clone https://github.com/envytools/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/michael/src/envytools/rnndb/root.xml ( 514 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/copyright.xml ( 6452 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv_mmio.xml ( 7175 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/nvchipsets.xml ( 2759 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/bus/pmc.xml ( 11361 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pbus.xml ( 19778 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/g80_defs.xml ( 18175 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/g80_vm.xml ( 9832 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv_vga.xml ( 13101 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pci.xml ( 17513 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv1_pfifo.xml ( 10542 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv4_pfifo.xml ( 24010 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/g80_pfifo.xml ( 23184 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/gf100_pfifo.xml ( 26735 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_vm.xml ( 8722 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/nv40_pclock.xml ( 1166 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/g80_pclock.xml ( 16434 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/gt215_pclock.xml ( 4960 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/nv10_pvideo.xml ( 2468 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/ptimer.xml ( 2285 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv10_pcounter.xml ( 5914 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv40_pcounter.xml ( 9663 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pmpeg.xml ( 12735 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pvpe.xml ( 703 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/mpeg_fifo.xml ( 2614 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/nv_object.xml ( 15326 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pme.xml ( 5105 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/nv17_ptv.xml ( 457 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pnvio.xml ( 31893 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/pvp1.xml ( 2108 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pvp2.xml ( 1615 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/xtensa.xml ( 5390 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/ptherm.xml ( 34788 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/bus/pfuse.xml ( 1158 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/punits.xml ( 4661 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp3/pvld.xml ( 13271 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/falcon.xml ( 17092 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/falcon_crypt.xml ( 3446 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp3/ppdec.xml ( 14150 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp3/pppp.xml ( 8842 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/nv_defs.xml ( 4399 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp3/psec.xml ( 993 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/g84_punk089.xml ( 448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_prmvio.xml ( 651 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv1_pdma.xml ( 5339 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv3_pfb.xml ( 4493 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv10_pfb.xml ( 18821 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv_pfb.xml ( 1135 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/g80_pfb.xml ( 11139 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pffb.xml ( 2712 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pstraps.xml ( 8118 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pcipher.xml ( 3572 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/pbsp.xml ( 10610 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/pcopy.xml ( 7877 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/gt215_pcodec.xml ( 449 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/gt215_pkfuse.xml ( 448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/pdaemon.xml ( 19259 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/pm/10e000.xml ( 1185 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/memory/gf100_pbfb.xml ( 3917 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/pibus.xml ( 8545 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/pm/gf100_pclock.xml ( 7338 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/memory/gf100_pp2p.xml ( 1949 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pxbar.xml ( 1516 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/gf100_pmfb.xml ( 3646 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/gf100_pcounter.xml ( 12713 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/pvcomp.xml ( 8687 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/pvenc.xml ( 1416 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/display/gf119_punk1c3.xml ( 981 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pmedia.xml ( 432 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/nv1_paudio.xml ( 1862 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/extdev/ad1848.xml ( 5260 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv1_pgraph.xml ( 14207 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv1_2d.xml ( 36532 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_pgraph.xml ( 4004 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_pgraph.xml ( 11327 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/pgraph.xml ( 31568 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/tpc.xml ( 6832 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/mpc.xml ( 6373 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_pgraph/mp.xml ( 16762 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/pgraph.xml ( 26735 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/hw_blk.xml ( 760 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/ctxctl.xml ( 13155 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/gpc.xml ( 13114 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/tpc.xml ( 22154 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/ppc.xml ( 2131 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_pgraph/rop.xml ( 5134 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_pdma.xml ( 2290 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv1_pfb.xml ( 4030 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_pcrtc.xml ( 1108 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/memory/nv1_pram.xml ( 1235 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/pchipid.xml ( 493 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv1_pdac.xml ( 4628 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/io/peeprom.xml ( 702 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv3_pramdac.xml ( 4419 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/g80_pdisplay.xml ( 39075 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/bus/prm.xml ( 5094 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/display/nv_evo.xml ( 10448 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/fifo/nv_objects.xml ( 1053 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv_m2mf.xml ( 2691 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_m2mf.xml ( 2783 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_dvd.xml ( 2994 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv3_3d.xml ( 5197 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv4_3d.xml ( 17716 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv_3ddefs.xml ( 16390 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv10_3d.xml ( 18416 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv20_3d.xml ( 21096 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/nv30-40_3d.xml ( 32451 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_2d.xml ( 11440 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_3d.xml ( 65900 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_compute.xml ( 14027 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_3d.xml ( 59845 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gk104_p2mf.xml ( 2376 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_compute.xml ( 11143 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gk104_compute.xml ( 10182 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/me_fifo.xml ( 1685 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vpe/vp1_fifo.xml ( 670 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/vdec/vp2/cipher_fifo.xml ( 2071 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/fifo/gk104_copy.xml ( 3938 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/g80_texture.xml ( 8881 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/graph/gf100_shaders.xml ( 9244 bytes, from 2014-11-02 20:39:42)
+- /home/michael/src/envytools/rnndb/vdec/vpe/mpeg_cmd.xml ( 7682 bytes, from 2014-11-02 20:39:43)
+- /home/michael/src/envytools/rnndb/extdev/adt7473.xml ( 11411 bytes, from 2014-11-02 20:39:42)
+
+Copyright (C) 2006-2014 by the following authors:
+- Artur Huillet <arthur.huillet@free.fr> (ahuillet)
+- Ben Skeggs (darktama, darktama_)
+- B. R. <koala_br@users.sourceforge.net> (koala_br)
+- Carlos Martin <carlosmn@users.sf.net> (carlosmn)
+- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr)
+- Dawid Gajownik <gajownik@users.sf.net> (gajownik)
+- Dmitry Baryshkov
+- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag)
+- EdB <edb_@users.sf.net> (edb_)
+- Erik Waling <erikwailing@users.sf.net> (erikwaling)
+- Francisco Jerez <currojerez@riseup.net> (curro)
+- imirkin <imirkin@users.sf.net> (imirkin)
+- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome)
+- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy)
+- Laurent Carlier <lordheavym@gmail.com> (lordheavy)
+- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1)
+- Maarten Maathuis <madman2003@gmail.com> (stillunknown)
+- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin)
+- Mark Carey <mark.carey@gmail.com> (careym)
+- Matthieu Castet <matthieu.castet@parrot.com> (mat-c)
+- nvidiaman <nvidiaman@users.sf.net> (nvidiaman)
+- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata)
+- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen)
+- Peter Popov <ironpeter@users.sf.net> (ironpeter)
+- Richard Hughes <hughsient@users.sf.net> (hughsient)
+- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar)
+- Serge Martin
+- Simon Raffeiner
+- Stephane Loeuillet <leroutier@users.sf.net> (leroutier)
+- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu)
+- sturmflut <sturmflut@users.sf.net> (sturmflut)
+- Sylvain Munaut <tnt@246tNt.com>
+- Victor Stinner <victor.stinner@haypocalc.com> (haypo)
+- Wladmir van der Laan <laanwj@gmail.com> (miathan6)
+- Younes Manton <younes.m@gmail.com> (ymanton)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#define NV1_DMA_FROM_MEMORY 0x00000002
+#define NV1_DMA_TO_MEMORY 0x00000003
+#define NV1_NULL 0x00000030
+#define NV3_DMA_IN_MEMORY 0x0000003d
+#define NV1_OP_CLIP 0x00000010
+#define NV1_OP_BLEND_AND 0x00000011
+#define NV1_BETA 0x00000012
+#define NV4_BETA4 0x00000072
+#define NV1_OP_ROP_AND 0x00000013
+#define NV1_ROP 0x00000014
+#define NV3_ROP 0x00000043
+#define NV1_OP_CHROMA 0x00000015
+#define NV1_OP_PLANE_SWITCH 0x00000016
+#define NV1_CHROMA 0x00000017
+#define NV4_CHROMA 0x00000057
+#define NV1_PATTERN 0x00000018
+#define NV4_PATTERN 0x00000044
+#define NV1_CLIP 0x00000019
+#define NV1_OP_SRCCOPY_AND 0x00000064
+#define NV3_OP_SRCCOPY 0x00000065
+#define NV4_OP_SRCCOPY_PREMULT 0x00000066
+#define NV4_OP_BLEND_PREMULT 0x00000067
+#define NV1_POINT 0x0000001a
+#define NV1_LINE 0x0000001b
+#define NV1_LIN 0x0000001c
+#define NV4_LIN 0x0000005c
+#define NV30_LIN 0x0000035c
+#define NV40_LIN 0x0000305c
+#define NV1_TRI 0x0000001d
+#define NV4_TRI 0x0000005d
+#define NV1_RECT 0x0000001e
+#define NV4_RECT 0x0000005e
+#define NV1_BLIT 0x0000001f
+#define NV4_BLIT 0x0000005f
+#define NV15_BLIT 0x0000009f
+#define NV1_IFM 0x00000020
+#define NV1_IFC 0x00000021
+#define NV4_IFC 0x00000061
+#define NV5_IFC 0x00000065
+#define NV10_IFC 0x0000008a
+#define NV30_IFC 0x0000038a
+#define NV40_IFC 0x0000308a
+#define NV1_BITMAP 0x00000022
+#define NV1_ITM 0x00000025
+#define NV3_SIFC 0x00000036
+#define NV4_SIFC 0x00000076
+#define NV5_SIFC 0x00000066
+#define NV30_SIFC 0x00000366
+#define NV40_SIFC 0x00003066
+#define NV3_SIFM 0x00000037
+#define NV4_SIFM 0x00000077
+#define NV5_SIFM 0x00000063
+#define NV10_SIFM 0x00000089
+#define NV30_SIFM 0x00000389
+#define NV40_SIFM 0x00003089
+#define G80_SIFM 0x00005089
+#define NV3_GDI 0x0000004b
+#define NV4_GDI 0x0000004a
+#define NV4_SURFACE_SWZ 0x00000052
+#define NV20_SURFACE_SWZ 0x0000009e
+#define NV30_SURFACE_SWZ 0x0000039e
+#define NV40_SURFACE_SWZ 0x0000309e
+#define NV3_SURFACE_DST 0x00000058
+#define NV3_SURFACE_SRC 0x00000059
+#define NV4_SURFACE_2D 0x00000042
+#define NV10_SURFACE_2D 0x00000062
+#define NV30_SURFACE_2D 0x00000362
+#define NV40_SURFACE_2D 0x00003062
+#define G80_SURFACE_2D 0x00005062
+#define NV4_INDEX 0x00000060
+#define NV5_INDEX 0x00000064
+#define NV30_INDEX 0x00000364
+#define NV40_INDEX 0x00003064
+#define NV10_TEXUPLOAD 0x0000007b
+#define NV30_TEXUPLOAD 0x0000037b
+#define NV40_TEXUPLOAD 0x0000307b
+#define NV1_TEXLIN 0x00000023
+#define NV1_TEXQUAD 0x00000024
+#define NV1_TEXLINBETA 0x00000034
+#define NV1_TEXQUADBETA 0x00000035
+#define NV4_DVD_SUBPICTURE 0x00000038
+#define NV10_DVD_SUBPICTURE 0x00000088
+#define NV3_M2MF 0x00000039
+#define G80_M2MF 0x00005039
+#define GF100_M2MF 0x00009039
+#define GK104_P2MF 0x0000a040
+#define GK110_P2MF 0x0000a140
+#define NV3_SURFACE_COLOR 0x0000005a
+#define NV3_SURFACE_ZETA 0x0000005b
+#define NV3_TEXTURED_TRIANGLE 0x00000048
+#define NV4_TEXTURED_TRIANGLE 0x00000054
+#define NV10_TEXTURED_TRIANGLE 0x00000094
+#define NV4_SURFACE_3D 0x00000053
+#define NV10_SURFACE_3D 0x00000093
+#define NV4_MULTITEX_TRIANGLE 0x00000055
+#define NV10_MULTITEX_TRIANGLE 0x00000095
+#define NV10_3D 0x00000056
+#define NV15_3D 0x00000096
+#define NV11_3D 0x00000098
+#define NV17_3D 0x00000099
+#define NV20_3D 0x00000097
+#define NV25_3D 0x00000597
+#define NV30_3D 0x00000397
+#define NV35_3D 0x00000497
+#define NV34_3D 0x00000697
+#define NV40_3D 0x00004097
+#define NV44_3D 0x00004497
+#define G80_3D 0x00005097
+#define G84_3D 0x00008297
+#define G200_3D 0x00008397
+#define GT215_3D 0x00008597
+#define MCP89_3D 0x00008697
+#define GF100_3D 0x00009097
+#define GF108_3D 0x00009197
+#define GF110_3D 0x00009297
+#define GK104_3D 0x0000a097
+#define GK110_3D 0x0000a197
+#define GK20A_3D 0x0000a297
+#define GM107_3D 0x0000b097
+#define G80_2D 0x0000502d
+#define GF100_2D 0x0000902d
+#define G80_COMPUTE 0x000050c0
+#define GT215_COMPUTE 0x000085c0
+#define GF100_COMPUTE 0x000090c0
+#define GF110_COMPUTE 0x000091c0
+#define GK104_COMPUTE 0x0000a0c0
+#define GK110_COMPUTE 0x0000a1c0
+#define GM107_COMPUTE 0x0000b0c0
+#define G84_CIPHER 0x000074c1
+#define GK104_COPY 0x0000a0b5
+#define GM107_COPY 0x0000b0b5
+#define NV31_MPEG 0x00003174
+#define G84_MPEG 0x00008274
+#define NV40_ME 0x00004075
+#define NV41_VP1 0x00004176
+#define SUBCHAN__SIZE 0x00008000
+#define NV1_SUBCHAN 0x00000000
+
+#define NV1_SUBCHAN_OBJECT 0x00000000
+
+#define GF100_SUBCHAN_NOP 0x00000008
+
+#define G84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH 0x00000010
+
+#define G84_SUBCHAN_SEMAPHORE_ADDRESS_LOW 0x00000014
+
+#define G84_SUBCHAN_SEMAPHORE_SEQUENCE 0x00000018
+
+#define G84_SUBCHAN_SEMAPHORE_TRIGGER 0x0000001c
+#define G84_SUBCHAN_SEMAPHORE_TRIGGER_ACTION__MASK 0x0000000f
+#define G84_SUBCHAN_SEMAPHORE_TRIGGER_ACTION__SHIFT 0
+#define G84_SUBCHAN_SEMAPHORE_TRIGGER_ACTION_ACQUIRE_EQUAL 0x00000001
+#define G84_SUBCHAN_SEMAPHORE_TRIGGER_ACTION_RELEASE 0x00000002
+#define G84_SUBCHAN_SEMAPHORE_TRIGGER_ACTION_ACQUIRE_GEQUAL 0x00000004
+#define GF100_SUBCHAN_SEMAPHORE_TRIGGER_ACTION_ACQUIRE_MASK 0x00000008
+#define GF100_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000
+#define GF100_SUBCHAN_SEMAPHORE_TRIGGER_UNK20 0x00100000
+#define GF100_SUBCHAN_SEMAPHORE_TRIGGER_SHORT 0x01000000
+
+#define G84_SUBCHAN_NOTIFY_INTR 0x00000020
+
+#define G84_SUBCHAN_WRCACHE_FLUSH 0x00000024
+
+#define MCP89_SUBCHAN_UNK28 0x00000028
+
+#define MCP89_SUBCHAN_UNK2C 0x0000002c
+#define MCP89_SUBCHAN_UNK2C_UNK0__MASK 0x0fffffff
+#define MCP89_SUBCHAN_UNK2C_UNK0__SHIFT 0
+#define MCP89_SUBCHAN_UNK2C_UNK28 0x10000000
+#define MCP89_SUBCHAN_UNK2C_UNK29__MASK 0xe0000000
+#define MCP89_SUBCHAN_UNK2C_UNK29__SHIFT 29
+#define MCP89_SUBCHAN_UNK2C_UNK29_UNK0 0x00000000
+#define MCP89_SUBCHAN_UNK2C_UNK29_UNK1 0x20000000
+#define MCP89_SUBCHAN_UNK2C_UNK29_UNK2 0x40000000
+
+#define NV10_SUBCHAN_REF_CNT 0x00000050
+
+#define NV1A_SUBCHAN_DMA_SEMAPHORE 0x00000060
+
+#define NV1A_SUBCHAN_SEMAPHORE_OFFSET 0x00000064
+
+#define NV1A_SUBCHAN_SEMAPHORE_ACQUIRE 0x00000068
+
+#define NV1A_SUBCHAN_SEMAPHORE_RELEASE 0x0000006c
+
+#define GF100_SUBCHAN_UNK70 0x00000070
+
+#define GF100_SUBCHAN_UNK74 0x00000074
+
+#define GF100_SUBCHAN_UNK78 0x00000078
+
+#define GF100_SUBCHAN_UNK7C 0x0000007c
+
+#define NV40_SUBCHAN_YIELD 0x00000080
+
+#define NV1_GRAPH 0x00000000
+
+#define NV4_GRAPH_NOP 0x00000100
+
+#define NV4_GRAPH_NOTIFY 0x00000104
+#define NV4_GRAPH_NOTIFY_WRITE 0x00000000
+#define NV4_GRAPH_NOTIFY_WRITE_AND_AWAKEN 0x00000001
+
+#define GF100_GRAPH_NOTIFY_ADDRESS_HIGH 0x00000104
+
+#define GF100_GRAPH_NOTIFY_ADDRESS_LOW 0x00000108
+
+#define GF100_GRAPH_NOTIFY 0x0000010c
+#define GF100_GRAPH_NOTIFY_WRITE 0x00000000
+#define GF100_GRAPH_NOTIFY_WRITE_AND_AWAKEN 0x00000001
+
+#define G80_GRAPH_SERIALIZE 0x00000110
+
+#define GF100_GRAPH_MACRO_CODE_POS 0x00000114
+
+#define GF100_GRAPH_MACRO_CODE_DATA 0x00000118
+
+#define GF100_GRAPH_MACRO_ENTRY_POS 0x0000011c
+
+#define GF100_GRAPH_MACRO_ENTRY_DATA 0x00000120
+
+#define GF100_GRAPH_MACRO_UNK0124 0x00000124
+
+#define GT215_GRAPH_UNK0120 0x00000120
+
+#define GT215_GRAPH_UNK0124 0x00000124
+
+#define GF100_GRAPH_COND_MASTER_ADDRESS_HIGH 0x00000130
+
+#define GF100_GRAPH_COND_MASTER_ADDRESS_LOW 0x00000134
+
+#define GF100_GRAPH_COND_MASTER_MODE 0x00000138
+#define GF100_GRAPH_COND_MASTER_MODE_NEVER 0x00000000
+#define GF100_GRAPH_COND_MASTER_MODE_ALWAYS 0x00000001
+#define GF100_GRAPH_COND_MASTER_MODE_RES_NON_ZERO 0x00000002
+#define GF100_GRAPH_COND_MASTER_MODE_EQUAL 0x00000003
+#define GF100_GRAPH_COND_MASTER_MODE_NOT_EQUAL 0x00000004
+
+#define GF100_GRAPH_UNK013C 0x0000013c
+
+#define NV40_GRAPH_PM_TRIGGER 0x00000140
+
+#define GF100_GRAPH_UNK0150 0x00000150
+
+#define GF100_GRAPH_UNK0154 0x00000154
+
+#define GF100_GRAPH_SCRATCH(i0) (0x00003400 + 0x4*(i0))
+#define GF100_GRAPH_SCRATCH__ESIZE 0x00000004
+#define GF100_GRAPH_SCRATCH__LEN 0x00000080
+
+#define GF100_GRAPH_MACRO(i0) (0x00003800 + 0x8*(i0))
+#define GF100_GRAPH_MACRO__ESIZE 0x00000008
+#define GF100_GRAPH_MACRO__LEN 0x00000080
+
+#define GF100_GRAPH_MACRO_PARAM(i0) (0x00003804 + 0x8*(i0))
+#define GF100_GRAPH_MACRO_PARAM__ESIZE 0x00000008
+#define GF100_GRAPH_MACRO_PARAM__LEN 0x00000080
+
+
+#endif /* NV_OBJECT_XML */
diff --git a/src/wld/pixman.c b/src/wld/pixman.c
new file mode 100644
index 0000000..5f14a7b
--- /dev/null
+++ b/src/wld/pixman.c
@@ -0,0 +1,450 @@
+/* wld: pixman.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pixman.h"
+#include "wld-private.h"
+
+#define PIXMAN_COLOR(c) { \
+ .alpha = ((c >> 24) & 0xff) * 0x101, \
+ .red = ((c >> 16) & 0xff) * 0x101, \
+ .green = ((c >> 8) & 0xff) * 0x101, \
+ .blue = ((c >> 0) & 0xff) * 0x101, \
+}
+
+struct pixman_renderer
+{
+ struct wld_renderer base;
+ pixman_image_t * target;
+ pixman_glyph_cache_t * glyph_cache;
+};
+
+struct pixman_buffer
+{
+ struct buffer base;
+ pixman_image_t * image;
+};
+
+struct pixman_map
+{
+ struct wld_exporter exporter;
+ struct wld_destructor destructor;
+ pixman_image_t * image;
+};
+
+#include "interface/context.h"
+#define RENDERER_IMPLEMENTS_REGION
+#include "interface/renderer.h"
+#include "interface/buffer.h"
+IMPL(pixman_renderer, wld_renderer)
+IMPL(pixman_buffer, wld_buffer)
+
+static struct wld_context context = { .impl = &wld_context_impl };
+
+EXPORT
+struct wld_context * wld_pixman_context = &context;
+
+struct wld_renderer * context_create_renderer(struct wld_context * context)
+{
+ struct pixman_renderer * renderer;
+
+ if (!(renderer = malloc(sizeof *renderer)))
+ goto error0;
+
+ if (!(renderer->glyph_cache = pixman_glyph_cache_create()))
+ goto error1;
+
+ renderer_initialize(&renderer->base, &wld_renderer_impl);
+ renderer->target = NULL;
+
+ return &renderer->base;
+
+ error1:
+ free(renderer);
+ error0:
+ return NULL;
+}
+
+static struct buffer * new_buffer(pixman_image_t * image)
+{
+ struct pixman_buffer * buffer;
+
+ if (!(buffer = malloc(sizeof *buffer)))
+ return NULL;
+
+ buffer_initialize(&buffer->base, &wld_buffer_impl,
+ pixman_image_get_width(image),
+ pixman_image_get_height(image),
+ format_pixman_to_wld(pixman_image_get_format(image)),
+ pixman_image_get_stride(image));
+ buffer->base.base.map = pixman_image_get_data(image);
+ buffer->image = image;
+
+ return &buffer->base;
+}
+
+struct buffer * context_create_buffer(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ struct buffer * buffer;
+ pixman_image_t * image;
+
+ image = pixman_image_create_bits(format_wld_to_pixman(format),
+ width, height, NULL, 0);
+
+ if (!image)
+ goto error0;
+
+ if (!(buffer = new_buffer(image)))
+ goto error1;
+
+ return buffer;
+
+ error1:
+ pixman_image_unref(image);
+ error0:
+ return NULL;
+}
+
+struct buffer * context_import_buffer(struct wld_context * context,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ struct buffer * buffer;
+ pixman_image_t * image;
+
+ switch (type)
+ {
+ case WLD_OBJECT_DATA:
+ image = pixman_image_create_bits(format_wld_to_pixman(format),
+ width, height, object.ptr, pitch);
+ break;
+ default: image = NULL;
+ }
+
+ if (!image)
+ goto error0;
+
+ if (!(buffer = new_buffer(image)))
+ goto error1;
+
+ return buffer;
+
+ error1:
+ pixman_image_unref(image);
+ error0:
+ return NULL;
+
+}
+
+void context_destroy(struct wld_context * context)
+{
+}
+
+uint32_t renderer_capabilities(struct wld_renderer * renderer,
+ struct buffer * buffer)
+{
+ /* The pixman renderer can read and write to any buffer using it's map
+ * implementation. */
+ return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
+}
+
+static void destroy_image(pixman_image_t * image, void * data)
+{
+ struct buffer * buffer = data;
+
+ wld_unmap(&buffer->base);
+}
+
+bool map_export(struct wld_exporter * exporter, struct wld_buffer * buffer,
+ uint32_t type, union wld_object * object)
+{
+ struct pixman_map * map
+ = CONTAINER_OF(exporter, struct pixman_map, exporter);
+
+ switch (type)
+ {
+ case WLD_PIXMAN_OBJECT_IMAGE:
+ object->ptr = pixman_image_ref(map->image);
+ return true;
+ default:
+ return false;
+ }
+}
+
+void map_destroy(struct wld_destructor * destructor)
+{
+ struct pixman_map * map
+ = CONTAINER_OF(destructor, struct pixman_map, destructor);
+
+ pixman_image_unref(map->image);
+ free(map);
+}
+
+static pixman_image_t * pixman_image(struct buffer * buffer)
+{
+ if (buffer->base.impl == &wld_buffer_impl)
+ return pixman_image_ref(pixman_buffer(&buffer->base)->image);
+
+ union wld_object object;
+
+ if (wld_export(&buffer->base, WLD_PIXMAN_OBJECT_IMAGE, &object))
+ return object.ptr;
+
+ struct pixman_map * map;
+ pixman_image_t * image;
+
+ if (!wld_map(&buffer->base))
+ goto error0;
+
+ image = pixman_image_create_bits(format_wld_to_pixman(buffer->base.format),
+ buffer->base.width, buffer->base.height,
+ buffer->base.map, buffer->base.pitch);
+
+ if (!image)
+ goto error1;
+
+ if (!(map = malloc(sizeof *map)))
+ goto error2;
+
+ map->image = image;
+ map->exporter.export = &map_export;
+ wld_buffer_add_exporter(&buffer->base, &map->exporter);
+ map->destructor.destroy = &map_destroy;
+ wld_buffer_add_destructor(&buffer->base, &map->destructor);
+ pixman_image_set_destroy_function(image, &destroy_image, buffer);
+
+ return pixman_image_ref(image);
+
+ error2:
+ pixman_image_unref(image);
+ error1:
+ wld_unmap(&buffer->base);
+ error0:
+ return NULL;
+}
+
+bool renderer_set_target(struct wld_renderer * base, struct buffer * buffer)
+{
+ struct pixman_renderer * renderer = pixman_renderer(base);
+
+ if (renderer->target)
+ pixman_image_unref(renderer->target);
+
+ if (buffer)
+ return (renderer->target = pixman_image(buffer));
+
+ renderer->target = NULL;
+ return true;
+}
+
+void renderer_fill_rectangle(struct wld_renderer * base, uint32_t color,
+ int32_t x, int32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct pixman_renderer * renderer = pixman_renderer(base);
+ pixman_color_t pixman_color = PIXMAN_COLOR(color);
+ pixman_box32_t box = { x, y, x + width, y + height };
+
+ pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target,
+ &pixman_color, 1, &box);
+}
+
+void renderer_fill_region(struct wld_renderer * base, uint32_t color,
+ pixman_region32_t * region)
+{
+ struct pixman_renderer * renderer = pixman_renderer(base);
+ pixman_color_t pixman_color = PIXMAN_COLOR(color);
+ pixman_box32_t * boxes;
+ int num_boxes;
+
+ boxes = pixman_region32_rectangles(region, &num_boxes);
+ pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target,
+ &pixman_color, num_boxes, boxes);
+}
+
+void renderer_copy_rectangle(struct wld_renderer * base, struct buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ int32_t src_x, int32_t src_y,
+ uint32_t width, uint32_t height)
+{
+ struct pixman_renderer * renderer = pixman_renderer(base);
+ pixman_image_t * src = pixman_image(buffer), * dst = renderer->target;
+
+ if (!src) return;
+
+ pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
+ src_x, src_y, 0, 0, dst_x, dst_y, width, height);
+}
+
+void renderer_copy_region(struct wld_renderer * base, struct buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ pixman_region32_t * region)
+{
+ struct pixman_renderer * renderer = pixman_renderer(base);
+ pixman_image_t * src = pixman_image(buffer), * dst = renderer->target;
+
+ if (!src) return;
+
+ pixman_image_set_clip_region32(src, region);
+ pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
+ region->extents.x1, region->extents.y1, 0, 0,
+ region->extents.x1 + dst_x,
+ region->extents.y1 + dst_y,
+ region->extents.x2 - region->extents.x1,
+ region->extents.y2 - region->extents.y1);
+ pixman_image_set_clip_region32(src, NULL);
+}
+
+static inline uint8_t reverse(uint8_t byte)
+{
+ byte = ((byte << 1) & 0xaa) | ((byte >> 1) & 0x55);
+ byte = ((byte << 2) & 0xcc) | ((byte >> 2) & 0x33);
+ byte = ((byte << 4) & 0xf0) | ((byte >> 4) & 0x0f);
+
+ return byte;
+}
+
+void renderer_draw_text(struct wld_renderer * base,
+ struct font * font, uint32_t color,
+ int32_t x, int32_t y, const char * text,
+ uint32_t length, struct wld_extents * extents)
+{
+ struct pixman_renderer * renderer = pixman_renderer(base);
+ int ret;
+ uint32_t c;
+ struct glyph * glyph;
+ FT_UInt glyph_index;
+ pixman_glyph_t glyphs[length == -1 ? (length = strlen(text)) : length];
+ uint32_t index = 0, origin_x = 0;
+ pixman_color_t pixman_color = PIXMAN_COLOR(color);
+ pixman_image_t * solid;
+
+ solid = pixman_image_create_solid_fill(&pixman_color);
+
+ while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length)) > 0 && c != '\0')
+ {
+ text += ret;
+ length -= ret;
+ glyph_index = FT_Get_Char_Index(font->face, c);
+
+ if (!font_ensure_glyph(font, glyph_index))
+ continue;
+
+ glyph = font->glyphs[glyph_index];
+
+ glyphs[index].x = origin_x;
+ glyphs[index].y = 0;
+ glyphs[index].glyph = pixman_glyph_cache_lookup(renderer->glyph_cache,
+ font, glyph);
+
+ /* If we don't have the glyph in our cache, do some conversions to make
+ * pixman happy, and then insert it. */
+ if (!glyphs[index].glyph)
+ {
+ uint8_t * src, * dst;
+ uint32_t row, byte_index, bytes_per_row, pitch;
+ pixman_image_t * image;
+ FT_Bitmap * bitmap;
+
+ bitmap = &glyph->bitmap;
+ image = pixman_image_create_bits
+ (PIXMAN_a1, bitmap->width, bitmap->rows, NULL, bitmap->pitch);
+
+ if (!image)
+ goto advance;
+
+ pitch = pixman_image_get_stride(image);
+ bytes_per_row = (bitmap->width + 7) / 8;
+ src = bitmap->buffer;
+ dst = (uint8_t *) pixman_image_get_data(image);
+
+ for (row = 0; row < bitmap->rows; ++row)
+ {
+ /* Pixman's A1 format expects the bits in the opposite order
+ * that Freetype gives us. Sigh... */
+ for (byte_index = 0; byte_index < bytes_per_row; ++byte_index)
+ dst[byte_index] = reverse(src[byte_index]);
+
+ dst += pitch;
+ src += bitmap->pitch;
+ }
+
+ /* Insert the glyph into the cache. */
+ pixman_glyph_cache_freeze(renderer->glyph_cache);
+ glyphs[index].glyph = pixman_glyph_cache_insert
+ (renderer->glyph_cache, font, glyph,
+ -glyph->x, -glyph->y, image);
+ pixman_glyph_cache_thaw(renderer->glyph_cache);
+
+ /* The glyph cache copies the contents of the glyph bitmap. */
+ pixman_image_unref(image);
+ }
+
+ ++index;
+
+ advance:
+ origin_x += glyph->advance;
+ }
+
+ pixman_composite_glyphs_no_mask(PIXMAN_OP_OVER, solid, renderer->target,
+ 0, 0, x, y, renderer->glyph_cache,
+ index, glyphs);
+
+ pixman_image_unref(solid);
+
+ if (extents)
+ extents->advance = origin_x;
+}
+
+void renderer_flush(struct wld_renderer * renderer)
+{
+}
+
+void renderer_destroy(struct wld_renderer * base)
+{
+ struct pixman_renderer * renderer = pixman_renderer(base);
+
+ pixman_glyph_cache_destroy(renderer->glyph_cache);
+ free(renderer);
+}
+
+bool buffer_map(struct buffer * buffer)
+{
+ return true;
+}
+
+bool buffer_unmap(struct buffer * buffer)
+{
+ return true;
+}
+
+void buffer_destroy(struct buffer * base)
+{
+ struct pixman_buffer * buffer = pixman_buffer(&base->base);
+
+ pixman_image_unref(buffer->image);
+ free(buffer);
+}
+
diff --git a/src/wld/pixman.h b/src/wld/pixman.h
new file mode 100644
index 0000000..c864385
--- /dev/null
+++ b/src/wld/pixman.h
@@ -0,0 +1,44 @@
+/* wld: pixman.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_PIXMAN_H
+#define WLD_PIXMAN_H
+
+#include <stdint.h>
+
+#define WLD_PIXMAN_ID (0x01 << 24)
+
+enum wld_pixman_object_type
+{
+ WLD_PIXMAN_OBJECT_IMAGE = WLD_PIXMAN_ID
+};
+
+extern struct wld_context * wld_pixman_context;
+
+static inline struct wld_context * wld_pixman_create_context()
+{
+ return wld_pixman_context;
+}
+
+#endif
+
diff --git a/src/wld/protocol/local.mk b/src/wld/protocol/local.mk
new file mode 100644
index 0000000..216a4dd
--- /dev/null
+++ b/src/wld/protocol/local.mk
@@ -0,0 +1,18 @@
+# wld: protocol/local.mk
+
+dir := protocol
+
+PROTOCOL_EXTENSIONS = $(dir)/wayland-drm.xml
+
+$(dir)/%-protocol.c: $(dir)/%.xml
+ $(call quiet,GEN,$(WAYLAND_SCANNER)) code < $< > $@
+
+$(dir)/%-client-protocol.h: $(dir)/%.xml
+ $(call quiet,GEN,$(WAYLAND_SCANNER)) client-header < $< > $@
+
+CLEAN_FILES += \
+ $(PROTOCOL_EXTENSIONS:%.xml=%-protocol.c) \
+ $(PROTOCOL_EXTENSIONS:%.xml=%-client-protocol.h)
+
+include common.mk
+
diff --git a/src/wld/protocol/wayland-drm.xml b/src/wld/protocol/wayland-drm.xml
new file mode 100644
index 0000000..5e64622
--- /dev/null
+++ b/src/wld/protocol/wayland-drm.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm">
+
+ <copyright>
+ Copyright © 2008-2011 Kristian Høgsberg
+ Copyright © 2010-2011 Intel Corporation
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that\n the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <!-- drm support. This object is created by the server and published
+ using the display's global event. -->
+ <interface name="wl_drm" version="2">
+ <enum name="error">
+ <entry name="authenticate_fail" value="0"/>
+ <entry name="invalid_format" value="1"/>
+ <entry name="invalid_name" value="2"/>
+ </enum>
+
+ <enum name="format">
+ <!-- The drm format codes match the #defines in drm_fourcc.h.
+ The formats actually supported by the compositor will be
+ reported by the format event. -->
+ <entry name="c8" value="0x20203843"/>
+ <entry name="rgb332" value="0x38424752"/>
+ <entry name="bgr233" value="0x38524742"/>
+ <entry name="xrgb4444" value="0x32315258"/>
+ <entry name="xbgr4444" value="0x32314258"/>
+ <entry name="rgbx4444" value="0x32315852"/>
+ <entry name="bgrx4444" value="0x32315842"/>
+ <entry name="argb4444" value="0x32315241"/>
+ <entry name="abgr4444" value="0x32314241"/>
+ <entry name="rgba4444" value="0x32314152"/>
+ <entry name="bgra4444" value="0x32314142"/>
+ <entry name="xrgb1555" value="0x35315258"/>
+ <entry name="xbgr1555" value="0x35314258"/>
+ <entry name="rgbx5551" value="0x35315852"/>
+ <entry name="bgrx5551" value="0x35315842"/>
+ <entry name="argb1555" value="0x35315241"/>
+ <entry name="abgr1555" value="0x35314241"/>
+ <entry name="rgba5551" value="0x35314152"/>
+ <entry name="bgra5551" value="0x35314142"/>
+ <entry name="rgb565" value="0x36314752"/>
+ <entry name="bgr565" value="0x36314742"/>
+ <entry name="rgb888" value="0x34324752"/>
+ <entry name="bgr888" value="0x34324742"/>
+ <entry name="xrgb8888" value="0x34325258"/>
+ <entry name="xbgr8888" value="0x34324258"/>
+ <entry name="rgbx8888" value="0x34325852"/>
+ <entry name="bgrx8888" value="0x34325842"/>
+ <entry name="argb8888" value="0x34325241"/>
+ <entry name="abgr8888" value="0x34324241"/>
+ <entry name="rgba8888" value="0x34324152"/>
+ <entry name="bgra8888" value="0x34324142"/>
+ <entry name="xrgb2101010" value="0x30335258"/>
+ <entry name="xbgr2101010" value="0x30334258"/>
+ <entry name="rgbx1010102" value="0x30335852"/>
+ <entry name="bgrx1010102" value="0x30335842"/>
+ <entry name="argb2101010" value="0x30335241"/>
+ <entry name="abgr2101010" value="0x30334241"/>
+ <entry name="rgba1010102" value="0x30334152"/>
+ <entry name="bgra1010102" value="0x30334142"/>
+ <entry name="yuyv" value="0x56595559"/>
+ <entry name="yvyu" value="0x55595659"/>
+ <entry name="uyvy" value="0x59565955"/>
+ <entry name="vyuy" value="0x59555956"/>
+ <entry name="ayuv" value="0x56555941"/>
+ <entry name="nv12" value="0x3231564e"/>
+ <entry name="nv21" value="0x3132564e"/>
+ <entry name="nv16" value="0x3631564e"/>
+ <entry name="nv61" value="0x3136564e"/>
+ <entry name="yuv410" value="0x39565559"/>
+ <entry name="yvu410" value="0x39555659"/>
+ <entry name="yuv411" value="0x31315559"/>
+ <entry name="yvu411" value="0x31315659"/>
+ <entry name="yuv420" value="0x32315559"/>
+ <entry name="yvu420" value="0x32315659"/>
+ <entry name="yuv422" value="0x36315559"/>
+ <entry name="yvu422" value="0x36315659"/>
+ <entry name="yuv444" value="0x34325559"/>
+ <entry name="yvu444" value="0x34325659"/>
+ </enum>
+
+ <!-- Call this request with the magic received from drmGetMagic().
+ It will be passed on to the drmAuthMagic() or
+ DRIAuthConnection() call. This authentication must be
+ completed before create_buffer could be used. -->
+ <request name="authenticate">
+ <arg name="id" type="uint"/>
+ </request>
+
+ <!-- Create a wayland buffer for the named DRM buffer. The DRM
+ surface must have a name using the flink ioctl -->
+ <request name="create_buffer">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="uint"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="stride" type="uint"/>
+ <arg name="format" type="uint"/>
+ </request>
+
+ <!-- Create a wayland buffer for the named DRM buffer. The DRM
+ surface must have a name using the flink ioctl -->
+ <request name="create_planar_buffer">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="uint"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="format" type="uint"/>
+ <arg name="offset0" type="int"/>
+ <arg name="stride0" type="int"/>
+ <arg name="offset1" type="int"/>
+ <arg name="stride1" type="int"/>
+ <arg name="offset2" type="int"/>
+ <arg name="stride2" type="int"/>
+ </request>
+
+ <!-- Notification of the path of the drm device which is used by
+ the server. The client should use this device for creating
+ local buffers. Only buffers created from this device should
+ be be passed to the server using this drm object's
+ create_buffer request. -->
+ <event name="device">
+ <arg name="name" type="string"/>
+ </event>
+
+ <event name="format">
+ <arg name="format" type="uint"/>
+ </event>
+
+ <!-- Raised if the authenticate request succeeded -->
+ <event name="authenticated"/>
+
+ <enum name="capability" since="2">
+ <description summary="wl_drm capability bitmask">
+ Bitmask of capabilities.
+ </description>
+ <entry name="prime" value="1" summary="wl_drm prime available"/>
+ </enum>
+
+ <event name="capabilities">
+ <arg name="value" type="uint"/>
+ </event>
+
+ <!-- Version 2 additions -->
+
+ <!-- Create a wayland buffer for the prime fd. Use for regular and planar
+ buffers. Pass 0 for offset and stride for unused planes. -->
+ <request name="create_prime_buffer" since="2">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="fd"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="format" type="uint"/>
+ <arg name="offset0" type="int"/>
+ <arg name="stride0" type="int"/>
+ <arg name="offset1" type="int"/>
+ <arg name="stride1" type="int"/>
+ <arg name="offset2" type="int"/>
+ <arg name="stride2" type="int"/>
+ </request>
+
+ </interface>
+
+</protocol>
diff --git a/src/wld/renderer.c b/src/wld/renderer.c
new file mode 100644
index 0000000..a038095
--- /dev/null
+++ b/src/wld/renderer.c
@@ -0,0 +1,157 @@
+/* wld: renderer.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wld-private.h"
+
+void default_fill_region(struct wld_renderer * renderer, uint32_t color,
+ pixman_region32_t * region)
+{
+ pixman_box32_t * box;
+ int num_boxes;
+
+ box = pixman_region32_rectangles(region, &num_boxes);
+
+ while (num_boxes--)
+ {
+ renderer->impl->fill_rectangle(renderer, color, box->x1, box->y1,
+ box->x2 - box->x1, box->y2 - box->y1);
+ ++box;
+ }
+}
+
+void default_copy_region(struct wld_renderer * renderer, struct buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ pixman_region32_t * region)
+{
+ pixman_box32_t * box;
+ int num_boxes;
+
+ box = pixman_region32_rectangles(region, &num_boxes);
+
+ while (num_boxes--)
+ {
+ renderer->impl->copy_rectangle(renderer, buffer,
+ dst_x + box->x1, dst_y + box->y1,
+ box->x1, box->y1,
+ box->x2 - box->x1, box->y2 - box->y1);
+ ++box;
+ }
+}
+
+void renderer_initialize(struct wld_renderer * renderer,
+ const struct wld_renderer_impl * impl)
+{
+ *((const struct wld_renderer_impl **) &renderer->impl) = impl;
+ renderer->target = NULL;
+}
+
+EXPORT
+void wld_destroy_renderer(struct wld_renderer * renderer)
+{
+ renderer->impl->destroy(renderer);
+}
+
+EXPORT
+uint32_t wld_capabilities(struct wld_renderer * renderer,
+ struct wld_buffer * buffer)
+{
+ return renderer->impl->capabilities(renderer, (struct buffer *) buffer);
+}
+
+EXPORT
+bool wld_set_target_buffer(struct wld_renderer * renderer,
+ struct wld_buffer * buffer)
+{
+ if (!renderer->impl->set_target(renderer, (struct buffer *) buffer))
+ return false;
+
+ renderer->target = buffer;
+
+ return true;
+}
+
+EXPORT
+bool wld_set_target_surface(struct wld_renderer * renderer,
+ struct wld_surface * surface)
+{
+ struct buffer * back_buffer;
+
+ if (!(back_buffer = surface->impl->back(surface)))
+ return false;
+
+ return renderer->impl->set_target(renderer, back_buffer);
+}
+
+EXPORT
+void wld_fill_rectangle(struct wld_renderer * renderer, uint32_t color,
+ int32_t x, int32_t y, uint32_t width, uint32_t height)
+{
+ renderer->impl->fill_rectangle(renderer, color, x, y, width, height);
+}
+
+EXPORT
+void wld_fill_region(struct wld_renderer * renderer, uint32_t color,
+ pixman_region32_t * region)
+{
+ renderer->impl->fill_region(renderer, color, region);
+}
+
+EXPORT
+void wld_copy_rectangle(struct wld_renderer * renderer,
+ struct wld_buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ int32_t src_x, int32_t src_y,
+ uint32_t width, uint32_t height)
+{
+ renderer->impl->copy_rectangle(renderer, (struct buffer *) buffer,
+ dst_x, dst_y, src_x, src_y, width, height);
+}
+
+EXPORT
+void wld_copy_region(struct wld_renderer * renderer,
+ struct wld_buffer * buffer,
+ int32_t dst_x, int32_t dst_y, pixman_region32_t * region)
+{
+ renderer->impl->copy_region(renderer, (struct buffer *) buffer,
+ dst_x, dst_y, region);
+}
+
+EXPORT
+void wld_draw_text(struct wld_renderer * renderer,
+ struct wld_font * font_base, uint32_t color,
+ int32_t x, int32_t y, const char * text, uint32_t length,
+ struct wld_extents * extents)
+{
+ struct font * font = (void *) font_base;
+
+ renderer->impl->draw_text(renderer, font, color, x, y, text, length,
+ extents);
+}
+
+EXPORT
+void wld_flush(struct wld_renderer * renderer)
+{
+ renderer->impl->flush(renderer);
+ renderer->impl->set_target(renderer, NULL);
+}
+
diff --git a/src/wld/surface.c b/src/wld/surface.c
new file mode 100644
index 0000000..3f936bd
--- /dev/null
+++ b/src/wld/surface.c
@@ -0,0 +1,70 @@
+/* wld: surface.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wld-private.h"
+
+struct wld_surface * default_create_surface(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ return buffered_surface_create(context, width, height, format, flags, NULL);
+}
+
+void surface_initialize(struct wld_surface * surface,
+ const struct wld_surface_impl * impl)
+{
+ *((const struct wld_surface_impl **) &surface->impl) = impl;
+}
+
+EXPORT
+pixman_region32_t * wld_surface_damage(struct wld_surface * surface,
+ pixman_region32_t * new_damage)
+{
+ return surface->impl->damage(surface, new_damage);
+}
+
+EXPORT
+struct wld_buffer * wld_surface_take(struct wld_surface * surface)
+{
+ return &surface->impl->take(surface)->base;
+}
+
+EXPORT
+void wld_surface_release(struct wld_surface * surface,
+ struct wld_buffer * buffer)
+{
+ surface->impl->release(surface, (struct buffer *) buffer);
+}
+
+EXPORT
+bool wld_swap(struct wld_surface * surface)
+{
+ return surface->impl->swap(surface);
+}
+
+EXPORT
+void wld_destroy_surface(struct wld_surface * surface)
+{
+ surface->impl->destroy(surface);
+}
+
diff --git a/src/wld/wayland-drm.c b/src/wld/wayland-drm.c
new file mode 100644
index 0000000..7e7fe4c
--- /dev/null
+++ b/src/wld/wayland-drm.c
@@ -0,0 +1,296 @@
+/* wld: wayland-drm.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wayland.h"
+#include "drm.h"
+#include "wayland-drm-client-protocol.h"
+#include "wayland-private.h"
+#include "wld-private.h"
+#include "drm-private.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <xf86drm.h>
+
+struct drm_context
+{
+ struct wayland_context base;
+ struct wld_context * driver_context;
+ struct wl_drm * wl;
+ struct wl_registry * registry;
+ struct wl_array formats;
+ uint32_t capabilities;
+ int fd;
+ bool authenticated;
+};
+
+#define WAYLAND_IMPL_NAME drm
+#include "interface/context.h"
+#include "interface/wayland.h"
+IMPL(drm_context, wld_context)
+
+static void registry_global(void * data, struct wl_registry * registry,
+ uint32_t name, const char * interface,
+ uint32_t version);
+static void registry_global_remove(void * data, struct wl_registry * registry,
+ uint32_t name);
+
+static void drm_device(void * data, struct wl_drm * wl, const char * name);
+static void drm_format(void * data, struct wl_drm * wl, uint32_t format);
+static void drm_authenticated(void * data, struct wl_drm * wl);
+static void drm_capabilities(void * data, struct wl_drm * wl,
+ uint32_t capabilities);
+
+const static struct wl_registry_listener registry_listener = {
+ .global = &registry_global,
+ .global_remove = &registry_global_remove
+};
+
+const static struct wl_drm_listener drm_listener = {
+ .device = &drm_device,
+ .format = &drm_format,
+ .authenticated = &drm_authenticated,
+ .capabilities = &drm_capabilities
+};
+
+struct wayland_context * wayland_create_context(struct wl_display * display,
+ struct wl_event_queue * queue)
+{
+ struct drm_context * context;
+
+ if (!(context = malloc(sizeof *context)))
+ goto error0;
+
+ context_initialize(&context->base.base, &wld_context_impl);
+ context->wl = NULL;
+ context->fd = -1;
+ context->capabilities = 0;
+ wl_array_init(&context->formats);
+
+ if (!(context->registry = wl_display_get_registry(display)))
+ goto error1;
+
+ wl_registry_add_listener(context->registry, &registry_listener, context);
+ wl_proxy_set_queue((struct wl_proxy *) context->registry, queue);
+
+ /* Wait for wl_drm global. */
+ wl_display_roundtrip_queue(display, queue);
+
+ if (!context->wl)
+ {
+ DEBUG("No wl_drm global\n");
+ goto error2;
+ }
+
+ wl_drm_add_listener(context->wl, &drm_listener, context);
+
+ /* Wait for DRM capabilities and device. */
+ wl_display_roundtrip_queue(display, queue);
+
+ if (!(context->capabilities & WL_DRM_CAPABILITY_PRIME))
+ {
+ DEBUG("No PRIME support\n");
+ goto error3;
+ }
+
+ if (context->fd == -1)
+ {
+ DEBUG("No DRM device\n");
+ goto error3;
+ }
+
+ /* Wait for DRM authentication. */
+ wl_display_roundtrip_queue(display, queue);
+
+ if (!context->authenticated)
+ {
+ DEBUG("DRM authentication failed\n");
+ goto error4;
+ }
+
+ if (!(context->driver_context = wld_drm_create_context(context->fd)))
+ {
+ DEBUG("Couldn't initialize context for DRM device\n");
+ goto error4;
+ }
+
+ return &context->base;
+
+ error4:
+ close(context->fd);
+ error3:
+ wl_drm_destroy(context->wl);
+ error2:
+ wl_registry_destroy(context->registry);
+ error1:
+ wl_array_release(&context->formats);
+ free(context);
+ error0:
+ return NULL;
+}
+
+bool wayland_has_format(struct wld_context * base, uint32_t format)
+{
+ struct drm_context * context = drm_context(base);
+ uint32_t * supported_format;
+
+ wl_array_for_each(supported_format, &context->formats)
+ {
+ if (*supported_format == format)
+ return true;
+ }
+
+ return false;
+}
+
+EXPORT
+int wld_wayland_drm_get_fd(struct wld_context * base)
+{
+ struct drm_context * context = drm_context(base);
+
+ return context->authenticated ? context->fd : -1;
+}
+
+struct wld_renderer * context_create_renderer(struct wld_context * base)
+{
+ struct drm_context * context = drm_context(base);
+
+ return wld_create_renderer(context->driver_context);
+}
+
+struct buffer * context_create_buffer(struct wld_context * base,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ struct drm_context * context = drm_context(base);
+ struct buffer * buffer;
+ union wld_object object;
+ struct wl_buffer * wl;
+
+ if (!wayland_has_format(base, format))
+ goto error0;
+
+ buffer = context->driver_context->impl->create_buffer
+ (context->driver_context, width, height, format, flags);
+
+ if (!buffer)
+ goto error0;
+
+ if (!wld_export(&buffer->base, WLD_DRM_OBJECT_PRIME_FD, &object))
+ goto error1;
+
+ wl = wl_drm_create_prime_buffer(context->wl, object.i, width, height,
+ format, 0, buffer->base.pitch, 0, 0, 0, 0);
+ close(object.i);
+
+ if (!wl)
+ goto error1;
+
+ if (!wayland_buffer_add_exporter(buffer, wl))
+ goto error2;
+
+ return buffer;
+
+ error2:
+ wl_buffer_destroy(wl);
+ error1:
+ wld_buffer_unreference(&buffer->base);
+ error0:
+ return NULL;
+}
+
+struct buffer * context_import_buffer(struct wld_context * context,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ return NULL;
+}
+
+void context_destroy(struct wld_context * base)
+{
+ struct drm_context * context = drm_context(base);
+
+ wld_destroy_context(context->driver_context);
+ close(context->fd);
+ wl_drm_destroy(context->wl);
+ wl_registry_destroy(context->registry);
+ wl_array_release(&context->formats);
+ wl_event_queue_destroy(context->base.queue);
+ free(context);
+}
+
+void registry_global(void * data, struct wl_registry * registry, uint32_t name,
+ const char * interface, uint32_t version)
+{
+ struct drm_context * context = data;
+
+ if (strcmp(interface, "wl_drm") == 0 && version >= 2)
+ context->wl = wl_registry_bind(registry, name, &wl_drm_interface, 2);
+}
+
+void registry_global_remove(void * data, struct wl_registry * registry,
+ uint32_t name)
+{
+}
+
+void drm_device(void * data, struct wl_drm * wl, const char * name)
+{
+ struct drm_context * context = data;
+ drm_magic_t magic;
+
+ context->fd = open(name, O_RDWR);
+
+ if (context->fd == -1)
+ {
+ DEBUG("Couldn't open DRM device '%s'\n", name);
+ return;
+ }
+
+ drmGetMagic(context->fd, &magic);
+ wl_drm_authenticate(wl, magic);
+}
+
+void drm_format(void * data, struct wl_drm * wl, uint32_t format)
+{
+ struct drm_context * context = data;
+
+ *((uint32_t *) wl_array_add(&context->formats, sizeof format)) = format;
+}
+
+void drm_authenticated(void * data, struct wl_drm * wl)
+{
+ struct drm_context * context = data;
+
+ context->authenticated = true;
+}
+
+void drm_capabilities(void * data, struct wl_drm * wl, uint32_t capabilities)
+{
+ struct drm_context * context = data;
+
+ context->capabilities = capabilities;
+}
+
diff --git a/src/wld/wayland-private.h b/src/wld/wayland-private.h
new file mode 100644
index 0000000..f52e3ae
--- /dev/null
+++ b/src/wld/wayland-private.h
@@ -0,0 +1,60 @@
+/* wld: wayland-private.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_WAYLAND_PRIVATE_H
+#define WLD_WAYLAND_PRIVATE_H
+
+#include "wld.h"
+
+struct buffer;
+struct wl_display;
+struct wl_event_queue;
+struct wl_buffer;
+
+struct wayland_context
+{
+ struct wld_context base;
+ const struct wayland_impl * impl;
+ struct wl_display * display;
+ struct wl_event_queue * queue;
+};
+
+struct wayland_impl
+{
+ struct wayland_context * (* create_context)(struct wl_display * display,
+ struct wl_event_queue * queue);
+ bool (* has_format)(struct wld_context * context, uint32_t format);
+};
+
+#if WITH_WAYLAND_DRM
+extern const struct wayland_impl drm_wayland_impl;
+#endif
+
+#if WITH_WAYLAND_SHM
+extern const struct wayland_impl shm_wayland_impl;
+#endif
+
+bool wayland_buffer_add_exporter(struct buffer * buffer, struct wl_buffer * wl);
+
+#endif
+
diff --git a/src/wld/wayland-shm.c b/src/wld/wayland-shm.c
new file mode 100644
index 0000000..520eb2c
--- /dev/null
+++ b/src/wld/wayland-shm.c
@@ -0,0 +1,294 @@
+/* wld: wayland-shm.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define _GNU_SOURCE /* Required for mkostemp */
+
+#include "wayland.h"
+#include "wayland-private.h"
+#include "wld-private.h"
+#include "pixman.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <wayland-client.h>
+
+struct shm_context
+{
+ struct wayland_context base;
+ struct wl_registry * registry;
+ struct wl_shm * wl;
+ struct wl_array formats;
+};
+
+struct shm_buffer
+{
+ struct buffer base;
+ int fd;
+};
+
+#define WAYLAND_IMPL_NAME shm
+#include "interface/context.h"
+#include "interface/buffer.h"
+#include "interface/wayland.h"
+IMPL(shm_context, wld_context)
+IMPL(shm_buffer, wld_buffer)
+
+static void registry_global(void * data, struct wl_registry * registry,
+ uint32_t name, const char * interface,
+ uint32_t version);
+static void registry_global_remove(void * data, struct wl_registry * registry,
+ uint32_t name);
+
+static void shm_format(void * data, struct wl_shm * wl, uint32_t format);
+
+const static struct wl_registry_listener registry_listener = {
+ .global = &registry_global,
+ .global_remove = &registry_global_remove
+};
+
+const static struct wl_shm_listener shm_listener = {
+ .format = &shm_format,
+};
+
+static inline uint32_t format_wld_to_shm(uint32_t format)
+{
+ switch (format)
+ {
+ case WLD_FORMAT_ARGB8888:
+ return WL_SHM_FORMAT_ARGB8888;
+ case WLD_FORMAT_XRGB8888:
+ return WL_SHM_FORMAT_XRGB8888;
+ default:
+ return 0;
+ }
+}
+
+struct wayland_context * wayland_create_context(struct wl_display * display,
+ struct wl_event_queue * queue)
+{
+ struct shm_context * context;
+
+ if (!(context = malloc(sizeof *context)))
+ goto error0;
+
+ context_initialize(&context->base.base, &wld_context_impl);
+ context->wl = NULL;
+ wl_array_init(&context->formats);
+
+ if (!(context->registry = wl_display_get_registry(display)))
+ {
+ DEBUG("Couldn't get registry\n");
+ goto error1;
+ }
+
+ wl_registry_add_listener(context->registry, &registry_listener, context);
+ wl_proxy_set_queue((struct wl_proxy *) context->registry, queue);
+
+ /* Wait for wl_shm global. */
+ wl_display_roundtrip_queue(display, queue);
+
+ if (!context->wl)
+ {
+ DEBUG("No wl_shm global\n");
+ goto error2;
+ }
+
+ wl_shm_add_listener(context->wl, &shm_listener, context);
+
+ /* Wait for SHM formats. */
+ wl_display_roundtrip_queue(display, queue);
+
+ return &context->base;
+
+ error2:
+ wl_registry_destroy(context->registry);
+ error1:
+ wl_array_release(&context->formats);
+ free(context);
+ error0:
+ return NULL;
+}
+
+bool wayland_has_format(struct wld_context * base, uint32_t format)
+{
+ struct shm_context * context = shm_context(base);
+ uint32_t * supported_format;
+ uint32_t shm_format = format_wld_to_shm(format);
+
+ wl_array_for_each(supported_format, &context->formats)
+ {
+ if (*supported_format == shm_format)
+ return true;
+ }
+
+ return false;
+}
+
+struct wld_renderer * context_create_renderer(struct wld_context * context)
+{
+ return wld_create_renderer(wld_pixman_context);
+}
+
+struct buffer * context_create_buffer(struct wld_context * base,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ struct shm_context * context = shm_context(base);
+ struct shm_buffer * buffer;
+ char name[] = "/tmp/wld-XXXXXX";
+ uint32_t pitch = width * format_bytes_per_pixel(format);
+ size_t size = pitch * height;
+ int fd;
+ struct wl_shm_pool * pool;
+ struct wl_buffer * wl;
+
+ if (!wayland_has_format(base, format))
+ goto error0;
+
+ if (!(buffer = malloc(sizeof *buffer)))
+ goto error0;
+
+ fd = mkostemp(name, O_CLOEXEC);
+
+ if (fd < 0)
+ goto error1;
+
+ unlink(name);
+
+ if (posix_fallocate(fd, 0, size) != 0)
+ goto error2;
+
+ if (!(pool = wl_shm_create_pool(context->wl, fd, size)))
+ goto error2;
+
+ wl = wl_shm_pool_create_buffer(pool, 0, width, height, pitch,
+ format_wld_to_shm(format));
+ wl_shm_pool_destroy(pool);
+
+ if (!wl)
+ goto error2;
+
+ buffer_initialize(&buffer->base, &wld_buffer_impl,
+ width, height, format, pitch);
+ buffer->fd = fd;
+
+ if (!(wayland_buffer_add_exporter(&buffer->base, wl)))
+ goto error3;
+
+ return &buffer->base;
+
+ error3:
+ wl_buffer_destroy(wl);
+ error2:
+ close(fd);
+ error1:
+ free(buffer);
+ error0:
+ return NULL;
+}
+
+struct buffer * context_import_buffer(struct wld_context * context,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch)
+{
+ return NULL;
+}
+
+void context_destroy(struct wld_context * base)
+{
+ struct shm_context * context = shm_context(base);
+
+ wl_shm_destroy(context->wl);
+ wl_registry_destroy(context->registry);
+ wl_array_release(&context->formats);
+ wl_event_queue_destroy(context->base.queue);
+ free(context);
+}
+
+/**** Buffer ****/
+
+bool buffer_map(struct buffer * base)
+{
+ struct shm_buffer * buffer = shm_buffer(&base->base);
+ void * data;
+
+ data = mmap(NULL, buffer->base.base.pitch * buffer->base.base.height,
+ PROT_READ | PROT_WRITE, MAP_SHARED, buffer->fd, 0);
+
+ if (data == MAP_FAILED)
+ return false;
+
+ buffer->base.base.map = data;
+
+ return true;
+}
+
+bool buffer_unmap(struct buffer * buffer)
+{
+ if (munmap(buffer->base.map,
+ buffer->base.pitch * buffer->base.height) == -1)
+ {
+ return false;
+ }
+
+ buffer->base.map = NULL;
+
+ return true;
+}
+
+void buffer_destroy(struct buffer * base)
+{
+ struct shm_buffer * buffer = shm_buffer(&base->base);
+
+ close(buffer->fd);
+ free(buffer);
+}
+
+void registry_global(void * data, struct wl_registry * registry, uint32_t name,
+ const char * interface, uint32_t version)
+{
+ struct shm_context * context = data;
+
+ if (strcmp(interface, "wl_shm") == 0)
+ context->wl = wl_registry_bind(registry, name, &wl_shm_interface, 1);
+}
+
+void registry_global_remove(void * data, struct wl_registry * registry,
+ uint32_t name)
+{
+}
+
+void shm_format(void * data, struct wl_shm * wl, uint32_t format)
+{
+ struct shm_context * context = data;
+ uint32_t * added_format;
+
+ if (!(added_format = wl_array_add(&context->formats, sizeof format)))
+ return;
+ *added_format = format;
+}
+
diff --git a/src/wld/wayland.c b/src/wld/wayland.c
new file mode 100644
index 0000000..40a4b34
--- /dev/null
+++ b/src/wld/wayland.c
@@ -0,0 +1,308 @@
+/* wld: wayland.c
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "wayland.h"
+#include "wayland-private.h"
+#include "wld-private.h"
+
+#include <stdlib.h>
+#include <wayland-client.h>
+
+struct wayland_buffer
+{
+ struct wld_exporter exporter;
+ struct wld_destructor destructor;
+ struct wl_buffer * wl;
+};
+
+struct wayland_buffer_socket
+{
+ struct buffer_socket base;
+ struct wl_buffer_listener listener;
+ struct wld_surface * surface;
+ struct wl_surface * wl;
+ struct wl_display * display;
+ struct wl_event_queue * queue;
+};
+
+static bool buffer_socket_attach(struct buffer_socket * socket,
+ struct buffer * buffer);
+static void buffer_socket_process(struct buffer_socket * socket);
+static void buffer_socket_destroy(struct buffer_socket * socket);
+
+static const struct buffer_socket_impl buffer_socket_impl = {
+ .attach = &buffer_socket_attach,
+ .process = &buffer_socket_process,
+ .destroy = &buffer_socket_destroy
+};
+
+IMPL(wayland_buffer_socket, buffer_socket)
+
+static void sync_done(void * data, struct wl_callback * callback,
+ uint32_t msecs);
+
+static const struct wl_callback_listener sync_listener = {
+ .done = &sync_done
+};
+
+static void buffer_release(void * data, struct wl_buffer * buffer);
+
+const static struct wayland_impl * impls[] = {
+#if WITH_WAYLAND_DRM
+ [WLD_DRM] = &drm_wayland_impl,
+#endif
+
+#if WITH_WAYLAND_SHM
+ [WLD_SHM] = &shm_wayland_impl,
+#endif
+};
+
+enum wld_wayland_interface_id interface_id(const char * string)
+{
+ if (strcmp(string, "drm") == 0)
+ return WLD_DRM;
+ if (strcmp(string, "shm") == 0)
+ return WLD_SHM;
+
+ fprintf(stderr, "Unknown Wayland interface specified: '%s'\n", string);
+
+ return WLD_NONE;
+}
+
+EXPORT
+struct wld_context * wld_wayland_create_context
+ (struct wl_display * display, enum wld_wayland_interface_id id, ...)
+{
+ struct wayland_context * context = NULL;
+ struct wl_event_queue * queue;
+ va_list requested_impls;
+ bool impls_tried[ARRAY_LENGTH(impls)] = {0};
+ const char * interface_string;
+
+ if (!(queue = wl_display_create_queue(display)))
+ return NULL;
+
+ if ((interface_string = getenv("WLD_WAYLAND_INTERFACE")))
+ {
+ id = interface_id(interface_string);
+
+ if ((context = impls[id]->create_context(display, queue)))
+ return &context->base;
+
+ fprintf(stderr, "Could not create context for Wayland interface '%s'\n",
+ interface_string);
+
+ return NULL;
+ }
+
+ va_start(requested_impls, id);
+
+ while (id >= 0)
+ {
+ if (impls_tried[id] || !impls[id])
+ continue;
+
+ if ((context = impls[id]->create_context(display, queue)))
+ goto done;
+
+ impls_tried[id] = true;
+ id = va_arg(requested_impls, enum wld_wayland_interface_id);
+ }
+
+ va_end(requested_impls);
+
+ /* If the user specified WLD_ANY, try any remaining implementations. */
+ if (!context && id == WLD_ANY)
+ {
+ for (id = 0; id < ARRAY_LENGTH(impls); ++id)
+ {
+ if (impls_tried[id] || !impls[id])
+ continue;
+
+ if ((context = impls[id]->create_context(display, queue)))
+ break;
+ }
+ }
+
+ if (!context)
+ {
+ DEBUG("Could not initialize any of the specified implementations\n");
+ return NULL;
+ }
+
+ done:
+ context->impl = impls[id];
+ context->display = display;
+ context->queue = queue;
+
+ return &context->base;
+}
+
+EXPORT
+struct wld_surface * wld_wayland_create_surface(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags,
+ struct wl_surface * wl)
+{
+ struct wayland_buffer_socket * socket;
+
+ if (!(socket = malloc(sizeof *socket)))
+ goto error0;
+
+ socket->base.impl = &buffer_socket_impl;
+ socket->listener.release = &buffer_release;
+ socket->wl = wl;
+ socket->queue = ((struct wayland_context *) context)->queue;
+ socket->display = ((struct wayland_context *) context)->display;
+ socket->surface = buffered_surface_create(context, width, height, format,
+ flags, &socket->base);
+
+ if (!socket->surface)
+ goto error1;
+
+ return socket->surface;
+
+ error1:
+ free(socket);
+ error0:
+ return NULL;
+}
+
+EXPORT
+bool wld_wayland_has_format(struct wld_context * base, uint32_t format)
+{
+ struct wayland_context * context = (void *) base;
+
+ return context->impl->has_format(base, format);
+}
+
+static bool buffer_export(struct wld_exporter * exporter,
+ struct wld_buffer * buffer,
+ uint32_t type, union wld_object * object)
+{
+ struct wayland_buffer * wayland_buffer
+ = CONTAINER_OF(exporter, struct wayland_buffer, exporter);
+
+ switch (type)
+ {
+ case WLD_WAYLAND_OBJECT_BUFFER:
+ object->ptr = wayland_buffer->wl;
+ return true;
+ default: return false;
+ }
+}
+
+static void buffer_destroy(struct wld_destructor * destructor)
+{
+ struct wayland_buffer * wayland_buffer
+ = CONTAINER_OF(destructor, struct wayland_buffer, destructor);
+
+ wl_buffer_destroy(wayland_buffer->wl);
+ free(wayland_buffer);
+}
+
+bool wayland_buffer_add_exporter(struct buffer * buffer, struct wl_buffer * wl)
+{
+ struct wayland_buffer * wayland_buffer;
+
+ if (!(wayland_buffer = malloc(sizeof *wayland_buffer)))
+ return false;
+
+ wayland_buffer->wl = wl;
+ wayland_buffer->exporter.export = &buffer_export;
+ wld_buffer_add_exporter(&buffer->base, &wayland_buffer->exporter);
+ wayland_buffer->destructor.destroy = &buffer_destroy;
+ wld_buffer_add_destructor(&buffer->base, &wayland_buffer->destructor);
+
+ return true;
+}
+
+bool buffer_socket_attach(struct buffer_socket * base, struct buffer * buffer)
+{
+ struct wayland_buffer_socket * socket = wayland_buffer_socket(base);
+ struct wl_buffer * wl;
+ union wld_object object;
+
+ if (!wld_export(&buffer->base, WLD_WAYLAND_OBJECT_BUFFER, &object))
+ return false;
+
+ wl = object.ptr;
+
+ if (!wl_proxy_get_listener((struct wl_proxy *) wl))
+ wl_buffer_add_listener(wl, &socket->listener, buffer);
+
+ wl_surface_attach(socket->wl, wl, 0, 0);
+
+ if (pixman_region32_not_empty(&buffer->base.damage))
+ {
+ pixman_box32_t * box;
+ int num_boxes;
+
+ box = pixman_region32_rectangles(&buffer->base.damage, &num_boxes);
+
+ while (num_boxes--)
+ {
+ wl_surface_damage(socket->wl, box->x1, box->y1,
+ box->x2 - box->x1, box->y2 - box->y1);
+ }
+ }
+
+ wl_surface_commit(socket->wl);
+
+ return true;
+}
+
+void buffer_socket_process(struct buffer_socket * base)
+{
+ struct wayland_buffer_socket * socket = wayland_buffer_socket(base);
+
+ /* Since events for our wl_buffers lie in a special queue used by WLD, we
+ * must dispatch these events here so that we see any release events before
+ * the next back buffer is chosen. */
+ wl_display_dispatch_queue_pending(socket->display, socket->queue);
+}
+
+void buffer_socket_destroy(struct buffer_socket * socket)
+{
+ free(socket);
+}
+
+void sync_done(void * data, struct wl_callback * callback, uint32_t msecs)
+{
+ bool * done = data;
+
+ *done = true;
+ wl_callback_destroy(callback);
+}
+
+void buffer_release(void * data, struct wl_buffer * wl)
+{
+ struct wld_buffer * buffer = data;
+ const struct wl_buffer_listener * listener
+ = wl_proxy_get_listener((struct wl_proxy *) wl);
+ struct wayland_buffer_socket * socket
+ = CONTAINER_OF(listener, struct wayland_buffer_socket, listener);
+
+ wld_surface_release(socket->surface, buffer);
+}
+
diff --git a/src/wld/wayland.h b/src/wld/wayland.h
new file mode 100644
index 0000000..3127ee6
--- /dev/null
+++ b/src/wld/wayland.h
@@ -0,0 +1,84 @@
+/* wld: wayland.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_WAYLAND_H
+#define WLD_WAYLAND_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+struct wl_display;
+struct wl_surface;
+
+#define WLD_WAYLAND_ID (0x3 << 24)
+
+enum wld_wayland_interface_id
+{
+ /**
+ * Give up on trying any new interfaces. This can be considered as a
+ * sentinel for wld_wayland_create_context.
+ */
+ WLD_NONE = -2,
+
+ /**
+ * Try any available interface.
+ */
+ WLD_ANY = -1,
+ WLD_DRM,
+ WLD_SHM
+};
+
+enum wld_wayland_object_type
+{
+ WLD_WAYLAND_OBJECT_BUFFER = WLD_WAYLAND_ID
+};
+
+/**
+ * Create a new WLD context which uses various available Wayland interfaces
+ * (such as wl_shm and wl_drm) to create wl_buffers backed by implementations
+ * specific to the interface.
+ *
+ * You can specify the particular interface you want to use by specifying them
+ * as arguments. Interfaces will be tried in the order they are given.
+ *
+ * The last argument must be either WLD_NONE or WLD_ANY.
+ *
+ * @see enum wld_wayland_interface_id
+ */
+struct wld_context * wld_wayland_create_context
+ (struct wl_display * display, enum wld_wayland_interface_id id, ...);
+
+struct wld_surface * wld_wayland_create_surface(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags,
+ struct wl_surface * surface);
+
+/**
+ * Check if the wayland implementation supports a particular pixel format.
+ *
+ * @see enum wld_format
+ */
+bool wld_wayland_has_format(struct wld_context * context, uint32_t format);
+
+#endif
+
diff --git a/src/wld/wld-private.h b/src/wld/wld-private.h
new file mode 100644
index 0000000..e812b11
--- /dev/null
+++ b/src/wld/wld-private.h
@@ -0,0 +1,243 @@
+/* wld: wld-private.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_PRIVATE_H
+#define WLD_PRIVATE_H
+
+#include "wld.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_BITMAP_H
+
+#define ARRAY_LENGTH(array) (sizeof (array) / sizeof (array)[0])
+#if ENABLE_DEBUG
+# define DEBUG(format, ...) \
+ fprintf(stderr, "# %s: " format, __func__, ## __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+#define EXPORT __attribute__((visibility("default")))
+#define CONTAINER_OF(ptr, type, member) \
+ ((type *)((uintptr_t) ptr - offsetof(type, member)))
+#define IMPL(impl_type, base_type) \
+ static inline struct impl_type * impl_type(struct base_type * object) \
+ { \
+ assert(object->impl == &base_type ## _impl); \
+ return (struct impl_type *) object; \
+ }
+
+struct wld_font_context
+{
+ FT_Library library;
+};
+
+struct glyph
+{
+ FT_Bitmap bitmap;
+
+ /**
+ * The offset from the origin to the top left corner of the bitmap.
+ */
+ int16_t x, y;
+
+ /**
+ * The width to advance to the origin of the next character.
+ */
+ uint16_t advance;
+};
+
+struct font
+{
+ struct wld_font base;
+
+ struct wld_font_context * context;
+ FT_Face face;
+ struct glyph ** glyphs;
+};
+
+struct wld_context_impl
+{
+ struct wld_renderer * (* create_renderer)(struct wld_context * context);
+ struct buffer * (* create_buffer)(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags);
+ struct buffer * (* import_buffer)(struct wld_context * context,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch);
+ struct wld_surface * (* create_surface)(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags);
+ void (* destroy)(struct wld_context * context);
+};
+
+struct wld_renderer_impl
+{
+ uint32_t (* capabilities)(struct wld_renderer * renderer,
+ struct buffer * buffer);
+ bool (* set_target)(struct wld_renderer * renderer, struct buffer * buffer);
+ void (* fill_rectangle)(struct wld_renderer * renderer,
+ uint32_t color, int32_t x, int32_t y,
+ uint32_t width, uint32_t height);
+ void (* fill_region)(struct wld_renderer * renderer,
+ uint32_t color, pixman_region32_t * region);
+ void (* copy_rectangle)(struct wld_renderer * renderer, struct buffer * src,
+ int32_t dst_x, int32_t dst_y,
+ int32_t src_x, int32_t src_y,
+ uint32_t width, uint32_t height);
+ void (* copy_region)(struct wld_renderer * renderer, struct buffer * src,
+ int32_t dst_x, int32_t dst_y,
+ pixman_region32_t * region);
+ void (* draw_text)(struct wld_renderer * renderer,
+ struct font * font, uint32_t color,
+ int32_t x, int32_t y, const char * text, uint32_t length,
+ struct wld_extents * extents);
+ void (* flush)(struct wld_renderer * renderer);
+ void (* destroy)(struct wld_renderer * renderer);
+};
+
+struct buffer
+{
+ struct wld_buffer base;
+
+ unsigned references, map_references;
+ struct wld_exporter * exporters;
+ struct wld_destructor * destructors;
+};
+
+struct wld_buffer_impl
+{
+ bool (* map)(struct buffer * buffer);
+ bool (* unmap)(struct buffer * buffer);
+ void (* destroy)(struct buffer * buffer);
+};
+
+struct wld_surface_impl
+{
+ pixman_region32_t * (* damage)(struct wld_surface * surface,
+ pixman_region32_t * damage);
+ struct buffer * (* back)(struct wld_surface * surface);
+ struct buffer * (* take)(struct wld_surface * surface);
+ bool (* release)(struct wld_surface * surface, struct buffer * buffer);
+ bool (* swap)(struct wld_surface * surface);
+ void (* destroy)(struct wld_surface * surface);
+};
+
+struct buffer_socket
+{
+ const struct buffer_socket_impl * impl;
+};
+
+struct buffer_socket_impl
+{
+ bool (* attach)(struct buffer_socket * socket, struct buffer * buffer);
+ void (* process)(struct buffer_socket * socket);
+ void (* destroy)(struct buffer_socket * socket);
+};
+
+bool font_ensure_glyph(struct font * font, FT_UInt glyph_index);
+
+/**
+ * Returns the number of bytes per pixel for the given format.
+ */
+static inline uint8_t format_bytes_per_pixel(enum wld_format format)
+{
+ switch (format)
+ {
+ case WLD_FORMAT_ARGB8888:
+ case WLD_FORMAT_XRGB8888:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+static inline pixman_format_code_t format_wld_to_pixman(uint32_t format)
+{
+ switch (format)
+ {
+ case WLD_FORMAT_ARGB8888:
+ return PIXMAN_a8r8g8b8;
+ case WLD_FORMAT_XRGB8888:
+ return PIXMAN_x8r8g8b8;
+ default:
+ return 0;
+ }
+}
+
+static inline uint32_t format_pixman_to_wld(pixman_format_code_t format)
+{
+ switch (format)
+ {
+ case PIXMAN_a8r8g8b8:
+ return WLD_FORMAT_ARGB8888;
+ case PIXMAN_x8r8g8b8:
+ return WLD_FORMAT_XRGB8888;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * This default fill_region method is implemented in terms of fill_rectangle.
+ */
+void default_fill_region(struct wld_renderer * renderer, uint32_t color,
+ pixman_region32_t * region);
+
+/**
+ * This default copy_region method is implemented in terms of copy_rectangle.
+ */
+void default_copy_region(struct wld_renderer * renderer, struct buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ pixman_region32_t * region);
+
+struct wld_surface * default_create_surface(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags);
+
+struct wld_surface * buffered_surface_create(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags,
+ struct buffer_socket * socket);
+
+void context_initialize(struct wld_context * context,
+ const struct wld_context_impl * impl);
+
+void renderer_initialize(struct wld_renderer * renderer,
+ const struct wld_renderer_impl * impl);
+
+void buffer_initialize(struct buffer * buffer,
+ const struct wld_buffer_impl * impl,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch);
+
+void surface_initialize(struct wld_surface * surface,
+ const struct wld_surface_impl * impl);
+
+#endif
+
diff --git a/src/wld/wld.h b/src/wld/wld.h
new file mode 100644
index 0000000..c36081c
--- /dev/null
+++ b/src/wld/wld.h
@@ -0,0 +1,283 @@
+/* wld: wld.h
+ *
+ * Copyright (c) 2013, 2014 Michael Forney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WLD_H
+#define WLD_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <pixman.h>
+#include <fontconfig/fontconfig.h>
+
+#define WLD_USER_ID (0xff << 24)
+
+#define __WLD_FOURCC(a, b, c, d) ( (a) \
+ | ((b) << 8) \
+ | ((c) << 16) \
+ | ((d) << 24) )
+
+/**
+ * Supported pixel formats.
+ *
+ * These formats can safely be interchanged with GBM and wl_drm formats.
+ */
+enum wld_format
+{
+ WLD_FORMAT_XRGB8888 = __WLD_FOURCC('X', 'R', '2', '4'),
+ WLD_FORMAT_ARGB8888 = __WLD_FOURCC('A', 'R', '2', '4')
+};
+
+enum wld_flags
+{
+ WLD_FLAG_MAP = 0x1 << 16
+};
+
+bool wld_lookup_named_color(const char * name, uint32_t * color);
+
+/**** WLD Context ****/
+
+enum wld_object_type
+{
+ WLD_OBJECT_DATA
+};
+
+union wld_object
+{
+ void * ptr;
+ uint32_t u32;
+ int i;
+};
+
+struct wld_context
+{
+ const struct wld_context_impl * const impl;
+};
+
+struct wld_renderer * wld_create_renderer(struct wld_context * context);
+
+struct wld_buffer * wld_create_buffer(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags);
+
+struct wld_buffer * wld_import_buffer(struct wld_context * context,
+ uint32_t type, union wld_object object,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t pitch);
+
+struct wld_surface * wld_create_surface(struct wld_context * context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags);
+
+void wld_destroy_context(struct wld_context * context);
+
+/**** Font Handling ****/
+
+struct wld_extents
+{
+ uint32_t advance;
+};
+
+struct wld_font
+{
+ uint32_t ascent, descent;
+ uint32_t height;
+ uint32_t max_advance;
+};
+
+/**
+ * Create a new font context.
+ *
+ * This sets up the underlying FreeType library.
+ */
+struct wld_font_context * wld_font_create_context();
+
+/**
+ * Destroy a font context.
+ */
+void wld_font_destroy_context(struct wld_font_context * context);
+
+/**
+ * Open a new font from the given fontconfig match.
+ */
+struct wld_font * wld_font_open_pattern(struct wld_font_context * context,
+ FcPattern * match);
+
+/**
+ * Open a new font from a fontconfig pattern string.
+ */
+struct wld_font * wld_font_open_name(struct wld_font_context * context,
+ const char * name);
+
+/**
+ * Close a font.
+ */
+void wld_font_close(struct wld_font * font);
+
+/**
+ * Check if the given font has a particular character (in UTF-32), and if so,
+ * load the glyph.
+ */
+bool wld_font_ensure_char(struct wld_font * font, uint32_t character);
+
+/**
+ * Calculate the text extents of the given UTF-8 string.
+ *
+ * @param length The maximum number of bytes in the string to process
+ */
+void wld_font_text_extents_n(struct wld_font * font,
+ const char * text, int32_t length,
+ struct wld_extents * extents);
+
+static inline void wld_font_text_extents(struct wld_font * font,
+ const char * text,
+ struct wld_extents * extents)
+{
+ wld_font_text_extents_n(font, text, INT32_MAX, extents);
+}
+
+/**** Buffers ****/
+
+struct wld_exporter
+{
+ bool (* export)(struct wld_exporter * exporter, struct wld_buffer * buffer,
+ uint32_t type, union wld_object * object);
+ struct wld_exporter * next;
+};
+
+struct wld_destructor
+{
+ void (* destroy)(struct wld_destructor * destructor);
+ struct wld_destructor * next;
+};
+
+struct wld_buffer
+{
+ const struct wld_buffer_impl * const impl;
+
+ uint32_t width, height, pitch;
+ enum wld_format format;
+ pixman_region32_t damage;
+ void * map;
+};
+
+bool wld_map(struct wld_buffer * buffer);
+bool wld_unmap(struct wld_buffer * buffer);
+
+bool wld_export(struct wld_buffer * buffer,
+ uint32_t type, union wld_object * object);
+
+void wld_buffer_add_exporter(struct wld_buffer * buffer,
+ struct wld_exporter * exporter);
+
+void wld_buffer_add_destructor(struct wld_buffer * buffer,
+ struct wld_destructor * destructor);
+
+/**
+ * Increase the reference count of a buffer.
+ */
+void wld_buffer_reference(struct wld_buffer * buffer);
+
+/**
+ * Decrease the reference count of a buffer.
+ *
+ * When the reference count drops to zero, the buffer will be destroyed.
+ */
+void wld_buffer_unreference(struct wld_buffer * buffer);
+
+/**** Surfaces ****/
+
+struct wld_surface
+{
+ const struct wld_surface_impl * const impl;
+};
+
+pixman_region32_t * wld_surface_damage(struct wld_surface * surface,
+ pixman_region32_t * new_damage);
+
+struct wld_buffer * wld_surface_take(struct wld_surface * surface);
+
+void wld_surface_release(struct wld_surface * surface,
+ struct wld_buffer * buffer);
+
+bool wld_swap(struct wld_surface * surface);
+
+void wld_destroy_surface(struct wld_surface * surface);
+
+/**** Renderers ****/
+
+struct wld_renderer
+{
+ const struct wld_renderer_impl * const impl;
+ struct wld_buffer * target;
+};
+
+enum wld_capability
+{
+ WLD_CAPABILITY_READ = 1<<0,
+ WLD_CAPABILITY_WRITE = 1<<1,
+};
+
+void wld_destroy_renderer(struct wld_renderer * renderer);
+
+uint32_t wld_capabilities(struct wld_renderer * renderer,
+ struct wld_buffer * buffer);
+
+bool wld_set_target_buffer(struct wld_renderer * renderer,
+ struct wld_buffer * buffer);
+
+bool wld_set_target_surface(struct wld_renderer * renderer,
+ struct wld_surface * surface);
+
+void wld_fill_rectangle(struct wld_renderer * renderer, uint32_t color,
+ int32_t x, int32_t y, uint32_t width, uint32_t height);
+
+void wld_fill_region(struct wld_renderer * renderer, uint32_t color,
+ pixman_region32_t * region);
+
+void wld_copy_rectangle(struct wld_renderer * renderer,
+ struct wld_buffer * buffer,
+ int32_t dst_x, int32_t dst_y,
+ int32_t src_x, int32_t src_y,
+ uint32_t width, uint32_t height);
+
+void wld_copy_region(struct wld_renderer * renderer,
+ struct wld_buffer * buffer,
+ int32_t dst_x, int32_t dst_y, pixman_region32_t * region);
+
+/**
+ * Draw a UTF-8 text string to the given buffer.
+ *
+ * @param length The maximum number of bytes in the string to process. If
+ * length is -1, then draw until a NULL byte is found.
+ * @param extents If not NULL, will be initialized to the extents of the
+ * drawn text
+ */
+void wld_draw_text(struct wld_renderer * renderer,
+ struct wld_font * font, uint32_t color,
+ int32_t x, int32_t y, const char * text, uint32_t length,
+ struct wld_extents * extents);
+
+void wld_flush(struct wld_renderer * renderer);
+
+#endif
+
diff --git a/src/wld/wld.pc.in b/src/wld/wld.pc.in
new file mode 100644
index 0000000..e9790a1
--- /dev/null
+++ b/src/wld/wld.pc.in
@@ -0,0 +1,13 @@
+prefix=@PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: wld
+Description: A primitive drawing library library targeted at Wayland
+Version: @VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lwld
+
+Requires: @WLD_REQUIRES@
+Requires.private: @WLD_REQUIRES_PRIVATE@
+