OSDN Git Service

Import minigbm
authorStéphane Marchesin <marcheu@chromium.org>
Fri, 12 Sep 2014 23:18:59 +0000 (16:18 -0700)
committerStéphane Marchesin <marcheu@chromium.org>
Sat, 13 Sep 2014 01:34:56 +0000 (01:34 +0000)
Minigbm is a gbm implementation for a few DRM targets. Currently the
targets are:
- cirrus
- exynos
- gma500
- i915
- rockchip
- tegra
- udl

Right some targets are controlled with GBM_{TARGET} flags. I would
like to get to a place where we can just build all the targets in a
single library, but we need the drm headers for all targets for that
to happen so this needs more thinking.

BUG=chromium:394868,chromium:402597,chromium:413947,chromium:412508
TEST=unit tests, which I will need to import later

Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
Change-Id: I36ae07f2a59827a807e19e1432891ca196b28803
Reviewed-on: https://chromium-review.googlesource.com/218030

16 files changed:
Makefile [new file with mode: 0644]
cirrus.c [new file with mode: 0644]
common.mk [new file with mode: 0644]
exynos.c [new file with mode: 0644]
gbm.c [new file with mode: 0644]
gbm.h [new file with mode: 0644]
gbm_priv.h [new file with mode: 0644]
gma500.c [new file with mode: 0644]
helpers.c [new file with mode: 0644]
helpers.h [new file with mode: 0644]
i915.c [new file with mode: 0644]
rockchip.c [new file with mode: 0644]
tegra.c [new file with mode: 0644]
test.c [new file with mode: 0644]
udl.c [new file with mode: 0644]
util.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a6985e6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+# Copyright 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
+
+PC_DEPS = libdrm
+PC_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(PC_DEPS))
+PC_LIBS := $(shell $(PKG_CONFIG) --libs $(PC_DEPS))
+
+CPPFLAGS += -std=c99 -D_GNU_SOURCE=1
+CFLAGS += -Wall -Wsign-compare -Wpointer-arith -Wcast-qual -Wcast-align
+
+CPPFLAGS += $(PC_CFLAGS)
+LDLIBS += $(PC_LIBS)
+
+CC_LIBRARY(libgbm.so): $(C_OBJECTS)
+
+all: CC_LIBRARY(libgbm.so)
+
+clean: CLEAN(libgbm.so)
+
+install: all
+       mkdir -p $(DESTDIR)/usr/lib
+       install -m 755 $(OUT)/libgbm.so $(DESTDIR)/usr/lib/
diff --git a/cirrus.c b/cirrus.c
new file mode 100644 (file)
index 0000000..ae86c67
--- /dev/null
+++ b/cirrus.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gbm_priv.h"
+#include "helpers.h"
+
+struct gbm_driver gbm_driver_cirrus =
+{
+       .name = "cirrus",
+       .bo_create = gbm_dumb_bo_create,
+       .bo_destroy = gbm_dumb_bo_destroy,
+       .format_list = {
+               {GBM_FORMAT_RGB888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+       }
+};
diff --git a/common.mk b/common.mk
new file mode 100644 (file)
index 0000000..21de50c
--- /dev/null
+++ b/common.mk
@@ -0,0 +1,931 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# If this file is part of another source distribution, it's license may be
+# stored in LICENSE.makefile or LICENSE.common.mk.
+#
+# NOTE NOTE NOTE
+#  The authoritative common.mk is located in:
+#    https://chromium.googlesource.com/chromiumos/platform2/+/master/common-mk
+#  Please make all changes there, then copy into place in other repos.
+# NOTE NOTE NOTE
+#
+# This file provides a common architecture for building C/C++ source trees.
+# It uses recursive makefile inclusion to create a single make process which
+# can be built in the source tree or with the build artifacts placed elsewhere.
+#
+# It is fully parallelizable for all targets, including static archives.
+#
+# To use:
+# 1. Place common.mk in your top source level
+# 2. In your top-level Makefile, place "include common.mk" at the top
+# 3. In all subdirectories, create a 'module.mk' file that starts with:
+#      include common.mk
+#    And then contains the remainder of your targets.
+# 4. All build targets should look like:
+#    relative/path/target: relative/path/obj.o
+#
+# See existing makefiles for rule examples.
+#
+# Exported macros:
+#   - cc_binary, cxx_binary provide standard compilation steps for binaries
+#   - cxx_library, cc_library provide standard compilation steps for
+#     shared objects.
+#   All of the above optionally take an argument for extra flags.
+#   - update_archive creates/updates a given .a target
+#
+# Instead of using the build macros, most users can just use wrapped targets:
+#   - CXX_BINARY, CC_BINARY, CC_STATIC_BINARY, CXX_STATIC_BINARY
+#   - CXX_LIBRARY, CC_LIBRARY, CC_STATIC_LIBRARY, CXX_STATIC_LIBRARY
+#   - E.g., CXX_BINARY(mahbinary): foo.o
+#   - object.depends targets may be used when a prerequisite is required for an
+#     object file. Because object files result in multiple build artifacts to
+#     handle PIC and PIE weirdness. E.g.
+#       foo.o.depends: generated/dbus.h
+#   - TEST(binary) or TEST(CXX_BINARY(binary)) may be used as a prerequisite
+#     for the tests target to trigger an automated test run.
+#   - CLEAN(file_or_dir) dependency can be added to 'clean'.
+#
+# If source code is being generated, rules will need to be registered for
+# compiling the objects.  This can be done by adding one of the following
+# to the Makefile:
+#   - For C source files
+#   $(eval $(call add_object_rules,sub/dir/gen_a.o sub/dir/b.o,CC,c,CFLAGS))
+#   - For C++ source files
+#   $(eval $(call add_object_rules,sub/dir/gen_a.o sub/dir/b.o,CXX,cc,CXXFLAGS))
+#
+# Exported targets meant to have prerequisites added to:
+#  - all - Your desired targets should be given
+#  - tests - Any TEST(test_binary) targets should be given
+#  - FORCE - force the given target to run regardless of changes
+#            In most cases, using .PHONY is preferred.
+#
+# Possible command line variables:
+#   - COLOR=[0|1] to set ANSI color output (default: 1)
+#   - VERBOSE=[0|1] to hide/show commands (default: 0)
+#   - MODE=[opt|dbg|profiling] (default: opt)
+#          opt - Enable optimizations for release builds
+#          dbg - Turn down optimization for debugging
+#          profiling - Turn off optimization and turn on profiling/coverage
+#                      support.
+#   - ARCH=[x86|arm|supported qemu name] (default: from portage or uname -m)
+#   - SPLITDEBUG=[0|1] splits debug info in target.debug (default: 0)
+#        If NOSTRIP=1, SPLITDEBUG will never strip the final emitted objects.
+#   - NOSTRIP=[0|1] determines if binaries are stripped. (default: 1)
+#        NOSTRIP=0 and MODE=opt will also drop -g from the CFLAGS.
+#   - VALGRIND=[0|1] runs tests under valgrind (default: 0)
+#   - OUT=/path/to/builddir puts all output in given path (default: $PWD)
+#   - VALGRIND_ARGS="" supplies extra memcheck arguments
+#
+# Per-target(-ish) variable:
+#   - NEEDS_ROOT=[0|1] allows a TEST() target to run with root.
+#     Default is 0 unless it is running under QEmu.
+#   - NEEDS_MOUNTS=[0|1] allows a TEST() target running on QEmu to get
+#     setup mounts in the $(SYSROOT)
+#
+# Caveats:
+# - Directories or files with spaces in them DO NOT get along with GNU Make.
+#   If you need them, all uses of dir/notdir/etc will need to have magic
+#   wrappers.  Proceed at risk to your own sanity.
+# - External CXXFLAGS and CFLAGS should be passed via the environment since
+#   this file does not use 'override' to control them.
+# - Our version of GNU Make doesn't seem to support the 'private' variable
+#   annotation, so you can't tag a variable private on a wrapping target.
+
+# Behavior configuration variables
+SPLITDEBUG ?= 0
+NOSTRIP ?= 1
+VALGRIND ?= 0
+COLOR ?= 1
+VERBOSE ?= 0
+MODE ?= opt
+CXXEXCEPTIONS ?= 0
+ARCH ?= $(shell uname -m)
+
+# Put objects in a separate tree based on makefile locations
+# This means you can build a tree without touching it:
+#   make -C $SRCDIR  # will create ./build-$(MODE)
+# Or
+#   make -C $SRCDIR OUT=$PWD
+# This variable is extended on subdir calls and doesn't need to be re-called.
+OUT ?= $(PWD)/
+
+# Make OUT now so we can use realpath.
+$(shell mkdir -p "$(OUT)")
+
+# TODO(wad) Relative paths are resolved against SRC and not the calling dir.
+# Ensure a command-line supplied OUT has a slash
+override OUT := $(realpath $(OUT))/
+
+# SRC is not meant to be set by the end user, but during make call relocation.
+# $(PWD) != $(CURDIR) all the time.
+export SRC ?= $(CURDIR)
+
+# Re-start in the $(OUT) directory if we're not there.
+# We may be invoked using -C or bare and we need to ensure behavior
+# is consistent so we check both PWD vs OUT and PWD vs CURDIR.
+override RELOCATE_BUILD := 0
+ifneq (${PWD}/,${OUT})
+override RELOCATE_BUILD := 1
+endif
+# Make sure we're running with no builtin targets. They cause
+# leakage and mayhem!
+ifneq (${PWD},${CURDIR})
+override RELOCATE_BUILD := 1
+# If we're run from the build dir, don't let it get cleaned up later.
+ifeq (${PWD}/,${OUT})
+$(shell touch "$(PWD)/.dont_delete_on_clean")
+endif
+endif  # ifneq (${PWD},${CURDIR}
+
+# "Relocate" if we need to restart without implicit rules.
+ifeq ($(subst r,,$(MAKEFLAGS)),$(MAKEFLAGS))
+override RELOCATE_BUILD := 1
+endif
+
+ifeq (${RELOCATE_BUILD},1)
+# By default, silence build output. Reused below as well.
+QUIET = @
+ifeq ($(VERBOSE),1)
+  QUIET=
+endif
+
+# This target will override all targets, including prerequisites. To avoid
+# calling $(MAKE) once per prereq on the given CMDGOAL, we guard it with a local
+# variable.
+RUN_ONCE := 0
+MAKECMDGOALS ?= all
+# Keep the rules split as newer make does not allow them to be declared
+# on the same line.  But the way :: rules work, the _all here will also
+# invoke the %:: rule while retaining "_all" as the default.
+_all::
+%::
+       $(if $(filter 0,$(RUN_ONCE)), \
+         cd "$(OUT)" && \
+         $(MAKE) -r -I "$(SRC)" -f "$(CURDIR)/Makefile" \
+           SRC="$(CURDIR)" OUT="$(OUT)" $(foreach g,$(MAKECMDGOALS),"$(g)"),)
+       $(eval RUN_ONCE := 1)
+pass-to-subcall := 1
+endif
+
+ifeq ($(pass-to-subcall),)
+
+# Only call MODULE if we're in a submodule
+MODULES_LIST := $(filter-out Makefile %.d,$(MAKEFILE_LIST))
+ifeq ($(words $(filter-out Makefile common.mk %.d $(SRC)/Makefile \
+                           $(SRC)/common.mk,$(MAKEFILE_LIST))),0)
+
+# All the top-level defines outside of module.mk.
+
+#
+# Helper macros
+#
+
+# Create the directory if it doesn't yet exist.
+define auto_mkdir
+  $(if $(wildcard $(dir $1)),$2,$(QUIET)mkdir -p "$(dir $1)")
+endef
+
+# Creates the actual archive with an index.
+# The target $@ must end with .pic.a or .pie.a.
+define update_archive
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
+  $(QUIET)# Create the archive in one step to avoid parallel use accessing it
+  $(QUIET)# before all the symbols are present.
+  @$(ECHO) "AR         $(subst \
+$(SRC)/,,$(^:.o=$(suffix $(basename $(TARGET_OR_MEMBER))).o)) \
+-> $(subst $(SRC)/,,$(TARGET_OR_MEMBER))"
+  $(QUIET)$(AR) rcs $(TARGET_OR_MEMBER) \
+          $(subst $(SRC)/,,$(^:.o=$(suffix $(basename $(TARGET_OR_MEMBER))).o))
+endef
+
+# Default compile from objects using pre-requisites but filters out
+# subdirs and .d files.
+define cc_binary
+  $(call COMPILE_BINARY_implementation,CC,$(CFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+
+define cxx_binary
+  $(call COMPILE_BINARY_implementation,CXX,$(CXXFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+
+# Default compile from objects using pre-requisites but filters out
+# subdirs and .d files.
+define cc_library
+  $(call COMPILE_LIBRARY_implementation,CC,$(CFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+define cxx_library
+  $(call COMPILE_LIBRARY_implementation,CXX,$(CXXFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+
+# Deletes files silently if they exist. Meant for use in any local
+# clean targets.
+define silent_rm
+  $(if $(wildcard $(1)),
+  $(QUIET)($(ECHO) -n '$(COLOR_RED)CLEANFILE$(COLOR_RESET)             ' && \
+    $(ECHO) '$(subst $(OUT)/,,$(wildcard $(1)))' && \
+    $(RM) $(1) 2>/dev/null) || true,)
+endef
+define silent_rmdir
+  $(if $(wildcard $(1)),
+    $(if $(wildcard $(1)/*),
+  $(QUIET)# $(1) not empty [$(wildcard $(1)/*)]. Not deleting.,
+  $(QUIET)($(ECHO) -n '$(COLOR_RED)CLEANDIR$(COLOR_RESET)              ' && \
+    $(ECHO) '$(subst $(OUT)/,,$(wildcard $(1)))' && \
+    $(RMDIR) $(1) 2>/dev/null) || true),)
+endef
+
+#
+# Default variable values
+#
+
+# Only override toolchain vars if they are from make.
+CROSS_COMPILE ?=
+define override_var
+ifneq ($(filter undefined default,$(origin $1)),)
+$1 = $(CROSS_COMPILE)$2
+endif
+endef
+$(eval $(call override_var,AR,ar))
+$(eval $(call override_var,CC,gcc))
+$(eval $(call override_var,CXX,g++))
+$(eval $(call override_var,OBJCOPY,objcopy))
+$(eval $(call override_var,PKG_CONFIG,pkg-config))
+$(eval $(call override_var,RANLIB,ranlib))
+$(eval $(call override_var,STRIP,strip))
+
+RMDIR ?= rmdir
+ECHO = /bin/echo -e
+
+ifeq ($(lastword $(subst /, ,$(CC))),clang)
+CDRIVER = clang
+else
+CDRIVER = gcc
+endif
+
+ifeq ($(lastword $(subst /, ,$(CXX))),clang++)
+CXXDRIVER = clang
+else
+CXXDRIVER = gcc
+endif
+
+# Internal macro to support check_XXX macros below.
+# Usage: $(call check_compile, [code], [compiler], [code_type], [c_flags],
+#               [extra_c_flags], [library_flags], [success_ret], [fail_ret])
+# Return: [success_ret] if compile succeeded, otherwise [fail_ret]
+check_compile = $(shell printf '%b\n' $(1) | \
+  $($(2)) $($(4)) -x $(3) $(LDFLAGS) $(5) - $(6) -o /dev/null > /dev/null 2>&1 \
+  && echo "$(7)" || echo "$(8)")
+
+# Helper macro to check whether a test program will compile with the specified
+# compiler flags.
+# Usage: $(call check_compile_cc, [code], [flags], [alternate_flags])
+# Return: [flags] if compile succeeded, otherwise [alternate_flags]
+check_compile_cc = $(call check_compile,$(1),CC,c,CFLAGS,$(2),,$(2),$(3))
+check_compile_cxx = $(call check_compile,$(1),CXX,c++,CXXFLAGS,$(2),,$(2),$(3))
+
+# Helper macro to check whether a test program will compile with the specified
+# libraries.
+# Usage: $(call check_compile_cc, [code], [library_flags], [alternate_flags])
+# Return: [library_flags] if compile succeeded, otherwise [alternate_flags]
+check_libs_cc = $(call check_compile,$(1),CC,c,CFLAGS,,$(2),$(2),$(3))
+check_libs_cxx = $(call check_compile,$(1),CXX,c++,CXXFLAGS,,$(2),$(2),$(3))
+
+# Helper macro to check whether the compiler accepts the specified flags.
+# Usage: $(call check_compile_cc, [flags], [alternate_flags])
+# Return: [flags] if compile succeeded, otherwise [alternate_flags]
+check_cc = $(call check_compile_cc,'int main() { return 0; }',$(1),$(2))
+check_cxx = $(call check_compile_cxx,'int main() { return 0; }',$(1),$(2))
+
+# Choose the stack protector flags based on whats supported by the compiler.
+SSP_CFLAGS := $(call check_cc,-fstack-protector-strong)
+ifeq ($(SSP_CFLAGS),)
+ SSP_CFLAGS := $(call check_cc,-fstack-protector-all)
+endif
+
+# To update these from an including Makefile:
+#  CXXFLAGS += -mahflag  # Append to the list
+#  CXXFLAGS := -mahflag $(CXXFLAGS) # Prepend to the list
+#  CXXFLAGS := $(filter-out badflag,$(CXXFLAGS)) # Filter out a value
+# The same goes for CFLAGS.
+COMMON_CFLAGS-gcc := -fvisibility=internal -ggdb3 -Wa,--noexecstack
+COMMON_CFLAGS-clang := -fvisibility=hidden -ggdb
+COMMON_CFLAGS := -Wall -Werror -fno-strict-aliasing $(SSP_CFLAGS) -O1 -Wformat=2
+CXXFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CXXDRIVER))
+CFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CDRIVER))
+CPPFLAGS += -D_FORTIFY_SOURCE=2
+
+# Disable exceptions based on the CXXEXCEPTIONS setting.
+ifeq ($(CXXEXCEPTIONS),0)
+  CXXFLAGS := $(CXXFLAGS) -fno-exceptions -fno-unwind-tables \
+    -fno-asynchronous-unwind-tables
+endif
+
+ifeq ($(MODE),opt)
+  # Up the optimizations.
+  CFLAGS := $(filter-out -O1,$(CFLAGS)) -O2
+  CXXFLAGS := $(filter-out -O1,$(CXXFLAGS)) -O2
+  # Only drop -g* if symbols aren't desired.
+  ifeq ($(NOSTRIP),0)
+    # TODO: do we want -fomit-frame-pointer on x86?
+    CFLAGS := $(filter-out -ggdb3,$(CFLAGS))
+    CXXFLAGS := $(filter-out -ggdb3,$(CXXFLAGS))
+  endif
+endif
+
+ifeq ($(MODE),profiling)
+  CFLAGS := $(CFLAGS) -O0 -g  --coverage
+  CXXFLAGS := $(CXXFLAGS) -O0 -g  --coverage
+  LDFLAGS := $(LDFLAGS) --coverage
+endif
+
+LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now
+
+# Fancy helpers for color if a prompt is defined
+ifeq ($(COLOR),1)
+COLOR_RESET = \x1b[0m
+COLOR_GREEN = \x1b[32;01m
+COLOR_RED = \x1b[31;01m
+COLOR_YELLOW = \x1b[33;01m
+endif
+
+# By default, silence build output.
+QUIET = @
+ifeq ($(VERBOSE),1)
+  QUIET=
+endif
+
+#
+# Implementation macros for compile helpers above
+#
+
+# Useful for dealing with pie-broken toolchains.
+# Call make with PIE=0 to disable default PIE use.
+OBJ_PIE_FLAG = -fPIE
+COMPILE_PIE_FLAG = -pie
+ifeq ($(PIE),0)
+  OBJ_PIE_FLAG =
+  COMPILE_PIE_FLAG =
+endif
+
+# Favor member targets first for CXX_BINARY(%) magic.
+# And strip out nested members if possible.
+LP := (
+RP := )
+TARGET_OR_MEMBER = $(lastword $(subst $(LP), ,$(subst $(RP),,$(or $%,$@))))
+
+# Default compile from objects using pre-requisites but filters out
+# all non-.o files.
+define COMPILE_BINARY_implementation
+  @$(ECHO) "LD$(1)             $(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
+  $(QUIET)$($(1)) $(COMPILE_PIE_FLAGS) -o $(TARGET_OR_MEMBER) \
+    $(2) $(LDFLAGS) \
+    $(filter %.o %.a,$(^:.o=.pie.o)) \
+    $(foreach so,$(filter %.so,$^),-L$(dir $(so)) \
+                            -l$(patsubst lib%,%,$(basename $(notdir $(so))))) \
+    $(LDLIBS)
+  $(call conditional_strip)
+  @$(ECHO) -n "BIN             "
+  @$(ECHO) "$(COLOR_GREEN)$(subst $(PWD)/,,$(TARGET_OR_MEMBER))$(COLOR_RESET)"
+  @$(ECHO) "   $(COLOR_YELLOW)-----$(COLOR_RESET)"
+endef
+
+# TODO: add version support extracted from PV environment variable
+#ifeq ($(PV),9999)
+#$(warning PV=$(PV). If shared object versions matter, please force PV=.)
+#endif
+# Then add -Wl,-soname,$@.$(PV) ?
+
+# Default compile from objects using pre-requisites but filters out
+# all non-.o values. (Remember to add -L$(OUT) -llib)
+COMMA := ,
+define COMPILE_LIBRARY_implementation
+  @$(ECHO) "SHARED$(1) $(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
+  $(QUIET)$($(1)) -shared -Wl,-E -o $(TARGET_OR_MEMBER) \
+    $(2) $(LDFLAGS) \
+    $(if $(filter %.a,$^),-Wl$(COMMA)--whole-archive,) \
+    $(filter %.o ,$(^:.o=.pic.o)) \
+    $(foreach a,$(filter %.a,$^),-L$(dir $(a)) \
+                            -l$(patsubst lib%,%,$(basename $(notdir $(a))))) \
+    $(foreach so,$(filter %.so,$^),-L$(dir $(so)) \
+                            -l$(patsubst lib%,%,$(basename $(notdir $(so))))) \
+    $(LDLIBS)
+  $(call conditional_strip)
+  @$(ECHO) -n "LIB             $(COLOR_GREEN)"
+  @$(ECHO) "$(subst $(PWD)/,,$(TARGET_OR_MEMBER))$(COLOR_RESET)"
+  @$(ECHO) "   $(COLOR_YELLOW)-----$(COLOR_RESET)"
+endef
+
+define conditional_strip
+  $(if $(filter 0,$(NOSTRIP)),$(call strip_artifact))
+endef
+
+define strip_artifact
+  @$(ECHO) "STRIP              $(subst $(OUT)/,,$(TARGET_OR_MEMBER))"
+  $(if $(filter 1,$(SPLITDEBUG)), @$(ECHO) -n "DEBUG   "; \
+    $(ECHO) "$(COLOR_YELLOW)\
+$(subst $(OUT)/,,$(TARGET_OR_MEMBER)).debug$(COLOR_RESET)")
+  $(if $(filter 1,$(SPLITDEBUG)), \
+    $(QUIET)$(OBJCOPY) --only-keep-debug "$(TARGET_OR_MEMBER)" \
+      "$(TARGET_OR_MEMBER).debug")
+  $(if $(filter-out dbg,$(MODE)),$(QUIET)$(STRIP) --strip-unneeded \
+    "$(TARGET_OR_MEMBER)",)
+endef
+
+#
+# Global pattern rules
+#
+
+# Below, the archive member syntax is abused to create fancier
+# syntactic sugar for recipe authors that avoids needed to know
+# subcall options.  The downside is that make attempts to look
+# into the phony archives for timestamps. This will cause the final
+# target to be rebuilt/linked on _every_ call to make even when nothing
+# has changed.  Until a better way presents itself, we have helpers that
+# do the stat check on make's behalf.  Dodgy but simple.
+define old_or_no_timestamp
+  $(if $(realpath $%),,$(1))
+  $(if $(shell find $^ -cnewer "$%" 2>/dev/null),$(1))
+endef
+
+define check_deps
+  $(if $(filter 0,$(words $^)),\
+    $(error Missing dependencies or declaration of $@($%)),)
+endef
+
+# Build a cxx target magically
+CXX_BINARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call cxx_binary))
+clean: CLEAN(CXX_BINARY*)
+
+CC_BINARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call cc_binary))
+clean: CLEAN(CC_BINARY*)
+
+CXX_STATIC_BINARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call cxx_binary,-static))
+clean: CLEAN(CXX_STATIC_BINARY*)
+
+CC_STATIC_BINARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call cc_binary,-static))
+clean: CLEAN(CC_STATIC_BINARY*)
+
+CXX_LIBRARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call cxx_library))
+clean: CLEAN(CXX_LIBRARY*)
+
+CXX_LIBARY(%):
+       $(error Typo alert! LIBARY != LIBRARY)
+
+CC_LIBRARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call cc_library))
+clean: CLEAN(CC_LIBRARY*)
+
+CC_LIBARY(%):
+       $(error Typo alert! LIBARY != LIBRARY)
+
+CXX_STATIC_LIBRARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call update_archive))
+clean: CLEAN(CXX_STATIC_LIBRARY*)
+
+CXX_STATIC_LIBARY(%):
+       $(error Typo alert! LIBARY != LIBRARY)
+
+CC_STATIC_LIBRARY(%):
+       $(call check_deps)
+       $(call old_or_no_timestamp,$(call update_archive))
+clean: CLEAN(CC_STATIC_LIBRARY*)
+
+CC_STATIC_LIBARY(%):
+       $(error Typo alert! LIBARY != LIBRARY)
+
+
+TEST(%): % qemu_chroot_install
+       $(call TEST_implementation)
+.PHONY: TEST
+
+# multiple targets with a wildcard need to share an directory.
+# Don't use this directly it just makes sure the directory is removed _after_
+# the files are.
+CLEANFILE(%):
+       $(call silent_rm,$(TARGET_OR_MEMBER))
+.PHONY: CLEANFILE
+
+CLEAN(%): CLEANFILE(%)
+       $(QUIET)# CLEAN($%) meta-target called
+       $(if $(filter-out $(PWD)/,$(dir $(abspath $(TARGET_OR_MEMBER)))), \
+         $(call silent_rmdir,$(dir $(abspath $(TARGET_OR_MEMBER)))),\
+         $(QUIET)# Not deleting $(dir $(abspath $(TARGET_OR_MEMBER))) yet.)
+.PHONY: CLEAN
+
+#
+# Top-level objects and pattern rules
+#
+
+# All objects for .c files at the top level
+C_OBJECTS = $(patsubst $(SRC)/%.c,%.o,$(wildcard $(SRC)/*.c))
+
+
+# All objects for .cxx files at the top level
+CXX_OBJECTS = $(patsubst $(SRC)/%.cc,%.o,$(wildcard $(SRC)/*.cc))
+
+# Note, the catch-all pattern rules don't work in subdirectories because
+# we're building from the $(OUT) directory. At the top-level (here) they will
+# work, but we go ahead and match using the module form.  Then we can place a
+# generic pattern rule to capture leakage from the main Makefile. (Later in the
+# file.)
+#
+# The reason target specific pattern rules work well for modules,
+# MODULE_C_OBJECTS, is because it scopes the behavior to the given target which
+# ensures we get a relative directory offset from $(OUT) which otherwise would
+# not match without further magic on a per-subdirectory basis.
+
+# Creates object file rules. Call with eval.
+# $(1) list of .o files
+# $(2) source type (CC or CXX)
+# $(3) source suffix (cc or c)
+# $(4) compiler flag name (CFLAGS or CXXFLAGS)
+# $(5) source dir: _only_ if $(SRC). Leave blank for obj tree.
+define add_object_rules
+$(patsubst %.o,%.pie.o,$(1)): %.pie.o: $(5)%.$(3) %.o.depends
+       $$(call auto_mkdir,$$@)
+       $$(call OBJECT_PATTERN_implementation,$(2),\
+          $$(basename $$@),$$($(4)) $$(CPPFLAGS) $$(OBJ_PIE_FLAG))
+
+$(patsubst %.o,%.pic.o,$(1)): %.pic.o: $(5)%.$(3) %.o.depends
+       $$(call auto_mkdir,$$@)
+       $$(call OBJECT_PATTERN_implementation,$(2),\
+          $$(basename $$@),$$($(4)) $$(CPPFLAGS) -fPIC)
+
+# Placeholder for depends
+$(patsubst %.o,%.o.depends,$(1)):
+       $$(call auto_mkdir,$$@)
+       $$(QUIET)touch "$$@"
+
+$(1): %.o: %.pic.o %.pie.o
+       $$(call auto_mkdir,$$@)
+       $$(QUIET)touch "$$@"
+endef
+
+define OBJECT_PATTERN_implementation
+  @$(ECHO) "$(1)               $(subst $(SRC)/,,$<) -> $(2).o"
+  $(call auto_mkdir,$@)
+  $(QUIET)$($(1)) -c -MD -MF $(2).d $(3) -o $(2).o $<
+  $(QUIET)# Wrap all the deps in $$(wildcard) so a missing header
+  $(QUIET)# won't cause weirdness.  First we remove newlines and \,
+  $(QUIET)# then wrap it.
+  $(QUIET)sed -i -e :j -e '$$!N;s|\\\s*\n| |;tj' \
+    -e 's|^\(.*\s*:\s*\)\(.*\)$$|\1 $$\(wildcard \2\)|' $(2).d
+endef
+
+# Now actually register handlers for C(XX)_OBJECTS.
+$(eval $(call add_object_rules,$(C_OBJECTS),CC,c,CFLAGS,$(SRC)/))
+$(eval $(call add_object_rules,$(CXX_OBJECTS),CXX,cc,CXXFLAGS,$(SRC)/))
+
+# Disable default pattern rules to help avoid leakage.
+# These may already be handled by '-r', but let's keep it to be safe.
+%: %.o ;
+%.a: %.o ;
+%.o: %.c ;
+%.o: %.cc ;
+
+# NOTE: A specific rule for archive objects is avoided because parallel
+#       update of the archive causes build flakiness.
+# Instead, just make the objects the prerequisites and use update_archive
+# To use the foo.a(obj.o) functionality, targets would need to specify the
+# explicit object they expect on the prerequisite line.
+
+#
+# Architecture detection and QEMU wrapping
+#
+
+HOST_ARCH ?= $(shell uname -m)
+override ARCH := $(strip $(ARCH))
+override HOST_ARCH := $(strip $(HOST_ARCH))
+# emake will supply "x86" or "arm" for ARCH, but
+# if uname -m runs and you get x86_64, then this subst
+# will break.
+ifeq ($(subst x86,i386,$(ARCH)),i386)
+  QEMU_ARCH := $(subst x86,i386,$(ARCH))  # x86 -> i386
+else ifeq ($(subst amd64,x86_64,$(ARCH)),x86_64)
+  QEMU_ARCH := $(subst amd64,x86_64,$(ARCH))  # amd64 -> x86_64
+else
+  QEMU_ARCH = $(ARCH)
+endif
+override QEMU_ARCH := $(strip $(QEMU_ARCH))
+
+# If we're cross-compiling, try to use qemu for running the tests.
+ifneq ($(QEMU_ARCH),$(HOST_ARCH))
+  ifeq ($(SYSROOT),)
+    $(info SYSROOT not defined. qemu-based testing disabled)
+  else
+    # A SYSROOT is assumed for QEmu use.
+    USE_QEMU ?= 1
+
+    # Allow 64-bit hosts to run 32-bit without qemu.
+    ifeq ($(HOST_ARCH),x86_64)
+      ifeq ($(QEMU_ARCH),i386)
+        USE_QEMU = 0
+      endif
+    endif
+  endif
+else
+  USE_QEMU ?= 0
+endif
+
+# Normally we don't need to run as root or do bind mounts, so only
+# enable it by default when we're using QEMU.
+NEEDS_ROOT ?= $(USE_QEMU)
+NEEDS_MOUNTS ?= $(USE_QEMU)
+
+SYSROOT_OUT = $(OUT)
+ifneq ($(SYSROOT),)
+  SYSROOT_OUT = $(subst $(SYSROOT),,$(OUT))
+else
+  # Default to / when all the empty-sysroot logic is done.
+  SYSROOT = /
+endif
+
+QEMU_NAME = qemu-$(QEMU_ARCH)
+QEMU_PATH = /build/bin/$(QEMU_NAME)
+QEMU_SYSROOT_PATH = $(SYSROOT)$(QEMU_PATH)
+QEMU_SRC_PATH = /usr/bin/$(QEMU_NAME)
+QEMU_BINFMT_PATH = /proc/sys/fs/binfmt_misc/$(QEMU_NAME)
+QEMU_REGISTER_PATH = /proc/sys/fs/binfmt_misc/register
+
+QEMU_MAGIC_arm = ":$(QEMU_NAME):M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/build/bin/qemu-arm:"
+
+
+#
+# Output full configuration at top level
+#
+
+# Don't show on clean
+ifneq ($(MAKECMDGOALS),clean)
+  $(info build configuration:)
+  $(info - OUT=$(OUT))
+  $(info - SRC=$(SRC))
+  $(info - MODE=$(MODE))
+  $(info - SPLITDEBUG=$(SPLITDEBUG))
+  $(info - NOSTRIP=$(NOSTRIP))
+  $(info - VALGRIND=$(VALGRIND))
+  $(info - COLOR=$(COLOR))
+  $(info - CXXEXCEPTIONS=$(CXXEXCEPTIONS))
+  $(info - ARCH=$(ARCH))
+  $(info - QEMU_ARCH=$(QEMU_ARCH))
+  $(info - USE_QEMU=$(USE_QEMU))
+  $(info - NEEDS_ROOT=$(NEEDS_ROOT))
+  $(info - NEEDS_MOUNTS=$(NEEDS_MOUNTS))
+  $(info - SYSROOT=$(SYSROOT))
+  $(info )
+endif
+
+#
+# Standard targets with detection for when they are improperly configured.
+#
+
+# all does not include tests by default
+all:
+       $(QUIET)(test -z "$^" && \
+       $(ECHO) "You must add your targets as 'all' prerequisites") || true
+       $(QUIET)test -n "$^"
+
+# Builds and runs tests for the target arch
+# Run them in parallel
+# After the test have completed, if profiling, run coverage analysis
+tests:
+ifeq ($(MODE),profiling)
+       @$(ECHO) "COVERAGE [$(COLOR_YELLOW)STARTED$(COLOR_RESET)]"
+       $(QUIET)FILES="";                                               \
+               for GCNO in `find . -name "*.gcno"`; do                 \
+                       GCDA="$${GCNO%.gcno}.gcda";                     \
+                       if [ -e $${GCDA} ]; then                        \
+                               FILES="$${FILES} $${GCDA}";             \
+                       fi                                              \
+               done;                                                   \
+               if [ -n "$${FILES}" ]; then                             \
+                       gcov -l $${FILES};                              \
+                       lcov --capture --directory .                    \
+                               --output-file=lcov-coverage.info;       \
+                       genhtml lcov-coverage.info                      \
+                               --output-directory lcov-html;           \
+               fi
+       @$(ECHO) "COVERAGE [$(COLOR_YELLOW)FINISHED$(COLOR_RESET)]"
+endif
+.PHONY: tests
+
+qemu_chroot_install:
+ifeq ($(USE_QEMU),1)
+       $(QUIET)$(ECHO) "QEMU   Preparing $(QEMU_NAME)"
+       @# Copying strategy
+       @# Compare /usr/bin/qemu inode to /build/$board/build/bin/qemu, if different
+       @# hard link to a temporary file, then rename temp to target. This should
+       @# ensure that once $QEMU_SYSROOT_PATH exists it will always exist, regardless
+       @# of simultaneous test setups.
+       $(QUIET)if [[ ! -e $(QEMU_SYSROOT_PATH) || \
+           `stat -c %i $(QEMU_SRC_PATH)` != `stat -c %i $(QEMU_SYSROOT_PATH)` \
+           ]]; then \
+         $(ROOT_CMD) ln -Tf $(QEMU_SRC_PATH) $(QEMU_SYSROOT_PATH).$$$$; \
+         $(ROOT_CMD) mv -Tf $(QEMU_SYSROOT_PATH).$$$$ $(QEMU_SYSROOT_PATH); \
+       fi
+
+       @# Prep the binfmt handler. First mount if needed, then unregister any bad
+       @# mappings and then register our mapping.
+       @# There may still be some race conditions here where one script de-registers
+       @# and another script starts executing before it gets re-registered, however
+       @# it should be rare.
+       -$(QUIET)[[ -e $(QEMU_REGISTER_PATH) ]] || \
+         $(ROOT_CMD) mount binfmt_misc -t binfmt_misc \
+           /proc/sys/fs/binfmt_misc
+
+       -$(QUIET)if [[ -e $(QEMU_BINFMT_PATH) && \
+             `awk '$$1 == "interpreter" {print $$NF}' $(QEMU_BINFMT_PATH)` != \
+             "$(QEMU_PATH)" ]]; then \
+         echo -1 | $(ROOT_CMD) tee $(QEMU_BINFMT_PATH) >/dev/null; \
+       fi
+
+       -$(if $(QEMU_MAGIC_$(ARCH)),$(QUIET)[[ -e $(QEMU_BINFMT_PATH) ]] || \
+         echo $(QEMU_MAGIC_$(ARCH)) | $(ROOT_CMD) tee $(QEMU_REGISTER_PATH) \
+           >/dev/null)
+endif
+.PHONY: qemu_clean qemu_chroot_install
+
+# TODO(wad) Move to -L $(SYSROOT) and fakechroot when qemu-user
+#           doesn't hang traversing /proc from SYSROOT.
+SUDO_CMD = sudo
+UNSHARE_CMD = unshare
+QEMU_CMD =
+ROOT_CMD = $(if $(filter 1,$(NEEDS_ROOT)),$(SUDO_CMD) , )
+MOUNT_CMD = $(if $(filter 1,$(NEEDS_MOUNTS)),$(ROOT_CMD) mount, \#)
+UMOUNT_CMD = $(if $(filter 1,$(NEEDS_MOUNTS)),$(ROOT_CMD) umount, \#)
+QEMU_LDPATH = $(SYSROOT_LDPATH):/lib64:/lib:/usr/lib64:/usr/lib
+ROOT_CMD_LDPATH = $(SYSROOT_LDPATH):$(SYSROOT)/lib64:
+ROOT_CMD_LDPATH := $(ROOT_CMD_LDPATH):$(SYSROOT)/lib:$(SYSROOT)/usr/lib64:
+ROOT_CMD_LDPATH := $(ROOT_CMD_LDPATH):$(SYSROOT)/usr/lib
+ifeq ($(USE_QEMU),1)
+  export QEMU_CMD = \
+   $(SUDO_CMD) chroot $(SYSROOT) $(QEMU_PATH) \
+   -drop-ld-preload \
+   -E LD_LIBRARY_PATH="$(QEMU_LDPATH):$(patsubst $(OUT),,$(LD_DIRS))" \
+   -E HOME="$(HOME)" -E SRC="$(SRC)" --
+  # USE_QEMU conditional function
+  define if_qemu
+    $(1)
+  endef
+else
+  ROOT_CMD = $(if $(filter 1,$(NEEDS_ROOT)),sudo, ) \
+    LD_LIBRARY_PATH="$(ROOT_CMD_LDPATH):$(LD_DIRS)"
+  define if_qemu
+    $(2)
+  endef
+endif
+
+VALGRIND_CMD =
+ifeq ($(VALGRIND),1)
+  VALGRIND_CMD = /usr/bin/valgrind --tool=memcheck $(VALGRIND_ARGS) --
+endif
+
+define TEST_implementation
+  $(QUIET)$(call TEST_setup)
+  $(QUIET)$(call TEST_run)
+  $(QUIET)$(call TEST_teardown)
+  $(QUIET)exit $$(cat $(OUT)$(TARGET_OR_MEMBER).status.test)
+endef
+
+define TEST_setup
+  @$(ECHO) -n "TEST            $(TARGET_OR_MEMBER) "
+  @$(ECHO) "[$(COLOR_YELLOW)SETUP$(COLOR_RESET)]"
+  $(QUIET)# Setup a target-specific results file
+  $(QUIET)(echo > $(OUT)$(TARGET_OR_MEMBER).setup.test)
+  $(QUIET)(echo 1 > $(OUT)$(TARGET_OR_MEMBER).status.test)
+  $(QUIET)(echo > $(OUT)$(TARGET_OR_MEMBER).cleanup.test)
+  $(QUIET)# No setup if we are not using QEMU
+  $(QUIET)# TODO(wad) this is racy until we use a vfs namespace
+  $(call if_qemu,\
+    $(QUIET)(echo "mkdir -p '$(SYSROOT)/proc' '$(SYSROOT)/dev' \
+                            '$(SYSROOT)/mnt/host/source'" \
+             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+  $(call if_qemu,\
+    $(QUIET)(echo "$(MOUNT_CMD) --bind /mnt/host/source \
+             '$(SYSROOT)/mnt/host/source'" \
+             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+  $(call if_qemu,\
+    $(QUIET)(echo "$(MOUNT_CMD) --bind /proc '$(SYSROOT)/proc'" \
+             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+  $(call if_qemu,\
+    $(QUIET)(echo "$(MOUNT_CMD) --bind /dev '$(SYSROOT)/dev'" \
+             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+endef
+
+define TEST_teardown
+  @$(ECHO) -n "TEST            $(TARGET_OR_MEMBER) "
+  @$(ECHO) "[$(COLOR_YELLOW)TEARDOWN$(COLOR_RESET)]"
+  $(call if_qemu, $(QUIET)$(SHELL) "$(OUT)$(TARGET_OR_MEMBER).cleanup.test")
+endef
+
+# Use GTEST_ARGS.[arch] if defined.
+override GTEST_ARGS.real = \
+ $(call if_qemu,$(GTEST_ARGS.qemu.$(QEMU_ARCH)),$(GTEST_ARGS.host.$(HOST_ARCH)))
+
+define TEST_run
+  @$(ECHO) -n "TEST            $(TARGET_OR_MEMBER) "
+  @$(ECHO) "[$(COLOR_GREEN)RUN$(COLOR_RESET)]"
+  $(QUIET)(echo 1 > "$(OUT)$(TARGET_OR_MEMBER).status.test")
+  $(QUIET)(echo $(ROOT_CMD) SRC="$(SRC)" $(QEMU_CMD) $(VALGRIND_CMD) \
+    "$(strip $(call if_qemu, $(SYSROOT_OUT),$(OUT))$(TARGET_OR_MEMBER))" \
+      $(if $(filter-out 0,$(words $(GTEST_ARGS.real))),$(GTEST_ARGS.real),\
+           $(GTEST_ARGS)) >> "$(OUT)$(TARGET_OR_MEMBER).setup.test")
+  -$(QUIET)$(call if_qemu,$(SUDO_CMD) $(UNSHARE_CMD) -m) $(SHELL) \
+      $(OUT)$(TARGET_OR_MEMBER).setup.test \
+  && echo 0 > "$(OUT)$(TARGET_OR_MEMBER).status.test"
+endef
+
+# Recursive list reversal so that we get RMDIR_ON_CLEAN in reverse order.
+define reverse
+$(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
+endef
+
+clean: qemu_clean
+clean: CLEAN($(OUT)*.d) CLEAN($(OUT)*.o) CLEAN($(OUT)*.debug)
+clean: CLEAN($(OUT)*.test) CLEAN($(OUT)*.depends)
+clean: CLEAN($(OUT)*.gcno) CLEAN($(OUT)*.gcda) CLEAN($(OUT)*.gcov)
+clean: CLEAN($(OUT)lcov-coverage.info) CLEAN($(OUT)lcov-html)
+
+clean:
+       $(QUIET)# Always delete the containing directory last.
+       $(call silent_rmdir,$(OUT))
+
+FORCE: ;
+# Empty rule for use when no special targets are needed, like large_tests
+NONE:
+
+.PHONY: clean NONE valgrind NONE
+.DEFAULT_GOAL  :=  all
+# Don't let make blow away "intermediates"
+.PRECIOUS: %.pic.o %.pie.o %.a %.pic.a %.pie.a %.test
+
+# Start accruing build info
+OUT_DIRS = $(OUT)
+LD_DIRS = $(OUT)
+SRC_DIRS = $(SRC)
+
+include $(wildcard $(OUT)*.d)
+SUBMODULE_DIRS = $(wildcard $(SRC)/*/module.mk)
+include $(SUBMODULE_DIRS)
+
+
+else  ## In duplicate inclusions of common.mk
+
+# Get the current inclusion directory without a trailing slash
+MODULE := $(patsubst %/,%, \
+           $(dir $(lastword $(filter-out %common.mk,$(MAKEFILE_LIST)))))
+MODULE := $(subst $(SRC)/,,$(MODULE))
+MODULE_NAME := $(subst /,_,$(MODULE))
+#VPATH := $(MODULE):$(VPATH)
+
+
+# Depth first
+$(eval OUT_DIRS += $(OUT)$(MODULE))
+$(eval SRC_DIRS += $(OUT)$(MODULE))
+$(eval LD_DIRS := $(LD_DIRS):$(OUT)$(MODULE))
+
+# Add the defaults from this dir to rm_clean
+clean: CLEAN($(OUT)$(MODULE)/*.d) CLEAN($(OUT)$(MODULE)/*.o)
+clean: CLEAN($(OUT)$(MODULE)/*.debug) CLEAN($(OUT)$(MODULE)/*.test)
+clean: CLEAN($(OUT)$(MODULE)/*.depends)
+clean: CLEAN($(OUT)$(MODULE)/*.gcno) CLEAN($(OUT)$(MODULE)/*.gcda)
+clean: CLEAN($(OUT)$(MODULE)/*.gcov) CLEAN($(OUT)lcov-coverage.info)
+clean: CLEAN($(OUT)lcov-html)
+
+$(info + submodule: $(MODULE_NAME))
+# We must eval otherwise they may be dropped.
+MODULE_C_OBJECTS = $(patsubst $(SRC)/$(MODULE)/%.c,$(MODULE)/%.o,\
+  $(wildcard $(SRC)/$(MODULE)/*.c))
+$(eval $(MODULE_NAME)_C_OBJECTS ?= $(MODULE_C_OBJECTS))
+MODULE_CXX_OBJECTS = $(patsubst $(SRC)/$(MODULE)/%.cc,$(MODULE)/%.o,\
+  $(wildcard $(SRC)/$(MODULE)/*.cc))
+$(eval $(MODULE_NAME)_CXX_OBJECTS ?= $(MODULE_CXX_OBJECTS))
+
+# Note, $(MODULE) is implicit in the path to the %.c.
+# See $(C_OBJECTS) for more details.
+# Register rules for the module objects.
+$(eval $(call add_object_rules,$(MODULE_C_OBJECTS),CC,c,CFLAGS,$(SRC)/))
+$(eval $(call add_object_rules,$(MODULE_CXX_OBJECTS),CXX,cc,CXXFLAGS,$(SRC)/))
+
+# Continue recursive inclusion of module.mk files
+SUBMODULE_DIRS = $(wildcard $(SRC)/$(MODULE)/*/module.mk)
+include $(wildcard $(OUT)$(MODULE)/*.d)
+include $(SUBMODULE_DIRS)
+
+endif
+endif  ## pass-to-subcall wrapper for relocating the call directory
diff --git a/exynos.c b/exynos.c
new file mode 100644 (file)
index 0000000..6b2e6d8
--- /dev/null
+++ b/exynos.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef GBM_EXYNOS
+
+#include <string.h>
+#include <xf86drm.h>
+#include <exynos_drm.h>
+
+#include "gbm_priv.h"
+#include "helpers.h"
+
+int gbm_exynos_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+       size_t size = width * height * gbm_bytes_from_format(format);
+       struct drm_exynos_gem_create gem_create;
+       int ret;
+
+       memset(&gem_create, 0, sizeof(gem_create));
+       gem_create.size = size;
+       gem_create.flags = EXYNOS_BO_NONCONTIG;
+
+       ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &gem_create);
+       if (ret)
+               return ret;
+
+       bo->handle.u32 = gem_create.handle;
+       bo->size = size;
+
+       return 0;
+}
+
+const struct gbm_driver gbm_driver_exynos =
+{
+       .name = "exynos",
+       .bo_create = gbm_exynos_bo_create,
+       .bo_destroy = gbm_gem_bo_destroy,
+       .format_list = {
+               {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+       }
+};
+
+#endif
diff --git a/gbm.c b/gbm.c
new file mode 100644 (file)
index 0000000..8a18d13
--- /dev/null
+++ b/gbm.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <xf86drm.h>
+
+#include "gbm_priv.h"
+#include "util.h"
+
+/*
+gbm_buffer_base.cc:  gbm_bo_get_width(bo),
+gbm_buffer_base.cc:  gbm_bo_get_height(bo),
+gbm_buffer_base.cc:  gbm_bo_get_stride(bo),
+gbm_buffer_base.cc:  gbm_bo_get_handle(bo).u32,
+gbm_buffer_base.cc:  return gbm_bo_get_handle(bo_).u32;
+gbm_buffer_base.cc:  return gfx::Size(gbm_bo_get_width(bo_), gbm_bo_get_height(bo_));
+gbm_buffer.cc:    gbm_bo_destroy(bo());
+gbm_buffer.cc:  gbm_bo* bo = gbm_bo_create(device,
+gbm_surface.cc:    gbm_bo_set_user_data(bo, this, GbmSurfaceBuffer::Destroy);
+gbm_surface.cc:      static_cast<GbmSurfaceBuffer*>(gbm_bo_get_user_data(buffer)));
+gbm_surface.cc:    gbm_surface_release_buffer(native_surface_, current_buffer_);
+gbm_surface.cc:    gbm_surface_destroy(native_surface_);
+gbm_surface.cc:  native_surface_ = gbm_surface_create(
+gbm_surface.cc:  gbm_bo* pending_buffer = gbm_surface_lock_front_buffer(native_surface_);
+gbm_surface.cc:    gbm_surface_release_buffer(native_surface_, current_buffer_);
+ozone_platform_gbm.cc:        device_(gbm_create_device(dri_->get_fd())) {}
+ozone_platform_gbm.cc:    gbm_device_destroy(device_);
+*/
+
+extern struct gbm_driver gbm_driver_cirrus;
+#ifdef GBM_EXYNOS
+extern struct gbm_driver gbm_driver_exynos;
+#endif
+extern struct gbm_driver gbm_driver_gma500;
+#ifdef GBM_I915
+extern struct gbm_driver gbm_driver_i915;
+#endif
+#ifdef GBM_ROCKCHIP
+extern struct gbm_driver gbm_driver_rockchip;
+#endif
+#ifdef GBM_TEGRA
+extern struct gbm_driver gbm_driver_tegra;
+#endif
+extern struct gbm_driver gbm_driver_udl;
+
+static struct gbm_driver *gbm_get_driver(int fd)
+{
+       drmVersionPtr drm_version;
+       unsigned int i;
+
+       drm_version = drmGetVersion(fd);
+
+       if (!drm_version)
+               return NULL;
+
+       struct gbm_driver *driver_list[] = {
+               &gbm_driver_cirrus,
+#ifdef GBM_EXYNOS
+               &gbm_driver_exynos,
+#endif
+               &gbm_driver_gma500,
+#ifdef GBM_I915
+               &gbm_driver_i915,
+#endif
+#ifdef GBM_ROCKCHIP
+               &gbm_driver_rockchip,
+#endif
+#ifdef GBM_TEGRA
+               &gbm_driver_tegra,
+#endif
+               &gbm_driver_udl,
+       };
+
+       for(i = 0; i < ARRAY_SIZE(driver_list); i++)
+               if (!strcmp(drm_version->name, driver_list[i]->name))
+               {
+                       drmFreeVersion(drm_version);
+                       return driver_list[i];
+               }
+
+       drmFreeVersion(drm_version);
+       return NULL;
+}
+
+PUBLIC int
+gbm_device_get_fd(struct gbm_device *gbm)
+{
+       return gbm->fd;
+}
+
+PUBLIC const char *
+gbm_device_get_backend_name(struct gbm_device *gbm)
+{
+       return gbm->driver->name;
+}
+
+PUBLIC int
+gbm_device_is_format_supported(struct gbm_device *gbm,
+                             uint32_t format, uint32_t usage)
+{
+       unsigned i;
+
+       if (format == GBM_BO_FORMAT_XRGB8888)
+               format = GBM_FORMAT_XRGB8888;
+       if (format == GBM_BO_FORMAT_ARGB8888)
+               format = GBM_FORMAT_ARGB8888;
+
+       if (usage & GBM_BO_USE_CURSOR &&
+               usage & GBM_BO_USE_RENDERING)
+               return 0;
+
+       for(i = 0 ; i < ARRAY_SIZE(gbm->driver->format_list); i++)
+       {
+               if (!gbm->driver->format_list[i].format)
+                       break;
+
+               if (gbm->driver->format_list[i].format == format &&
+                       (gbm->driver->format_list[i].usage & usage) == usage)
+                       return 1;
+       }
+
+       return 0;
+}
+
+PUBLIC struct gbm_device *gbm_create_device(int fd)
+{
+       struct gbm_device *gbm;
+       int ret;
+
+       gbm = (struct gbm_device*) malloc(sizeof(*gbm));
+       if (!gbm)
+               return NULL;
+
+       gbm->fd = fd;
+
+       gbm->driver = gbm_get_driver(fd);
+       if (!gbm->driver) {
+               free(gbm);
+               return NULL;
+       }
+
+       if (gbm->driver->init) {
+               ret = gbm->driver->init(gbm);
+               if (ret) {
+                       free(gbm);
+                       return NULL;
+               }
+       }
+
+       return gbm;
+}
+
+PUBLIC void gbm_device_destroy(struct gbm_device *gbm)
+{
+       if (gbm->driver->close)
+               gbm->driver->close(gbm);
+       free(gbm);
+}
+
+PUBLIC struct gbm_surface *gbm_surface_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+       struct gbm_surface *surface = (struct gbm_surface*) malloc(sizeof(*surface));
+       if (!surface)
+               return NULL;
+
+       return surface;
+}
+
+PUBLIC void gbm_surface_destroy(struct gbm_surface *surface)
+{
+       free(surface);
+}
+
+PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface)
+{
+       return NULL;
+}
+
+PUBLIC void gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo)
+{
+}
+
+PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+       struct gbm_bo *bo;
+       int ret;
+
+       bo = (struct gbm_bo*) malloc(sizeof(*bo));
+       if (!bo)
+               return NULL;
+
+       bo->gbm = gbm;
+       bo->width = width;
+       bo->height = height;
+       bo->stride = 0;
+       bo->format = format;
+       bo->handle.u32 = 0;
+       bo->destroy_user_data = NULL;
+       bo->user_data = NULL;
+
+       ret = gbm->driver->bo_create(bo, width, height, format, flags);
+       if (ret) {
+               free(bo);
+               return NULL;
+       }
+
+       return bo;
+}
+
+PUBLIC void gbm_bo_destroy(struct gbm_bo *bo)
+{
+       if (bo->destroy_user_data) {
+               bo->destroy_user_data(bo, bo->user_data);
+               bo->destroy_user_data = NULL;
+               bo->user_data = NULL;
+       }
+
+       bo->gbm->driver->bo_destroy(bo);
+       free(bo);
+}
+
+PUBLIC uint32_t
+gbm_bo_get_width(struct gbm_bo *bo)
+{
+       return bo->width;
+}
+
+PUBLIC uint32_t
+gbm_bo_get_height(struct gbm_bo *bo)
+{
+       return bo->height;
+}
+
+PUBLIC uint32_t
+gbm_bo_get_stride(struct gbm_bo *bo)
+{
+       return bo->stride;
+}
+
+PUBLIC uint32_t
+gbm_bo_get_format(struct gbm_bo *bo)
+{
+       return bo->format;
+}
+
+PUBLIC struct gbm_device *
+gbm_bo_get_device(struct gbm_bo *bo)
+{
+       return bo->gbm;
+}
+
+PUBLIC union gbm_bo_handle
+gbm_bo_get_handle(struct gbm_bo *bo)
+{
+       return bo->handle;
+}
+
+PUBLIC int
+gbm_bo_get_fd(struct gbm_bo *bo)
+{
+       return bo->gbm->fd;
+}
+
+PUBLIC void
+gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
+                    void (*destroy_user_data)(struct gbm_bo *, void *))
+{
+       bo->user_data = data;
+       bo->destroy_user_data = destroy_user_data;
+}
+
+PUBLIC void *
+gbm_bo_get_user_data(struct gbm_bo *bo)
+{
+       return bo->user_data;
+}
diff --git a/gbm.h b/gbm.h
new file mode 100644 (file)
index 0000000..374cef8
--- /dev/null
+++ b/gbm.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ *    Benjamin Franzke <benjaminfranzke@googlemail.com>
+ */
+
+#ifndef _GBM_H_
+#define _GBM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define __GBM__ 1
+
+#include <stdint.h>
+
+/**
+ * \file gbm.h
+ * \brief Generic Buffer Manager
+ */
+
+struct gbm_device;
+struct gbm_bo;
+struct gbm_surface;
+
+/**
+ * \mainpage The Generic Buffer Manager
+ *
+ * This module provides an abstraction that the caller can use to request a
+ * buffer from the underlying memory management system for the platform.
+ *
+ * This allows the creation of portable code whilst still allowing access to
+ * the underlying memory manager.
+ */
+
+/**
+ * Abstraction representing the handle to a buffer allocated by the
+ * manager
+ */
+union gbm_bo_handle {
+   void *ptr;
+   int32_t s32;
+   uint32_t u32;
+   int64_t s64;
+   uint64_t u64;
+};
+
+/** Format of the allocated buffer */
+enum gbm_bo_format {
+   /** RGB with 8 bits per channel in a 32 bit value */
+   GBM_BO_FORMAT_XRGB8888, 
+   /** ARGB with 8 bits per channel in a 32 bit value */
+   GBM_BO_FORMAT_ARGB8888
+};
+
+#define __gbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
+                             ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
+
+#define GBM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
+
+/* color index */
+#define GBM_FORMAT_C8          __gbm_fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
+
+/* 8 bpp RGB */
+#define GBM_FORMAT_RGB332      __gbm_fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */
+#define GBM_FORMAT_BGR233      __gbm_fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */
+
+/* 16 bpp RGB */
+#define GBM_FORMAT_XRGB4444    __gbm_fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */
+#define GBM_FORMAT_XBGR4444    __gbm_fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */
+#define GBM_FORMAT_RGBX4444    __gbm_fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */
+#define GBM_FORMAT_BGRX4444    __gbm_fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */
+
+#define GBM_FORMAT_ARGB4444    __gbm_fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */
+#define GBM_FORMAT_ABGR4444    __gbm_fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */
+#define GBM_FORMAT_RGBA4444    __gbm_fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */
+#define GBM_FORMAT_BGRA4444    __gbm_fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */
+
+#define GBM_FORMAT_XRGB1555    __gbm_fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */
+#define GBM_FORMAT_XBGR1555    __gbm_fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */
+#define GBM_FORMAT_RGBX5551    __gbm_fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */
+#define GBM_FORMAT_BGRX5551    __gbm_fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */
+
+#define GBM_FORMAT_ARGB1555    __gbm_fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */
+#define GBM_FORMAT_ABGR1555    __gbm_fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */
+#define GBM_FORMAT_RGBA5551    __gbm_fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */
+#define GBM_FORMAT_BGRA5551    __gbm_fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */
+
+#define GBM_FORMAT_RGB565      __gbm_fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
+#define GBM_FORMAT_BGR565      __gbm_fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */
+
+/* 24 bpp RGB */
+#define GBM_FORMAT_RGB888      __gbm_fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
+#define GBM_FORMAT_BGR888      __gbm_fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */
+
+/* 32 bpp RGB */
+#define GBM_FORMAT_XRGB8888    __gbm_fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
+#define GBM_FORMAT_XBGR8888    __gbm_fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */
+#define GBM_FORMAT_RGBX8888    __gbm_fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */
+#define GBM_FORMAT_BGRX8888    __gbm_fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */
+
+#define GBM_FORMAT_ARGB8888    __gbm_fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
+#define GBM_FORMAT_ABGR8888    __gbm_fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
+#define GBM_FORMAT_RGBA8888    __gbm_fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */
+#define GBM_FORMAT_BGRA8888    __gbm_fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */
+
+#define GBM_FORMAT_XRGB2101010 __gbm_fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */
+#define GBM_FORMAT_XBGR2101010 __gbm_fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */
+#define GBM_FORMAT_RGBX1010102 __gbm_fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */
+#define GBM_FORMAT_BGRX1010102 __gbm_fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */
+
+#define GBM_FORMAT_ARGB2101010 __gbm_fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */
+#define GBM_FORMAT_ABGR2101010 __gbm_fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */
+#define GBM_FORMAT_RGBA1010102 __gbm_fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */
+#define GBM_FORMAT_BGRA1010102 __gbm_fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */
+
+/* packed YCbCr */
+#define GBM_FORMAT_YUYV                __gbm_fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
+#define GBM_FORMAT_YVYU                __gbm_fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
+#define GBM_FORMAT_UYVY                __gbm_fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
+#define GBM_FORMAT_VYUY                __gbm_fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
+
+#define GBM_FORMAT_AYUV                __gbm_fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [7:0] Y
+ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
+ * or
+ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
+ */
+#define GBM_FORMAT_NV12                __gbm_fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
+#define GBM_FORMAT_NV21                __gbm_fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */
+#define GBM_FORMAT_NV16                __gbm_fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
+#define GBM_FORMAT_NV61                __gbm_fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
+
+/*
+ * 3 plane YCbCr
+ * index 0: Y plane, [7:0] Y
+ * index 1: Cb plane, [7:0] Cb
+ * index 2: Cr plane, [7:0] Cr
+ * or
+ * index 1: Cr plane, [7:0] Cr
+ * index 2: Cb plane, [7:0] Cb
+ */
+#define GBM_FORMAT_YUV410      __gbm_fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU410      __gbm_fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV411      __gbm_fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU411      __gbm_fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV420      __gbm_fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU420      __gbm_fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV422      __gbm_fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU422      __gbm_fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV444      __gbm_fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU444      __gbm_fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
+
+
+/**
+ * Flags to indicate the intended use for the buffer - these are passed into
+ * gbm_bo_create(). The caller must set the union of all the flags that are
+ * appropriate
+ *
+ * \sa Use gbm_device_is_format_supported() to check if the combination of format
+ * and use flags are supported
+ */
+enum gbm_bo_flags {
+   /**
+    * Buffer is going to be presented to the screen using an API such as KMS
+    */
+   GBM_BO_USE_SCANOUT      = (1 << 0),
+   /**
+    * Buffer is going to be used as cursor
+    */
+   GBM_BO_USE_CURSOR       = (1 << 1),
+   /**
+    * Deprecated
+    */
+   GBM_BO_USE_CURSOR_64X64 = GBM_BO_USE_CURSOR,
+   /**
+    * Buffer is to be used for rendering - for example it is going to be used
+    * as the storage for a color buffer
+    */
+   GBM_BO_USE_RENDERING    = (1 << 2),
+   /**
+    * Buffer can be used for gbm_bo_write.  This is guaranteed to work
+    * with GBM_BO_USE_CURSOR. but may not work for other combinations.
+    */
+   GBM_BO_USE_WRITE    = (1 << 3),
+};
+
+int
+gbm_device_get_fd(struct gbm_device *gbm);
+
+const char *
+gbm_device_get_backend_name(struct gbm_device *gbm);
+
+int
+gbm_device_is_format_supported(struct gbm_device *gbm,
+                               uint32_t format, uint32_t usage);
+
+void
+gbm_device_destroy(struct gbm_device *gbm);
+
+struct gbm_device *
+gbm_create_device(int fd);
+
+struct gbm_bo *
+gbm_bo_create(struct gbm_device *gbm,
+              uint32_t width, uint32_t height,
+              uint32_t format, uint32_t flags);
+
+#define GBM_BO_IMPORT_WL_BUFFER         0x5501
+#define GBM_BO_IMPORT_EGL_IMAGE         0x5502
+#define GBM_BO_IMPORT_FD                0x5503
+
+struct gbm_import_fd_data {
+   int fd;
+   uint32_t width;
+   uint32_t height;
+   uint32_t stride;
+   uint32_t format;
+};
+
+struct gbm_bo *
+gbm_bo_import(struct gbm_device *gbm, uint32_t type,
+              void *buffer, uint32_t usage);
+
+uint32_t
+gbm_bo_get_width(struct gbm_bo *bo);
+
+uint32_t
+gbm_bo_get_height(struct gbm_bo *bo);
+
+uint32_t
+gbm_bo_get_stride(struct gbm_bo *bo);
+
+uint32_t
+gbm_bo_get_format(struct gbm_bo *bo);
+
+struct gbm_device *
+gbm_bo_get_device(struct gbm_bo *bo);
+
+union gbm_bo_handle
+gbm_bo_get_handle(struct gbm_bo *bo);
+
+int
+gbm_bo_get_fd(struct gbm_bo *bo);
+
+int
+gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count);
+
+void
+gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
+                    void (*destroy_user_data)(struct gbm_bo *, void *));
+
+void *
+gbm_bo_get_user_data(struct gbm_bo *bo);
+
+void
+gbm_bo_destroy(struct gbm_bo *bo);
+
+struct gbm_surface *
+gbm_surface_create(struct gbm_device *gbm,
+                   uint32_t width, uint32_t height,
+                  uint32_t format, uint32_t flags);
+
+struct gbm_bo *
+gbm_surface_lock_front_buffer(struct gbm_surface *surface);
+
+void
+gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo);
+
+int
+gbm_surface_has_free_buffers(struct gbm_surface *surface);
+
+void
+gbm_surface_destroy(struct gbm_surface *surface);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gbm_priv.h b/gbm_priv.h
new file mode 100644 (file)
index 0000000..1cda331
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GBM_PRIV_H
+#define GBM_PRIV_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include "gbm.h"
+
+struct gbm_device
+{
+       int fd;
+       struct gbm_driver *driver;
+       void *priv;
+};
+
+struct gbm_surface
+{
+};
+
+struct gbm_bo
+{
+       struct gbm_device *gbm;
+       uint32_t width;
+       uint32_t height;
+       uint32_t size;
+       uint32_t stride;
+       uint32_t format;
+       union gbm_bo_handle handle;
+       void *priv;
+       void *user_data;
+       void (*destroy_user_data)(struct gbm_bo *, void *);
+};
+
+struct gbm_driver
+{
+       char *name;
+       int (*init)(struct gbm_device *gbm);
+       void (*close)(struct gbm_device *gbm);
+       int (*bo_create)(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags);
+       int (*bo_destroy)(struct gbm_bo *bo);
+       struct format_supported {
+               uint32_t format;
+               enum gbm_bo_flags usage;
+       }
+       format_list[10];
+};
+
+#endif
diff --git a/gma500.c b/gma500.c
new file mode 100644 (file)
index 0000000..95d663c
--- /dev/null
+++ b/gma500.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gbm_priv.h"
+#include "helpers.h"
+
+struct gbm_driver gbm_driver_gma500 =
+{
+       .name = "gma500",
+       .bo_create = gbm_dumb_bo_create,
+       .bo_destroy = gbm_dumb_bo_destroy,
+       .format_list = {
+               {GBM_FORMAT_RGBX8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+       }
+};
diff --git a/helpers.c b/helpers.c
new file mode 100644 (file)
index 0000000..4158f0f
--- /dev/null
+++ b/helpers.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <xf86drm.h>
+
+#include "gbm_priv.h"
+
+int gbm_bpp_from_format(uint32_t format)
+{
+       if (format == GBM_BO_FORMAT_XRGB8888)
+               format = GBM_FORMAT_XRGB8888;
+       if (format == GBM_BO_FORMAT_ARGB8888)
+               format = GBM_FORMAT_ARGB8888;
+
+       switch(format)
+       {
+               case GBM_FORMAT_C8:
+               case GBM_FORMAT_RGB332:
+               case GBM_FORMAT_BGR233:
+                       return 8;
+
+               case GBM_FORMAT_XRGB4444:
+               case GBM_FORMAT_XBGR4444:
+               case GBM_FORMAT_RGBX4444:
+               case GBM_FORMAT_BGRX4444:
+               case GBM_FORMAT_ARGB4444:
+               case GBM_FORMAT_ABGR4444:
+               case GBM_FORMAT_RGBA4444:
+               case GBM_FORMAT_BGRA4444:
+               case GBM_FORMAT_XRGB1555:
+               case GBM_FORMAT_XBGR1555:
+               case GBM_FORMAT_RGBX5551:
+               case GBM_FORMAT_BGRX5551:
+               case GBM_FORMAT_ARGB1555:
+               case GBM_FORMAT_ABGR1555:
+               case GBM_FORMAT_RGBA5551:
+               case GBM_FORMAT_BGRA5551:
+               case GBM_FORMAT_RGB565:
+               case GBM_FORMAT_BGR565:
+                       return 16;
+
+               case GBM_FORMAT_RGB888:
+               case GBM_FORMAT_BGR888:
+                       return 24;
+
+               case GBM_FORMAT_XRGB8888:
+               case GBM_FORMAT_XBGR8888:
+               case GBM_FORMAT_RGBX8888:
+               case GBM_FORMAT_BGRX8888:
+               case GBM_FORMAT_ARGB8888:
+               case GBM_FORMAT_ABGR8888:
+               case GBM_FORMAT_RGBA8888:
+               case GBM_FORMAT_BGRA8888:
+               case GBM_FORMAT_XRGB2101010:
+               case GBM_FORMAT_XBGR2101010:
+               case GBM_FORMAT_RGBX1010102:
+               case GBM_FORMAT_BGRX1010102:
+               case GBM_FORMAT_ARGB2101010:
+               case GBM_FORMAT_ABGR2101010:
+               case GBM_FORMAT_RGBA1010102:
+               case GBM_FORMAT_BGRA1010102:
+               case GBM_FORMAT_YUYV:
+               case GBM_FORMAT_YVYU:
+               case GBM_FORMAT_UYVY:
+               case GBM_FORMAT_VYUY:
+               case GBM_FORMAT_AYUV:
+                       return 32;
+       }
+
+       printf("UNKNOWN FORMAT %d\n", format);
+       return 0;
+}
+
+int gbm_bytes_from_format(uint32_t format)
+{
+       return gbm_bpp_from_format(format) / 8;
+}
+
+int gbm_is_format_supported(struct gbm_bo *bo)
+{
+       return 1;
+}
+
+int gbm_dumb_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+       struct drm_mode_create_dumb create_dumb;
+       int ret;
+
+       memset(&create_dumb, 0, sizeof(create_dumb));
+       create_dumb.height = height;
+       create_dumb.width = width;
+       create_dumb.bpp = gbm_bpp_from_format(format);
+       create_dumb.flags = 0;
+
+       ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
+       if (ret)
+               return ret;
+
+       bo->handle.u32 = create_dumb.handle;
+       bo->size = create_dumb.size;
+
+       return 0;
+}
+
+int gbm_dumb_bo_destroy(struct gbm_bo *bo)
+{
+       struct drm_mode_destroy_dumb destroy_dumb;
+       int ret;
+
+       memset(&destroy_dumb, 0, sizeof(destroy_dumb));
+       destroy_dumb.handle = bo->handle.u32;
+
+       ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int gbm_gem_bo_destroy(struct gbm_bo *bo)
+{
+       struct drm_gem_close gem_close;
+       int ret;
+
+       memset(&gem_close, 0, sizeof(gem_close));
+       gem_close.handle = bo->handle.u32;
+
+       ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+       if (ret)
+               return ret;
+
+       return 0;
+}
diff --git a/helpers.h b/helpers.h
new file mode 100644 (file)
index 0000000..d4523b0
--- /dev/null
+++ b/helpers.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef HELPERS_H
+#define HELPERS_H
+
+int gbm_bpp_from_format(uint32_t format);
+int gbm_bytes_from_format(uint32_t format);
+int gbm_is_format_supported(struct gbm_bo *bo);
+int gbm_dumb_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags);
+int gbm_dumb_bo_destroy(struct gbm_bo *bo);
+int gbm_gem_bo_destroy(struct gbm_bo *bo);
+
+#endif
diff --git a/i915.c b/i915.c
new file mode 100644 (file)
index 0000000..6daee56
--- /dev/null
+++ b/i915.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef GBM_I915
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <xf86drm.h>
+#include <i915_drm.h>
+
+#include "gbm_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+struct gbm_i915_device
+{
+       int gen;
+};
+
+
+static int get_gen(int device_id)
+{
+       const uint16_t gen3_ids[] = {0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE, 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011};
+       int i;
+       for(i = 0; i < ARRAY_SIZE(gen3_ids); i++)
+               if (gen3_ids[i] == device_id)
+                       return 3;
+
+       return 4;
+}
+
+int gbm_i915_init(struct gbm_device *gbm)
+{
+       struct gbm_i915_device *i915_gbm;
+       drm_i915_getparam_t get_param;
+       int device_id;
+       int ret;
+
+       i915_gbm = (struct gbm_i915_device*)malloc(sizeof(*i915_gbm));
+       if (!i915_gbm)
+               return -1;
+
+       memset(&get_param, 0, sizeof(get_param));
+       get_param.param = I915_PARAM_CHIPSET_ID;
+       get_param.value = &device_id;
+       ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
+       if (ret) {
+               free(i915_gbm);
+               return -1;
+       }
+
+       i915_gbm->gen = get_gen(device_id);
+
+       gbm->priv = i915_gbm;
+
+       return 0;
+}
+
+void gbm_i915_close(struct gbm_device *gbm)
+{
+       free(gbm->priv);
+       gbm->priv = NULL;
+}
+
+static int i915_get_pitch(struct gbm_device *gbm, uint32_t pitch, int tiling_mode)
+{
+       struct gbm_i915_device *dev_priv = (struct gbm_i915_device *)gbm->priv;
+       if (tiling_mode == I915_TILING_NONE)
+               return ALIGN(pitch, 64);
+
+       if (dev_priv->gen >= 4) {
+               uint32_t tile_width = tiling_mode == I915_TILING_X ? 512 : 128;
+               return ALIGN(pitch, tile_width);
+       } else {
+               uint32_t i = 128;
+               while(i < pitch)
+                       i <<= 1;
+               return i;
+       }
+}
+
+int gbm_i915_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+       size_t size = width * height * gbm_bytes_from_format(format);
+       struct drm_i915_gem_create gem_create;
+       struct drm_i915_gem_set_tiling gem_set_tiling;
+       uint32_t tiling_mode = I915_TILING_NONE;
+       int ret;
+
+       memset(&gem_create, 0, sizeof(gem_create));
+       gem_create.size = size;
+
+       ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
+       if (ret)
+               return ret;
+
+       bo->handle.u32 = gem_create.handle;
+       bo->size = size;
+
+       if (flags & GBM_BO_USE_CURSOR)
+               tiling_mode = I915_TILING_NONE;
+       else if (flags & GBM_BO_USE_SCANOUT)
+               tiling_mode = I915_TILING_X;
+       else if (flags & GBM_BO_USE_RENDERING)
+               tiling_mode = I915_TILING_Y;
+
+       memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
+       do {
+               gem_set_tiling.handle = bo->handle.u32;
+               gem_set_tiling.tiling_mode = tiling_mode;
+               gem_set_tiling.stride = i915_get_pitch(bo->gbm,
+                                                       width * gbm_bytes_from_format(format),
+                                                       tiling_mode);
+               ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
+       } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+       if (ret == -1) {
+               struct drm_gem_close gem_close;
+               gem_close.handle = bo->handle.u32;
+               drmIoctl(bo->gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+               return -errno;
+       }
+
+       return 0;
+}
+
+const struct gbm_driver gbm_driver_i915 =
+{
+       .name = "i915",
+       .init = gbm_i915_init,
+       .close = gbm_i915_close,
+       .bo_create = gbm_i915_bo_create,
+       .bo_destroy = gbm_gem_bo_destroy,
+       .format_list = {
+               {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_XBGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_ABGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_XRGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_ARGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_RGB565,   GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+       }
+};
+
+#endif
diff --git a/rockchip.c b/rockchip.c
new file mode 100644 (file)
index 0000000..72748cf
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef GBM_ROCKCHIP
+
+#include <string.h>
+#include <xf86drm.h>
+#include <rockchip_drm.h>
+
+#include "gbm_priv.h"
+
+int gbm_rockchip_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+       size_t size = width * height * ;
+       struct drm_rockchip_gem_create gem_create;
+       int ret;
+
+       memset(&gem_create, 0, sizeof(gem_create));
+       gem_create.size = size;
+
+       ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &gem_create);
+       if (ret)
+               return ret;
+
+       bo->handle.u32 = gem_create.handle;
+       bo->size = size;
+
+       return 0;
+}
+
+struct gbm_driver gbm_driver_rockchip =
+{
+       .name = "rockchip",
+       .bo_create = gbm_rockchip_bo_create,
+       .bo_destroy = gbm_gem_bo_destroy,
+       .format_list = {
+               {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+       }
+};
+
+#endif
diff --git a/tegra.c b/tegra.c
new file mode 100644 (file)
index 0000000..46105a3
--- /dev/null
+++ b/tegra.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef GBM_TEGRA
+
+#include <string.h>
+#include <xf86drm.h>
+#include <tegra_drm.h>
+
+#include "gbm_priv.h"
+#include "helpers.h"
+
+int gbm_tegra_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
+{
+       size_t size = width * height * gbm_bytes_from_format(format);
+       struct drm_tegra_gem_create gem_create;
+       int ret;
+
+       memset(&gem_create, 0, sizeof(gem_create));
+       gem_create.size = size;
+       gem_create.flags = 0;
+
+       ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_TEGRA_GEM_CREATE, &gem_create);
+       if (ret)
+               return ret;
+
+       bo->handle.u32 = gem_create.handle;
+       bo->size = size;
+
+       return 0;
+}
+
+struct gbm_driver gbm_driver_tegra =
+{
+       .name = "tegra",
+       .bo_create = gbm_tegra_bo_create,
+       .bo_destroy = gbm_gem_bo_destroy,
+       .format_list = {
+               {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+       }
+};
+
+#endif
diff --git a/test.c b/test.c
new file mode 100644 (file)
index 0000000..203ffaf
--- /dev/null
+++ b/test.c
@@ -0,0 +1,4 @@
+int pouet()
+{
+       return 0;
+}
diff --git a/udl.c b/udl.c
new file mode 100644 (file)
index 0000000..497064a
--- /dev/null
+++ b/udl.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gbm_priv.h"
+#include "helpers.h"
+
+const struct gbm_driver gbm_driver_udl =
+{
+       .name = "udl",
+       .bo_create = gbm_dumb_bo_create,
+       .bo_destroy = gbm_dumb_bo_destroy,
+       .format_list = {
+               {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+               {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
+       }
+};
diff --git a/util.h b/util.h
new file mode 100644 (file)
index 0000000..197312a
--- /dev/null
+++ b/util.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*(A)))
+#define PUBLIC __attribute__((visibility("default")))
+#define ALIGN(A, B) (((A) + (B) - 1) / (B) * (B))
+
+#endif