Add cairo framebuffer example
This commit is contained in:
parent
daa2bf8053
commit
daa9cb4e04
5 changed files with 280 additions and 0 deletions
65
cairo/.cproject
Normal file
65
cairo/.cproject
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||||
|
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.1978501621">
|
||||||
|
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.1978501621" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||||
|
<externalSettings/>
|
||||||
|
<extensions>
|
||||||
|
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
</extensions>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||||
|
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.1978501621" name="Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug">
|
||||||
|
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.1978501621." name="/" resourcePath="">
|
||||||
|
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.debug.306393296" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.debug">
|
||||||
|
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.801937591" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
||||||
|
<builder buildPath="${workspace_loc:/cairo}/Debug" id="cdt.managedbuild.builder.gnu.cross.470768732" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
||||||
|
<tool command="${CC}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1376072995" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
||||||
|
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.626117689" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||||
|
<option id="gnu.c.compiler.option.debugging.level.335209179" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
|
||||||
|
<option id="gnu.c.compiler.option.misc.other.1208394549" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="${CFLAGS} -c --sysroot=/usr/local/oecore-x86_64/sysroots/armv7at2hf-neon-angstrom-linux-gnueabi/" valueType="string"/>
|
||||||
|
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.259154356" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||||
|
</tool>
|
||||||
|
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.4296937" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
||||||
|
<option id="gnu.cpp.compiler.option.optimization.level.2146025131" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
|
||||||
|
<option id="gnu.cpp.compiler.option.debugging.level.961860275" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
|
||||||
|
</tool>
|
||||||
|
<tool command="${CC}" id="cdt.managedbuild.tool.gnu.cross.c.linker.915568386" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker">
|
||||||
|
<option id="gnu.c.link.option.libs.1910771565" name="Libraries (-l)" superClass="gnu.c.link.option.libs" useByScannerDiscovery="false" valueType="libs">
|
||||||
|
<listOptionValue builtIn="false" value="cairo"/>
|
||||||
|
</option>
|
||||||
|
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1563375529" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
|
||||||
|
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||||
|
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||||
|
</inputType>
|
||||||
|
</tool>
|
||||||
|
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.142079573" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"/>
|
||||||
|
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.2048185446" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
||||||
|
<tool command="${AS}" id="cdt.managedbuild.tool.gnu.cross.assembler.1249241851" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
||||||
|
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.558119385" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||||
|
</tool>
|
||||||
|
</toolChain>
|
||||||
|
</folderInfo>
|
||||||
|
</configuration>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||||
|
</cconfiguration>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||||
|
<project id="cairo.cdt.managedbuild.target.gnu.cross.exe.1794891953" name="Executable" projectType="cdt.managedbuild.target.gnu.cross.exe"/>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="scannerConfiguration">
|
||||||
|
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||||
|
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.1978501621;cdt.managedbuild.config.gnu.cross.exe.debug.1978501621.;cdt.managedbuild.tool.gnu.cross.c.compiler.1376072995;cdt.managedbuild.tool.gnu.c.compiler.input.259154356">
|
||||||
|
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||||
|
</scannerConfigBuildInfo>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||||
|
<storageModule moduleId="refreshScope"/>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||||
|
</cproject>
|
1
cairo/.gitignore
vendored
Normal file
1
cairo/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/Debug/
|
26
cairo/.project
Normal file
26
cairo/.project
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>cairo</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||||
|
<triggers>clean,full,incremental,</triggers>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||||
|
<triggers>full,incremental,</triggers>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||||
|
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||||
|
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
14
cairo/.settings/language.settings.xml
Normal file
14
cairo/.settings/language.settings.xml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<project>
|
||||||
|
<configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.1978501621" name="Debug">
|
||||||
|
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||||
|
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||||
|
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
|
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
|
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="643270697067650404" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||||
|
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||||
|
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||||
|
</provider>
|
||||||
|
</extension>
|
||||||
|
</configuration>
|
||||||
|
</project>
|
174
cairo/cairo.c
Normal file
174
cairo/cairo.c
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/ioctl.h>
|
||||||
|
#include <linux/fb.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <cairo/cairo.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#define DELAY_IN_SECS 5
|
||||||
|
#define SCALE_WIDTH 256.0
|
||||||
|
#define SCALE_HEIGHT 256.0
|
||||||
|
|
||||||
|
typedef struct _cairo_linuxfb_device {
|
||||||
|
int fb_fd;
|
||||||
|
unsigned char *fb_data;
|
||||||
|
long fb_screensize;
|
||||||
|
struct fb_var_screeninfo fb_vinfo;
|
||||||
|
struct fb_fix_screeninfo fb_finfo;
|
||||||
|
} cairo_linuxfb_device_t;
|
||||||
|
|
||||||
|
/* Destroy a cairo surface */
|
||||||
|
void cairo_linuxfb_surface_destroy(void *device)
|
||||||
|
{
|
||||||
|
cairo_linuxfb_device_t *dev = (cairo_linuxfb_device_t *)device;
|
||||||
|
|
||||||
|
if (dev == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
munmap(dev->fb_data, dev->fb_screensize);
|
||||||
|
close(dev->fb_fd);
|
||||||
|
free(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a cairo surface using the specified framebuffer */
|
||||||
|
cairo_surface_t *cairo_linuxfb_surface_create(const char *fb_name)
|
||||||
|
{
|
||||||
|
cairo_linuxfb_device_t *device;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
|
||||||
|
/* Use fb0 if no fram buffer is specified */
|
||||||
|
if (fb_name == NULL) {
|
||||||
|
fb_name = "/dev/fb0";
|
||||||
|
}
|
||||||
|
|
||||||
|
device = malloc(sizeof(*device));
|
||||||
|
if (!device) {
|
||||||
|
perror("Error: cannot allocate memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file for reading and writing
|
||||||
|
device->fb_fd = open(fb_name, O_RDWR);
|
||||||
|
if (device->fb_fd == -1) {
|
||||||
|
perror("Error: cannot open framebuffer device");
|
||||||
|
goto handle_allocate_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get variable screen information
|
||||||
|
if (ioctl(device->fb_fd, FBIOGET_VSCREENINFO, &device->fb_vinfo) == -1) {
|
||||||
|
perror("Error: reading variable information");
|
||||||
|
goto handle_ioctl_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out the size of the screen in bytes
|
||||||
|
device->fb_screensize = device->fb_vinfo.xres * device->fb_vinfo.yres
|
||||||
|
* device->fb_vinfo.bits_per_pixel / 8;
|
||||||
|
|
||||||
|
// Map the device to memory
|
||||||
|
device->fb_data = (unsigned char *)mmap(0, device->fb_screensize,
|
||||||
|
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
device->fb_fd, 0);
|
||||||
|
if ((int)device->fb_data == -1) {
|
||||||
|
perror("Error: failed to map framebuffer device to memory");
|
||||||
|
goto handle_ioctl_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get fixed screen information
|
||||||
|
if (ioctl(device->fb_fd, FBIOGET_FSCREENINFO, &device->fb_finfo) == -1) {
|
||||||
|
perror("Error reading fixed information");
|
||||||
|
goto handle_ioctl_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the cairo surface which will be used to draw to */
|
||||||
|
surface = cairo_image_surface_create_for_data(device->fb_data,
|
||||||
|
CAIRO_FORMAT_RGB16_565,
|
||||||
|
device->fb_vinfo.xres,
|
||||||
|
device->fb_vinfo.yres,
|
||||||
|
cairo_format_stride_for_width(CAIRO_FORMAT_RGB16_565,
|
||||||
|
device->fb_vinfo.xres));
|
||||||
|
cairo_surface_set_user_data(surface, NULL, device,
|
||||||
|
&cairo_linuxfb_surface_destroy);
|
||||||
|
|
||||||
|
return surface;
|
||||||
|
|
||||||
|
handle_ioctl_error:
|
||||||
|
close(device->fb_fd);
|
||||||
|
handle_allocate_error:
|
||||||
|
free(device);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int image_width;
|
||||||
|
int image_height;
|
||||||
|
char frame_buffer_number;
|
||||||
|
char fb_node[16] = {0};
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_surface_t *image;
|
||||||
|
cairo_t *cr;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: ./cairo /path/to/png/image\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], ".png") == NULL) {
|
||||||
|
printf("Only png images are supported with this example\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Enter frame buffer number:\t");
|
||||||
|
scanf("%c", &frame_buffer_number);
|
||||||
|
sprintf(fb_node, "/dev/fb");
|
||||||
|
fb_node[strlen(fb_node)] = frame_buffer_number;
|
||||||
|
fb_node[strlen(fb_node)] = '\0';
|
||||||
|
printf("Frame buffer node is: %s\n", fb_node);
|
||||||
|
|
||||||
|
surface = cairo_linuxfb_surface_create(fb_node);
|
||||||
|
cr = cairo_create(surface);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We clear the cairo surface here before drawing
|
||||||
|
* This is required in case something was drawn on this surface
|
||||||
|
* previously, the previous contents would not be cleared without this.
|
||||||
|
*/
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
|
||||||
|
cairo_paint(cr);
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||||
|
|
||||||
|
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
||||||
|
cairo_set_font_size(cr, 32.0);
|
||||||
|
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
|
||||||
|
cairo_move_to(cr, 100, 300);
|
||||||
|
cairo_show_text(cr, "Toradex Cairo Example!");
|
||||||
|
|
||||||
|
/* Wait for the result of drawing operation to persist for the user to see */
|
||||||
|
sleep(DELAY_IN_SECS);
|
||||||
|
/* Clear the surface and prepare for a new drawing operation */
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
|
||||||
|
cairo_paint(cr);
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||||
|
|
||||||
|
image = cairo_image_surface_create_from_png(argv[1]);
|
||||||
|
image_width = cairo_image_surface_get_width(image);
|
||||||
|
image_height = cairo_image_surface_get_height(image);
|
||||||
|
|
||||||
|
/* Scale the image arbitrarily */
|
||||||
|
cairo_scale(cr, SCALE_WIDTH/image_width, SCALE_HEIGHT/image_height);
|
||||||
|
|
||||||
|
cairo_set_source_surface(cr, image, 350, 200);
|
||||||
|
cairo_paint(cr);
|
||||||
|
/* Wait for the result of the drawing operation to persist for the user to see */
|
||||||
|
sleep(DELAY_IN_SECS);
|
||||||
|
|
||||||
|
/* Destroy and release all cairo related contexts */
|
||||||
|
cairo_destroy(cr);
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue