OpenVG 1.0 State Tracker

Import of the OpenVG 1.0 state tracker for Gallium.
This commit is contained in:
Zack Rusin 2009-05-01 12:41:38 -04:00
parent fbceedd2de
commit 544dd4b11f
86 changed files with 24891 additions and 0 deletions

48
docs/openvg.html Normal file
View File

@ -0,0 +1,48 @@
<HTML>
<TITLE>Mesa Release Notes</TITLE>
<head><link rel="stylesheet" type="text/css" href="mesa.css"></head>
<BODY>
<body bgcolor="#eeeeee">
<H1>OpenVG State Tracker</H1>
<p>
The current version of the OpenVG state tracker implements OpenVG 1.0.
</p>
<p>
More informations about OpenVG can be found at <a href="http://www.khronos.org/openvg/">http://www.khronos.org/openvg/</a> .
</p>
<p>
The OpenVG state tracker depends on the Gallium architecture and a working EGL implementation.
</p>
<h2>Building the library</h2>
<ol>
<li>Build Mesa3D with Gallium3D. Any build that builds Gallium3D libraries and EGL will suffice</li>
<li>cd src/gallium/state_trackers/vega; make</li>
<li>The last step will build libOpenVG library. You can add the libdir to LD_LIBRARY_PATH or install libOpenVG</li>
</ol>
<h3>Sample build</h3>
A sample build looks as follows:
<pre>
make linux-x86-64-debug
cd src/gallium/state_trackers/vega
make
cd ../../../..
export LD_LIBRARY_PATH=$PWD/lib64
export EGL_DRIVER="egl_softpipe"
</pre>
<h2>Notes</h2>
<ul>
<li>EGL_DRIVER environmental variable: forces usage of a specific EGL driver. Unless you force egl_softpipe the implementation will look for a DRI hardware accelerate driver and unless you have a Gallium driver that supports it, you'll see crashes</li>
</ul>
</body>
</html>

686
include/VG/openvg.h Normal file
View File

@ -0,0 +1,686 @@
/* $Revision: 6822 $ on $Date:: 2008-10-30 05:14:19 -0400 #$ */
/*------------------------------------------------------------------------
*
* OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2008 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*//**
* \file
* \brief OpenVG 1.0.1 API.
*//*-------------------------------------------------------------------*/
#ifndef _OPENVG_H
#define _OPENVG_H
#include <VG/vgplatform.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OPENVG_VERSION_1_0 1
#define OPENVG_VERSION_1_0_1 1
#ifndef VG_MAXSHORT
#define VG_MAXSHORT 0x7FFF
#endif
#ifndef VG_MAXINT
#define VG_MAXINT 0x7FFFFFFF
#endif
#ifndef VG_MAX_ENUM
#define VG_MAX_ENUM 0x7FFFFFFF
#endif
typedef long VGHandle;
typedef VGHandle VGPath;
typedef VGHandle VGImage;
typedef VGHandle VGPaint;
#define VG_INVALID_HANDLE ((VGHandle)0)
typedef enum {
VG_FALSE = 0,
VG_TRUE = 1,
VG_BOOLEAN_FORCE_SIZE = VG_MAX_ENUM
} VGboolean;
typedef enum {
VG_NO_ERROR = 0,
VG_BAD_HANDLE_ERROR = 0x1000,
VG_ILLEGAL_ARGUMENT_ERROR = 0x1001,
VG_OUT_OF_MEMORY_ERROR = 0x1002,
VG_PATH_CAPABILITY_ERROR = 0x1003,
VG_UNSUPPORTED_IMAGE_FORMAT_ERROR = 0x1004,
VG_UNSUPPORTED_PATH_FORMAT_ERROR = 0x1005,
VG_IMAGE_IN_USE_ERROR = 0x1006,
VG_NO_CONTEXT_ERROR = 0x1007,
VG_ERROR_CODE_FORCE_SIZE = VG_MAX_ENUM
} VGErrorCode;
typedef enum {
/* Mode settings */
VG_MATRIX_MODE = 0x1100,
VG_FILL_RULE = 0x1101,
VG_IMAGE_QUALITY = 0x1102,
VG_RENDERING_QUALITY = 0x1103,
VG_BLEND_MODE = 0x1104,
VG_IMAGE_MODE = 0x1105,
/* Scissoring rectangles */
VG_SCISSOR_RECTS = 0x1106,
/* Stroke parameters */
VG_STROKE_LINE_WIDTH = 0x1110,
VG_STROKE_CAP_STYLE = 0x1111,
VG_STROKE_JOIN_STYLE = 0x1112,
VG_STROKE_MITER_LIMIT = 0x1113,
VG_STROKE_DASH_PATTERN = 0x1114,
VG_STROKE_DASH_PHASE = 0x1115,
VG_STROKE_DASH_PHASE_RESET = 0x1116,
/* Edge fill color for VG_TILE_FILL tiling mode */
VG_TILE_FILL_COLOR = 0x1120,
/* Color for vgClear */
VG_CLEAR_COLOR = 0x1121,
/* Enable/disable alpha masking and scissoring */
VG_MASKING = 0x1130,
VG_SCISSORING = 0x1131,
/* Pixel layout information */
VG_PIXEL_LAYOUT = 0x1140,
VG_SCREEN_LAYOUT = 0x1141,
/* Source format selection for image filters */
VG_FILTER_FORMAT_LINEAR = 0x1150,
VG_FILTER_FORMAT_PREMULTIPLIED = 0x1151,
/* Destination write enable mask for image filters */
VG_FILTER_CHANNEL_MASK = 0x1152,
/* Implementation limits (read-only) */
VG_MAX_SCISSOR_RECTS = 0x1160,
VG_MAX_DASH_COUNT = 0x1161,
VG_MAX_KERNEL_SIZE = 0x1162,
VG_MAX_SEPARABLE_KERNEL_SIZE = 0x1163,
VG_MAX_COLOR_RAMP_STOPS = 0x1164,
VG_MAX_IMAGE_WIDTH = 0x1165,
VG_MAX_IMAGE_HEIGHT = 0x1166,
VG_MAX_IMAGE_PIXELS = 0x1167,
VG_MAX_IMAGE_BYTES = 0x1168,
VG_MAX_FLOAT = 0x1169,
VG_MAX_GAUSSIAN_STD_DEVIATION = 0x116A,
VG_PARAM_TYPE_FORCE_SIZE = VG_MAX_ENUM
} VGParamType;
typedef enum {
VG_RENDERING_QUALITY_NONANTIALIASED = 0x1200,
VG_RENDERING_QUALITY_FASTER = 0x1201,
VG_RENDERING_QUALITY_BETTER = 0x1202, /* Default */
VG_RENDERING_QUALITY_FORCE_SIZE = VG_MAX_ENUM
} VGRenderingQuality;
typedef enum {
VG_PIXEL_LAYOUT_UNKNOWN = 0x1300,
VG_PIXEL_LAYOUT_RGB_VERTICAL = 0x1301,
VG_PIXEL_LAYOUT_BGR_VERTICAL = 0x1302,
VG_PIXEL_LAYOUT_RGB_HORIZONTAL = 0x1303,
VG_PIXEL_LAYOUT_BGR_HORIZONTAL = 0x1304,
VG_PIXEL_LAYOUT_FORCE_SIZE = VG_MAX_ENUM
} VGPixelLayout;
typedef enum {
VG_MATRIX_PATH_USER_TO_SURFACE = 0x1400,
VG_MATRIX_IMAGE_USER_TO_SURFACE = 0x1401,
VG_MATRIX_FILL_PAINT_TO_USER = 0x1402,
VG_MATRIX_STROKE_PAINT_TO_USER = 0x1403,
VG_MATRIX_MODE_FORCE_SIZE = VG_MAX_ENUM
} VGMatrixMode;
typedef enum {
VG_CLEAR_MASK = 0x1500,
VG_FILL_MASK = 0x1501,
VG_SET_MASK = 0x1502,
VG_UNION_MASK = 0x1503,
VG_INTERSECT_MASK = 0x1504,
VG_SUBTRACT_MASK = 0x1505,
VG_MASK_OPERATION_FORCE_SIZE = VG_MAX_ENUM
} VGMaskOperation;
#define VG_PATH_FORMAT_STANDARD 0
typedef enum {
VG_PATH_DATATYPE_S_8 = 0,
VG_PATH_DATATYPE_S_16 = 1,
VG_PATH_DATATYPE_S_32 = 2,
VG_PATH_DATATYPE_F = 3,
VG_PATH_DATATYPE_FORCE_SIZE = VG_MAX_ENUM
} VGPathDatatype;
typedef enum {
VG_ABSOLUTE = 0,
VG_RELATIVE = 1,
VG_PATH_ABS_REL_FORCE_SIZE = VG_MAX_ENUM
} VGPathAbsRel;
typedef enum {
VG_CLOSE_PATH = ( 0 << 1),
VG_MOVE_TO = ( 1 << 1),
VG_LINE_TO = ( 2 << 1),
VG_HLINE_TO = ( 3 << 1),
VG_VLINE_TO = ( 4 << 1),
VG_QUAD_TO = ( 5 << 1),
VG_CUBIC_TO = ( 6 << 1),
VG_SQUAD_TO = ( 7 << 1),
VG_SCUBIC_TO = ( 8 << 1),
VG_SCCWARC_TO = ( 9 << 1),
VG_SCWARC_TO = (10 << 1),
VG_LCCWARC_TO = (11 << 1),
VG_LCWARC_TO = (12 << 1),
VG_PATH_SEGMENT_FORCE_SIZE = VG_MAX_ENUM
} VGPathSegment;
typedef enum {
VG_MOVE_TO_ABS = VG_MOVE_TO | VG_ABSOLUTE,
VG_MOVE_TO_REL = VG_MOVE_TO | VG_RELATIVE,
VG_LINE_TO_ABS = VG_LINE_TO | VG_ABSOLUTE,
VG_LINE_TO_REL = VG_LINE_TO | VG_RELATIVE,
VG_HLINE_TO_ABS = VG_HLINE_TO | VG_ABSOLUTE,
VG_HLINE_TO_REL = VG_HLINE_TO | VG_RELATIVE,
VG_VLINE_TO_ABS = VG_VLINE_TO | VG_ABSOLUTE,
VG_VLINE_TO_REL = VG_VLINE_TO | VG_RELATIVE,
VG_QUAD_TO_ABS = VG_QUAD_TO | VG_ABSOLUTE,
VG_QUAD_TO_REL = VG_QUAD_TO | VG_RELATIVE,
VG_CUBIC_TO_ABS = VG_CUBIC_TO | VG_ABSOLUTE,
VG_CUBIC_TO_REL = VG_CUBIC_TO | VG_RELATIVE,
VG_SQUAD_TO_ABS = VG_SQUAD_TO | VG_ABSOLUTE,
VG_SQUAD_TO_REL = VG_SQUAD_TO | VG_RELATIVE,
VG_SCUBIC_TO_ABS = VG_SCUBIC_TO | VG_ABSOLUTE,
VG_SCUBIC_TO_REL = VG_SCUBIC_TO | VG_RELATIVE,
VG_SCCWARC_TO_ABS = VG_SCCWARC_TO | VG_ABSOLUTE,
VG_SCCWARC_TO_REL = VG_SCCWARC_TO | VG_RELATIVE,
VG_SCWARC_TO_ABS = VG_SCWARC_TO | VG_ABSOLUTE,
VG_SCWARC_TO_REL = VG_SCWARC_TO | VG_RELATIVE,
VG_LCCWARC_TO_ABS = VG_LCCWARC_TO | VG_ABSOLUTE,
VG_LCCWARC_TO_REL = VG_LCCWARC_TO | VG_RELATIVE,
VG_LCWARC_TO_ABS = VG_LCWARC_TO | VG_ABSOLUTE,
VG_LCWARC_TO_REL = VG_LCWARC_TO | VG_RELATIVE,
VG_PATH_COMMAND_FORCE_SIZE = VG_MAX_ENUM
} VGPathCommand;
typedef enum {
VG_PATH_CAPABILITY_APPEND_FROM = (1 << 0),
VG_PATH_CAPABILITY_APPEND_TO = (1 << 1),
VG_PATH_CAPABILITY_MODIFY = (1 << 2),
VG_PATH_CAPABILITY_TRANSFORM_FROM = (1 << 3),
VG_PATH_CAPABILITY_TRANSFORM_TO = (1 << 4),
VG_PATH_CAPABILITY_INTERPOLATE_FROM = (1 << 5),
VG_PATH_CAPABILITY_INTERPOLATE_TO = (1 << 6),
VG_PATH_CAPABILITY_PATH_LENGTH = (1 << 7),
VG_PATH_CAPABILITY_POINT_ALONG_PATH = (1 << 8),
VG_PATH_CAPABILITY_TANGENT_ALONG_PATH = (1 << 9),
VG_PATH_CAPABILITY_PATH_BOUNDS = (1 << 10),
VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS = (1 << 11),
VG_PATH_CAPABILITY_ALL = (1 << 12) - 1,
VG_PATH_CAPABILITIES_FORCE_SIZE = VG_MAX_ENUM
} VGPathCapabilities;
typedef enum {
VG_PATH_FORMAT = 0x1600,
VG_PATH_DATATYPE = 0x1601,
VG_PATH_SCALE = 0x1602,
VG_PATH_BIAS = 0x1603,
VG_PATH_NUM_SEGMENTS = 0x1604,
VG_PATH_NUM_COORDS = 0x1605,
VG_PATH_PARAM_TYPE_FORCE_SIZE = VG_MAX_ENUM
} VGPathParamType;
typedef enum {
VG_CAP_BUTT = 0x1700,
VG_CAP_ROUND = 0x1701,
VG_CAP_SQUARE = 0x1702,
VG_CAP_STYLE_FORCE_SIZE = VG_MAX_ENUM
} VGCapStyle;
typedef enum {
VG_JOIN_MITER = 0x1800,
VG_JOIN_ROUND = 0x1801,
VG_JOIN_BEVEL = 0x1802,
VG_JOIN_STYLE_FORCE_SIZE = VG_MAX_ENUM
} VGJoinStyle;
typedef enum {
VG_EVEN_ODD = 0x1900,
VG_NON_ZERO = 0x1901,
VG_FILL_RULE_FORCE_SIZE = VG_MAX_ENUM
} VGFillRule;
typedef enum {
VG_STROKE_PATH = (1 << 0),
VG_FILL_PATH = (1 << 1),
VG_PAINT_MODE_FORCE_SIZE = VG_MAX_ENUM
} VGPaintMode;
typedef enum {
/* Color paint parameters */
VG_PAINT_TYPE = 0x1A00,
VG_PAINT_COLOR = 0x1A01,
VG_PAINT_COLOR_RAMP_SPREAD_MODE = 0x1A02,
VG_PAINT_COLOR_RAMP_PREMULTIPLIED = 0x1A07,
VG_PAINT_COLOR_RAMP_STOPS = 0x1A03,
/* Linear gradient paint parameters */
VG_PAINT_LINEAR_GRADIENT = 0x1A04,
/* Radial gradient paint parameters */
VG_PAINT_RADIAL_GRADIENT = 0x1A05,
/* Pattern paint parameters */
VG_PAINT_PATTERN_TILING_MODE = 0x1A06,
VG_PAINT_PARAM_TYPE_FORCE_SIZE = VG_MAX_ENUM
} VGPaintParamType;
typedef enum {
VG_PAINT_TYPE_COLOR = 0x1B00,
VG_PAINT_TYPE_LINEAR_GRADIENT = 0x1B01,
VG_PAINT_TYPE_RADIAL_GRADIENT = 0x1B02,
VG_PAINT_TYPE_PATTERN = 0x1B03,
VG_PAINT_TYPE_FORCE_SIZE = VG_MAX_ENUM
} VGPaintType;
typedef enum {
VG_COLOR_RAMP_SPREAD_PAD = 0x1C00,
VG_COLOR_RAMP_SPREAD_REPEAT = 0x1C01,
VG_COLOR_RAMP_SPREAD_REFLECT = 0x1C02,
VG_COLOR_RAMP_SPREAD_MODE_FORCE_SIZE = VG_MAX_ENUM
} VGColorRampSpreadMode;
typedef enum {
VG_TILE_FILL = 0x1D00,
VG_TILE_PAD = 0x1D01,
VG_TILE_REPEAT = 0x1D02,
VG_TILE_REFLECT = 0x1D03,
VG_TILING_MODE_FORCE_SIZE = VG_MAX_ENUM
} VGTilingMode;
typedef enum {
/* RGB{A,X} channel ordering */
VG_sRGBX_8888 = 0,
VG_sRGBA_8888 = 1,
VG_sRGBA_8888_PRE = 2,
VG_sRGB_565 = 3,
VG_sRGBA_5551 = 4,
VG_sRGBA_4444 = 5,
VG_sL_8 = 6,
VG_lRGBX_8888 = 7,
VG_lRGBA_8888 = 8,
VG_lRGBA_8888_PRE = 9,
VG_lL_8 = 10,
VG_A_8 = 11,
VG_BW_1 = 12,
/* {A,X}RGB channel ordering */
VG_sXRGB_8888 = 0 | (1 << 6),
VG_sARGB_8888 = 1 | (1 << 6),
VG_sARGB_8888_PRE = 2 | (1 << 6),
VG_sARGB_1555 = 4 | (1 << 6),
VG_sARGB_4444 = 5 | (1 << 6),
VG_lXRGB_8888 = 7 | (1 << 6),
VG_lARGB_8888 = 8 | (1 << 6),
VG_lARGB_8888_PRE = 9 | (1 << 6),
/* BGR{A,X} channel ordering */
VG_sBGRX_8888 = 0 | (1 << 7),
VG_sBGRA_8888 = 1 | (1 << 7),
VG_sBGRA_8888_PRE = 2 | (1 << 7),
VG_sBGR_565 = 3 | (1 << 7),
VG_sBGRA_5551 = 4 | (1 << 7),
VG_sBGRA_4444 = 5 | (1 << 7),
VG_lBGRX_8888 = 7 | (1 << 7),
VG_lBGRA_8888 = 8 | (1 << 7),
VG_lBGRA_8888_PRE = 9 | (1 << 7),
/* {A,X}BGR channel ordering */
VG_sXBGR_8888 = 0 | (1 << 6) | (1 << 7),
VG_sABGR_8888 = 1 | (1 << 6) | (1 << 7),
VG_sABGR_8888_PRE = 2 | (1 << 6) | (1 << 7),
VG_sABGR_1555 = 4 | (1 << 6) | (1 << 7),
VG_sABGR_4444 = 5 | (1 << 6) | (1 << 7),
VG_lXBGR_8888 = 7 | (1 << 6) | (1 << 7),
VG_lABGR_8888 = 8 | (1 << 6) | (1 << 7),
VG_lABGR_8888_PRE = 9 | (1 << 6) | (1 << 7),
VG_IMAGE_FORMAT_FORCE_SIZE = VG_MAX_ENUM
} VGImageFormat;
typedef enum {
VG_IMAGE_QUALITY_NONANTIALIASED = (1 << 0),
VG_IMAGE_QUALITY_FASTER = (1 << 1),
VG_IMAGE_QUALITY_BETTER = (1 << 2),
VG_IMAGE_QUALITY_FORCE_SIZE = VG_MAX_ENUM
} VGImageQuality;
typedef enum {
VG_IMAGE_FORMAT = 0x1E00,
VG_IMAGE_WIDTH = 0x1E01,
VG_IMAGE_HEIGHT = 0x1E02,
VG_IMAGE_PARAM_TYPE_FORCE_SIZE = VG_MAX_ENUM
} VGImageParamType;
typedef enum {
VG_DRAW_IMAGE_NORMAL = 0x1F00,
VG_DRAW_IMAGE_MULTIPLY = 0x1F01,
VG_DRAW_IMAGE_STENCIL = 0x1F02,
VG_IMAGE_MODE_FORCE_SIZE = VG_MAX_ENUM
} VGImageMode;
typedef enum {
VG_RED = (1 << 3),
VG_GREEN = (1 << 2),
VG_BLUE = (1 << 1),
VG_ALPHA = (1 << 0),
VG_IMAGE_CHANNEL_FORCE_SIZE = VG_MAX_ENUM
} VGImageChannel;
typedef enum {
VG_BLEND_SRC = 0x2000,
VG_BLEND_SRC_OVER = 0x2001,
VG_BLEND_DST_OVER = 0x2002,
VG_BLEND_SRC_IN = 0x2003,
VG_BLEND_DST_IN = 0x2004,
VG_BLEND_MULTIPLY = 0x2005,
VG_BLEND_SCREEN = 0x2006,
VG_BLEND_DARKEN = 0x2007,
VG_BLEND_LIGHTEN = 0x2008,
VG_BLEND_ADDITIVE = 0x2009,
VG_BLEND_MODE_FORCE_SIZE = VG_MAX_ENUM
} VGBlendMode;
typedef enum {
VG_IMAGE_FORMAT_QUERY = 0x2100,
VG_PATH_DATATYPE_QUERY = 0x2101,
VG_HARDWARE_QUERY_TYPE_FORCE_SIZE = VG_MAX_ENUM
} VGHardwareQueryType;
typedef enum {
VG_HARDWARE_ACCELERATED = 0x2200,
VG_HARDWARE_UNACCELERATED = 0x2201,
VG_HARDWARE_QUERY_RESULT_FORCE_SIZE = VG_MAX_ENUM
} VGHardwareQueryResult;
typedef enum {
VG_VENDOR = 0x2300,
VG_RENDERER = 0x2301,
VG_VERSION = 0x2302,
VG_EXTENSIONS = 0x2303,
VG_STRING_ID_FORCE_SIZE = VG_MAX_ENUM
} VGStringID;
/* Function Prototypes */
#ifndef VG_API_CALL
# error VG_API_CALL must be defined
#endif
#ifndef VG_API_ENTRY
# error VG_API_ENTRY must be defined
#endif
#ifndef VG_API_EXIT
# error VG_API_EXIT must be defined
#endif
VG_API_CALL VGErrorCode VG_API_ENTRY vgGetError(void) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgFlush(void) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgFinish(void) VG_API_EXIT;
/* Getters and Setters */
VG_API_CALL void VG_API_ENTRY vgSetf (VGParamType type, VGfloat value) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSeti (VGParamType type, VGint value) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetfv(VGParamType type, VGint count,
const VGfloat * values) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetiv(VGParamType type, VGint count,
const VGint * values) VG_API_EXIT;
VG_API_CALL VGfloat VG_API_ENTRY vgGetf(VGParamType type) VG_API_EXIT;
VG_API_CALL VGint VG_API_ENTRY vgGeti(VGParamType type) VG_API_EXIT;
VG_API_CALL VGint VG_API_ENTRY vgGetVectorSize(VGParamType type) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGetfv(VGParamType type, VGint count, VGfloat * values) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGetiv(VGParamType type, VGint count, VGint * values) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetParameterf(VGHandle object,
VGint paramType,
VGfloat value) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetParameteri(VGHandle object,
VGint paramType,
VGint value) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetParameterfv(VGHandle object,
VGint paramType,
VGint count, const VGfloat * values) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetParameteriv(VGHandle object,
VGint paramType,
VGint count, const VGint * values) VG_API_EXIT;
VG_API_CALL VGfloat VG_API_ENTRY vgGetParameterf(VGHandle object,
VGint paramType) VG_API_EXIT;
VG_API_CALL VGint VG_API_ENTRY vgGetParameteri(VGHandle object,
VGint paramType);
VG_API_CALL VGint VG_API_ENTRY vgGetParameterVectorSize(VGHandle object,
VGint paramType) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGetParameterfv(VGHandle object,
VGint paramType,
VGint count, VGfloat * values) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGetParameteriv(VGHandle object,
VGint paramType,
VGint count, VGint * values) VG_API_EXIT;
/* Matrix Manipulation */
VG_API_CALL void VG_API_ENTRY vgLoadIdentity(void) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgLoadMatrix(const VGfloat * m) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGetMatrix(VGfloat * m) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgMultMatrix(const VGfloat * m) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgTranslate(VGfloat tx, VGfloat ty) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgScale(VGfloat sx, VGfloat sy) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgShear(VGfloat shx, VGfloat shy) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgRotate(VGfloat angle) VG_API_EXIT;
/* Masking and Clearing */
VG_API_CALL void VG_API_ENTRY vgMask(VGImage mask, VGMaskOperation operation,
VGint x, VGint y, VGint width, VGint height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgClear(VGint x, VGint y, VGint width, VGint height) VG_API_EXIT;
/* Paths */
VG_API_CALL VGPath VG_API_ENTRY vgCreatePath(VGint pathFormat,
VGPathDatatype datatype,
VGfloat scale, VGfloat bias,
VGint segmentCapacityHint,
VGint coordCapacityHint,
VGbitfield capabilities) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgClearPath(VGPath path, VGbitfield capabilities) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgDestroyPath(VGPath path) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgRemovePathCapabilities(VGPath path,
VGbitfield capabilities) VG_API_EXIT;
VG_API_CALL VGbitfield VG_API_ENTRY vgGetPathCapabilities(VGPath path) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgAppendPath(VGPath dstPath, VGPath srcPath) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgAppendPathData(VGPath dstPath,
VGint numSegments,
const VGubyte * pathSegments,
const void * pathData) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgModifyPathCoords(VGPath dstPath, VGint startIndex,
VGint numSegments,
const void * pathData) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgTransformPath(VGPath dstPath, VGPath srcPath) VG_API_EXIT;
VG_API_CALL VGboolean VG_API_ENTRY vgInterpolatePath(VGPath dstPath,
VGPath startPath,
VGPath endPath,
VGfloat amount) VG_API_EXIT;
VG_API_CALL VGfloat VG_API_ENTRY vgPathLength(VGPath path,
VGint startSegment, VGint numSegments) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgPointAlongPath(VGPath path,
VGint startSegment, VGint numSegments,
VGfloat distance,
VGfloat * x, VGfloat * y,
VGfloat * tangentX, VGfloat * tangentY) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgPathBounds(VGPath path,
VGfloat * minX, VGfloat * minY,
VGfloat * width, VGfloat * height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgPathTransformedBounds(VGPath path,
VGfloat * minX, VGfloat * minY,
VGfloat * width, VGfloat * height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgDrawPath(VGPath path, VGbitfield paintModes) VG_API_EXIT;
/* Paint */
VG_API_CALL VGPaint VG_API_ENTRY vgCreatePaint(void) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgDestroyPaint(VGPaint paint) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetPaint(VGPaint paint, VGbitfield paintModes) VG_API_EXIT;
VG_API_CALL VGPaint VG_API_ENTRY vgGetPaint(VGPaintMode paintMode) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetColor(VGPaint paint, VGuint rgba) VG_API_EXIT;
VG_API_CALL VGuint VG_API_ENTRY vgGetColor(VGPaint paint) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgPaintPattern(VGPaint paint, VGImage pattern) VG_API_EXIT;
/* Images */
VG_API_CALL VGImage VG_API_ENTRY vgCreateImage(VGImageFormat format,
VGint width, VGint height,
VGbitfield allowedQuality) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgDestroyImage(VGImage image) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgClearImage(VGImage image,
VGint x, VGint y, VGint width, VGint height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgImageSubData(VGImage image,
const void * data, VGint dataStride,
VGImageFormat dataFormat,
VGint x, VGint y, VGint width, VGint height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGetImageSubData(VGImage image,
void * data, VGint dataStride,
VGImageFormat dataFormat,
VGint x, VGint y,
VGint width, VGint height) VG_API_EXIT;
VG_API_CALL VGImage VG_API_ENTRY vgChildImage(VGImage parent,
VGint x, VGint y, VGint width, VGint height) VG_API_EXIT;
VG_API_CALL VGImage VG_API_ENTRY vgGetParent(VGImage image) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgCopyImage(VGImage dst, VGint dx, VGint dy,
VGImage src, VGint sx, VGint sy,
VGint width, VGint height,
VGboolean dither) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgDrawImage(VGImage image) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSetPixels(VGint dx, VGint dy,
VGImage src, VGint sx, VGint sy,
VGint width, VGint height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgWritePixels(const void * data, VGint dataStride,
VGImageFormat dataFormat,
VGint dx, VGint dy,
VGint width, VGint height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGetPixels(VGImage dst, VGint dx, VGint dy,
VGint sx, VGint sy,
VGint width, VGint height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgReadPixels(void * data, VGint dataStride,
VGImageFormat dataFormat,
VGint sx, VGint sy,
VGint width, VGint height) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgCopyPixels(VGint dx, VGint dy,
VGint sx, VGint sy,
VGint width, VGint height) VG_API_EXIT;
/* Image Filters */
VG_API_CALL void VG_API_ENTRY vgColorMatrix(VGImage dst, VGImage src,
const VGfloat * matrix) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgConvolve(VGImage dst, VGImage src,
VGint kernelWidth, VGint kernelHeight,
VGint shiftX, VGint shiftY,
const VGshort * kernel,
VGfloat scale,
VGfloat bias,
VGTilingMode tilingMode) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgSeparableConvolve(VGImage dst, VGImage src,
VGint kernelWidth,
VGint kernelHeight,
VGint shiftX, VGint shiftY,
const VGshort * kernelX,
const VGshort * kernelY,
VGfloat scale,
VGfloat bias,
VGTilingMode tilingMode) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgGaussianBlur(VGImage dst, VGImage src,
VGfloat stdDeviationX,
VGfloat stdDeviationY,
VGTilingMode tilingMode) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgLookup(VGImage dst, VGImage src,
const VGubyte * redLUT,
const VGubyte * greenLUT,
const VGubyte * blueLUT,
const VGubyte * alphaLUT,
VGboolean outputLinear,
VGboolean outputPremultiplied) VG_API_EXIT;
VG_API_CALL void VG_API_ENTRY vgLookupSingle(VGImage dst, VGImage src,
const VGuint * lookupTable,
VGImageChannel sourceChannel,
VGboolean outputLinear,
VGboolean outputPremultiplied) VG_API_EXIT;
/* Hardware Queries */
VG_API_CALL VGHardwareQueryResult VG_API_ENTRY vgHardwareQuery(VGHardwareQueryType key,
VGint setting) VG_API_EXIT;
/* Renderer and Extension Information */
VG_API_CALL const VGubyte * VG_API_ENTRY vgGetString(VGStringID name) VG_API_EXIT;
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _OPENVG_H */

233
include/VG/vgext.h Normal file
View File

@ -0,0 +1,233 @@
/* $Revision: 6810 $ on $Date:: 2008-10-29 10:31:37 -0400 #$ */
/*------------------------------------------------------------------------
*
* VG extensions Reference Implementation
* -------------------------------------
*
* Copyright (c) 2008 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*//**
* \file
* \brief VG extensions
*//*-------------------------------------------------------------------*/
#ifndef _VGEXT_H
#define _VGEXT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <VG/openvg.h>
#include <VG/vgu.h>
#ifndef VG_API_ENTRYP
# define VG_API_ENTRYP VG_API_ENTRY*
#endif
#ifndef VGU_API_ENTRYP
# define VGU_API_ENTRYP VGU_API_ENTRY*
#endif
/*-------------------------------------------------------------------------------
* KHR extensions
*------------------------------------------------------------------------------*/
typedef enum {
#ifndef VG_KHR_iterative_average_blur
VG_MAX_AVERAGE_BLUR_DIMENSION_KHR = 0x116B,
VG_AVERAGE_BLUR_DIMENSION_RESOLUTION_KHR = 0x116C,
VG_MAX_AVERAGE_BLUR_ITERATIONS_KHR = 0x116D,
#endif
VG_PARAM_TYPE_KHR_FORCE_SIZE = VG_MAX_ENUM
} VGParamTypeKHR;
#ifndef VG_KHR_EGL_image
#define VG_KHR_EGL_image 1
/* VGEGLImageKHR is an opaque handle to an EGLImage */
typedef void* VGeglImageKHR;
#ifdef VG_VGEXT_PROTOTYPES
VG_API_CALL VGImage VG_API_ENTRY vgCreateEGLImageTargetKHR(VGeglImageKHR image);
#endif
typedef VGImage (VG_API_ENTRYP PFNVGCREATEEGLIMAGETARGETKHRPROC) (VGeglImageKHR image);
#endif
#ifndef VG_KHR_iterative_average_blur
#define VG_KHR_iterative_average_blur 1
#ifdef VG_VGEXT_PROTOTYPES
VG_API_CALL void vgIterativeAverageBlurKHR(VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGTilingMode tilingMode);
#endif
typedef void (VG_API_ENTRYP PFNVGITERATIVEAVERAGEBLURKHRPROC) (VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGTilingMode tilingMode);
#endif
#ifndef VG_KHR_advanced_blending
#define VG_KHR_advanced_blending 1
typedef enum {
VG_BLEND_OVERLAY_KHR = 0x2010,
VG_BLEND_HARDLIGHT_KHR = 0x2011,
VG_BLEND_SOFTLIGHT_SVG_KHR = 0x2012,
VG_BLEND_SOFTLIGHT_KHR = 0x2013,
VG_BLEND_COLORDODGE_KHR = 0x2014,
VG_BLEND_COLORBURN_KHR = 0x2015,
VG_BLEND_DIFFERENCE_KHR = 0x2016,
VG_BLEND_SUBTRACT_KHR = 0x2017,
VG_BLEND_INVERT_KHR = 0x2018,
VG_BLEND_EXCLUSION_KHR = 0x2019,
VG_BLEND_LINEARDODGE_KHR = 0x201a,
VG_BLEND_LINEARBURN_KHR = 0x201b,
VG_BLEND_VIVIDLIGHT_KHR = 0x201c,
VG_BLEND_LINEARLIGHT_KHR = 0x201d,
VG_BLEND_PINLIGHT_KHR = 0x201e,
VG_BLEND_HARDMIX_KHR = 0x201f,
VG_BLEND_CLEAR_KHR = 0x2020,
VG_BLEND_DST_KHR = 0x2021,
VG_BLEND_SRC_OUT_KHR = 0x2022,
VG_BLEND_DST_OUT_KHR = 0x2023,
VG_BLEND_SRC_ATOP_KHR = 0x2024,
VG_BLEND_DST_ATOP_KHR = 0x2025,
VG_BLEND_XOR_KHR = 0x2026,
VG_BLEND_MODE_KHR_FORCE_SIZE= VG_MAX_ENUM
} VGBlendModeKHR;
#endif
#ifndef VG_KHR_parametric_filter
#define VG_KHR_parametric_filter 1
typedef enum {
VG_PF_OBJECT_VISIBLE_FLAG_KHR = (1 << 0),
VG_PF_KNOCKOUT_FLAG_KHR = (1 << 1),
VG_PF_OUTER_FLAG_KHR = (1 << 2),
VG_PF_INNER_FLAG_KHR = (1 << 3),
VG_PF_TYPE_KHR_FORCE_SIZE = VG_MAX_ENUM
} VGPfTypeKHR;
typedef enum {
VGU_IMAGE_IN_USE_ERROR = 0xF010,
VGU_ERROR_CODE_KHR_FORCE_SIZE = VG_MAX_ENUM
} VGUErrorCodeKHR;
#ifdef VG_VGEXT_PROTOTYPES
VG_API_CALL void VG_API_ENTRY vgParametricFilterKHR(VGImage dst,VGImage src,VGImage blur,VGfloat strength,VGfloat offsetX,VGfloat offsetY,VGbitfield filterFlags,VGPaint highlightPaint,VGPaint shadowPaint);
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguDropShadowKHR(VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint shadowColorRGBA);
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguGlowKHR(VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint glowColorRGBA) ;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguBevelKHR(VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint highlightColorRGBA,VGuint shadowColorRGBA);
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguGradientGlowKHR(VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint stopsCount,const VGfloat* glowColorRampStops);
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguGradientBevelKHR(VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint stopsCount,const VGfloat* bevelColorRampStops);
#endif
typedef void (VG_API_ENTRYP PFNVGPARAMETRICFILTERKHRPROC) (VGImage dst,VGImage src,VGImage blur,VGfloat strength,VGfloat offsetX,VGfloat offsetY,VGbitfield filterFlags,VGPaint highlightPaint,VGPaint shadowPaint);
typedef VGUErrorCode (VGU_API_ENTRYP PFNVGUDROPSHADOWKHRPROC) (VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint shadowColorRGBA);
typedef VGUErrorCode (VGU_API_ENTRYP PFNVGUGLOWKHRPROC) (VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint glowColorRGBA);
typedef VGUErrorCode (VGU_API_ENTRYP PFNVGUBEVELKHRPROC) (VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint highlightColorRGBA,VGuint shadowColorRGBA);
typedef VGUErrorCode (VGU_API_ENTRYP PFNVGUGRADIENTGLOWKHRPROC) (VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint stopsCount,const VGfloat* glowColorRampStops);
typedef VGUErrorCode (VGU_API_ENTRYP PFNVGUGRADIENTBEVELKHRPROC) (VGImage dst,VGImage src,VGfloat dimX,VGfloat dimY,VGuint iterative,VGfloat strength,VGfloat distance,VGfloat angle,VGbitfield filterFlags,VGbitfield allowedQuality,VGuint stopsCount,const VGfloat* bevelColorRampStops);
#endif
/*-------------------------------------------------------------------------------
* NDS extensions
*------------------------------------------------------------------------------*/
#ifndef VG_NDS_paint_generation
#define VG_NDS_paint_generation 1
typedef enum {
VG_PAINT_COLOR_RAMP_LINEAR_NDS = 0x1A10,
VG_COLOR_MATRIX_NDS = 0x1A11,
VG_PAINT_COLOR_TRANSFORM_LINEAR_NDS = 0x1A12,
VG_PAINT_PARAM_TYPE_NDS_FORCE_SIZE = VG_MAX_ENUM
} VGPaintParamTypeNds;
typedef enum {
VG_DRAW_IMAGE_COLOR_MATRIX_NDS = 0x1F10,
VG_IMAGE_MODE_NDS_FORCE_SIZE = VG_MAX_ENUM
} VGImageModeNds;
#endif
#ifndef VG_NDS_projective_geometry
#define VG_NDS_projective_geometry 1
typedef enum {
VG_CLIP_MODE_NDS = 0x1180,
VG_CLIP_LINES_NDS = 0x1181,
VG_MAX_CLIP_LINES_NDS = 0x1182,
VG_PARAM_TYPE_NDS_FORCE_SIZE = VG_MAX_ENUM
} VGParamTypeNds;
typedef enum {
VG_CLIPMODE_NONE_NDS = 0x3000,
VG_CLIPMODE_CLIP_CLOSED_NDS = 0x3001,
VG_CLIPMODE_CLIP_OPEN_NDS = 0x3002,
VG_CLIPMODE_CULL_NDS = 0x3003,
VG_CLIPMODE_NDS_FORCE_SIZE = VG_MAX_ENUM
} VGClipModeNds;
typedef enum {
VG_RQUAD_TO_NDS = ( 13 << 1 ),
VG_RCUBIC_TO_NDS = ( 14 << 1 ),
VG_PATH_SEGMENT_NDS_FORCE_SIZE = VG_MAX_ENUM
} VGPathSegmentNds;
typedef enum {
VG_RQUAD_TO_ABS_NDS = (VG_RQUAD_TO_NDS | VG_ABSOLUTE),
VG_RQUAD_TO_REL_NDS = (VG_RQUAD_TO_NDS | VG_RELATIVE),
VG_RCUBIC_TO_ABS_NDS = (VG_RCUBIC_TO_NDS | VG_ABSOLUTE),
VG_RCUBIC_TO_REL_NDS = (VG_RCUBIC_TO_NDS | VG_RELATIVE),
VG_PATH_COMMAND_NDS_FORCE_SIZE = VG_MAX_ENUM
} VGPathCommandNds;
#ifdef VG_VGEXT_PROTOTYPES
VG_API_CALL void VG_API_ENTRY vgProjectiveMatrixNDS(VGboolean enable) ;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguTransformClipLineNDS(const VGfloat Ain,const VGfloat Bin,const VGfloat Cin,const VGfloat* matrix,const VGboolean inverse,VGfloat* Aout,VGfloat* Bout,VGfloat* Cout);
#endif
typedef void (VG_API_ENTRYP PFNVGPROJECTIVEMATRIXNDSPROC) (VGboolean enable) ;
typedef VGUErrorCode (VGU_API_ENTRYP PFNVGUTRANSFORMCLIPLINENDSPROC) (const VGfloat Ain,const VGfloat Bin,const VGfloat Cin,const VGfloat* matrix,const VGboolean inverse,VGfloat* Aout,VGfloat* Bout,VGfloat* Cout);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _VGEXT_H */

106
include/VG/vgplatform.h Normal file
View File

@ -0,0 +1,106 @@
/* $Revision: 6810 $ on $Date:: 2008-10-29 10:31:37 -0400 #$ */
/*------------------------------------------------------------------------
*
* VG platform specific header Reference Implementation
* ----------------------------------------------------
*
* Copyright (c) 2008 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*//**
* \file
* \brief VG platform specific header
*//*-------------------------------------------------------------------*/
#ifndef _VGPLATFORM_H
#define _VGPLATFORM_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VG_API_CALL
#if defined(OPENVG_STATIC_LIBRARY)
# define VG_API_CALL
#else
# if defined(_WIN32) || defined(__VC32__) /* Win32 */
# if defined (OPENVG_DLL_EXPORTS)
# define VG_API_CALL __declspec(dllexport)
# else
# define VG_API_CALL __declspec(dllimport)
# endif
# else
# define VG_API_CALL extern
# endif /* defined(_WIN32) ||... */
#endif /* defined OPENVG_STATIC_LIBRARY */
#endif /* ifndef VG_API_CALL */
#ifndef VGU_API_CALL
#if defined(OPENVG_STATIC_LIBRARY)
# define VGU_API_CALL
#else
# if defined(_WIN32) || defined(__VC32__) /* Win32 */
# if defined (OPENVG_DLL_EXPORTS)
# define VGU_API_CALL __declspec(dllexport)
# else
# define VGU_API_CALL __declspec(dllimport)
# endif
# else
# define VGU_API_CALL extern
# endif /* defined(_WIN32) ||... */
#endif /* defined OPENVG_STATIC_LIBRARY */
#endif /* ifndef VGU_API_CALL */
#ifndef VG_API_ENTRY
#define VG_API_ENTRY
#endif
#ifndef VG_API_EXIT
#define VG_API_EXIT
#endif
#ifndef VGU_API_ENTRY
#define VGU_API_ENTRY
#endif
#ifndef VGU_API_EXIT
#define VGU_API_EXIT
#endif
typedef float VGfloat;
typedef signed char VGbyte;
typedef unsigned char VGubyte;
typedef signed short VGshort;
typedef signed int VGint;
typedef unsigned int VGuint;
typedef unsigned int VGbitfield;
#ifndef VG_VGEXT_PROTOTYPES
#define VG_VGEXT_PROTOTYPES
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _VGPLATFORM_H */

130
include/VG/vgu.h Normal file
View File

@ -0,0 +1,130 @@
/* $Revision: 6810 $ on $Date:: 2008-10-29 10:31:37 -0400 #$ */
/*------------------------------------------------------------------------
*
* VGU 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2008 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*//**
* \file
* \brief VGU 1.0.1 API.
*//*-------------------------------------------------------------------*/
#ifndef _VGU_H
#define _VGU_H
#ifdef __cplusplus
extern "C" {
#endif
#include <VG/openvg.h>
#define VGU_VERSION_1_0 1
#ifndef VGU_API_CALL
# error VGU_API_CALL must be defined
#endif
#ifndef VGU_API_ENTRY
# error VGU_API_ENTRY must be defined
#endif
#ifndef VGU_API_EXIT
# error VGU_API_EXIT must be defined
#endif
typedef enum {
VGU_NO_ERROR = 0,
VGU_BAD_HANDLE_ERROR = 0xF000,
VGU_ILLEGAL_ARGUMENT_ERROR = 0xF001,
VGU_OUT_OF_MEMORY_ERROR = 0xF002,
VGU_PATH_CAPABILITY_ERROR = 0xF003,
VGU_BAD_WARP_ERROR = 0xF004,
VGU_ERROR_CODE_FORCE_SIZE = VG_MAX_ENUM
} VGUErrorCode;
typedef enum {
VGU_ARC_OPEN = 0xF100,
VGU_ARC_CHORD = 0xF101,
VGU_ARC_PIE = 0xF102,
VGU_ARC_TYPE_FORCE_SIZE = VG_MAX_ENUM
} VGUArcType;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguLine(VGPath path,
VGfloat x0, VGfloat y0,
VGfloat x1, VGfloat y1) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguPolygon(VGPath path,
const VGfloat * points, VGint count,
VGboolean closed) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguRect(VGPath path,
VGfloat x, VGfloat y,
VGfloat width, VGfloat height) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguRoundRect(VGPath path,
VGfloat x, VGfloat y,
VGfloat width, VGfloat height,
VGfloat arcWidth, VGfloat arcHeight) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguEllipse(VGPath path,
VGfloat cx, VGfloat cy,
VGfloat width, VGfloat height) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguArc(VGPath path,
VGfloat x, VGfloat y,
VGfloat width, VGfloat height,
VGfloat startAngle, VGfloat angleExtent,
VGUArcType arcType) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
VGfloat sx3, VGfloat sy3,
VGfloat * matrix) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0,
VGfloat dx1, VGfloat dy1,
VGfloat dx2, VGfloat dy2,
VGfloat dx3, VGfloat dy3,
VGfloat * matrix) VGU_API_EXIT;
VGU_API_CALL VGUErrorCode VGU_API_ENTRY vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0,
VGfloat dx1, VGfloat dy1,
VGfloat dx2, VGfloat dy2,
VGfloat dx3, VGfloat dy3,
VGfloat sx0, VGfloat sy0,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
VGfloat sx3, VGfloat sy3,
VGfloat * matrix) VGU_API_EXIT;
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* #ifndef _VGU_H */

View File

@ -0,0 +1,40 @@
# progs/vg/Makefile
TOP = ../../..
include $(TOP)/configs/current
VG_LIBS=-lm -pthread -lEGL -lOpenVG
INCLUDE_DIRS = -I$(TOP)/include
PROGRAMS = \
gears \
lion
.c.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
default: $(PROGRAMS)
gears: gears.o
$(CC) $(CFLAGS) gears.o -L$(TOP)/$(LIB_DIR) $(VG_LIBS) -o $@
gears.o: gears.c $(HEADERS)
$(CC) -c $(CFLAGS) -I$(TOP)/include gears.c
lion: lion.o lion-render.o
$(CC) $(CFLAGS) lion.o lion-render.o -L$(TOP)/$(LIB_DIR) $(VG_LIBS) -o $@
lion.o: lion.c lion-render.h $(HEADERS)
$(CC) -c $(CFLAGS) -I$(TOP)/include lion.c
lion-render.o: lion-render.c lion-render.h $(HEADERS)
$(CC) -c $(CFLAGS) -I$(TOP)/include lion-render.c
clean:
rm -f *.o *~
rm -f *.so
rm -f $(PROGRAMS)

394
progs/openvg/demos/gears.c Normal file
View File

@ -0,0 +1,394 @@
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <VG/openvg.h>
#include <GLES/egl.h>
static VGint width, height;
static VGPath gear1;
static VGPath gear2;
static VGPath gear3;
static VGPaint fill;
const VGfloat color[4] = {0.5, 0.5, 0.5, 1.0};
static VGfloat gear1_angle = 35;
static VGfloat gear2_angle = 24;
static VGfloat gear3_angle = 33.5;
static void moveTo(VGPath path, VGfloat x, VGfloat y)
{
static VGubyte moveTo = VG_MOVE_TO | VG_ABSOLUTE;
VGfloat pathData[2];
pathData[0] = x; pathData[1] = y;
vgAppendPathData(path, 1, &moveTo, pathData);
}
static void lineTo(VGPath path, VGfloat x, VGfloat y)
{
static VGubyte lineTo = VG_LINE_TO | VG_ABSOLUTE;
VGfloat pathData[2];
pathData[0] = x; pathData[1] = y;
vgAppendPathData(path, 1, &lineTo, pathData);
}
static void closeSubpath(VGPath path)
{
static VGubyte close = VG_CLOSE_PATH | VG_ABSOLUTE;
VGfloat pathData[2];
vgAppendPathData(path, 1, &close, pathData);
}
static void cubicTo(VGPath path, VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2,
VGfloat midx, VGfloat midy)
{
static VGubyte cubic = VG_CUBIC_TO | VG_ABSOLUTE;
VGfloat pathData[6];
pathData[0] = x1;
pathData[1] = y1;
pathData[2] = x2;
pathData[3] = y2;
pathData[4] = midx;
pathData[5] = midy;
vgAppendPathData(path, 1, &cubic, pathData);
}
static VGPath gearsPath(double inner_radius, double outer_radius,
int teeth, double tooth_depth)
{
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f,
0, 0, (unsigned int)VG_PATH_CAPABILITY_ALL);
int i;
double r0, r1, r2;
double angle, da;
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * M_PI / (VGfloat) teeth / 4.0;
angle = 0.0;
moveTo(path, r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da));
for (i = 1; i <= teeth; i++) {
angle = i * 2.0 * M_PI / (VGfloat)teeth;
lineTo(path, r1 * cos(angle), r1 * sin(angle));
lineTo(path, r2 * cos(angle + da), r2 * sin(angle + da));
lineTo(path, r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da));
if (i < teeth)
lineTo(path, r1 * cos(angle + 3 * da),
r1 * sin(angle + 3 * da));
}
closeSubpath(path);
moveTo(path, r0 * cos(angle + 3 * da), r0 * sin(angle + 3 * da));
for (i = 1; i <= teeth; i++) {
angle = i * 2.0 * M_PI / (VGfloat) teeth;
lineTo(path, r0 * cos(angle), r0 * sin(angle));
}
closeSubpath(path);
return path;
}
static void
draw(void)
{
vgClear(0, 0, width, height);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
vgLoadIdentity();
vgTranslate(170, 330);
vgRotate(gear1_angle);
vgDrawPath(gear1, VG_FILL_PATH);
vgLoadIdentity();
vgTranslate(369, 330);
vgRotate(gear2_angle);
vgDrawPath(gear2, VG_FILL_PATH);
vgLoadIdentity();
vgTranslate(170, 116);
vgRotate(gear3_angle);
vgDrawPath(gear3, VG_FILL_PATH);
gear1_angle += 1;
gear2_angle -= (20.0 / 12.0);
gear3_angle -= (20.0 / 14.0);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
width = w;
height = h;
}
static void
init(void)
{
float clear_color[4] = {1.0, 1.0, 1.0, 1.0};
vgSetfv(VG_CLEAR_COLOR, 4, clear_color);
gear1 = gearsPath(30.0, 120.0, 20, 20.0);
gear2 = gearsPath(15.0, 75.0, 12, 20.0);
gear3 = gearsPath(20.0, 90.0, 14, 20.0);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
vgSetPaint(fill, VG_FILL_PATH);
}
/*
* Create an RGB, double-buffered X window.
* Return the window and context handles.
*/
static void
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
const char *name,
int x, int y, int width, int height,
Window *winRet,
EGLContext *ctxRet,
EGLSurface *surfRet)
{
static const EGLint attribs[] = {
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
EGL_BLUE_SIZE, 1,
EGL_NONE
};
int scrnum;
XSetWindowAttributes attr;
unsigned long mask;
Window root;
Window win;
XVisualInfo *visInfo, visTemplate;
int num_visuals;
EGLContext ctx;
EGLConfig config;
EGLint num_configs;
EGLint vid;
scrnum = DefaultScreen( x_dpy );
root = RootWindow( x_dpy, scrnum );
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
printf("Error: couldn't get an EGL visual config\n");
exit(1);
}
assert(config);
assert(num_configs > 0);
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
printf("Error: eglGetConfigAttrib() failed\n");
exit(1);
}
/* The X window visual must match the EGL config */
visTemplate.visualid = vid;
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!visInfo) {
printf("Error: couldn't get X visual\n");
exit(1);
}
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
0, visInfo->depth, InputOutput,
visInfo->visual, mask, &attr );
/* set hints and properties */
{
XSizeHints sizehints;
sizehints.x = x;
sizehints.y = y;
sizehints.width = width;
sizehints.height = height;
sizehints.flags = USSize | USPosition;
XSetNormalHints(x_dpy, win, &sizehints);
XSetStandardProperties(x_dpy, win, name, name,
None, (char **)NULL, 0, &sizehints);
}
eglBindAPI(EGL_OPENVG_API);
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
if (!ctx) {
printf("Error: eglCreateContext failed\n");
exit(1);
}
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
if (!*surfRet) {
printf("Error: eglCreateWindowSurface failed\n");
exit(1);
}
XFree(visInfo);
*winRet = win;
*ctxRet = ctx;
}
static void
event_loop(Display *dpy, Window win,
EGLDisplay egl_dpy, EGLSurface egl_surf)
{
while (1) {
XEvent event;
while (XPending(dpy) > 0) {
XNextEvent(dpy, &event);
switch (event.type) {
case Expose:
break;
case ConfigureNotify:
reshape(event.xconfigure.width, event.xconfigure.height);
break;
case KeyPress:
{
char buffer[10];
int r, code;
code = XLookupKeysym(&event.xkey, 0);
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
NULL, NULL);
if (buffer[0] == 27) {
/* escape */
return;
}
}
break;
default:
; /*no-op*/
}
}
draw();
eglSwapBuffers(egl_dpy, egl_surf);
}
}
static void
usage(void)
{
printf("Usage:\n");
printf(" -display <displayname> set the display to run on\n");
printf(" -info display OpenGL renderer info\n");
}
int
main(int argc, char *argv[])
{
const int winWidth = 500, winHeight = 500;
Display *x_dpy;
Window win;
EGLSurface egl_surf;
EGLContext egl_ctx;
EGLDisplay egl_dpy;
char *dpyName = NULL;
GLboolean printInfo = GL_FALSE;
EGLint egl_major, egl_minor;
int i;
const char *s;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-display") == 0) {
dpyName = argv[i+1];
i++;
}
else if (strcmp(argv[i], "-info") == 0) {
printInfo = GL_TRUE;
}
else {
usage();
return -1;
}
}
x_dpy = XOpenDisplay(dpyName);
if (!x_dpy) {
printf("Error: couldn't open display %s\n",
dpyName ? dpyName : getenv("DISPLAY"));
return -1;
}
egl_dpy = eglGetDisplay(x_dpy);
if (!egl_dpy) {
printf("Error: eglGetDisplay() failed\n");
return -1;
}
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
printf("Error: eglInitialize() failed\n");
return -1;
}
s = eglQueryString(egl_dpy, EGL_VERSION);
printf("EGL_VERSION = %s\n", s);
make_x_window(x_dpy, egl_dpy,
"xegl_tri", 0, 0, winWidth, winHeight,
&win, &egl_ctx, &egl_surf);
XMapWindow(x_dpy, win);
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
printf("Error: eglMakeCurrent() failed\n");
return -1;
}
if (printInfo) {
printf("VG_RENDERER = %s\n", (char *) vgGetString(VG_RENDERER));
printf("VG_VERSION = %s\n", (char *) vgGetString(VG_VERSION));
printf("VG_VENDOR = %s\n", (char *) vgGetString(VG_VENDOR));
}
init();
/* Set initial projection/viewing transformation.
* We can't be sure we'll get a ConfigureNotify event when the window
* first appears.
*/
reshape(winWidth, winHeight);
event_loop(x_dpy, win, egl_dpy, egl_surf);
eglDestroyContext(egl_dpy, egl_ctx);
eglDestroySurface(egl_dpy, egl_surf);
eglTerminate(egl_dpy);
XDestroyWindow(x_dpy, win);
XCloseDisplay(x_dpy);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
#ifndef LION_RENDER_H
#define LION_RENDER_H
#include <VG/openvg.h>
#define LION_SIZE 132
struct lion {
VGPath paths[LION_SIZE];
VGPaint fills[LION_SIZE];
};
struct lion *lion_create(void);
void lion_render(struct lion *l);
void lion_destroy(struct lion *l);
#endif

288
progs/openvg/demos/lion.c Normal file
View File

@ -0,0 +1,288 @@
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <VG/openvg.h>
#include <GLES/egl.h>
#include "lion-render.h"
static VGint width, height;
struct lion *lion = 0;
VGfloat angle = 0;
static void
draw(void)
{
vgClear(0, 0, width, height);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
vgTranslate(width/2, height/2);
vgRotate(angle);
vgTranslate(-width/2, -height/2);
lion_render(lion);
++angle;
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
width = w;
height = h;
}
static void
init(void)
{
float clear_color[4] = {1.0, 1.0, 1.0, 1.0};
vgSetfv(VG_CLEAR_COLOR, 4, clear_color);
lion = lion_create();
}
/*
* Create an RGB, double-buffered X window.
* Return the window and context handles.
*/
static void
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
const char *name,
int x, int y, int width, int height,
Window *winRet,
EGLContext *ctxRet,
EGLSurface *surfRet)
{
static const EGLint attribs[] = {
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
EGL_BLUE_SIZE, 1,
EGL_NONE
};
int scrnum;
XSetWindowAttributes attr;
unsigned long mask;
Window root;
Window win;
XVisualInfo *visInfo, visTemplate;
int num_visuals;
EGLContext ctx;
EGLConfig config;
EGLint num_configs;
EGLint vid;
scrnum = DefaultScreen( x_dpy );
root = RootWindow( x_dpy, scrnum );
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
printf("Error: couldn't get an EGL visual config\n");
exit(1);
}
assert(config);
assert(num_configs > 0);
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
printf("Error: eglGetConfigAttrib() failed\n");
exit(1);
}
/* The X window visual must match the EGL config */
visTemplate.visualid = vid;
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!visInfo) {
printf("Error: couldn't get X visual\n");
exit(1);
}
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
0, visInfo->depth, InputOutput,
visInfo->visual, mask, &attr );
/* set hints and properties */
{
XSizeHints sizehints;
sizehints.x = x;
sizehints.y = y;
sizehints.width = width;
sizehints.height = height;
sizehints.flags = USSize | USPosition;
XSetNormalHints(x_dpy, win, &sizehints);
XSetStandardProperties(x_dpy, win, name, name,
None, (char **)NULL, 0, &sizehints);
}
eglBindAPI(EGL_OPENVG_API);
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
if (!ctx) {
printf("Error: eglCreateContext failed\n");
exit(1);
}
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
if (!*surfRet) {
printf("Error: eglCreateWindowSurface failed\n");
exit(1);
}
XFree(visInfo);
*winRet = win;
*ctxRet = ctx;
}
static void
event_loop(Display *dpy, Window win,
EGLDisplay egl_dpy, EGLSurface egl_surf)
{
while (1) {
XEvent event;
while (XPending(dpy) > 0) {
XNextEvent(dpy, &event);
switch (event.type) {
case Expose:
break;
case ConfigureNotify:
reshape(event.xconfigure.width, event.xconfigure.height);
break;
case KeyPress:
{
char buffer[10];
int r, code;
code = XLookupKeysym(&event.xkey, 0);
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
NULL, NULL);
if (buffer[0] == 27) {
/* escape */
return;
}
}
break;
default:
; /*no-op*/
}
}
draw();
eglSwapBuffers(egl_dpy, egl_surf);
}
}
static void
usage(void)
{
printf("Usage:\n");
printf(" -display <displayname> set the display to run on\n");
printf(" -info display OpenGL renderer info\n");
}
int
main(int argc, char *argv[])
{
const int winWidth = 350, winHeight = 450;
Display *x_dpy;
Window win;
EGLSurface egl_surf;
EGLContext egl_ctx;
EGLDisplay egl_dpy;
char *dpyName = NULL;
GLboolean printInfo = GL_FALSE;
EGLint egl_major, egl_minor;
int i;
const char *s;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-display") == 0) {
dpyName = argv[i+1];
i++;
}
else if (strcmp(argv[i], "-info") == 0) {
printInfo = GL_TRUE;
}
else {
usage();
return -1;
}
}
x_dpy = XOpenDisplay(dpyName);
if (!x_dpy) {
printf("Error: couldn't open display %s\n",
dpyName ? dpyName : getenv("DISPLAY"));
return -1;
}
egl_dpy = eglGetDisplay(x_dpy);
if (!egl_dpy) {
printf("Error: eglGetDisplay() failed\n");
return -1;
}
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
printf("Error: eglInitialize() failed\n");
return -1;
}
s = eglQueryString(egl_dpy, EGL_VERSION);
printf("EGL_VERSION = %s\n", s);
make_x_window(x_dpy, egl_dpy,
"Lion Example", 0, 0, winWidth, winHeight,
&win, &egl_ctx, &egl_surf);
XMapWindow(x_dpy, win);
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
printf("Error: eglMakeCurrent() failed\n");
return -1;
}
if (printInfo) {
printf("VG_RENDERER = %s\n", (char *) vgGetString(VG_RENDERER));
printf("VG_VERSION = %s\n", (char *) vgGetString(VG_VERSION));
printf("VG_VENDOR = %s\n", (char *) vgGetString(VG_VENDOR));
}
init();
/* Set initial projection/viewing transformation.
* We can't be sure we'll get a ConfigureNotify event when the window
* first appears.
*/
reshape(winWidth, winHeight);
event_loop(x_dpy, win, egl_dpy, egl_surf);
eglDestroyContext(egl_dpy, egl_ctx);
eglDestroySurface(egl_dpy, egl_surf);
eglTerminate(egl_dpy);
XDestroyWindow(x_dpy, win);
XCloseDisplay(x_dpy);
return 0;
}

103
progs/openvg/demos/sp.c Normal file
View File

@ -0,0 +1,103 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <VG/vgu.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <X11/keysym.h>
struct object {
VGPath path;
VGPaint fill;
VGPaint stroke;
VGint draw_mode;
};
struct character {
struct object objects[32];
VGint num_objects;
};
struct character cartman;
static void init_character()
{
struct object object;
VGint num_objects = 0;
{
const VGint num_segments = 6;
const VGubyte segments[] = {VG_MOVE_TO_ABS,
VG_CUBIC_TO_ABS,
VG_CUBIC_TO_ABS,
VG_CUBIC_TO_ABS,
VG_CUBIC_TO_ABS,
VG_CLOSE_PATH};
const VGfloat coords[] = {181.83267, 102.60408,
181.83267,102.60408 185.53793,114.5749 186.5355,115.00243,
187.53306,115.42996 286.0073,115.00243 286.0073,115.00243,
286.0073,115.00243 292.70526,103.45914 290.85263,101.03648,
289.00001,98.61381 181.54765,102.31906 181.83267,102.60408
};
VGuint color = 0x7c4e32ff;
object.path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
vgAppendPathData(object.path, num_segments, segments, coords);
object.fill = vgCreatePaint();
vgSetColor(object.fill, color);
character.objects[objects.num_objects] = object;
++objects.num_objects;
}
{
}
}
static void
init(void)
{
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
int key_press(unsigned key)
{
switch(key) {
case XK_Right:
break;
case XK_Left:
break;
case XK_Up:
break;
case XK_Down:
break;
case 'a':
break;
case 's':
break;
default:
break;
}
return VG_FALSE;
}
static void
draw(void)
{
}
int main(int argc, char **argv)
{
set_window_size(400, 400);
return run(argc, argv, init, reshape, draw, key_press);
}

View File

@ -0,0 +1,127 @@
# These programs aren't intended to be included with the normal distro.
# They're not too interesting but they're good for testing.
TOP = ../../../
include $(TOP)/configs/current
INCLUDES = -I. -I$(TOP)/include
LIBS=-L$(TOP)/$(LIB_DIR) -lm -lEGL -lOpenVG -lpthread
CFLAGS += $(INCLUDES)
HEADERS=eglcommon.h
PROGRAMS = \
arc \
cap \
clear \
coord \
dash \
ellipse \
filter \
gradorigin \
lineto \
lingrad \
lookup \
mask4 \
mask \
path3 \
radialgrad \
readpixels \
roundedrect \
star-nonzero \
star-oddeven \
stroke2 \
stroke \
vguarc
.c.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
default: $(PROGRAMS)
arc: arc.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
cap: cap.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
clear: clear.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
coord: coord.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
dash: dash.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
ellipse: ellipse.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
filter: filter.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
gradorigin: gradorigin.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
image: image.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
lineto: lineto.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
lingrad: lingrad.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
lookup: lookup.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
mask: mask.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
mask4: mask4.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
path3: path3.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
pattern: pattern.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
radialgrad: radialgrad.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
readpixels: readpixels.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
roundedrect: roundedrect.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
star-nonzero: star-nonzero.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
star-oddeven: star-oddeven.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
stroke: stroke.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
stroke2: stroke2.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
vguarc: vguarc.c eglcommon.o
$(CC) $(CFLAGS) $^ $(LIBS) $(APP_LIB_DEPS) -o $@
eglcommon.o: eglcommon.c $(HEADERS)
$(CC) -c $(CFLAGS) eglcommon.c
clean:
rm -f *.o *~
rm -f *.so
rm -f $(PROGRAMS)

139
progs/openvg/trivial/arc.c Normal file
View File

@ -0,0 +1,139 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <math.h>
const VGfloat clear_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {1.0, 1.0, 1.0, 0.5};
VGPath vgPath;
static void ellipse(VGPath vgPath, VGfloat rx, VGfloat ry, VGfloat angle)
{
static const VGubyte cmd[] =
{ VG_MOVE_TO_ABS, VG_SCCWARC_TO_REL, VG_SCCWARC_TO_REL, VG_CLOSE_PATH };
VGfloat val[12];
VGfloat c = cos(angle) * rx;
VGfloat s = sin(angle) * rx;
val[0] = c;
val[1] = s;
val[2] = rx;
val[3] = ry;
val[4] = angle;
val[5] = -2.0f * c;
val[6] = -2.0f * s;
val[7] = rx;
val[8] = ry;
val[9] = angle;
val[10] = 2.0f * c;
val[11] = 2.0f * s;
vgClearPath(vgPath, VG_PATH_CAPABILITY_ALL);
vgAppendPathData(vgPath, sizeof(cmd), cmd, val);
vgDrawPath(vgPath, VG_FILL_PATH | VG_STROKE_PATH);
}
static void
init(void)
{
VGPaint vgPaint;
vgSetfv(VG_CLEAR_COLOR, 4, clear_color);
vgPath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0,
VG_PATH_CAPABILITY_ALL);
vgPaint = vgCreatePaint();
vgSetParameteri(vgPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetColor(vgPaint, 0x00ff00ff);
vgSetPaint(vgPaint, VG_FILL_PATH);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
vgSetf(VG_STROKE_LINE_WIDTH, 2.0f);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_SQUARE);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
vgSetf(VG_STROKE_MITER_LIMIT, 4.0f);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
#if 0
vgLoadIdentity();
vgTranslate(40.0f, 24.0f);
vgScale(0.61804f, 0.61804f);
vgShear(-1.0f, 0.0f);
vgDrawPath(vgPath, VG_FILL_PATH | VG_STROKE_PATH);
#else
/* row 1, col 1: Identity transform. */
vgLoadIdentity();
vgTranslate(8.0f, 8.0f);
ellipse(vgPath, 4.0f, 4.0f, 0.0f);
/* row 1, col 2: 10^3 horizontal squeeze. */
vgLoadIdentity();
vgTranslate(24.0f, 8.0f);
vgScale(1.0e-3f, 1.0f);
ellipse(vgPath, 4.0e3f, 4.0f, 0.0f);
/* row 1, col 3: 10^6 horizontal squeeze. */
vgLoadIdentity();
vgTranslate(40.0f, 8.0f);
vgScale(1.0e-6f, 1.0f);
ellipse(vgPath, 4.0e6f, 4.0f, 0.0f);
/* row 1, col 4: 10^9 horizontal squeeze. */
vgLoadIdentity();
vgTranslate(56.0f, 8.0f);
vgScale(1.0e-9f, 1.0f);
ellipse(vgPath, 4.0e9f, 4.0f, 0.0f);
/* row 2, col 1: 10^3 vertical squeeze. */
vgLoadIdentity();
vgTranslate(8.0f, 24.0f);
vgScale(1.0f, 1.0e-3f);
ellipse(vgPath, 4.0f, 4.0e3f, 0.0f);
/* row 2, col 2: Shear 0. */
vgLoadIdentity();
vgTranslate(24.0f, 24.0f);
vgShear(0.0f, 0.0f);
ellipse(vgPath, 4.0f, 4.0f, 0.0f);
/* row 2, col 3: Horizontal shear -1. */
vgLoadIdentity();
vgTranslate(40.0f, 24.0f);
vgScale(0.61804f, 0.61804f);
vgShear(-1.0f, 0.0f);
ellipse(vgPath, 10.47213f, 4.0f, 31.717f);
#endif
vgFlush();
}
int main(int argc, char **argv)
{
set_window_size(64, 64);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,75 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
static void
init(void)
{
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
const int subtest = 0;
static void
draw(void)
{
VGPath line;
VGPaint fillPaint;
VGubyte lineCommands[3] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS};
VGfloat lineCoords[] = {-2.0f,-1.0f, 0.0f,0.0f, -1.0f, -2.0f};
VGfloat clearColor[] = {0.0f, 0.0f, 0.0f, 1.0f};/* black color */
VGfloat fillColor[] = {1.0f, 1.0f, 1.0f, 1.0f};/* white color */
//VGfloat testRadius = 60.0f;
VGfloat testRadius = 10.0f;
int WINDSIZEX = window_width();
int WINDSIZEY = window_height();
line = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
fillPaint = vgCreatePaint();
vgSetf(VG_STROKE_LINE_WIDTH, 1.0f);
//vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_ROUND);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
//vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_BEVEL);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_BETTER);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
vgTranslate(60, 60);
vgScale(testRadius * 2, testRadius * 2);
vgAppendPathData(line, 3, lineCommands, lineCoords);
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
vgSetPaint(fillPaint, VG_STROKE_PATH);
vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, fillColor);
vgSetParameteri( fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgClear(0, 0, WINDSIZEX, WINDSIZEY);
vgDrawPath(line, VG_STROKE_PATH);
vgDestroyPath(line);
vgDestroyPaint(fillPaint);
}
int main(int argc, char **argv)
{
set_window_size(100, 100);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,42 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <stdio.h>
float red_color[4] = {1.0, 0.0, 0.0, 1.0};
float blue_color[4] = {0.0, 0.0, 1.0, 1.0};
static void
init(void)
{
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
VGint scissor[4] = {100, 100, 25, 25};
vgSetfv(VG_CLEAR_COLOR, 4, red_color);
vgClear(0, 0, window_width(), window_height());
vgSetfv(VG_CLEAR_COLOR, 4, blue_color);
vgClear(50, 50, 50, 50);
//vgSetiv(VG_SCISSOR_RECTS, 4, scissor);
//vgSeti(VG_SCISSORING, VG_TRUE);
vgCopyPixels(100, 100, 50, 50, 50, 50);
vgClear(150, 150, 50, 50);
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,66 @@
#include "eglcommon.h"
#include <VG/openvg.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.4, 0.1, 1.0, 1.0};
VGPath path;
VGPaint fill;
static void
init(void)
{
/* Absent VG_CLOSE_PATH */
VGubyte commands[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS,
VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS};
VGfloat clearColor[] = {1.0f, 1.0f, 1.0f, 1.0f};/* white color */
VGfloat fillColor[] = {1.0f, 0.0f, 0.0f, 1.0f};/* red color */
VGfloat coords[] = {-16.0f, -16.0f, 0.0f, -16.0f, 0.0f, 0.0f, -16.0f, 0.0f,
0.0f, 0.0f, 16.0f, 0.0f, 16.0f, 16.0f, 0.0f, 16.0f};
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
vgTranslate(32.0f, 32.0f);
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0,
VG_PATH_CAPABILITY_ALL);
if (path == VG_INVALID_HANDLE)
return;
fill = vgCreatePaint();
if (fill == VG_INVALID_HANDLE) {
vgDestroyPath(path);
return;
}
vgAppendPathData(path, 8, commands, coords);
vgSetPaint(fill, VG_FILL_PATH);
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, fillColor);
vgSetParameteri(fill, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_FILL_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
set_window_size(64, 64);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,95 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <X11/keysym.h>
#include <stdio.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.4, 0.1, 1.0, 1.0};
VGPath path;
VGPaint fill;
VGint cap_style = VG_CAP_BUTT;
static void
init(void)
{
static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
VG_LINE_TO_ABS,
VG_LINE_TO_ABS
};
#if 1
static const VGfloat coords[] = {100, 100, 150, 100,
150, 200
};
#else
static const VGfloat coords[] = {100, 20, 100, 220,
};
#endif
VGfloat dash_pattern[2] = { 20.f, 20.f };
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 3, cmds, coords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
vgSetPaint(fill, VG_FILL_PATH);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
vgSetf(VG_STROKE_LINE_WIDTH, 20);
vgSeti(VG_STROKE_CAP_STYLE, cap_style);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
vgSetfv(VG_STROKE_DASH_PATTERN, 2, dash_pattern);
vgSetf(VG_STROKE_DASH_PHASE, 0.0f);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_STROKE_PATH);
vgFlush();
}
static int key_press(unsigned key)
{
switch(key) {
case XK_c:
case XK_C:
++cap_style;
if (cap_style > VG_CAP_SQUARE)
cap_style = VG_CAP_BUTT;
switch(cap_style) {
case VG_CAP_BUTT:
fprintf(stderr, "Cap style 'butt'\n");
break;
case VG_CAP_ROUND:
fprintf(stderr, "Cap style 'round'\n");
break;
case VG_CAP_SQUARE:
fprintf(stderr, "Cap style 'square'\n");
break;
}
vgSeti(VG_STROKE_CAP_STYLE, cap_style);
break;
default:
break;
}
return VG_TRUE;
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, key_press);
}

View File

@ -0,0 +1,288 @@
#include "eglcommon.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <VG/openvg.h> /* using full OpenGL for now */
#include <GLES/egl.h>
static init_func init = 0;
static draw_func draw = 0;
static reshape_func reshape = 0;
static key_func keyPress = 0;
static VGint width = 300, height = 300;
void set_window_size(int w, int h)
{
width = w;
height = h;
}
/*
* Create an RGB, double-buffered X window.
* Return the window and context handles.
*/
static void
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
const char *name,
int x, int y, int width, int height,
Window *winRet,
EGLContext *ctxRet,
EGLSurface *surfRet)
{
static const EGLint attribs[] = {
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
EGL_BLUE_SIZE, 1,
EGL_NONE
};
int scrnum;
XSetWindowAttributes attr;
unsigned long mask;
Window root;
Window win;
XVisualInfo *visInfo, visTemplate;
int num_visuals;
EGLContext ctx;
EGLConfig config;
EGLint num_configs;
EGLint vid;
scrnum = DefaultScreen( x_dpy );
root = RootWindow( x_dpy, scrnum );
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
printf("Error: couldn't get an EGL visual config\n");
exit(1);
}
assert(config);
assert(num_configs > 0);
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
printf("Error: eglGetConfigAttrib() failed\n");
exit(1);
}
/* The X window visual must match the EGL config */
visTemplate.visualid = vid;
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!visInfo) {
printf("Error: couldn't get X visual\n");
exit(1);
}
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
0, visInfo->depth, InputOutput,
visInfo->visual, mask, &attr );
/* set hints and properties */
{
XSizeHints sizehints;
sizehints.x = x;
sizehints.y = y;
sizehints.width = width;
sizehints.height = height;
sizehints.flags = USSize | USPosition;
XSetNormalHints(x_dpy, win, &sizehints);
XSetStandardProperties(x_dpy, win, name, name,
None, (char **)NULL, 0, &sizehints);
}
eglBindAPI(EGL_OPENVG_API);
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
if (!ctx) {
printf("Error: eglCreateContext failed\n");
exit(1);
}
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
if (!*surfRet) {
printf("Error: eglCreateWindowSurface failed\n");
exit(1);
}
XFree(visInfo);
*winRet = win;
*ctxRet = ctx;
}
static void
event_loop(Display *dpy, Window win,
EGLDisplay egl_dpy, EGLSurface egl_surf)
{
while (1) {
int redraw = 0;
XEvent event;
XNextEvent(dpy, &event);
switch (event.type) {
case Expose:
redraw = 1;
break;
case ConfigureNotify:
if (reshape) {
width = event.xconfigure.width;
height = event.xconfigure.height;
reshape(event.xconfigure.width, event.xconfigure.height);
}
break;
case KeyPress:
{
char buffer[10];
int r, code;
code = XLookupKeysym(&event.xkey, 0);
if (!keyPress || !keyPress(code)) {
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
NULL, NULL);
if (buffer[0] == 27) {
/* escape */
return;
}
}
}
redraw = 1;
break;
default:
; /*no-op*/
}
if (redraw) {
draw();
eglSwapBuffers(egl_dpy, egl_surf);
}
}
}
int window_width(void)
{
return width;
}
int window_height(void)
{
return height;
}
static void
usage(void)
{
printf("Usage:\n");
printf(" -display <displayname> set the display to run on\n");
printf(" -info display OpenGL renderer info\n");
}
int run(int argc, char **argv,
init_func init_f,
reshape_func resh_f,
draw_func draw_f,
key_func key_f)
{
const int winWidth = width, winHeight = height;
Display *x_dpy;
Window win;
EGLSurface egl_surf;
EGLContext egl_ctx;
EGLDisplay egl_dpy;
char *dpyName = NULL;
GLboolean printInfo = GL_FALSE;
EGLint egl_major, egl_minor;
int i;
const char *s;
init = init_f;
draw = draw_f;
reshape = resh_f;
keyPress = key_f;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-display") == 0) {
dpyName = argv[i+1];
i++;
}
else if (strcmp(argv[i], "-info") == 0) {
printInfo = GL_TRUE;
}
}
x_dpy = XOpenDisplay(dpyName);
if (!x_dpy) {
printf("Error: couldn't open display %s\n",
dpyName ? dpyName : getenv("DISPLAY"));
return -1;
}
egl_dpy = eglGetDisplay(x_dpy);
if (!egl_dpy) {
printf("Error: eglGetDisplay() failed\n");
return -1;
}
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
printf("Error: eglInitialize() failed\n");
return -1;
}
s = eglQueryString(egl_dpy, EGL_VERSION);
printf("EGL_VERSION = %s\n", s);
make_x_window(x_dpy, egl_dpy,
"OpenVG Example", 0, 0, winWidth, winHeight,
&win, &egl_ctx, &egl_surf);
XMapWindow(x_dpy, win);
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
printf("Error: eglMakeCurrent() failed\n");
return -1;
}
if (printInfo) {
printf("VG_RENDERER = %s\n", (char *) vgGetString(VG_RENDERER));
printf("VG_VERSION = %s\n", (char *) vgGetString(VG_VERSION));
printf("VG_VENDOR = %s\n", (char *) vgGetString(VG_VENDOR));
}
if (init)
init();
/* Set initial projection/viewing transformation.
* We can't be sure we'll get a ConfigureNotify event when the window
* first appears.
*/
if (reshape)
reshape(winWidth, winHeight);
event_loop(x_dpy, win, egl_dpy, egl_surf);
eglMakeCurrent(egl_dpy, 0, 0, 0);
eglDestroyContext(egl_dpy, egl_ctx);
eglDestroySurface(egl_dpy, egl_surf);
eglTerminate(egl_dpy);
XDestroyWindow(x_dpy, win);
XCloseDisplay(x_dpy);
return 0;
}

View File

@ -0,0 +1,20 @@
#ifndef EGLCOMMON_H
#define EGLCOMMON_H
typedef void (*init_func)();
typedef void (*reshape_func)(int, int);
typedef void (*draw_func)();
typedef int (*key_func)(unsigned key);
void set_window_size(int width, int height);
int window_width(void);
int window_height(void);
int run(int argc, char **argv,
init_func init,
reshape_func resh,
draw_func draw,
key_func key);
#endif

View File

@ -0,0 +1,84 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <math.h>
#include <stdlib.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.0, 0.0, 0.0, 1.0};
VGPath path;
VGPaint paint;
static void
init(void)
{
VGfloat clearColor[] = {1.0f, 1.0f, 1.0f, 1.0f};/* white color */
VGfloat fillColor[] = {1.0f, 0.0f, 0.0f, 1.0f};/* red color */
static const VGubyte segments[4] = {VG_MOVE_TO_ABS,
VG_SCCWARC_TO_ABS,
VG_SCCWARC_TO_ABS,
VG_CLOSE_PATH};
VGfloat data[12];
const VGfloat cx = 0, cy=29, width=80, height=40;
const VGfloat hw = width * 0.5f;
const VGfloat hh = height * 0.5f;
data[0] = cx + hw;
data[1] = cy;
data[2] = hw;
data[3] = hh;
data[4] = 0;
data[5] = cx - hw;
data[6] = cy;
data[7] = hw;
data[8] = hh;
data[9] = 0;
data[10] = data[0];
data[11] = cy;
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
if (path == VG_INVALID_HANDLE) {
return;
}
paint = vgCreatePaint();
if (paint == VG_INVALID_HANDLE) {
vgDestroyPath(path);
return;
}
vgAppendPathData(path, 4, segments, data);
vgSetParameterfv(paint, VG_PAINT_COLOR, 4, fillColor);
vgSetParameteri( paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetPaint(paint, VG_FILL_PATH);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgLoadIdentity();
vgTranslate(50, 21);
vgDrawPath(path, VG_FILL_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
set_window_size(100, 100);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,107 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {1.0, 1.0, 1.0, 0.5};
VGImage srcImg;
VGImage dstImg;
VGPaint fill;
VGfloat bgCol[4] = {0.906f, 0.914f, 0.761f, 1.0f};
static void
init(void)
{
VGfloat red[4];
VGfloat grey[4];
VGfloat orange[4];
VGfloat blue[4];
VGfloat black[4];
VGfloat white[4];
VGshort transKernel[49] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
red[0] = 0.6710f;
red[1] = 0.1060f;
red[2] = 0.1330f;
red[3] = 1.0f;
grey[0] = 0.6347f;
grey[1] = 0.6561f;
grey[2] = 0.6057f;
grey[3] = 1.0f;
orange[0] = 1.0000f;
orange[1] = 0.8227f;
orange[2] = 0.5057f;
orange[3] = 1.0f;
blue[0] = 0.0000f;
blue[1] = 0.6908f;
blue[2] = 0.8595f;
blue[3] = 1.0f;
black[0] = 0;
black[1] = 0;
black[2] = 0;
black[3] = 1.0f;
white[0] = 1;
white[1] = 1;
white[2] = 1;
white[3] = 1.0f;
vgSetfv(VG_TILE_FILL_COLOR, 4, blue);
vgSeti(VG_FILTER_CHANNEL_MASK, 14);
/* Setup images */
srcImg = vgCreateImage(VG_sRGBA_8888, 32, 32,
VG_IMAGE_QUALITY_NONANTIALIASED);
dstImg = vgCreateImage(VG_sRGBA_8888, 32, 32,
VG_IMAGE_QUALITY_NONANTIALIASED);
vgSetfv(VG_CLEAR_COLOR, 4, black);
vgClearImage(srcImg, 0, 0, 32, 32);
vgSetfv(VG_CLEAR_COLOR, 4, red);
vgClearImage(srcImg, 3, 3, 27, 27);
vgSetfv(VG_CLEAR_COLOR, 4, orange);
vgClearImage(dstImg, 0, 0, 32, 32);
transKernel[8] = 1;
vgConvolve(dstImg, srcImg, 3, 3, 3, 0, transKernel,
1, 0, VG_TILE_FILL);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
static void
draw(void)
{
vgSetfv(VG_CLEAR_COLOR, 4, bgCol);
vgClear(0, 0, window_width(), window_height());
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadIdentity();
vgTranslate(10, 10);
vgDrawImage(dstImg);
vgFlush();
}
int main(int argc, char **argv)
{
set_window_size(64, 64);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,98 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <stdio.h>
#include <string.h>
static const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
static VGPath path;
static VGPaint fill;
VGColorRampSpreadMode spread = VG_COLOR_RAMP_SPREAD_PAD;
static void
init(void)
{
VGubyte commands[5] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS, VG_CLOSE_PATH};
VGfloat coords[8] = {0.0f,0.0f, 32.0f,0.0f, 32.0f,32.0f, 0.0f,32.0f };
VGfloat rampStop[20] = {-0.5f, 1.0f, 1.0f, 1.0f, 1.0f,
0.25f, 1.0f, 0.0f, 0.0f, 1.0f,
0.75f, 0.0f, 0.0f, 1.0f, 1.0f,
1.5f, 0.0f, 0.0f, 0.0f, 0.0f};
VGfloat defaultColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
VGfloat linearGradient[4] = {0.0f, 0.0f, 0.0f, 32.0f};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
if (path == VG_INVALID_HANDLE)
return;
fill = vgCreatePaint();
if (fill == VG_INVALID_HANDLE) {
vgDestroyPath(path);
return;
}
vgSetfv(VG_CLEAR_COLOR, 4, defaultColor);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
vgAppendPathData(path, 5, commands, coords);
vgSetPaint(fill, VG_FILL_PATH);
vgSetParameteri(fill, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
vgSetParameteri(fill, VG_PAINT_COLOR_RAMP_SPREAD_MODE,
VG_COLOR_RAMP_SPREAD_REPEAT);
vgSetParameterfv(fill, VG_PAINT_LINEAR_GRADIENT, 4, linearGradient);
vgSetParameterfv(fill, VG_PAINT_COLOR_RAMP_STOPS, 20, rampStop);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_FILL_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
if (argc > 1) {
const char *arg = argv[1];
if (!strcmp("-pad", arg))
spread = VG_COLOR_RAMP_SPREAD_PAD;
else if (!strcmp("-repeat", arg))
spread = VG_COLOR_RAMP_SPREAD_REPEAT;
else if (!strcmp("-reflect", arg))
spread = VG_COLOR_RAMP_SPREAD_REFLECT;
}
switch(spread) {
case VG_COLOR_RAMP_SPREAD_PAD:
printf("Using spread mode: pad\n");
break;
case VG_COLOR_RAMP_SPREAD_REPEAT:
printf("Using spread mode: repeat\n");
break;
case VG_COLOR_RAMP_SPREAD_REFLECT:
printf("Using spread mode: reflect\n");
}
set_window_size(200, 200);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,56 @@
#include "eglcommon.h"
#include <VG/openvg.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.4, 0.1, 1.0, 1.0};
VGPath path;
VGPaint fill;
static void
init(void)
{
static const VGubyte sqrCmds[5] = {VG_MOVE_TO_ABS, VG_HLINE_TO_ABS, VG_VLINE_TO_ABS, VG_HLINE_TO_ABS, VG_CLOSE_PATH};
static const VGfloat sqrCoords[5] = {50.0f, 50.0f, 250.0f, 250.0f, 50.0f};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 5, sqrCmds, sqrCoords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
vgSetPaint(fill, VG_FILL_PATH);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
vgSetf(VG_STROKE_LINE_WIDTH, 10);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
vgSetf(VG_STROKE_MITER_LIMIT, 4.0f);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER);
vgLoadIdentity();
vgScale(2.25, 2.25);
vgDrawPath(path, VG_STROKE_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,87 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <stdio.h>
#include <string.h>
static const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
static VGPath path;
static VGPaint fill;
VGColorRampSpreadMode spread = VG_COLOR_RAMP_SPREAD_PAD;
static void
init(void)
{
static const VGubyte sqrCmds[5] = {VG_MOVE_TO_ABS, VG_HLINE_TO_ABS, VG_VLINE_TO_ABS, VG_HLINE_TO_ABS, VG_CLOSE_PATH};
static const VGfloat sqrCoords[5] = {0.0f, 0.0f, 400.0f, 400.0f, 0.0f};
VGfloat rampStop[] = {0.00f, 1.0f, 1.0f, 1.0f, 1.0f,
0.33f, 1.0f, 0.0f, 0.0f, 1.0f,
0.66f, 0.0f, 1.0f, 0.0f, 1.0f,
1.00f, 0.0f, 0.0f, 1.0f, 1.0f};
VGfloat linearGradient[4] = {100.0f, 100.0f, 300.0f, 300.0f};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 5, sqrCmds, sqrCoords);
fill = vgCreatePaint();
vgSetPaint(fill, VG_FILL_PATH);
vgSetParameteri(fill, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
vgSetParameteri(fill, VG_PAINT_COLOR_RAMP_SPREAD_MODE, spread);
vgSetParameterfv(fill, VG_PAINT_LINEAR_GRADIENT, 4, linearGradient);
vgSetParameterfv(fill, VG_PAINT_COLOR_RAMP_STOPS, 20, rampStop);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_FILL_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
if (argc > 1) {
const char *arg = argv[1];
if (!strcmp("-pad", arg))
spread = VG_COLOR_RAMP_SPREAD_PAD;
else if (!strcmp("-repeat", arg))
spread = VG_COLOR_RAMP_SPREAD_REPEAT;
else if (!strcmp("-reflect", arg))
spread = VG_COLOR_RAMP_SPREAD_REFLECT;
}
switch(spread) {
case VG_COLOR_RAMP_SPREAD_PAD:
printf("Using spread mode: pad\n");
break;
case VG_COLOR_RAMP_SPREAD_REPEAT:
printf("Using spread mode: repeat\n");
break;
case VG_COLOR_RAMP_SPREAD_REFLECT:
printf("Using spread mode: reflect\n");
}
set_window_size(400, 400);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,71 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {1.0, 1.0, 1.0, 0.5};
VGfloat clearColor[] = {1.0f, 0.0f, 0.0f, 1.0f};/* red color */
VGImage parent;
VGPaint fill;
static void
init(void)
{
VGImage child1, child2;
VGubyte *data;
VGuint LUT[256];
VGint i;
data = (VGubyte *)malloc(sizeof(VGubyte)*window_width()*window_height());
for (i=0;i<window_width()*window_height();i++) {
data[i] = 0x00;
}
for (i=0; i<256; i++) {
if ( i == 0 )
LUT[0] = 0xFFFFFFFF;
else
LUT[i] = 0xFF00FFFF;
}
parent = vgCreateImage( VG_A_8, 64, 64, VG_IMAGE_QUALITY_NONANTIALIASED );
vgImageSubData(parent, data, window_width(), VG_A_8, 0, 0,
window_width(), window_height());
child1 = vgChildImage(parent, 0, 0, 32, 64);
child2 = vgChildImage(parent, 32, 0, 32, 64);
vgLookupSingle(child2, child1, LUT, VG_GREEN, VG_FALSE, VG_TRUE);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
static void
draw(void)
{
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
vgClear(0, 0, window_width(), window_height());
//vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
//vgLoadIdentity();
//vgTranslate(10, 10);
vgDrawImage(parent);
vgFlush();
}
int main(int argc, char **argv)
{
set_window_size(64, 64);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,58 @@
#include "eglcommon.h"
#include <VG/openvg.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.4, 0.1, 1.0, 1.0};
VGPath path;
VGPaint fill;
static void
init(void)
{
static const VGubyte sqrCmds[5] = {VG_MOVE_TO_ABS, VG_HLINE_TO_ABS, VG_VLINE_TO_ABS, VG_HLINE_TO_ABS, VG_CLOSE_PATH};
static const VGfloat sqrCoords[5] = {50.0f, 50.0f, 250.0f, 250.0f, 50.0f};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 5, sqrCmds, sqrCoords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
vgSetPaint(fill, VG_FILL_PATH);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
vgSetf(VG_STROKE_LINE_WIDTH, 10);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
vgSetf(VG_STROKE_MITER_LIMIT, 4.0f);
vgSeti(VG_MASKING, VG_TRUE);
vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK,
25, 25, 100, 100);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_FILL_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,132 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <VG/vgu.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <X11/keysym.h>
//VGint x_pos = -10, y_pos = -10;
VGint x_pos = 0, y_pos = 4;
VGint img_width = 120, img_height = 120;
static void RectToPath(VGPath path, VGfloat x, VGfloat y, VGfloat width, VGfloat height)
{
static const VGubyte segments[5] = {VG_MOVE_TO_ABS,
VG_HLINE_TO_ABS,
VG_VLINE_TO_ABS,
VG_HLINE_TO_ABS,
VG_CLOSE_PATH};
VGfloat data[5];
data[0] = x;
data[1] = y;
data[2] = x + width;
data[3] = y + height;
data[4] = x;
vgAppendPathData(path, 5, segments, data);
}
static void
init(void)
{
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
int key_press(unsigned key)
{
switch(key) {
case XK_Right:
x_pos +=1;
break;
case XK_Left:
x_pos -=1;
break;
case XK_Up:
y_pos +=1;
break;
case XK_Down:
y_pos -=1;
break;
case 'a':
img_width -= 5;
img_height -= 5;
break;
case 's':
img_width += 5;
img_height += 5;
break;
default:
break;
}
fprintf(stderr, "Posi = %dx%d\n", x_pos, y_pos);
fprintf(stderr, "Size = %dx%d\n", img_width, img_height);
return VG_FALSE;
}
static void
draw(void)
{
VGint WINDSIZEX = window_width();
VGint WINDSIZEY = window_height();
VGPaint fill;
VGPath box;
VGfloat color[4] = {1.f, 0.f, 0.f, 1.f};
VGfloat bgCol[4] = {0.7f, 0.7f, 0.7f, 1.0f};
VGfloat transCol[4] = {0.f, 0.f, 0.f, 0.f};
VGImage image = vgCreateImage(VG_sRGBA_8888, img_width, img_height,
VG_IMAGE_QUALITY_NONANTIALIASED);
/* Background clear */
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
vgSetPaint(fill, VG_FILL_PATH);
box = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
/* Rectangle to cover completely 16x16 pixel area. */
RectToPath(box, 0, 0, 64, 64);
vgSetfv(VG_CLEAR_COLOR, 4, transCol);
vgClearImage(image, 0, 0, img_width, img_height);
vgSetfv(VG_CLEAR_COLOR, 4, color);
vgClearImage(image, 10, 10, 12, 12);
//vgImageSubData(image, pukki_64x64_data, pukki_64x64_stride,
// VG_sRGBA_8888, 0, 0, 32, 32);
vgSeti(VG_MASKING, VG_TRUE);
vgLoadIdentity();
vgSetfv(VG_CLEAR_COLOR, 4, bgCol);
vgClear(0, 0, WINDSIZEX, WINDSIZEY);
vgMask(image, VG_FILL_MASK, 0, 0, window_width(), window_height());
vgMask(image, VG_SET_MASK, x_pos, y_pos, 100, 100);
vgDrawPath(box, VG_FILL_PATH);
//vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
//vgTranslate(-10, -10);
//vgDrawImage(image);
vgDestroyPaint(fill);
vgDestroyPath(box);
}
int main(int argc, char **argv)
{
set_window_size(64, 64);
return run(argc, argv, init, reshape,
draw, key_press);
}

View File

@ -0,0 +1,77 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <VG/vgu.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
static void
init(void)
{
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
static void
draw(void)
{
VGint WINDSIZEX = window_width();
VGint WINDSIZEY = window_height();
VGPath path;
VGPaint paint;
VGfloat clearColor[] = {1.0f, 1.0f, 1.0f, 0.0f};/* white color */
VGfloat fillColor[] = {1.0f, 0.0f, 0.0f, 1.0f};/* red color */
#if 1
VGubyte commands[4] = {VG_MOVE_TO_ABS, VG_LCWARC_TO_ABS, VG_SCWARC_TO_ABS, VG_CLOSE_PATH};
#else
VGubyte commands[4] = {VG_MOVE_TO_ABS, VG_SCCWARC_TO_ABS, VG_LCCWARC_TO_ABS,VG_CLOSE_PATH};
#endif
VGfloat coords[] = {32.0f, 0.0f,
-32.0f, -32.0f, 0.0f, 64.0f, 32.0f,
-32.0f, -32.0f, 0.0f, 32.0f, 0.0f};
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
vgClear(0, 0, WINDSIZEX, WINDSIZEY);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
//vgTranslate(32.0f, 32.0f);
path = vgCreatePath( VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL );
if ( path == VG_INVALID_HANDLE ) {
return;
}
paint = vgCreatePaint();
if ( paint == VG_INVALID_HANDLE ) {
vgDestroyPath(path);
return;
}
vgAppendPathData(path, 4, commands, coords);
vgSetParameterfv(paint, VG_PAINT_COLOR, 4, fillColor);
vgSetParameteri( paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetPaint(paint, VG_FILL_PATH);
vgDrawPath(path, VG_FILL_PATH);
vgDestroyPath(path);
vgDestroyPaint(paint);
}
int main(int argc, char **argv)
{
set_window_size(64, 64);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,99 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <stdio.h>
#include <string.h>
static const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
static VGPath path;
static VGPaint fill;
VGfloat centeredGradient[5] = {200.0f, 200.0f, 200.0f, 200.0f, 100};
VGfloat noncenteredGradient[5] = {200.0f, 200.0f, 250.0f, 250.0f, 100};
VGfloat *radialGradient = centeredGradient;
VGColorRampSpreadMode spread = VG_COLOR_RAMP_SPREAD_PAD;
static void
init(void)
{
static const VGubyte sqrCmds[5] = {VG_MOVE_TO_ABS, VG_HLINE_TO_ABS, VG_VLINE_TO_ABS, VG_HLINE_TO_ABS, VG_CLOSE_PATH};
static const VGfloat sqrCoords[5] = {0.0f, 0.0f, 400.0f, 400.0f, 0.0f};
VGfloat rampStop[] = {0.00f, 1.0f, 1.0f, 1.0f, 1.0f,
0.33f, 1.0f, 0.0f, 0.0f, 1.0f,
0.66f, 0.0f, 1.0f, 0.0f, 1.0f,
1.00f, 0.0f, 0.0f, 1.0f, 1.0f};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 5, sqrCmds, sqrCoords);
fill = vgCreatePaint();
vgSetPaint(fill, VG_FILL_PATH);
vgSetParameteri(fill, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT);
vgSetParameteri(fill, VG_PAINT_COLOR_RAMP_SPREAD_MODE, spread);
vgSetParameterfv(fill, VG_PAINT_RADIAL_GRADIENT, 5, radialGradient);
vgSetParameterfv(fill, VG_PAINT_COLOR_RAMP_STOPS, 20, rampStop);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_FILL_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
VGint i;
for (i = 1; i < argc; ++i) {
const char *arg = argv[i];
if (!strcmp("-pad", arg))
spread = VG_COLOR_RAMP_SPREAD_PAD;
else if (!strcmp("-repeat", arg))
spread = VG_COLOR_RAMP_SPREAD_REPEAT;
else if (!strcmp("-reflect", arg))
spread = VG_COLOR_RAMP_SPREAD_REFLECT;
else if (!strcmp("-center", arg)) {
printf("Centered radial gradient\n");
radialGradient = centeredGradient;
} else if (!strcmp("-noncenter", arg)) {
printf("Non centered radial gradient\n");
radialGradient = noncenteredGradient;
}
}
switch(spread) {
case VG_COLOR_RAMP_SPREAD_PAD:
printf("Using spread mode: pad\n");
break;
case VG_COLOR_RAMP_SPREAD_REPEAT:
printf("Using spread mode: repeat\n");
break;
case VG_COLOR_RAMP_SPREAD_REFLECT:
printf("Using spread mode: reflect\n");
}
set_window_size(400, 400);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,75 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
float red_color[4] = {1.0, 0.0, 0.0, 1.0};
float blue_color[4] = {0.0, 0.0, 1.0, 1.0};
VGint *data;
static void
init(void)
{
data = malloc(sizeof(VGint)*2048*2048);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
static const VGint red_pixel = 255 << 24 | 255 << 16 | 0 << 8 | 0;
static const VGint blue_pixel = 255 << 24 | 0 << 16 | 0 << 8 | 255;
VGint i;
vgSetfv(VG_CLEAR_COLOR, 4, red_color);
vgClear(0, 0, window_width(), window_height());
vgFlush();
memset(data, 0, window_width() * window_height() * sizeof(VGint));
vgReadPixels(data, window_width() * sizeof(VGint),
VG_lARGB_8888,
0, 0, window_width(), window_height());
fprintf(stderr, "Red 0 = 0x%x and at 600 = 0x%x\n",
data[0], data[600]);
for (i = 0; i < window_width() * window_height(); ++i) {
assert(data[i] == red_pixel);
}
vgSetfv(VG_CLEAR_COLOR, 4, blue_color);
vgClear(50, 50, 50, 50);
vgFlush();
memset(data, 0, window_width() * window_height() * sizeof(VGint));
vgReadPixels(data, 50 * sizeof(VGint),
VG_lARGB_8888,
50, 50, 50, 50);
fprintf(stderr, "Blue 0 = 0x%x and at 100 = 0x%x\n",
data[0], data[100]);
for (i = 0; i < 50 * 50; ++i) {
assert(data[i] == blue_pixel);
}
}
int main(int argc, char **argv)
{
int ret = run(argc, argv, init, reshape,
draw, 0);
free(data);
return ret;
}

View File

@ -0,0 +1,67 @@
#include "eglcommon.h"
#include <VG/openvg.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.9, 0.1, 0.1, 0.8};
VGPath path;
VGPaint fill;
static void
init(void)
{
static const VGubyte sqrCmds[10] = {VG_MOVE_TO_ABS,
VG_LINE_TO_ABS,
VG_CUBIC_TO_ABS,
VG_LINE_TO_ABS,
VG_CUBIC_TO_ABS,
VG_LINE_TO_ABS,
VG_CUBIC_TO_ABS,
VG_LINE_TO_ABS,
VG_CUBIC_TO_ABS,
VG_CLOSE_PATH};
static const VGfloat sqrCoords[] = {
45.885571, 62.857143,
154.11442, 62.857143,
162.1236, 62.857143, 168.57142, 70.260744, 168.57142, 79.457144,
168.57142, 123.4,
168.57142, 132.5964, 162.1236, 140, 154.11442, 140,
45.885571, 140,
37.876394, 140, 31.428572, 132.5964, 31.428572, 123.4,
31.428572, 79.457144,
31.428572, 70.260744, 37.876394,62.857143, 45.885571,62.857143
};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 10, sqrCmds, sqrCoords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
vgSetPaint(fill, VG_FILL_PATH);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
vgSetf(VG_STROKE_LINE_WIDTH, 6);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_STROKE_PATH);
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,55 @@
#include "eglcommon.h"
#include <VG/openvg.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat green_color[4] = {0.0, 1.0, 0.0, 0.8};
VGPath path;
VGPaint fill;
static void
init(void)
{
static const VGubyte cmds[6] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS,
VG_LINE_TO_ABS, VG_CLOSE_PATH};
static const VGfloat coords[] = { 0, 200,
300, 200,
50, 0,
150, 300,
250, 0};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 6, cmds, coords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, green_color);
vgSetPaint(fill, VG_FILL_PATH);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
vgSeti(VG_FILL_RULE, VG_NON_ZERO);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,102 @@
#include "eglcommon.h"
#include <VG/openvg.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat green_color[4] = {0.0, 1.0, 0.0, 0.8};
const VGfloat black_color[4] = {0.0, 0.0, 0.0, 1.0};
VGPath path;
VGPaint fill;
static void draw_point(VGfloat x, VGfloat y)
{
static const VGubyte cmds[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS,
VG_LINE_TO_ABS, VG_CLOSE_PATH};
const VGfloat coords[] = { x - 2, y - 2,
x + 2, y - 2,
x + 2, y + 2,
x - 2, y + 2};
VGPath path;
VGPaint fill;
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_ALL);
vgAppendPathData(path, 5, cmds, coords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, black_color);
vgSetPaint(fill, VG_FILL_PATH);
vgDrawPath(path, VG_FILL_PATH);
vgDestroyPath(path);
vgDestroyPaint(fill);
}
static void draw_marks(VGPath path)
{
VGfloat point[2], tangent[2];
int i = 0;
for (i = 0; i < 1300; i += 50) {
vgPointAlongPath(path, 0, 6, i,
point + 0, point + 1,
tangent + 0, tangent + 1);
draw_point(point[0], point[1]);
}
}
static void
init(void)
{
static const VGubyte cmds[6] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS,
VG_LINE_TO_ABS, VG_CLOSE_PATH};
static const VGfloat coords[] = { 0, 200,
300, 200,
50, 0,
150, 300,
250, 0};
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_ALL);
vgAppendPathData(path, 6, cmds, coords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, green_color);
vgSetPaint(fill, VG_FILL_PATH);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
VGfloat point[2], tangent[2];
int i = 0;
vgClear(0, 0, window_width(), window_height());
vgSetPaint(fill, VG_FILL_PATH);
vgDrawPath(path, VG_FILL_PATH);
draw_marks(path);
vgFlush();
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,116 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <X11/keysym.h>
#include <stdio.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.4, 0.1, 1.0, 1.0};
VGPath path;
VGPaint fill;
VGint cap_style = VG_CAP_BUTT;
VGint join_style = VG_JOIN_MITER;
static void
init(void)
{
#if 0
static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
VG_CUBIC_TO_ABS,
};
static const VGfloat coords[] = {30, 30, 264, 0, 0, 264, 234, 234
};
#else
static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
VG_LINE_TO_ABS,
VG_LINE_TO_ABS
};
static const VGfloat coords[] = {30, 30, 202, 30, 150, 224
};
#endif
VGfloat dash_pattern[2] = { 20.f, 20.f };
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
vgAppendPathData(path, 3, cmds, coords);
fill = vgCreatePaint();
vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
vgSetPaint(fill, VG_FILL_PATH);
vgSetfv(VG_CLEAR_COLOR, 4, white_color);
vgSetf(VG_STROKE_LINE_WIDTH, 20);
vgSeti(VG_STROKE_CAP_STYLE, cap_style);
vgSeti(VG_STROKE_JOIN_STYLE, join_style);
vgSetfv(VG_STROKE_DASH_PATTERN, 2, dash_pattern);
vgSetf(VG_STROKE_DASH_PHASE, 0.0f);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_STROKE_PATH);
vgFlush();
}
static int key_press(unsigned key)
{
switch(key) {
case XK_c:
case XK_C:
++cap_style;
if (cap_style > VG_CAP_SQUARE)
cap_style = VG_CAP_BUTT;
switch(cap_style) {
case VG_CAP_BUTT:
fprintf(stderr, "Cap style 'butt'\n");
break;
case VG_CAP_ROUND:
fprintf(stderr, "Cap style 'round'\n");
break;
case VG_CAP_SQUARE:
fprintf(stderr, "Cap style 'square'\n");
break;
}
vgSeti(VG_STROKE_CAP_STYLE, cap_style);
break;
case XK_j:
case XK_J:
++join_style;
if (join_style > VG_JOIN_BEVEL)
join_style = VG_JOIN_MITER;
switch(join_style) {
case VG_JOIN_MITER:
fprintf(stderr, "Join style 'miter'\n");
break;
case VG_JOIN_ROUND:
fprintf(stderr, "Join style 'round'\n");
break;
case VG_JOIN_BEVEL:
fprintf(stderr, "Join style 'bevel'\n");
break;
}
vgSeti(VG_STROKE_JOIN_STYLE, join_style);
break;
default:
break;
}
return VG_TRUE;
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, key_press);
}

View File

@ -0,0 +1,207 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <X11/keysym.h>
#include <stdio.h>
VGPaint stroke;
VGPath target;
VGPath lines;
VGfloat xform[9];
VGfloat color1[4];
VGfloat color2[4];
VGfloat bgCol[4];
static void
init(void)
{
VGubyte lineCmds[6];
VGfloat lineCoords[8];
VGfloat arcCoords[5];
VGubyte sccCmd[1];
VGubyte scCmd[1];
VGubyte lccCmd[1];
VGubyte lcCmd[1];
VGubyte moveCmd[1];
VGfloat moveCoords[2];
VGint i;
bgCol[0] = 1.0f;
bgCol[1] = 1.0f;
bgCol[2] = 1.0f;
bgCol[3] = 1.0f;
vgSetfv(VG_CLEAR_COLOR, 4, bgCol);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
stroke = vgCreatePaint();
/* Red */
color1[0] = 1.0f;
color1[1] = 0.0f;
color1[2] = 0.0f;
color1[3] = 1.0f;
/* Orange */
color2[0] = 1.0000f;
color2[1] = 1.0f;
color2[2] = 0.0f;
color2[3] = 1.0f;
vgSetPaint(stroke, VG_STROKE_PATH);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_SQUARE);
{
VGfloat temp[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
for (i = 0; i < 9; i++)
{
xform[i] = temp[i];
}
}
vgGetMatrix(xform);
target = vgCreatePath(VG_PATH_FORMAT_STANDARD,
VG_PATH_DATATYPE_F, 1, 0, 0, 0, VG_PATH_CAPABILITY_TRANSFORM_TO);
#if 0
/* Line path */
{
VGubyte temp[6] = {VG_MOVE_TO_ABS, VG_VLINE_TO_REL,
VG_MOVE_TO_ABS, VG_VLINE_TO_REL,
VG_HLINE_TO_REL, VG_VLINE_TO_REL};
for (i = 0; i < 6; i++)
{
lineCmds[i] = temp[i];
}
}
{
VGfloat temp[8] = {0.5f, 0.8f, -0.6f, 0.28f, 0.6f, -0.4f, 0.44f, 0.4f};
for (i = 0; i < 8; i++)
{
lineCoords[i] = temp[i] * window_width();
}
}
#else
{
VGfloat temp[5] = {0.35f, 0.15f, 29, 0.3f, 0.4f};
for (i = 0; i < 5; i++)
{
arcCoords[i] = temp[i] * window_width();
}
arcCoords[2] = 29;
}
{
VGubyte temp[1] = {VG_SCCWARC_TO_ABS};
for (i = 0; i < 1; i++)
{
sccCmd[i] = temp[i];
}
}
{
VGubyte temp[1] = {VG_SCWARC_TO_ABS};
for (i = 0; i < 1; i++)
{
scCmd[i] = temp[i];
}
}
{
VGubyte temp[1] = {VG_LCCWARC_TO_ABS};
for (i = 0; i < 1; i++)
{
lccCmd[i] = temp[i];
}
}
{
VGubyte temp[1] = {VG_LCWARC_TO_ABS};
for (i = 0; i < 1; i++)
{
lcCmd[i] = temp[i];
}
}
{
VGubyte temp[1] = {VG_MOVE_TO_ABS};
for (i = 0; i < 1; i++)
{
moveCmd[i] = temp[i];
}
}
{
VGfloat temp[2] = {0.7f, 0.6f};
for (i = 0; i < 2; i++)
{
moveCoords[i] = temp[i] * window_width();
}
}
#endif
lines = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1,
0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO|
VG_PATH_CAPABILITY_TRANSFORM_FROM);
#if 0
vgAppendPathData(lines, 6, lineCmds, lineCoords);
#else
vgAppendPathData(lines, 1, moveCmd, moveCoords);
vgAppendPathData(lines, 1, sccCmd, arcCoords);
vgAppendPathData(lines, 1, moveCmd, moveCoords);
vgAppendPathData(lines, 1, scCmd, arcCoords);
vgAppendPathData(lines, 1, moveCmd, moveCoords);
vgAppendPathData(lines, 1, lccCmd, arcCoords);
vgAppendPathData(lines, 1, moveCmd, moveCoords);
vgAppendPathData(lines, 1, lcCmd, arcCoords);
#endif
vgLoadIdentity();
vgTranslate(0.25f * window_width(), 0.25f * window_height());
vgRotate(30);
vgTranslate(-0.25f * window_width(), -0.25f * window_height());
vgTransformPath(target, lines);}
/* new window size or exposure */
static void
reshape(int w, int h)
{
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgLoadMatrix(xform);
vgLoadIdentity();
vgTranslate(0.25f * window_width(), 0.25f * window_height());
vgRotate(30);
vgTranslate(-0.25f * window_width(), -0.25f * window_height());
vgSetf(VG_STROKE_LINE_WIDTH, 7);
vgSetParameterfv(stroke, VG_PAINT_COLOR, 4, color1);
vgDrawPath(lines, VG_STROKE_PATH);
vgLoadMatrix(xform);
vgSetParameterfv(stroke, VG_PAINT_COLOR, 4, color2);
vgSetf(VG_STROKE_LINE_WIDTH, 3);
vgDrawPath(target, VG_STROKE_PATH);
}
static int key_press(unsigned key)
{
switch(key) {
case XK_c:
case XK_C:
break;
case XK_j:
case XK_J:
break;
default:
break;
}
return VG_TRUE;
}
int main(int argc, char **argv)
{
return run(argc, argv, init, reshape,
draw, key_press);
}

View File

@ -0,0 +1,74 @@
#include "eglcommon.h"
#include <VG/openvg.h>
#include <VG/vgu.h>
const VGfloat white_color[4] = {1.0, 1.0, 1.0, 1.0};
const VGfloat color[4] = {0.4, 0.1, 1.0, 1.0};
VGPath path;
VGPaint paint;
static void
init(void)
{
VGfloat clearColor[] = {0.0f, 0.0f, 0.0f, 1.0f};/* black color */
VGfloat greenColor[] = {0.0f, 1.0f, 0.0f, 1.0f};/* green color */
VGint arcType = VGU_ARC_OPEN;
VGfloat x, y, w, h, startAngle, angleExtent;
x = 150;
y = 150;
w = 150;
h = 150;
#if 0
startAngle = -540.0f;
angleExtent = 270.0f;
#else
startAngle = 270.0f;
angleExtent = 90.0f;
#endif
paint = vgCreatePaint();
vgSetPaint(paint, VG_STROKE_PATH);
vgSetParameterfv(paint, VG_PAINT_COLOR, 4, greenColor);
vgSetParameteri( paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetf(VG_STROKE_LINE_WIDTH, 6.0f);
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
vguArc(path, x, y, w, h, startAngle, angleExtent, arcType);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_BEVEL);
vgSetf(VG_STROKE_MITER_LIMIT, 4.0f);
}
/* new window size or exposure */
static void
reshape(int w, int h)
{
vgLoadIdentity();
}
static void
draw(void)
{
vgClear(0, 0, window_width(), window_height());
vgDrawPath(path, VG_STROKE_PATH);
vgFlush();
}
int main(int argc, char **argv)
{
// set_window_size(64, 63);
return run(argc, argv, init, reshape,
draw, 0);
}

View File

@ -0,0 +1,128 @@
# src/mesa/Makefile
TOP = ../../../..
include $(TOP)/configs/current
GALLIUM = $(TOP)
### Lists of source files, included by Makefiles
VG_SOURCES = \
api_context.c \
api_filters.c \
api_images.c \
api_masks.c \
api_misc.c \
api_paint.c \
api_params.c \
api_path.c \
api_text.c \
api_transform.c \
vgu.c \
vg_context.c \
vg_state.c \
vg_tracker.c \
vg_translate.c \
polygon.c \
bezier.c \
path.c \
paint.c \
arc.c \
image.c \
renderer.c \
stroker.c \
mask.c \
shader.c \
shaders_cache.c
### All the core C sources
ALL_SOURCES = \
$(VG_SOURCES)
### Object files
VG_OBJECTS = \
$(VG_SOURCES:.c=.o)
### Include directories
INCLUDE_DIRS = \
-I$(TOP)/include \
-I$(GALLIUM)/include \
-I$(GALLIUM)/src/gallium/include \
-I$(GALLIUM)/src/gallium/auxiliary
VG_LIB = OpenVG
VG_LIB_NAME = lib$(VG_LIB).so
VG_MAJOR = 1
VG_MINOR = 0
VG_TINY = 0
GALLIUM_LIBS = \
$(GALLIUM)/src/gallium/auxiliary/pipebuffer/libpipebuffer.a \
$(GALLIUM)/src/gallium/auxiliary/sct/libsct.a \
$(GALLIUM)/src/gallium/auxiliary/draw/libdraw.a \
$(GALLIUM)/src/gallium/auxiliary/rtasm/librtasm.a \
$(GALLIUM)/src/gallium/auxiliary/translate/libtranslate.a \
$(GALLIUM)/src/gallium/auxiliary/cso_cache/libcso_cache.a \
$(GALLIUM)/src/gallium/auxiliary/util/libutil.a \
$(GALLIUM)/src/gallium/auxiliary/tgsi/libtgsi.a
.SUFFIXES : .cpp
.c.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
.cpp.o:
$(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@
.S.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
default: depend subdirs $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME)
# Make the OpenVG library
$(TOP)/$(LIB_DIR)/$(VG_LIB_NAME): $(VG_OBJECTS) $(GALLIUM_LIBS)
$(TOP)/bin/mklib -o $(VG_LIB) \
-major $(VG_MAJOR) \
-minor $(VG_MINOR) \
-patch $(VG_TINY) \
-install $(TOP)/$(LIB_DIR) \
$(VG_OBJECTS) $(GALLIUM_LIBS) \
-Wl,--whole-archive $(LIBS) -Wl,--no-whole-archive $(SYS_LIBS)
######################################################################
# Generic stuff
depend: $(ALL_SOURCES)
@ echo "running $(MKDEP)"
@ rm -f depend # workaround oops on gutsy?!?
@ touch depend
@ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \
> /dev/null 2>/dev/null
subdirs:
install: default
$(INSTALL) -d $(INSTALL_DIR)/include/VG
$(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
$(INSTALL) -m 644 $(TOP)/include/VG/*.h $(INSTALL_DIR)/include/VG
@if [ -e $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) ]; then \
$(INSTALL) $(TOP)/$(LIB_DIR)/libOpenVG* $(INSTALL_DIR)/$(LIB_DIR); \
fi
# Emacs tags
tags:
etags `find . -name \*.[ch]` $(TOP)/include/VG/*.h
clean:
-rm -f *.o
-rm -f */*.o
-rm -f */*/*.o
-rm -f depend depend.bak
include depend

View File

@ -0,0 +1,56 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef API_CONSTS_H
#define API_CONSTS_H
/*must be at least 32*/
#define VEGA_MAX_SCISSOR_RECTS 32
/*must be at least 16*/
#define VEGA_MAX_DASH_COUNT 32
/*must be at least 7*/
#define VEGA_MAX_KERNEL_SIZE 7
/*must be at least 15*/
#define VEGA_MAX_SEPARABLE_KERNEL_SIZE 15
/*must be at least 32*/
#define VEGA_MAX_COLOR_RAMP_STOPS 256
#define VEGA_MAX_IMAGE_WIDTH 2048
#define VEGA_MAX_IMAGE_HEIGHT 2048
#define VEGA_MAX_IMAGE_PIXELS (2048*2048)
#define VEGA_MAX_IMAGE_BYTES (2048*2048 * 4)
/*must be at least 128*/
#define VEGA_MAX_GAUSSIAN_STD_DEVIATION 128
#endif

View File

@ -0,0 +1,75 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "vg_context.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
VGErrorCode vgGetError(void)
{
struct vg_context *ctx = vg_current_context();
VGErrorCode error = VG_NO_CONTEXT_ERROR;
if (!ctx)
return error;
error = ctx->_error;
ctx->_error = VG_NO_ERROR;
return error;
}
void vgFlush(void)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe;
if (!ctx)
return;
pipe = ctx->pipe;
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
}
void vgFinish(void)
{
struct vg_context *ctx = vg_current_context();
struct pipe_fence_handle *fence = NULL;
struct pipe_context *pipe;
if (!ctx)
return;
pipe = ctx->pipe;
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
pipe->screen->fence_finish(pipe->screen, fence, 0);
pipe->screen->fence_reference(pipe->screen, &fence, NULL);
}

View File

@ -0,0 +1,805 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "vg_context.h"
#include "image.h"
#include "renderer.h"
#include "shaders_cache.h"
#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
#include "pipe/p_screen.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_memory.h"
#include "asm_filters.h"
struct filter_info {
struct vg_image *dst;
struct vg_image *src;
struct vg_shader * (*setup_shader)(struct vg_context *, void *);
void *user_data;
const void *const_buffer;
VGint const_buffer_len;
VGTilingMode tiling_mode;
struct pipe_texture *extra_texture;
};
static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx,
const VGuint *color_data,
const VGint color_data_len)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_texture *tex = 0;
struct pipe_texture templ;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_1D;
templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
templ.last_level = 0;
templ.width[0] = color_data_len;
templ.height[0] = 1;
templ.depth[0] = 1;
pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &templ.block);
templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
tex = screen->texture_create(screen, &templ);
{ /* upload color_data */
struct pipe_transfer *transfer =
screen->get_tex_transfer(screen, tex,
0, 0, 0,
PIPE_TRANSFER_READ_WRITE ,
0, 0, tex->width[0], tex->height[0]);
void *map = screen->transfer_map(screen, transfer);
memcpy(map, color_data, sizeof(VGint)*color_data_len);
screen->transfer_unmap(screen, transfer);
screen->tex_transfer_destroy(transfer);
}
return tex;
}
static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
struct pipe_framebuffer_state fb;
struct pipe_surface *dst_surf = pipe->screen->get_tex_surface(
pipe->screen, dst->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* drawing dest */
memset(&fb, 0, sizeof(fb));
fb.width = dst->x + dst_surf->width;
fb.height = dst->y + dst_surf->height;
fb.nr_cbufs = 1;
fb.cbufs[0] = dst_surf;
{
VGint i;
for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
fb.cbufs[i] = 0;
}
cso_set_framebuffer(ctx->cso_context, &fb);
return dst_surf;
}
static void setup_viewport(struct vg_image *dst)
{
struct vg_context *ctx = vg_current_context();
vg_set_viewport(ctx, VEGA_Y0_TOP);
}
static void setup_blend()
{
struct vg_context *ctx = vg_current_context();
struct pipe_blend_state blend;
memset(&blend, 0, sizeof(blend));
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
if (ctx->state.vg.filter_channel_mask & VG_RED)
blend.colormask |= PIPE_MASK_R;
if (ctx->state.vg.filter_channel_mask & VG_GREEN)
blend.colormask |= PIPE_MASK_G;
if (ctx->state.vg.filter_channel_mask & VG_BLUE)
blend.colormask |= PIPE_MASK_B;
if (ctx->state.vg.filter_channel_mask & VG_ALPHA)
blend.colormask |= PIPE_MASK_A;
blend.blend_enable = 1;
cso_set_blend(ctx->cso_context, &blend);
}
static void setup_constant_buffer(struct vg_context *ctx, const void *buffer,
VGint param_bytes)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_constant_buffer *cbuf = &ctx->filter.buffer;
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization. */
pipe_buffer_reference(&cbuf->buffer, NULL);
cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
PIPE_BUFFER_USAGE_CONSTANT,
param_bytes);
if (cbuf->buffer) {
st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
0, param_bytes, buffer);
}
ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
}
static void setup_samplers(struct vg_context *ctx, struct filter_info *info)
{
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
struct pipe_sampler_state sampler[3];
int num_samplers = 0;
int num_textures = 0;
samplers[0] = NULL;
samplers[1] = NULL;
samplers[2] = NULL;
samplers[3] = NULL;
textures[0] = NULL;
textures[1] = NULL;
textures[2] = NULL;
textures[3] = NULL;
memset(&sampler[0], 0, sizeof(struct pipe_sampler_state));
sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler[0].wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler[0].min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
sampler[0].mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
sampler[0].normalized_coords = 1;
switch(info->tiling_mode) {
case VG_TILE_FILL:
sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
memcpy(sampler[0].border_color,
ctx->state.vg.tile_fill_color,
sizeof(VGfloat) * 4);
break;
case VG_TILE_PAD:
sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
break;
case VG_TILE_REPEAT:
sampler[0].wrap_s = PIPE_TEX_WRAP_REPEAT;
sampler[0].wrap_t = PIPE_TEX_WRAP_REPEAT;
break;
case VG_TILE_REFLECT:
sampler[0].wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
sampler[0].wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
break;
default:
debug_assert(!"Unknown tiling mode");
}
samplers[0] = &sampler[0];
textures[0] = info->src->texture;
++num_samplers;
++num_textures;
if (info->extra_texture) {
memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state));
samplers[1] = &sampler[1];
textures[1] = info->extra_texture;
++num_samplers;
++num_textures;
}
cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers);
cso_set_sampler_textures(ctx->cso_context, num_textures, textures);
}
static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data)
{
struct vg_shader *shader =
shader_create_from_text(ctx->pipe, color_matrix_asm, 200,
PIPE_SHADER_FRAGMENT);
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
static struct vg_shader * setup_convolution(struct vg_context *ctx, void *user_data)
{
char buffer[1024];
VGint num_consts = (VGint)(long)(user_data);
struct vg_shader *shader;
snprintf(buffer, 1023, convolution_asm, num_consts, num_consts / 2 + 1);
shader = shader_create_from_text(ctx->pipe, buffer, 200,
PIPE_SHADER_FRAGMENT);
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
static struct vg_shader * setup_lookup(struct vg_context *ctx, void *user_data)
{
struct vg_shader *shader =
shader_create_from_text(ctx->pipe, lookup_asm,
200, PIPE_SHADER_FRAGMENT);
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
static struct vg_shader * setup_lookup_single(struct vg_context *ctx, void *user_data)
{
char buffer[1024];
VGImageChannel channel = (VGImageChannel)(user_data);
struct vg_shader *shader;
switch(channel) {
case VG_RED:
snprintf(buffer, 1023, lookup_single_asm, "xxxx");
break;
case VG_GREEN:
snprintf(buffer, 1023, lookup_single_asm, "yyyy");
break;
case VG_BLUE:
snprintf(buffer, 1023, lookup_single_asm, "zzzz");
break;
case VG_ALPHA:
snprintf(buffer, 1023, lookup_single_asm, "wwww");
break;
default:
debug_assert(!"Unknown color channel");
}
shader = shader_create_from_text(ctx->pipe, buffer, 200,
PIPE_SHADER_FRAGMENT);
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
static void execute_filter(struct vg_context *ctx,
struct filter_info *info)
{
struct pipe_surface *dst_surf;
struct vg_shader *shader;
cso_save_framebuffer(ctx->cso_context);
cso_save_fragment_shader(ctx->cso_context);
cso_save_viewport(ctx->cso_context);
cso_save_blend(ctx->cso_context);
cso_save_samplers(ctx->cso_context);
cso_save_sampler_textures(ctx->cso_context);
dst_surf = setup_framebuffer(info->dst);
setup_viewport(info->dst);
setup_blend();
setup_constant_buffer(ctx, info->const_buffer, info->const_buffer_len);
shader = info->setup_shader(ctx, info->user_data);
setup_samplers(ctx, info);
renderer_draw_texture(ctx->renderer,
info->src->texture,
info->dst->x, info->dst->y,
info->dst->x + info->dst->width,
info->dst->y + info->dst->height,
info->dst->x, info->dst->y,
info->dst->x + info->dst->width,
info->dst->y + info->dst->height);
cso_restore_framebuffer(ctx->cso_context);
cso_restore_fragment_shader(ctx->cso_context);
cso_restore_viewport(ctx->cso_context);
cso_restore_blend(ctx->cso_context);
cso_restore_samplers(ctx->cso_context);
cso_restore_sampler_textures(ctx->cso_context);
vg_shader_destroy(ctx, shader);
pipe_surface_reference(&dst_surf, NULL);
}
void vgColorMatrix(VGImage dst, VGImage src,
const VGfloat * matrix)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *d, *s;
struct filter_info info;
if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!matrix || !is_aligned(matrix)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
d = (struct vg_image*)dst;
s = (struct vg_image*)src;
if (vg_image_overlaps(d, s)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
info.dst = d;
info.src = s;
info.setup_shader = &setup_color_matrix;
info.user_data = NULL;
info.const_buffer = matrix;
info.const_buffer_len = 20 * sizeof(VGfloat);
info.tiling_mode = VG_TILE_PAD;
info.extra_texture = 0;
execute_filter(ctx, &info);
}
static VGfloat texture_offset(VGfloat width, VGint kernelSize, VGint current, VGint shift)
{
VGfloat diff = current - shift;
return diff / width;
}
void vgConvolve(VGImage dst, VGImage src,
VGint kernelWidth, VGint kernelHeight,
VGint shiftX, VGint shiftY,
const VGshort * kernel,
VGfloat scale,
VGfloat bias,
VGTilingMode tilingMode)
{
struct vg_context *ctx = vg_current_context();
VGfloat *buffer;
VGint buffer_len;
VGint i, j;
VGint idx = 0;
struct vg_image *d, *s;
VGint kernel_size = kernelWidth * kernelHeight;
struct filter_info info;
const VGint max_kernel_size = vgGeti(VG_MAX_KERNEL_SIZE);
if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (kernelWidth <= 0 || kernelHeight <= 0 ||
kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!kernel || !is_aligned_to(kernel, 2)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (tilingMode < VG_TILE_FILL ||
tilingMode > VG_TILE_REFLECT) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
d = (struct vg_image*)dst;
s = (struct vg_image*)src;
if (vg_image_overlaps(d, s)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
vg_validate_state(ctx);
buffer_len = 8 + 2 * 4 * kernel_size;
buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat));
buffer[0] = 0.f;
buffer[1] = 1.f;
buffer[2] = 2.f; /*unused*/
buffer[3] = 4.f; /*unused*/
buffer[4] = kernelWidth * kernelHeight;
buffer[5] = scale;
buffer[6] = bias;
buffer[7] = 0.f;
idx = 8;
for (j = 0; j < kernelHeight; ++j) {
for (i = 0; i < kernelWidth; ++i) {
VGint index = j * kernelWidth + i;
VGfloat x, y;
x = texture_offset(s->width, kernelWidth, i, shiftX);
y = texture_offset(s->height, kernelHeight, j, shiftY);
buffer[idx + index*4 + 0] = x;
buffer[idx + index*4 + 1] = y;
buffer[idx + index*4 + 2] = 0.f;
buffer[idx + index*4 + 3] = 0.f;
}
}
idx += kernel_size * 4;
for (j = 0; j < kernelHeight; ++j) {
for (i = 0; i < kernelWidth; ++i) {
/* transpose the kernel */
VGint index = j * kernelWidth + i;
VGint kindex = (kernelWidth - i - 1) * kernelHeight + (kernelHeight - j - 1);
buffer[idx + index*4 + 0] = kernel[kindex];
buffer[idx + index*4 + 1] = kernel[kindex];
buffer[idx + index*4 + 2] = kernel[kindex];
buffer[idx + index*4 + 3] = kernel[kindex];
}
}
info.dst = d;
info.src = s;
info.setup_shader = &setup_convolution;
info.user_data = (void*)(long)(buffer_len/4);
info.const_buffer = buffer;
info.const_buffer_len = buffer_len * sizeof(VGfloat);
info.tiling_mode = tilingMode;
info.extra_texture = 0;
execute_filter(ctx, &info);
free(buffer);
}
void vgSeparableConvolve(VGImage dst, VGImage src,
VGint kernelWidth,
VGint kernelHeight,
VGint shiftX, VGint shiftY,
const VGshort * kernelX,
const VGshort * kernelY,
VGfloat scale,
VGfloat bias,
VGTilingMode tilingMode)
{
struct vg_context *ctx = vg_current_context();
VGshort *kernel;
VGint i, j, idx = 0;
const VGint max_kernel_size = vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE);
if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (kernelWidth <= 0 || kernelHeight <= 0 ||
kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!kernelX || !kernelY ||
!is_aligned_to(kernelX, 2) || !is_aligned_to(kernelY, 2)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (tilingMode < VG_TILE_FILL ||
tilingMode > VG_TILE_REFLECT) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
kernel = malloc(sizeof(VGshort)*kernelWidth*kernelHeight);
for (i = 0; i < kernelWidth; ++i) {
for (j = 0; j < kernelHeight; ++j) {
kernel[idx] = kernelX[i] * kernelY[j];
++idx;
}
}
vgConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY,
kernel, scale, bias, tilingMode);
free(kernel);
}
static INLINE VGfloat compute_gaussian_componenet(VGfloat x, VGfloat y,
VGfloat stdDeviationX,
VGfloat stdDeviationY)
{
VGfloat mult = 1 / ( 2 * M_PI * stdDeviationX * stdDeviationY);
VGfloat e = exp( - ( pow(x, 2)/(2*pow(stdDeviationX, 2)) +
pow(y, 2)/(2*pow(stdDeviationY, 2)) ) );
return mult * e;
}
static INLINE VGint compute_kernel_size(VGfloat deviation)
{
VGint size = ceil(2.146 * deviation);
if (size > 11)
return 11;
return size;
}
static void compute_gaussian_kernel(VGfloat *kernel,
VGint width, VGint height,
VGfloat stdDeviationX,
VGfloat stdDeviationY)
{
VGint i, j;
VGfloat scale = 0.0f;
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
VGint idx = (height - j -1) * width + (width - i -1);
kernel[idx] = compute_gaussian_componenet(i-(ceil(width/2))-1,
j-ceil(height/2)-1,
stdDeviationX, stdDeviationY);
scale += kernel[idx];
}
}
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
VGint idx = j * width + i;
kernel[idx] /= scale;
}
}
}
void vgGaussianBlur(VGImage dst, VGImage src,
VGfloat stdDeviationX,
VGfloat stdDeviationY,
VGTilingMode tilingMode)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *d, *s;
VGfloat *buffer, *kernel;
VGint kernel_width, kernel_height, kernel_size;
VGint buffer_len;
VGint idx, i, j;
struct filter_info info;
if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (stdDeviationX <= 0 || stdDeviationY <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (tilingMode < VG_TILE_FILL ||
tilingMode > VG_TILE_REFLECT) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
d = (struct vg_image*)dst;
s = (struct vg_image*)src;
if (vg_image_overlaps(d, s)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
kernel_width = compute_kernel_size(stdDeviationX);
kernel_height = compute_kernel_size(stdDeviationY);
kernel_size = kernel_width * kernel_height;
kernel = malloc(sizeof(VGfloat)*kernel_size);
compute_gaussian_kernel(kernel, kernel_width, kernel_height,
stdDeviationX, stdDeviationY);
buffer_len = 8 + 2 * 4 * kernel_size;
buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat));
buffer[0] = 0.f;
buffer[1] = 1.f;
buffer[2] = 2.f; /*unused*/
buffer[3] = 4.f; /*unused*/
buffer[4] = kernel_width * kernel_height;
buffer[5] = 1.f;/*scale*/
buffer[6] = 0.f;/*bias*/
buffer[7] = 0.f;
idx = 8;
for (j = 0; j < kernel_height; ++j) {
for (i = 0; i < kernel_width; ++i) {
VGint index = j * kernel_width + i;
VGfloat x, y;
x = texture_offset(s->width, kernel_width, i, kernel_width/2);
y = texture_offset(s->height, kernel_height, j, kernel_height/2);
buffer[idx + index*4 + 0] = x;
buffer[idx + index*4 + 1] = y;
buffer[idx + index*4 + 2] = 0.f;
buffer[idx + index*4 + 3] = 0.f;
}
}
idx += kernel_size * 4;
for (j = 0; j < kernel_height; ++j) {
for (i = 0; i < kernel_width; ++i) {
/* transpose the kernel */
VGint index = j * kernel_width + i;
VGint kindex = (kernel_width - i - 1) * kernel_height + (kernel_height - j - 1);
buffer[idx + index*4 + 0] = kernel[kindex];
buffer[idx + index*4 + 1] = kernel[kindex];
buffer[idx + index*4 + 2] = kernel[kindex];
buffer[idx + index*4 + 3] = kernel[kindex];
}
}
info.dst = d;
info.src = s;
info.setup_shader = &setup_convolution;
info.user_data = (void*)(long)(buffer_len/4);
info.const_buffer = buffer;
info.const_buffer_len = buffer_len * sizeof(VGfloat);
info.tiling_mode = tilingMode;
info.extra_texture = 0;
execute_filter(ctx, &info);
free(buffer);
free(kernel);
}
void vgLookup(VGImage dst, VGImage src,
const VGubyte * redLUT,
const VGubyte * greenLUT,
const VGubyte * blueLUT,
const VGubyte * alphaLUT,
VGboolean outputLinear,
VGboolean outputPremultiplied)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *d, *s;
VGuint color_data[256];
VGint i;
struct pipe_texture *lut_texture;
VGfloat buffer[4];
struct filter_info info;
if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!redLUT || !greenLUT || !blueLUT || !alphaLUT) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
d = (struct vg_image*)dst;
s = (struct vg_image*)src;
if (vg_image_overlaps(d, s)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
for (i = 0; i < 256; ++i) {
color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 |
redLUT[i] << 8 | alphaLUT[i];
}
lut_texture = create_texture_1d(ctx, color_data, 255);
buffer[0] = 0.f;
buffer[1] = 0.f;
buffer[2] = 1.f;
buffer[3] = 1.f;
info.dst = d;
info.src = s;
info.setup_shader = &setup_lookup;
info.user_data = NULL;
info.const_buffer = buffer;
info.const_buffer_len = 4 * sizeof(VGfloat);
info.tiling_mode = VG_TILE_PAD;
info.extra_texture = lut_texture;
execute_filter(ctx, &info);
pipe_texture_reference(&lut_texture, NULL);
}
void vgLookupSingle(VGImage dst, VGImage src,
const VGuint * lookupTable,
VGImageChannel sourceChannel,
VGboolean outputLinear,
VGboolean outputPremultiplied)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *d, *s;
struct pipe_texture *lut_texture;
VGfloat buffer[4];
struct filter_info info;
VGuint color_data[256];
VGint i;
if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!lookupTable || !is_aligned(lookupTable)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (sourceChannel != VG_RED && sourceChannel != VG_GREEN &&
sourceChannel != VG_BLUE && sourceChannel != VG_ALPHA) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
d = (struct vg_image*)dst;
s = (struct vg_image*)src;
if (vg_image_overlaps(d, s)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
for (i = 0; i < 256; ++i) {
VGuint rgba = lookupTable[i];
VGubyte blue, green, red, alpha;
red = (rgba & 0xff000000)>>24;
green = (rgba & 0x00ff0000)>>16;
blue = (rgba & 0x0000ff00)>> 8;
alpha = (rgba & 0x000000ff)>> 0;
color_data[i] = blue << 24 | green << 16 |
red << 8 | alpha;
}
lut_texture = create_texture_1d(ctx, color_data, 256);
buffer[0] = 0.f;
buffer[1] = 0.f;
buffer[2] = 1.f;
buffer[3] = 1.f;
info.dst = d;
info.src = s;
info.setup_shader = &setup_lookup_single;
info.user_data = (void*)sourceChannel;
info.const_buffer = buffer;
info.const_buffer_len = 4 * sizeof(VGfloat);
info.tiling_mode = VG_TILE_PAD;
info.extra_texture = lut_texture;
execute_filter(ctx, &info);
pipe_texture_reference(&lut_texture, NULL);
}

View File

@ -0,0 +1,489 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "image.h"
#include "VG/openvg.h"
#include "vg_context.h"
#include "vg_translate.h"
#include "api_consts.h"
#include "image.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_inlines.h"
#include "util/u_blit.h"
#include "util/u_tile.h"
#include "util/u_memory.h"
static INLINE VGboolean supported_image_format(VGImageFormat format)
{
switch(format) {
case VG_sRGBX_8888:
case VG_sRGBA_8888:
case VG_sRGBA_8888_PRE:
case VG_sRGB_565:
case VG_sRGBA_5551:
case VG_sRGBA_4444:
case VG_sL_8:
case VG_lRGBX_8888:
case VG_lRGBA_8888:
case VG_lRGBA_8888_PRE:
case VG_lL_8:
case VG_A_8:
case VG_BW_1:
#ifdef OPENVG_VERSION_1_1
case VG_A_1:
case VG_A_4:
#endif
case VG_sXRGB_8888:
case VG_sARGB_8888:
case VG_sARGB_8888_PRE:
case VG_sARGB_1555:
case VG_sARGB_4444:
case VG_lXRGB_8888:
case VG_lARGB_8888:
case VG_lARGB_8888_PRE:
case VG_sBGRX_8888:
case VG_sBGRA_8888:
case VG_sBGRA_8888_PRE:
case VG_sBGR_565:
case VG_sBGRA_5551:
case VG_sBGRA_4444:
case VG_lBGRX_8888:
case VG_lBGRA_8888:
case VG_lBGRA_8888_PRE:
case VG_sXBGR_8888:
case VG_sABGR_8888:
case VG_sABGR_8888_PRE:
case VG_sABGR_1555:
case VG_sABGR_4444:
case VG_lXBGR_8888:
case VG_lABGR_8888:
case VG_lABGR_8888_PRE:
return VG_TRUE;
default:
return VG_FALSE;
}
return VG_FALSE;
}
VGImage vgCreateImage(VGImageFormat format,
VGint width, VGint height,
VGbitfield allowedQuality)
{
struct vg_context *ctx = vg_current_context();
if (!supported_image_format(format)) {
vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
return VG_INVALID_HANDLE;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
if (width > vgGeti(VG_MAX_IMAGE_WIDTH) ||
height > vgGeti(VG_MAX_IMAGE_HEIGHT)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
if (!(allowedQuality & ((VG_IMAGE_QUALITY_NONANTIALIASED |
VG_IMAGE_QUALITY_FASTER |
VG_IMAGE_QUALITY_BETTER)))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
return (VGImage)image_create(format, width, height);
}
void vgDestroyImage(VGImage image)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *img = (struct vg_image *)image;
if (image == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
image_destroy(img);
}
void vgClearImage(VGImage image,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *img;
if (image == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
img = (struct vg_image*)image;
if (x + width < 0 || y + height < 0)
return;
image_clear(img, x, y, width, height);
}
void vgImageSubData(VGImage image,
const void * data,
VGint dataStride,
VGImageFormat dataFormat,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *img;
if (image == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!supported_image_format(dataFormat)) {
vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
return;
}
if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
img = (struct vg_image*)(image);
image_sub_data(img, data, dataStride, dataFormat,
x, y, width, height);
}
void vgGetImageSubData(VGImage image,
void * data,
VGint dataStride,
VGImageFormat dataFormat,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *img;
if (image == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!supported_image_format(dataFormat)) {
vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
return;
}
if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
img = (struct vg_image*)image;
image_get_sub_data(img, data, dataStride, dataFormat,
x, y, width, height);
}
VGImage vgChildImage(VGImage parent,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *p;
if (parent == VG_INVALID_HANDLE ||
!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void*)parent) ||
!vg_object_is_valid((void*)parent, VG_OBJECT_IMAGE)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return VG_INVALID_HANDLE;
}
if (width <= 0 || height <= 0 || x < 0 || y < 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
p = (struct vg_image *)parent;
if (x > p->width || y > p->height) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
if (x + width > p->width || y + height > p->height) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
return (VGImage)image_child_image(p, x, y, width, height);
}
VGImage vgGetParent(VGImage image)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *img;
if (image == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return VG_INVALID_HANDLE;
}
img = (struct vg_image*)image;
if (img->parent)
return (VGImage)img->parent;
else
return image;
}
void vgCopyImage(VGImage dst, VGint dx, VGint dy,
VGImage src, VGint sx, VGint sy,
VGint width, VGint height,
VGboolean dither)
{
struct vg_context *ctx = vg_current_context();
if (src == VG_INVALID_HANDLE || dst == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
vg_validate_state(ctx);
image_copy((struct vg_image*)dst, dx, dy,
(struct vg_image*)src, sx, sy,
width, height, dither);
}
void vgDrawImage(VGImage image)
{
struct vg_context *ctx = vg_current_context();
if (!ctx)
return;
if (image == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
vg_validate_state(ctx);
image_draw((struct vg_image*)image);
}
void vgSetPixels(VGint dx, VGint dy,
VGImage src, VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
vg_validate_state(ctx);
if (src == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width,
height);
}
void vgGetPixels(VGImage dst, VGint dx, VGint dy,
VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *img;
if (dst == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
img = (struct vg_image*)dst;
image_get_pixels(img, dx, dy,
sx, sy, width, height);
}
void vgWritePixels(const void * data, VGint dataStride,
VGImageFormat dataFormat,
VGint dx, VGint dy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
if (!supported_image_format(dataFormat)) {
vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
return;
}
if (!data || !is_aligned(data)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
vg_validate_state(ctx);
{
struct vg_image *img = image_create(dataFormat, width, height);
image_sub_data(img, data, dataStride, dataFormat, 0, 0,
width, height);
#if 0
struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix;
matrix_translate(matrix, dx, dy);
image_draw(img);
matrix_translate(matrix, -dx, -dy);
#else
/* this looks like a better approach */
image_set_pixels(dx, dy, img, 0, 0, width, height);
#endif
image_destroy(img);
}
/* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
}
void vgReadPixels(void * data, VGint dataStride,
VGImageFormat dataFormat,
VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->strb;
struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
VGfloat *df = (VGfloat*)temp;
VGint y = (fb->height - sy) - 1, yStep = -1;
VGint i;
VGubyte *dst = (VGubyte *)data;
VGint xoffset = 0, yoffset = 0;
if (!supported_image_format(dataFormat)) {
vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
return;
}
if (!data || !is_aligned(data)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
/* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
if (sx < 0) {
xoffset = -sx;
xoffset *= _vega_size_for_format(dataFormat);
width += sx;
sx = 0;
}
if (sy < 0) {
yoffset = -sy;
height += sy;
sy = 0;
y = (fb->height - sy) - 1;
yoffset *= dataStride;
}
{
struct pipe_transfer *transfer;
transfer = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
PIPE_TRANSFER_READ,
0, 0, width, height);
/* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) {
#if 0
debug_printf("%d-%d == %d\n", sy, height, y);
#endif
pipe_get_tile_rgba(transfer, sx, y, width, 1, df);
y += yStep;
_vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
dst + yoffset + xoffset);
dst += dataStride;
}
screen->tex_transfer_destroy(transfer);
}
}
void vgCopyPixels(VGint dx, VGint dy,
VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
struct st_renderbuffer *strb = ctx->draw_buffer->strb;
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
/* do nothing if we copy from outside the fb */
if (dx >= (VGint)fb->width || dy >= (VGint)fb->height ||
sx >= (VGint)fb->width || sy >= (VGint)fb->height)
return;
vg_validate_state(ctx);
/* make sure rendering has completed */
vgFinish();
vg_copy_surface(ctx, strb->surface, dx, dy,
strb->surface, sx, sy, width, height);
}

View File

@ -0,0 +1,373 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "mask.h"
#include "renderer.h"
#include "vg_context.h"
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
#include "pipe/internal/p_winsys_screen.h" /* for winsys->update_buffer */
#include "util/u_pack_color.h"
#include "util/u_draw_quad.h"
#include "util/u_memory.h"
#define DISABLE_1_1_MASKING 1
/**
* Draw a screen-aligned quadrilateral.
* Coords are window coords with y=0=bottom. These coords will be transformed
* by the vertex shader and viewport transform.
*/
static void
draw_clear_quad(struct vg_context *st,
float x0, float y0, float x1, float y1, float z,
const VGfloat color[4])
{
struct pipe_context *pipe = st->pipe;
struct pipe_buffer *buf;
VGuint i;
/* positions */
st->clear.vertices[0][0][0] = x0;
st->clear.vertices[0][0][1] = y0;
st->clear.vertices[1][0][0] = x1;
st->clear.vertices[1][0][1] = y0;
st->clear.vertices[2][0][0] = x1;
st->clear.vertices[2][0][1] = y1;
st->clear.vertices[3][0][0] = x0;
st->clear.vertices[3][0][1] = y1;
/* same for all verts: */
for (i = 0; i < 4; i++) {
st->clear.vertices[i][0][2] = z;
st->clear.vertices[i][0][3] = 1.0;
st->clear.vertices[i][1][0] = color[0];
st->clear.vertices[i][1][1] = color[1];
st->clear.vertices[i][1][2] = color[2];
st->clear.vertices[i][1][3] = color[3];
}
/* put vertex data into vbuf */
buf = pipe_user_buffer_create(pipe->screen,
st->clear.vertices,
sizeof(st->clear.vertices));
/* draw */
if (buf) {
util_draw_vertex_buffer(pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
pipe_buffer_reference(&buf, NULL);
}
}
/**
* Do vgClear by drawing a quadrilateral.
*/
static void
clear_with_quad(struct vg_context *st, float x0, float y0,
float width, float height, const VGfloat clear_color[4])
{
VGfloat x1, y1;
vg_validate_state(st);
x1 = x0 + width;
y1 = y0 + height;
/*
printf("%s %f,%f %f,%f\n", __FUNCTION__,
x0, y0,
x1, y1);
*/
if (st->pipe->winsys && st->pipe->winsys->update_buffer)
st->pipe->winsys->update_buffer( st->pipe->winsys,
st->pipe->priv );
cso_save_blend(st->cso_context);
cso_save_rasterizer(st->cso_context);
cso_save_fragment_shader(st->cso_context);
cso_save_vertex_shader(st->cso_context);
/* blend state: RGBA masking */
{
struct pipe_blend_state blend;
memset(&blend, 0, sizeof(blend));
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.colormask |= PIPE_MASK_R;
blend.colormask |= PIPE_MASK_G;
blend.colormask |= PIPE_MASK_B;
blend.colormask |= PIPE_MASK_A;
cso_set_blend(st->cso_context, &blend);
}
cso_set_rasterizer(st->cso_context, &st->clear.raster);
cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
cso_set_vertex_shader_handle(st->cso_context, vg_clear_vs(st));
/* draw quad matching scissor rect (XXX verify coord round-off) */
draw_clear_quad(st, x0, y0, x1, y1, 0, clear_color);
/* Restore pipe state */
cso_restore_blend(st->cso_context);
cso_restore_rasterizer(st->cso_context);
cso_restore_fragment_shader(st->cso_context);
cso_restore_vertex_shader(st->cso_context);
}
void vgMask(VGHandle mask, VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
if (width <=0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (operation < VG_CLEAR_MASK || operation > VG_SUBTRACT_MASK) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
vg_validate_state(ctx);
if (operation == VG_CLEAR_MASK) {
mask_fill(x, y, width, height, 0.f);
} else if (operation == VG_FILL_MASK) {
mask_fill(x, y, width, height, 1.f);
} else if (vg_object_is_valid((void*)mask, VG_OBJECT_IMAGE)) {
struct vg_image *image = (struct vg_image *)mask;
mask_using_image(image, operation, x, y, width, height);
} else if (vg_object_is_valid((void*)mask, VG_OBJECT_MASK)) {
#if DISABLE_1_1_MASKING
return;
#else
struct vg_mask_layer *layer = (struct vg_mask_layer *)mask;
mask_using_layer(layer, operation, x, y, width, height);
#endif
} else {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
}
}
void vgClear(VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_framebuffer_state *fb;
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
vg_validate_state(ctx);
#if 0
debug_printf("Clear [%d, %d, %d, %d] with [%f, %f, %f, %f]\n",
x, y, width, height,
ctx->state.vg.clear_color[0],
ctx->state.vg.clear_color[1],
ctx->state.vg.clear_color[2],
ctx->state.vg.clear_color[3]);
#endif
fb = &ctx->state.g3d.fb;
/* check for a whole surface clear */
if (!ctx->state.vg.scissoring &&
(x == 0 && y == 0 && width == fb->width && height == fb->height)) {
ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
ctx->state.vg.clear_color, 1., 0);
} else {
clear_with_quad(ctx, x, y, width, height, ctx->state.vg.clear_color);
}
}
#ifdef OPENVG_VERSION_1_1
void vgRenderToMask(VGPath path,
VGbitfield paintModes,
VGMaskOperation operation)
{
struct vg_context *ctx = vg_current_context();
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!paintModes || (paintModes&(~(VG_STROKE_PATH|VG_FILL_PATH)))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (operation < VG_CLEAR_MASK ||
operation > VG_SUBTRACT_MASK) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!vg_object_is_valid((void*)path, VG_OBJECT_PATH)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
#if DISABLE_1_1_MASKING
return;
#endif
vg_validate_state(ctx);
mask_render_to((struct path *)path, paintModes, operation);
}
VGMaskLayer vgCreateMaskLayer(VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
if (width <= 0 || height <= 0 ||
width > vgGeti(VG_MAX_IMAGE_WIDTH) ||
height > vgGeti(VG_MAX_IMAGE_HEIGHT)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
return (VGMaskLayer)mask_layer_create(width, height);
}
void vgDestroyMaskLayer(VGMaskLayer maskLayer)
{
struct vg_mask_layer *mask = 0;
struct vg_context *ctx = vg_current_context();
if (maskLayer == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
mask = (struct vg_mask_layer *)maskLayer;
mask_layer_destroy(mask);
}
void vgFillMaskLayer(VGMaskLayer maskLayer,
VGint x, VGint y,
VGint width, VGint height,
VGfloat value)
{
struct vg_mask_layer *mask = 0;
struct vg_context *ctx = vg_current_context();
if (maskLayer == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (value < 0 || value > 1) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (x < 0 || y < 0 || (x + width) < 0 || (y + height) < 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
mask = (struct vg_mask_layer*)maskLayer;
if (x + width > mask_layer_width(mask) ||
y + height > mask_layer_height(mask)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
#if DISABLE_1_1_MASKING
return;
#endif
mask_layer_fill(mask, x, y, width, height, value);
}
void vgCopyMask(VGMaskLayer maskLayer,
VGint sx, VGint sy,
VGint dx, VGint dy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_mask_layer *mask = 0;
if (maskLayer == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
#if DISABLE_1_1_MASKING
return;
#endif
mask = (struct vg_mask_layer*)maskLayer;
mask_copy(mask, sx, sy, dx, dy, width, height);
}
#endif

View File

@ -0,0 +1,83 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "vg_context.h"
/* Hardware Queries */
VGHardwareQueryResult vgHardwareQuery(VGHardwareQueryType key,
VGint setting)
{
struct vg_context *ctx = vg_current_context();
if (key < VG_IMAGE_FORMAT_QUERY ||
key > VG_PATH_DATATYPE_QUERY) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_HARDWARE_UNACCELERATED;
}
if (key == VG_IMAGE_FORMAT_QUERY) {
if (setting < VG_sRGBX_8888 ||
setting > VG_lABGR_8888_PRE) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_HARDWARE_UNACCELERATED;
}
} else if (key == VG_PATH_DATATYPE_QUERY) {
if (setting < VG_PATH_DATATYPE_S_8 ||
setting > VG_PATH_DATATYPE_F) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_HARDWARE_UNACCELERATED;
}
}
/* we're supposed to accelerate everything */
return VG_HARDWARE_ACCELERATED;
}
/* Renderer and Extension Information */
const VGubyte *vgGetString(VGStringID name)
{
struct vg_context *ctx = vg_current_context();
static const VGubyte *vendor = (VGubyte *)"Tungsten Graphics, Inc";
static const VGubyte *renderer = (VGubyte *)"Vega OpenVG 1.0";
static const VGubyte *version = (VGubyte *)"1.0";
if (!ctx)
return NULL;
switch(name) {
case VG_VENDOR:
return vendor;
case VG_RENDERER:
return renderer;
case VG_VERSION:
return version;
case VG_EXTENSIONS:
return NULL;
default:
return NULL;
}
}

View File

@ -0,0 +1,166 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "vg_context.h"
#include "paint.h"
#include "image.h"
VGPaint vgCreatePaint(void)
{
return (VGPaint) paint_create(vg_current_context());
}
void vgDestroyPaint(VGPaint p)
{
struct vg_context *ctx = vg_current_context();
struct vg_paint *paint;
if (p == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
paint = (struct vg_paint *)p;
paint_destroy(paint);
}
void vgSetPaint(VGPaint paint, VGbitfield paintModes)
{
struct vg_context *ctx = vg_current_context();
if (paint == VG_INVALID_HANDLE) {
/* restore the default */
paint = (VGPaint)ctx->default_paint;
} else if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!(paintModes & ((VG_FILL_PATH|VG_STROKE_PATH)))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (paintModes & VG_FILL_PATH) {
ctx->state.vg.fill_paint = (struct vg_paint *)paint;
}
if (paintModes & VG_STROKE_PATH) {
ctx->state.vg.stroke_paint = (struct vg_paint *)paint;
}
}
VGPaint vgGetPaint(VGPaintMode paintMode)
{
struct vg_context *ctx = vg_current_context();
VGPaint paint = VG_INVALID_HANDLE;
if (paintMode < VG_STROKE_PATH || paintMode > VG_FILL_PATH) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
if (paintMode == VG_FILL_PATH)
paint = (VGPaint)ctx->state.vg.fill_paint;
else if (paintMode == VG_STROKE_PATH)
paint = (VGPaint)ctx->state.vg.stroke_paint;
if (paint == (VGPaint)ctx->default_paint)
paint = VG_INVALID_HANDLE;
return paint;
}
void vgSetColor(VGPaint paint, VGuint rgba)
{
struct vg_context *ctx = vg_current_context();
if (paint == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
{
struct vg_paint *p = (struct vg_paint *)paint;
paint_set_colori(p, rgba);
}
}
VGuint vgGetColor(VGPaint paint)
{
struct vg_context *ctx = vg_current_context();
struct vg_paint *p;
VGuint rgba = 0;
if (paint == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return rgba;
}
if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return rgba;
}
p = (struct vg_paint *)paint;
return paint_colori(p);
}
void vgPaintPattern(VGPaint paint, VGImage pattern)
{
struct vg_context *ctx = vg_current_context();
if (paint == VG_INVALID_HANDLE ||
!vg_context_is_object_valid(ctx, VG_OBJECT_PAINT, (void *)paint)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (pattern == VG_INVALID_HANDLE) {
paint_set_type((struct vg_paint*)paint, VG_PAINT_TYPE_COLOR);
return;
}
if (!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)pattern)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT) ||
!vg_object_is_valid((void*)pattern, VG_OBJECT_IMAGE)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
paint_set_pattern((struct vg_paint*)paint,
(struct vg_image*)pattern);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,488 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "vg_context.h"
#include "path.h"
#include "polygon.h"
#include "paint.h"
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
#include "util/u_draw_quad.h"
VGPath vgCreatePath(VGint pathFormat,
VGPathDatatype datatype,
VGfloat scale, VGfloat bias,
VGint segmentCapacityHint,
VGint coordCapacityHint,
VGbitfield capabilities)
{
struct vg_context *ctx = vg_current_context();
if (pathFormat != VG_PATH_FORMAT_STANDARD) {
vg_set_error(ctx, VG_UNSUPPORTED_PATH_FORMAT_ERROR);
return VG_INVALID_HANDLE;
}
if (datatype < VG_PATH_DATATYPE_S_8 ||
datatype > VG_PATH_DATATYPE_F) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
if (!scale) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
return (VGPath)path_create(datatype, scale, bias,
segmentCapacityHint, coordCapacityHint,
capabilities);
}
void vgClearPath(VGPath path, VGbitfield capabilities)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
p = (struct path *)path;
path_clear(p, capabilities);
}
void vgDestroyPath(VGPath p)
{
struct path *path = 0;
struct vg_context *ctx = vg_current_context();
if (p == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
path = (struct path *)p;
path_destroy(path);
}
void vgRemovePathCapabilities(VGPath path,
VGbitfield capabilities)
{
struct vg_context *ctx = vg_current_context();
VGbitfield current;
struct path *p;
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
p = (struct path*)path;
current = path_capabilities(p);
path_set_capabilities(p, (current &
(~(capabilities & VG_PATH_CAPABILITY_ALL))));
}
VGbitfield vgGetPathCapabilities(VGPath path)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return 0;
}
p = (struct path*)path;
return path_capabilities(p);
}
void vgAppendPath(VGPath dstPath, VGPath srcPath)
{
struct vg_context *ctx = vg_current_context();
struct path *src, *dst;
if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
src = (struct path *)srcPath;
dst = (struct path *)dstPath;
if (!(path_capabilities(src) & VG_PATH_CAPABILITY_APPEND_FROM) ||
!(path_capabilities(dst) & VG_PATH_CAPABILITY_APPEND_TO)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return;
}
path_append_path(dst, src);
}
void vgAppendPathData(VGPath dstPath,
VGint numSegments,
const VGubyte * pathSegments,
const void * pathData)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
VGint i;
if (dstPath == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!pathSegments) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (numSegments <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
for (i = 0; i < numSegments; ++i) {
if (pathSegments[i] < VG_CLOSE_PATH ||
pathSegments[i] > VG_LCWARC_TO_REL) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
}
p = (struct path*)dstPath;
if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!(path_capabilities(p)&VG_PATH_CAPABILITY_APPEND_TO)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return;
}
path_append_data(p, numSegments, pathSegments, pathData);
}
void vgModifyPathCoords(VGPath dstPath,
VGint startIndex,
VGint numSegments,
const void * pathData)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
if (dstPath == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (startIndex < 0 || numSegments <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
p = (struct path *)dstPath;
if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (startIndex + numSegments > path_num_segments(p)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!(path_capabilities(p)&VG_PATH_CAPABILITY_MODIFY)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return;
}
path_modify_coords(p, startIndex, numSegments, pathData);
}
void vgTransformPath(VGPath dstPath, VGPath srcPath)
{
struct vg_context *ctx = vg_current_context();
struct path *src = 0, *dst = 0;
if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
src = (struct path *)srcPath;
dst = (struct path *)dstPath;
if (!(path_capabilities(src) & VG_PATH_CAPABILITY_TRANSFORM_FROM) ||
!(path_capabilities(dst) & VG_PATH_CAPABILITY_TRANSFORM_TO)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return;
}
path_transform(dst, src);
}
VGboolean vgInterpolatePath(VGPath dstPath,
VGPath startPath,
VGPath endPath,
VGfloat amount)
{
struct vg_context *ctx = vg_current_context();
struct path *start = 0, *dst = 0, *end = 0;
if (dstPath == VG_INVALID_HANDLE ||
startPath == VG_INVALID_HANDLE ||
endPath == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return VG_FALSE;
}
dst = (struct path *)dstPath;
start = (struct path *)startPath;
end = (struct path *)endPath;
if (!(path_capabilities(dst) & VG_PATH_CAPABILITY_INTERPOLATE_TO) ||
!(path_capabilities(start) & VG_PATH_CAPABILITY_INTERPOLATE_FROM) ||
!(path_capabilities(end) & VG_PATH_CAPABILITY_INTERPOLATE_FROM)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return VG_FALSE;
}
return path_interpolate(dst,
start, end, amount);
}
VGfloat vgPathLength(VGPath path,
VGint startSegment,
VGint numSegments)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return -1;
}
if (startSegment < 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return -1;
}
if (numSegments <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return -1;
}
p = (struct path*)path;
if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return -1;
}
if (startSegment + numSegments > path_num_segments(p)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return -1;
}
return path_length(p, startSegment, numSegments);
}
void vgPointAlongPath(VGPath path,
VGint startSegment,
VGint numSegments,
VGfloat distance,
VGfloat * x, VGfloat * y,
VGfloat * tangentX,
VGfloat * tangentY)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
VGbitfield caps;
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (startSegment < 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (numSegments <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!is_aligned(x) || !is_aligned(y) ||
!is_aligned(tangentX) || !is_aligned(tangentY)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
p = (struct path*)path;
caps = path_capabilities(p);
if (!(caps & VG_PATH_CAPABILITY_POINT_ALONG_PATH) ||
!(caps & VG_PATH_CAPABILITY_TANGENT_ALONG_PATH)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return;
}
if (startSegment + numSegments > path_num_segments(p)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
{
VGfloat point[2], normal[2];
path_point(p, startSegment, numSegments, distance,
point, normal);
if (x)
*x = point[0];
if (y)
*y = point[1];
if (tangentX)
*tangentX = -normal[1];
if (tangentY)
*tangentY = normal[0];
}
}
void vgPathBounds(VGPath path,
VGfloat * minX,
VGfloat * minY,
VGfloat * width,
VGfloat * height)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
VGbitfield caps;
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!minX || !minY || !width || !height) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!is_aligned(minX) || !is_aligned(minY) ||
!is_aligned(width) || !is_aligned(height)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
p = (struct path*)path;
caps = path_capabilities(p);
if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return;
}
path_bounding_rect(p, minX, minY, width, height);
}
void vgPathTransformedBounds(VGPath path,
VGfloat * minX,
VGfloat * minY,
VGfloat * width,
VGfloat * height)
{
struct vg_context *ctx = vg_current_context();
struct path *p = 0;
VGbitfield caps;
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!minX || !minY || !width || !height) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!is_aligned(minX) || !is_aligned(minY) ||
!is_aligned(width) || !is_aligned(height)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
p = (struct path*)path;
caps = path_capabilities(p);
if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) {
vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
return;
}
#if 0
/* faster, but seems to have precision problems... */
path_bounding_rect(p, minX, minY, width, height);
if (*width > 0 && *height > 0) {
VGfloat pts[] = {*minX, *minY,
*minX + *width, *minY,
*minX + *width, *minY + *height,
*minX, *minY + *height};
struct matrix *matrix = &ctx->state.vg.path_user_to_surface_matrix;
VGfloat maxX, maxY;
matrix_map_point(matrix, pts[0], pts[1], pts + 0, pts + 1);
matrix_map_point(matrix, pts[2], pts[3], pts + 2, pts + 3);
matrix_map_point(matrix, pts[4], pts[5], pts + 4, pts + 5);
matrix_map_point(matrix, pts[6], pts[7], pts + 6, pts + 7);
*minX = MIN2(pts[0], MIN2(pts[2], MIN2(pts[4], pts[6])));
*minY = MIN2(pts[1], MIN2(pts[3], MIN2(pts[5], pts[7])));
maxX = MAX2(pts[0], MAX2(pts[2], MAX2(pts[4], pts[6])));
maxY = MAX2(pts[1], MAX2(pts[3], MAX2(pts[5], pts[7])));
*width = maxX - *minX;
*height = maxY - *minY;
}
#else
{
struct path *dst = path_create(VG_PATH_DATATYPE_F, 1.0, 0,
0, 0, VG_PATH_CAPABILITY_ALL);
path_transform(dst, p);
path_bounding_rect(dst, minX, minY, width, height);
path_destroy(dst);
}
#endif
}
void vgDrawPath(VGPath path, VGbitfield paintModes)
{
struct vg_context *ctx = vg_current_context();
if (path == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!(paintModes & (VG_STROKE_PATH | VG_FILL_PATH))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (path_is_empty((struct path*)path))
return;
path_render((struct path*)path, paintModes);
}

View File

@ -0,0 +1,258 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "vg_context.h"
#include "util/u_memory.h"
#ifdef OPENVG_VERSION_1_1
struct vg_font {
struct vg_object base;
VGint glyph_indices[200];
VGint num_glyphs;
};
VGFont vgCreateFont(VGint glyphCapacityHint)
{
struct vg_font *font = 0;
struct vg_context *ctx = vg_current_context();
if (glyphCapacityHint < 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return VG_INVALID_HANDLE;
}
font = CALLOC_STRUCT(vg_font);
vg_init_object(&font->base, ctx, VG_OBJECT_FONT);
vg_context_add_object(ctx, VG_OBJECT_FONT, font);
return (VGFont)font;
}
void vgDestroyFont(VGFont f)
{
struct vg_font *font = (struct vg_font *)f;
struct vg_context *ctx = vg_current_context();
if (f == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
vg_context_remove_object(ctx, VG_OBJECT_FONT, font);
/*free(font);*/
}
void vgSetGlyphToPath(VGFont font,
VGuint glyphIndex,
VGPath path,
VGboolean isHinted,
VGfloat glyphOrigin [2],
VGfloat escapement[2])
{
struct vg_context *ctx = vg_current_context();
struct vg_object *pathObj;
struct vg_font *f;
if (font == VG_INVALID_HANDLE ||
!vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!glyphOrigin || !escapement ||
!is_aligned(glyphOrigin) || !is_aligned(escapement)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (path != VG_INVALID_HANDLE &&
!vg_context_is_object_valid(ctx, VG_OBJECT_PATH, (void *)path)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
pathObj = (struct vg_object*)path;
if (pathObj && pathObj->type != VG_OBJECT_PATH) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
f = (struct vg_font*)font;
f->glyph_indices[f->num_glyphs] = glyphIndex;
++f->num_glyphs;
}
void vgSetGlyphToImage(VGFont font,
VGuint glyphIndex,
VGImage image,
VGfloat glyphOrigin [2],
VGfloat escapement[2])
{
struct vg_context *ctx = vg_current_context();
struct vg_object *img_obj;
struct vg_font *f;
if (font == VG_INVALID_HANDLE ||
!vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (!glyphOrigin || !escapement ||
!is_aligned(glyphOrigin) || !is_aligned(escapement)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (image != VG_INVALID_HANDLE &&
!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)image)) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
img_obj = (struct vg_object*)image;
if (img_obj && img_obj->type != VG_OBJECT_IMAGE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
f = (struct vg_font*)font;
f->glyph_indices[f->num_glyphs] = glyphIndex;
++f->num_glyphs;
}
static INLINE VGboolean font_contains_glyph(struct vg_font *font,
VGuint glyph_index)
{
VGint i;
for (i = 0; i < font->num_glyphs; ++i) {
if (font->glyph_indices[i] == glyph_index) {
return VG_TRUE;
}
}
return VG_FALSE;
}
void vgClearGlyph(VGFont font,
VGuint glyphIndex)
{
struct vg_context *ctx = vg_current_context();
struct vg_font *f;
VGint i;
if (font == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (glyphIndex <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
f = (struct vg_font*)font;
if (!font_contains_glyph(f, glyphIndex)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
for (i = 0; i < f->num_glyphs; ++i) {
if (f->glyph_indices[i] == glyphIndex) {
/*FIXME*/
f->glyph_indices[f->num_glyphs] = 0;
--f->num_glyphs;
return;
}
}
}
void vgDrawGlyph(VGFont font,
VGuint glyphIndex,
VGbitfield paintModes,
VGboolean allowAutoHinting)
{
struct vg_context *ctx = vg_current_context();
struct vg_font *f;
if (font == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (glyphIndex <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
f = (struct vg_font*)font;
if (!font_contains_glyph(f, glyphIndex)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
}
void vgDrawGlyphs(VGFont font,
VGint glyphCount,
VGuint *glyphIndices,
VGfloat *adjustments_x,
VGfloat *adjustments_y,
VGbitfield paintModes,
VGboolean allowAutoHinting)
{
struct vg_context *ctx = vg_current_context();
VGint i;
struct vg_font *f;
if (font == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
if (glyphCount <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!glyphIndices || !is_aligned(glyphIndices)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (!adjustments_x || !is_aligned(adjustments_x) ||
!adjustments_y || !is_aligned(adjustments_y)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
f = (struct vg_font*)font;
for (i = 0; i < glyphCount; ++i) {
VGuint glyph_index = glyphIndices[i];
if (!font_contains_glyph(f, glyph_index)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
}
}
#endif

View File

@ -0,0 +1,128 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "vg_context.h"
#include "matrix.h"
void vgLoadIdentity(void)
{
struct vg_context *ctx = vg_current_context();
struct matrix *mat = vg_state_matrix(&ctx->state.vg);
matrix_load_identity(mat);
}
void vgLoadMatrix(const VGfloat * m)
{
struct vg_context *ctx = vg_current_context();
struct matrix *mat;
if (!ctx)
return;
if (!m || !is_aligned(m)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
mat = vg_state_matrix(&ctx->state.vg);
matrix_init(mat, m);
if (!matrix_is_affine(mat)) {
if (ctx->state.vg.matrix_mode != VG_MATRIX_IMAGE_USER_TO_SURFACE) {
matrix_make_affine(mat);
}
}
}
void vgGetMatrix(VGfloat * m)
{
struct vg_context *ctx = vg_current_context();
struct matrix *mat;
if (!ctx)
return;
if (!m || !is_aligned(m)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
mat = vg_state_matrix(&ctx->state.vg);
memcpy(m, mat->m, sizeof(VGfloat)*9);
}
void vgMultMatrix(const VGfloat * m)
{
struct vg_context *ctx = vg_current_context();
struct matrix *dst, src;
if (!ctx)
return;
if (!m || !is_aligned(m)) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
matrix_init(&src, m);
dst = vg_state_matrix(&ctx->state.vg);
if (!matrix_is_affine(&src)) {
if (ctx->state.vg.matrix_mode != VG_MATRIX_IMAGE_USER_TO_SURFACE) {
matrix_make_affine(&src);
}
}
matrix_mult(dst, &src);
}
void vgTranslate(VGfloat tx, VGfloat ty)
{
struct vg_context *ctx = vg_current_context();
struct matrix *dst = vg_state_matrix(&ctx->state.vg);
matrix_translate(dst, tx, ty);
}
void vgScale(VGfloat sx, VGfloat sy)
{
struct vg_context *ctx = vg_current_context();
struct matrix *dst = vg_state_matrix(&ctx->state.vg);
matrix_scale(dst, sx, sy);
}
void vgShear(VGfloat shx, VGfloat shy)
{
struct vg_context *ctx = vg_current_context();
struct matrix *dst = vg_state_matrix(&ctx->state.vg);
matrix_shear(dst, shx, shy);
}
void vgRotate(VGfloat angle)
{
struct vg_context *ctx = vg_current_context();
struct matrix *dst = vg_state_matrix(&ctx->state.vg);
matrix_rotate(dst, angle);
}

View File

@ -0,0 +1,708 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "arc.h"
#include "matrix.h"
#include "bezier.h"
#include "polygon.h"
#include "stroker.h"
#include "path.h"
#include "util/u_debug.h"
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define DEBUG_ARCS 0
static const VGfloat two_pi = M_PI * 2;
static const double coeffs3Low[2][4][4] = {
{
{ 3.85268, -21.229, -0.330434, 0.0127842 },
{ -1.61486, 0.706564, 0.225945, 0.263682 },
{ -0.910164, 0.388383, 0.00551445, 0.00671814 },
{ -0.630184, 0.192402, 0.0098871, 0.0102527 }
},
{
{ -0.162211, 9.94329, 0.13723, 0.0124084 },
{ -0.253135, 0.00187735, 0.0230286, 0.01264 },
{ -0.0695069, -0.0437594, 0.0120636, 0.0163087 },
{ -0.0328856, -0.00926032, -0.00173573, 0.00527385 }
}
};
/* coefficients for error estimation
while using cubic Bézier curves for approximation
1/4 <= b/a <= 1 */
static const double coeffs3High[2][4][4] = {
{
{ 0.0899116, -19.2349, -4.11711, 0.183362 },
{ 0.138148, -1.45804, 1.32044, 1.38474 },
{ 0.230903, -0.450262, 0.219963, 0.414038 },
{ 0.0590565, -0.101062, 0.0430592, 0.0204699 }
},
{
{ 0.0164649, 9.89394, 0.0919496, 0.00760802 },
{ 0.0191603, -0.0322058, 0.0134667, -0.0825018 },
{ 0.0156192, -0.017535, 0.00326508, -0.228157 },
{ -0.0236752, 0.0405821, -0.0173086, 0.176187 }
}
};
/* safety factor to convert the "best" error approximation
into a "max bound" error */
static const double safety3[] = {
0.001, 4.98, 0.207, 0.0067
};
/* The code below is from the OpenVG 1.1 Spec
* Section 18.4 */
/* Given: Points (x0, y0) and (x1, y1)
* Return: TRUE if a solution exists, FALSE otherwise
* Circle centers are written to (cx0, cy0) and (cx1, cy1)
*/
static VGboolean
find_unit_circles(double x0, double y0, double x1, double y1,
double *cx0, double *cy0,
double *cx1, double *cy1)
{
/* Compute differences and averages */
double dx = x0 - x1;
double dy = y0 - y1;
double xm = (x0 + x1)/2;
double ym = (y0 + y1)/2;
double dsq, disc, s, sdx, sdy;
/* Solve for intersecting unit circles */
dsq = dx*dx + dy*dy;
if (dsq == 0.0) return VG_FALSE; /* Points are coincident */
disc = 1.0/dsq - 1.0/4.0;
/* the precision we care about here is around float so if we're
* around the float defined zero then make it official to avoid
* precision problems later on */
if (floatIsZero(disc))
disc = 0.0;
if (disc < 0.0) return VG_FALSE; /* Points are too far apart */
s = sqrt(disc);
sdx = s*dx;
sdy = s*dy;
*cx0 = xm + sdy;
*cy0 = ym - sdx;
*cx1 = xm - sdy;
*cy1 = ym + sdx;
return VG_TRUE;
}
/* Given: Ellipse parameters rh, rv, rot (in degrees),
* endpoints (x0, y0) and (x1, y1)
* Return: TRUE if a solution exists, FALSE otherwise
* Ellipse centers are written to (cx0, cy0) and (cx1, cy1)
*/
static VGboolean
find_ellipses(double rh, double rv, double rot,
double x0, double y0, double x1, double y1,
double *cx0, double *cy0, double *cx1, double *cy1)
{
double COS, SIN, x0p, y0p, x1p, y1p, pcx0, pcy0, pcx1, pcy1;
/* Convert rotation angle from degrees to radians */
rot *= M_PI/180.0;
/* Pre-compute rotation matrix entries */
COS = cos(rot); SIN = sin(rot);
/* Transform (x0, y0) and (x1, y1) into unit space */
/* using (inverse) rotate, followed by (inverse) scale */
x0p = (x0*COS + y0*SIN)/rh;
y0p = (-x0*SIN + y0*COS)/rv;
x1p = (x1*COS + y1*SIN)/rh;
y1p = (-x1*SIN + y1*COS)/rv;
if (!find_unit_circles(x0p, y0p, x1p, y1p,
&pcx0, &pcy0, &pcx1, &pcy1)) {
return VG_FALSE;
}
/* Transform back to original coordinate space */
/* using (forward) scale followed by (forward) rotate */
pcx0 *= rh; pcy0 *= rv;
pcx1 *= rh; pcy1 *= rv;
*cx0 = pcx0*COS - pcy0*SIN;
*cy0 = pcx0*SIN + pcy0*COS;
*cx1 = pcx1*COS - pcy1*SIN;
*cy1 = pcx1*SIN + pcy1*COS;
return VG_TRUE;
}
static INLINE VGboolean
try_to_fix_radii(struct arc *arc)
{
double COS, SIN, rot, x0p, y0p, x1p, y1p;
double dx, dy, dsq, scale;
/* Convert rotation angle from degrees to radians */
rot = DEGREES_TO_RADIANS(arc->theta);
/* Pre-compute rotation matrix entries */
COS = cos(rot); SIN = sin(rot);
/* Transform (x0, y0) and (x1, y1) into unit space */
/* using (inverse) rotate, followed by (inverse) scale */
x0p = (arc->x1*COS + arc->y1*SIN)/arc->a;
y0p = (-arc->x1*SIN + arc->y1*COS)/arc->b;
x1p = (arc->x2*COS + arc->y2*SIN)/arc->a;
y1p = (-arc->x2*SIN + arc->y2*COS)/arc->b;
/* Compute differences and averages */
dx = x0p - x1p;
dy = y0p - y1p;
dsq = dx*dx + dy*dy;
#if 0
if (dsq <= 0.001) {
debug_printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaa\n");
}
#endif
scale = 1/(2/sqrt(dsq));
arc->a *= scale;
arc->b *= scale;
return VG_TRUE;
}
static INLINE double vector_normalize(double *v)
{
double sq = v[0] * v[0] + v[1] * v[1];
return sqrt(sq);
}
static INLINE double vector_orientation(double *v)
{
double norm = vector_normalize(v);
double cosa = v[0] / norm;
double sina = v[1] / norm;
return (sina>=0 ? acos(cosa) : 2*M_PI - acos(cosa));
}
static INLINE double vector_dot(double *v0,
double *v1)
{
return v0[0] * v1[0] + v0[1] * v1[1];
}
static INLINE double vector_angles(double *v0,
double *v1)
{
double dot = vector_dot(v0, v1);
double norm0 = vector_normalize(v0);
double norm1 = vector_normalize(v1);
return acos(dot / (norm0 * norm1));
}
static VGboolean find_angles(struct arc *arc)
{
double vec0[2], vec1[2];
double lambda1, lambda2;
double angle;
struct matrix matrix;
if (floatIsZero(arc->a) || floatIsZero(arc->b)) {
return VG_FALSE;
}
/* map the points to an identity circle */
matrix_load_identity(&matrix);
matrix_scale(&matrix, 1.f, arc->a/arc->b);
matrix_rotate(&matrix, -arc->theta);
matrix_map_point(&matrix,
arc->x1, arc->y1,
&arc->x1, &arc->y1);
matrix_map_point(&matrix,
arc->x2, arc->y2,
&arc->x2, &arc->y2);
matrix_map_point(&matrix,
arc->cx, arc->cy,
&arc->cx, &arc->cy);
#if DEBUG_ARCS
debug_printf("Matrix 3 [%f, %f, %f| %f, %f, %f| %f, %f, %f]\n",
matrix.m[0], matrix.m[1], matrix.m[2],
matrix.m[3], matrix.m[4], matrix.m[5],
matrix.m[6], matrix.m[7], matrix.m[8]);
debug_printf("Endpoints [%f, %f], [%f, %f]\n",
arc->x1, arc->y1, arc->x2, arc->y2);
#endif
vec0[0] = arc->x1 - arc->cx;
vec0[1] = arc->y1 - arc->cy;
vec1[0] = arc->x2 - arc->cx;
vec1[1] = arc->y2 - arc->cy;
#if DEBUG_ARCS
debug_printf("Vec is [%f, %f], [%f, %f], [%f, %f]\n",
vec0[0], vec0[1], vec1[0], vec1[1], arc->cx, arc->cy);
#endif
lambda1 = vector_orientation(vec0);
if (isnan(lambda1))
lambda1 = 0.f;
if (arc->type == VG_SCWARC_TO ||
arc->type == VG_SCCWARC_TO)
angle = vector_angles(vec0, vec1);
else if (arc->type == VG_LCWARC_TO ||
arc->type == VG_LCCWARC_TO) {
angle = 2*M_PI - vector_angles(vec0, vec1);
} else
abort();
if (isnan(angle))
angle = M_PI;
if (arc->type == VG_SCWARC_TO ||
arc->type == VG_LCWARC_TO)
lambda2 = lambda1 - angle;
else
lambda2 = lambda1 + angle;
#if DEBUG_ARCS
debug_printf("Angle is %f and (%f, %f)\n", angle, lambda1, lambda2);
#endif
#if 0
arc->eta1 = atan2(sin(lambda1) / arc->b,
cos(lambda1) / arc->a);
arc->eta2 = atan2(sin(lambda2) / arc->b,
cos(lambda2) / arc->a);
/* make sure we have eta1 <= eta2 <= eta1 + 2 PI */
arc->eta2 -= two_pi * floor((arc->eta2 - arc->eta1) / two_pi);
/* the preceding correction fails if we have exactly et2 - eta1 = 2 PI
it reduces the interval to zero length */
if ((lambda2 - lambda1 > M_PI) && (arc->eta2 - arc->eta1 < M_PI)) {
arc->eta2 += 2 * M_PI;
}
#else
arc->eta1 = lambda1;
arc->eta2 = lambda2;
#endif
return VG_TRUE;
}
#if DEBUG_ARCS
static void check_endpoints(struct arc *arc)
{
double x1, y1, x2, y2;
double a_cos_eta1 = arc->a * cos(arc->eta1);
double b_sin_eta1 = arc->b * sin(arc->eta1);
x1 = arc->cx + a_cos_eta1 * arc->cos_theta -
b_sin_eta1 * arc->sin_theta;
y1 = arc->cy + a_cos_eta1 * arc->sin_theta +
b_sin_eta1 * arc->cos_theta;
double a_cos_eta2 = arc->a * cos(arc->eta2);
double b_sin_eta2 = arc->b * sin(arc->eta2);
x2 = arc->cx + a_cos_eta2 * arc->cos_theta -
b_sin_eta2 * arc->sin_theta;
y2 = arc->cy + a_cos_eta2 * arc->sin_theta +
b_sin_eta2 * arc->cos_theta;
debug_printf("Computed (%f, %f), (%f, %f)\n",
x1, y1, x2, y2);
debug_printf("Real (%f, %f), (%f, %f)\n",
arc->x1, arc->y1,
arc->x2, arc->y2);
}
#endif
void arc_init(struct arc *arc,
VGPathSegment type,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2,
VGfloat rh, VGfloat rv,
VGfloat rot)
{
assert(type == VG_SCCWARC_TO ||
type == VG_SCWARC_TO ||
type == VG_LCCWARC_TO ||
type == VG_LCWARC_TO);
arc->type = type;
arc->x1 = x1;
arc->y1 = y1;
arc->x2 = x2;
arc->y2 = y2;
arc->a = rh;
arc->b = rv;
arc->theta = rot;
arc->cos_theta = cos(arc->theta);
arc->sin_theta = sin(arc->theta);
{
double cx0, cy0, cx1, cy1;
double cx, cy;
arc->is_valid = find_ellipses(rh, rv, rot, x1, y1, x2, y2,
&cx0, &cy0, &cx1, &cy1);
if (!arc->is_valid && try_to_fix_radii(arc)) {
rh = arc->a;
rv = arc->b;
arc->is_valid =
find_ellipses(rh, rv, rot, x1, y1, x2, y2,
&cx0, &cy0, &cx1, &cy1);
}
if (type == VG_SCWARC_TO ||
type == VG_LCCWARC_TO) {
cx = cx1;
cy = cy1;
} else {
cx = cx0;
cy = cy0;
}
#if DEBUG_ARCS
debug_printf("Centers are : (%f, %f) , (%f, %f). Real (%f, %f)\n",
cx0, cy0, cx1, cy1, cx, cy);
#endif
arc->cx = cx;
arc->cy = cy;
if (arc->is_valid) {
arc->is_valid = find_angles(arc);
#if DEBUG_ARCS
check_endpoints(arc);
#endif
/* remap a few points. find_angles requires
* rot in angles, the rest of the code
* will need them in radians. and find_angles
* modifies the center to match an identity
* circle so lets reset it */
arc->theta = DEGREES_TO_RADIANS(rot);
arc->cos_theta = cos(arc->theta);
arc->sin_theta = sin(arc->theta);
arc->cx = cx;
arc->cy = cy;
}
}
}
static INLINE double rational_function(double x, const double *c)
{
return (x * (x * c[0] + c[1]) + c[2]) / (x + c[3]);
}
static double estimate_error(struct arc *arc,
double etaA, double etaB)
{
double eta = 0.5 * (etaA + etaB);
double x = arc->b / arc->a;
double dEta = etaB - etaA;
double cos2 = cos(2 * eta);
double cos4 = cos(4 * eta);
double cos6 = cos(6 * eta);
double c0, c1;
/* select the right coeficients set according to degree and b/a */
const double (*coeffs)[4][4];
const double *safety;
coeffs = (x < 0.25) ? coeffs3Low : coeffs3High;
safety = safety3;
c0 = rational_function(x, coeffs[0][0])
+ cos2 * rational_function(x, coeffs[0][1])
+ cos4 * rational_function(x, coeffs[0][2])
+ cos6 * rational_function(x, coeffs[0][3]);
c1 = rational_function(x, coeffs[1][0])
+ cos2 * rational_function(x, coeffs[1][1])
+ cos4 * rational_function(x, coeffs[1][2])
+ cos6 * rational_function(x, coeffs[1][3]);
return rational_function(x, safety) * arc->a * exp(c0 + c1 * dEta);
}
struct arc_cb {
void (*move)(struct arc_cb *cb, VGfloat x, VGfloat y);
void (*point)(struct arc_cb *cb, VGfloat x, VGfloat y);
void (*bezier)(struct arc_cb *cb, struct bezier *bezier);
void *user_data;
};
static void cb_null_move(struct arc_cb *cb, VGfloat x, VGfloat y)
{
}
static void polygon_point(struct arc_cb *cb, VGfloat x, VGfloat y)
{
struct polygon *poly = (struct polygon*)cb->user_data;
polygon_vertex_append(poly, x, y);
}
static void polygon_bezier(struct arc_cb *cb, struct bezier *bezier)
{
struct polygon *poly = (struct polygon*)cb->user_data;
bezier_add_to_polygon(bezier, poly);
}
static void stroke_point(struct arc_cb *cb, VGfloat x, VGfloat y)
{
struct stroker *stroker = (struct stroker*)cb->user_data;
stroker_line_to(stroker, x, y);
}
static void stroke_curve(struct arc_cb *cb, struct bezier *bezier)
{
struct stroker *stroker = (struct stroker*)cb->user_data;
stroker_curve_to(stroker,
bezier->x2, bezier->y2,
bezier->x3, bezier->y3,
bezier->x4, bezier->y4);
}
static void stroke_emit_point(struct arc_cb *cb, VGfloat x, VGfloat y)
{
struct stroker *stroker = (struct stroker*)cb->user_data;
stroker_emit_line_to(stroker, x, y);
}
static void stroke_emit_curve(struct arc_cb *cb, struct bezier *bezier)
{
struct stroker *stroker = (struct stroker*)cb->user_data;
stroker_emit_curve_to(stroker,
bezier->x2, bezier->y2,
bezier->x3, bezier->y3,
bezier->x4, bezier->y4);
}
static void arc_path_move(struct arc_cb *cb, VGfloat x, VGfloat y)
{
struct path *path = (struct path*)cb->user_data;
path_move_to(path, x, y);
}
static void arc_path_point(struct arc_cb *cb, VGfloat x, VGfloat y)
{
struct path *path = (struct path*)cb->user_data;
path_line_to(path, x, y);
}
static void arc_path_bezier(struct arc_cb *cb, struct bezier *bezier)
{
struct path *path = (struct path*)cb->user_data;
path_cubic_to(path,
bezier->x2, bezier->y2,
bezier->x3, bezier->y3,
bezier->x4, bezier->y4);
}
static INLINE int num_beziers_needed(struct arc *arc)
{
double threshold = 0.05;
VGboolean found = VG_FALSE;
int n = 1;
double min_eta, max_eta;
min_eta = MIN2(arc->eta1, arc->eta2);
max_eta = MAX2(arc->eta1, arc->eta2);
while ((! found) && (n < 1024)) {
double d_eta = (max_eta - min_eta) / n;
if (d_eta <= 0.5 * M_PI) {
double eta_b = min_eta;
found = VG_TRUE;
for (int i = 0; found && (i < n); ++i) {
double etaA = eta_b;
eta_b += d_eta;
found = (estimate_error(arc, etaA, eta_b) <= threshold);
}
}
n = n << 1;
}
return n;
}
static void arc_to_beziers(struct arc *arc,
struct arc_cb cb,
struct matrix *matrix)
{
int n = 1;
double d_eta, eta_b, cos_eta_b,
sin_eta_b, a_cos_eta_b, b_sin_eta_b, a_sin_eta_b,
b_cos_eta_b, x_b, y_b, x_b_dot, y_b_dot, lx, ly;
double t, alpha;
{ /* always move to the start of the arc */
VGfloat x = arc->x1;
VGfloat y = arc->y1;
matrix_map_point(matrix, x, y, &x, &y);
cb.move(&cb, x, y);
}
if (!arc->is_valid) {
VGfloat x = arc->x2;
VGfloat y = arc->y2;
matrix_map_point(matrix, x, y, &x, &y);
cb.point(&cb, x, y);
return;
}
/* find the number of Bézier curves needed */
n = num_beziers_needed(arc);
d_eta = (arc->eta2 - arc->eta1) / n;
eta_b = arc->eta1;
cos_eta_b = cos(eta_b);
sin_eta_b = sin(eta_b);
a_cos_eta_b = arc->a * cos_eta_b;
b_sin_eta_b = arc->b * sin_eta_b;
a_sin_eta_b = arc->a * sin_eta_b;
b_cos_eta_b = arc->b * cos_eta_b;
x_b = arc->cx + a_cos_eta_b * arc->cos_theta -
b_sin_eta_b * arc->sin_theta;
y_b = arc->cy + a_cos_eta_b * arc->sin_theta +
b_sin_eta_b * arc->cos_theta;
x_b_dot = -a_sin_eta_b * arc->cos_theta -
b_cos_eta_b * arc->sin_theta;
y_b_dot = -a_sin_eta_b * arc->sin_theta +
b_cos_eta_b * arc->cos_theta;
{
VGfloat x = x_b, y = y_b;
matrix_map_point(matrix, x, y, &x, &y);
cb.point(&cb, x, y);
}
lx = x_b;
ly = y_b;
t = tan(0.5 * d_eta);
alpha = sin(d_eta) * (sqrt(4 + 3 * t * t) - 1) / 3;
for (int i = 0; i < n; ++i) {
struct bezier bezier;
double xA = x_b;
double yA = y_b;
double xADot = x_b_dot;
double yADot = y_b_dot;
eta_b += d_eta;
cos_eta_b = cos(eta_b);
sin_eta_b = sin(eta_b);
a_cos_eta_b = arc->a * cos_eta_b;
b_sin_eta_b = arc->b * sin_eta_b;
a_sin_eta_b = arc->a * sin_eta_b;
b_cos_eta_b = arc->b * cos_eta_b;
x_b = arc->cx + a_cos_eta_b * arc->cos_theta -
b_sin_eta_b * arc->sin_theta;
y_b = arc->cy + a_cos_eta_b * arc->sin_theta +
b_sin_eta_b * arc->cos_theta;
x_b_dot = -a_sin_eta_b * arc->cos_theta -
b_cos_eta_b * arc->sin_theta;
y_b_dot = -a_sin_eta_b * arc->sin_theta +
b_cos_eta_b * arc->cos_theta;
bezier_init(&bezier,
lx, ly,
(float) (xA + alpha * xADot), (float) (yA + alpha * yADot),
(float) (x_b - alpha * x_b_dot), (float) (y_b - alpha * y_b_dot),
(float) x_b, (float) y_b);
#if 0
debug_printf("%d) Bezier (%f, %f), (%f, %f), (%f, %f), (%f, %f)\n",
i,
bezier.x1, bezier.y1,
bezier.x2, bezier.y2,
bezier.x3, bezier.y3,
bezier.x4, bezier.y4);
#endif
bezier_transform(&bezier, matrix);
cb.bezier(&cb, &bezier);
lx = x_b;
ly = y_b;
}
}
void arc_add_to_polygon(struct arc *arc,
struct polygon *poly,
struct matrix *matrix)
{
struct arc_cb cb;
cb.move = cb_null_move;
cb.point = polygon_point;
cb.bezier = polygon_bezier;
cb.user_data = poly;
arc_to_beziers(arc, cb, matrix);
}
void arc_stroke_cb(struct arc *arc,
struct stroker *stroke,
struct matrix *matrix)
{
struct arc_cb cb;
cb.move = cb_null_move;
cb.point = stroke_point;
cb.bezier = stroke_curve;
cb.user_data = stroke;
arc_to_beziers(arc, cb, matrix);
}
void arc_stroker_emit(struct arc *arc,
struct stroker *stroker,
struct matrix *matrix)
{
struct arc_cb cb;
cb.move = cb_null_move;
cb.point = stroke_emit_point;
cb.bezier = stroke_emit_curve;
cb.user_data = stroker;
arc_to_beziers(arc, cb, matrix);
}
void arc_to_path(struct arc *arc,
struct path *path,
struct matrix *matrix)
{
struct arc_cb cb;
cb.move = arc_path_move;
cb.point = arc_path_point;
cb.bezier = arc_path_bezier;
cb.user_data = path;
arc_to_beziers(arc, cb, matrix);
}

View File

@ -0,0 +1,80 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef ARC_H
#define ARC_H
#include "VG/openvg.h"
struct polygon;
struct matrix;
struct stroker;
struct path;
struct arc {
VGPathSegment type;
VGfloat cx, cy;
VGfloat a, b;
VGfloat theta;
VGfloat cos_theta, sin_theta;
VGfloat eta1;
VGfloat eta2;
VGfloat x1, y1, x2, y2;
VGboolean is_valid;
};
void arc_init(struct arc *arc,
VGPathSegment type,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2,
VGfloat rh, VGfloat rv,
VGfloat rot);
void arc_add_to_polygon(struct arc *arc,
struct polygon *poly,
struct matrix *matrix);
void arc_to_path(struct arc *arc,
struct path *p,
struct matrix *matrix);
void arc_stroke_cb(struct arc *arc,
struct stroker *stroke,
struct matrix *matrix);
void arc_stroker_emit(struct arc *arc,
struct stroker *stroke,
struct matrix *matrix);
#endif

View File

@ -0,0 +1,246 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef ASM_FILL_H
#define ASM_FILL_H
static const char solid_fill_asm[] =
"MOV %s, CONST[0]\n";
static const char linear_grad_asm[] =
"MOV TEMP[0].xy, IN[0]\n"
"MOV TEMP[0].z, CONST[1].yyyy\n"
"DP3 TEMP[1], CONST[2], TEMP[0]\n"
"DP3 TEMP[2], CONST[3], TEMP[0]\n"
"DP3 TEMP[3], CONST[4], TEMP[0]\n"
"RCP TEMP[3], TEMP[3]\n"
"MUL TEMP[1], TEMP[1], TEMP[3]\n"
"MUL TEMP[2], TEMP[2], TEMP[3]\n"
"MOV TEMP[4].x, TEMP[1]\n"
"MOV TEMP[4].y, TEMP[2]\n"
"MUL TEMP[0], CONST[0].yyyy, TEMP[4].yyyy\n"
"MAD TEMP[1], CONST[0].xxxx, TEMP[4].xxxx, TEMP[0]\n"
"MUL TEMP[2], TEMP[1], CONST[0].zzzz\n"
"TEX %s, TEMP[2], SAMP[0], 1D\n";
static const char radial_grad_asm[] =
"MOV TEMP[0].xy, IN[0]\n"
"MOV TEMP[0].z, CONST[1].yyyy\n"
"DP3 TEMP[1], CONST[2], TEMP[0]\n"
"DP3 TEMP[2], CONST[3], TEMP[0]\n"
"DP3 TEMP[3], CONST[4], TEMP[0]\n"
"RCP TEMP[3], TEMP[3]\n"
"MUL TEMP[1], TEMP[1], TEMP[3]\n"
"MUL TEMP[2], TEMP[2], TEMP[3]\n"
"MOV TEMP[5].x, TEMP[1]\n"
"MOV TEMP[5].y, TEMP[2]\n"
"MUL TEMP[0], CONST[0].yyyy, TEMP[5].yyyy\n"
"MAD TEMP[1], CONST[0].xxxx, TEMP[5].xxxx, TEMP[0]\n"
"ADD TEMP[1], TEMP[1], TEMP[1]\n"
"MUL TEMP[3], TEMP[5].yyyy, TEMP[5].yyyy\n"
"MAD TEMP[4], TEMP[5].xxxx, TEMP[5].xxxx, TEMP[3]\n"
"MOV TEMP[4], -TEMP[4]\n"
"MUL TEMP[2], CONST[0].zzzz, TEMP[4]\n"
"MUL TEMP[0], CONST[1].wwww, TEMP[2]\n"
"MUL TEMP[3], TEMP[1], TEMP[1]\n"
"SUB TEMP[2], TEMP[3], TEMP[0]\n"
"RSQ TEMP[2], |TEMP[2]|\n"
"RCP TEMP[2], TEMP[2]\n"
"SUB TEMP[1], TEMP[2], TEMP[1]\n"
"ADD TEMP[0], CONST[0].zzzz, CONST[0].zzzz\n"
"RCP TEMP[0], TEMP[0]\n"
"MUL TEMP[2], TEMP[1], TEMP[0]\n"
"TEX %s, TEMP[2], SAMP[0], 1D\n";
static const char pattern_asm[] =
"MOV TEMP[0].xy, IN[0]\n"
"MOV TEMP[0].z, CONST[1].yyyy\n"
"DP3 TEMP[1], CONST[2], TEMP[0]\n"
"DP3 TEMP[2], CONST[3], TEMP[0]\n"
"DP3 TEMP[3], CONST[4], TEMP[0]\n"
"RCP TEMP[3], TEMP[3]\n"
"MUL TEMP[1], TEMP[1], TEMP[3]\n"
"MUL TEMP[2], TEMP[2], TEMP[3]\n"
"MOV TEMP[4].x, TEMP[1]\n"
"MOV TEMP[4].y, TEMP[2]\n"
"RCP TEMP[0], CONST[1].zwzw\n"
"MOV TEMP[1], TEMP[4]\n"
"MUL TEMP[1].x, TEMP[1], TEMP[0]\n"
"MUL TEMP[1].y, TEMP[1], TEMP[0]\n"
"TEX %s, TEMP[1], SAMP[0], 2D\n";
static const char mask_asm[] =
"TEX TEMP[1], IN[0], SAMP[1], 2D\n"
"MUL TEMP[0].w, TEMP[0].wwww, TEMP[1].wwww\n"
"MOV %s, TEMP[0]\n";
static const char image_normal_asm[] =
"TEX %s, IN[1], SAMP[3], 2D\n";
static const char image_multiply_asm[] =
"TEX TEMP[1], IN[1], SAMP[3], 2D\n"
"MUL %s, TEMP[0], TEMP[1]\n";
static const char image_stencil_asm[] =
"TEX TEMP[1], IN[1], SAMP[3], 2D\n"
"MUL %s, TEMP[0], TEMP[1]\n";
#define EXTENDED_BLEND_OVER \
"SUB TEMP[3], CONST[1].yyyy, TEMP[1].wwww\n" \
"SUB TEMP[4], CONST[1].yyyy, TEMP[0].wwww\n" \
"MUL TEMP[3], TEMP[0], TEMP[3]\n" \
"MUL TEMP[4], TEMP[1], TEMP[4]\n" \
"ADD TEMP[3], TEMP[3], TEMP[4]\n"
static const char blend_multiply_asm[] =
"TEX TEMP[1], IN[0], SAMP[2], 2D\n"
EXTENDED_BLEND_OVER
"MUL TEMP[4], TEMP[0], TEMP[1]\n"
"ADD TEMP[1], TEMP[4], TEMP[3]\n"/*result.rgb*/
"MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
"ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
"SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
"MOV %s, TEMP[1]\n";
#if 1
static const char blend_screen_asm[] =
"TEX TEMP[1], IN[0], SAMP[2], 2D\n"
"ADD TEMP[3], TEMP[0], TEMP[1]\n"
"MUL TEMP[2], TEMP[0], TEMP[1]\n"
"SUB %s, TEMP[3], TEMP[2]\n";
#else
static const char blend_screen_asm[] =
"TEX TEMP[1], IN[0], SAMP[2], 2D\n"
"MOV %s, TEMP[1]\n";
#endif
static const char blend_darken_asm[] =
"TEX TEMP[1], IN[0], SAMP[2], 2D\n"
EXTENDED_BLEND_OVER
"MUL TEMP[4], TEMP[0], TEMP[1].wwww\n"
"MUL TEMP[5], TEMP[1], TEMP[0].wwww\n"
"MIN TEMP[4], TEMP[4], TEMP[5]\n"
"ADD TEMP[1], TEMP[3], TEMP[4]\n"
"MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
"ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
"SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
"MOV %s, TEMP[1]\n";
static const char blend_lighten_asm[] =
"TEX TEMP[1], IN[0], SAMP[2], 2D\n"
EXTENDED_BLEND_OVER
"MUL TEMP[4], TEMP[0], TEMP[1].wwww\n"
"MUL TEMP[5], TEMP[1], TEMP[0].wwww\n"
"MAX TEMP[4], TEMP[4], TEMP[5]\n"
"ADD TEMP[1], TEMP[3], TEMP[4]\n"
"MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
"ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
"SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
"MOV %s, TEMP[1]\n";
static const char premultiply_asm[] =
"MUL TEMP[0].xyz, TEMP[0], TEMP[0].wwww\n";
static const char unpremultiply_asm[] =
"TEX TEMP[0], IN[0], SAMP[1], 2D\n";
static const char color_bw_asm[] =
"ADD TEMP[1], CONST[1].yyyy, CONST[1].yyyy\n"
"RCP TEMP[2], TEMP[1]\n"
"ADD TEMP[1], CONST[1].yyyy, TEMP[2]\n"
"ADD TEMP[2].x, TEMP[0].xxxx, TEMP[0].yyyy\n"
"ADD TEMP[2].x, TEMP[0].zzzz, TEMP[0].xxxx\n"
"SGE TEMP[0].xyz, TEMP[2].xxxx, TEMP[1]\n"
"SGE TEMP[0].w, TEMP[0].wwww, TEMP[2].yyyy\n"
"MOV %s, TEMP[0]\n";
struct shader_asm_info {
VGint id;
VGint num_tokens;
const char * txt;
VGboolean needs_position;
VGint start_const;
VGint num_consts;
VGint start_sampler;
VGint num_samplers;
VGint start_temp;
VGint num_temps;
};
static const struct shader_asm_info shaders_asm[] = {
/* fills */
{VEGA_SOLID_FILL_SHADER, 40, solid_fill_asm,
VG_FALSE, 0, 1, 0, 0, 0, 0},
{VEGA_LINEAR_GRADIENT_SHADER, 200, linear_grad_asm,
VG_TRUE, 0, 5, 0, 1, 0, 5},
{VEGA_RADIAL_GRADIENT_SHADER, 200, radial_grad_asm,
VG_TRUE, 0, 5, 0, 1, 0, 6},
{VEGA_PATTERN_SHADER, 100, pattern_asm,
VG_TRUE, 1, 4, 0, 1, 0, 5},
/* image draw modes */
{VEGA_IMAGE_NORMAL_SHADER, 200, image_normal_asm,
VG_TRUE, 0, 0, 3, 1, 0, 0},
{VEGA_IMAGE_MULTIPLY_SHADER, 200, image_multiply_asm,
VG_TRUE, 0, 0, 3, 1, 0, 2},
{VEGA_IMAGE_STENCIL_SHADER, 200, image_stencil_asm,
VG_TRUE, 0, 0, 3, 1, 0, 2},
{VEGA_MASK_SHADER, 100, mask_asm,
VG_TRUE, 0, 0, 1, 1, 0, 2},
/* extra blend modes */
{VEGA_BLEND_MULTIPLY_SHADER, 200, blend_multiply_asm,
VG_TRUE, 1, 1, 2, 1, 0, 5},
{VEGA_BLEND_SCREEN_SHADER, 200, blend_screen_asm,
VG_TRUE, 0, 0, 2, 1, 0, 4},
{VEGA_BLEND_DARKEN_SHADER, 200, blend_darken_asm,
VG_TRUE, 1, 1, 2, 1, 0, 6},
{VEGA_BLEND_LIGHTEN_SHADER, 200, blend_lighten_asm,
VG_TRUE, 1, 1, 2, 1, 0, 6},
/* premultiply */
{VEGA_PREMULTIPLY_SHADER, 100, premultiply_asm,
VG_FALSE, 0, 0, 0, 0, 0, 1},
{VEGA_UNPREMULTIPLY_SHADER, 100, unpremultiply_asm,
VG_FALSE, 0, 0, 0, 0, 0, 1},
/* color transform to black and white */
{VEGA_BW_SHADER, 150, color_bw_asm,
VG_FALSE, 1, 1, 0, 0, 0, 3},
};
#endif

View File

@ -0,0 +1,117 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef ASM_FILTERS_H
#define ASM_FILTERS_H
static const char color_matrix_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"DCL CONST[0..4], CONSTANT\n"
"DCL TEMP[0..4], CONSTANT\n"
"DCL SAMP[0], CONSTANT\n"
"TEX TEMP[0], IN[0], SAMP[0], 2D\n"
"MOV TEMP[1], TEMP[0].xxxx\n"
"MOV TEMP[2], TEMP[0].yyyy\n"
"MOV TEMP[3], TEMP[0].zzzz\n"
"MOV TEMP[4], TEMP[0].wwww\n"
"MUL TEMP[1], TEMP[1], CONST[0]\n"
"MUL TEMP[2], TEMP[2], CONST[1]\n"
"MUL TEMP[3], TEMP[3], CONST[2]\n"
"MUL TEMP[4], TEMP[4], CONST[3]\n"
"ADD TEMP[0], TEMP[1], CONST[4]\n"
"ADD TEMP[0], TEMP[0], TEMP[2]\n"
"ADD TEMP[0], TEMP[0], TEMP[3]\n"
"ADD TEMP[0], TEMP[0], TEMP[4]\n"
"MOV OUT[0], TEMP[0]\n"
"END\n";
static const char convolution_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"DCL TEMP[0..4], CONSTANT\n"
"DCL ADDR[0], CONSTANT\n"
"DCL CONST[0..%d], CONSTANT\n"
"DCL SAMP[0], CONSTANT\n"
"0: MOV TEMP[0], CONST[0].xxxx\n"
"1: MOV TEMP[1], CONST[0].xxxx\n"
"2: BGNLOOP2 :14\n"
"3: SGE TEMP[0].z, TEMP[0].yyyy, CONST[1].xxxx\n"
"4: IF TEMP[0].zzzz :7\n"
"5: BRK\n"
"6: ENDIF\n"
"7: ARL ADDR[0].x, TEMP[0].yyyy\n"
"8: MOV TEMP[3], CONST[ADDR[0]+2]\n"
"9: ADD TEMP[4].xy, IN[0], TEMP[3]\n"
"10: TEX TEMP[2], TEMP[4], SAMP[0], 2D\n"
"11: MOV TEMP[3], CONST[ADDR[0]+%d]\n"
"12: MAD TEMP[1], TEMP[2], TEMP[3], TEMP[1]\n"
"13: ADD TEMP[0].y, TEMP[0].yyyy, CONST[0].yyyy\n"
"14: ENDLOOP2 :2\n"
"15: MAD OUT[0], TEMP[1], CONST[1].yyyy, CONST[1].zzzz\n"
"16: END\n";
static const char lookup_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"DCL TEMP[0..2], CONSTANT\n"
"DCL CONST[0], CONSTANT\n"
"DCL SAMP[0..1], CONSTANT\n"
"TEX TEMP[0], IN[0], SAMP[0], 2D\n"
"MOV TEMP[1], TEMP[0]\n"
/* do red */
"TEX TEMP[2], TEMP[1].xxxx, SAMP[1], 1D\n"
"MOV TEMP[0].x, TEMP[2].xxxx\n"
/* do blue */
"TEX TEMP[2], TEMP[1].yyyy, SAMP[1], 1D\n"
"MOV TEMP[0].y, TEMP[2].yyyy\n"
/* do green */
"TEX TEMP[2], TEMP[1].zzzz, SAMP[1], 1D\n"
"MOV TEMP[0].z, TEMP[2].zzzz\n"
/* do alpha */
"TEX TEMP[2], TEMP[1].wwww, SAMP[1], 1D\n"
"MOV TEMP[0].w, TEMP[2].wwww\n"
"MOV OUT[0], TEMP[0]\n"
"END\n";
static const char lookup_single_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"DCL TEMP[0..2], CONSTANT\n"
"DCL CONST[0], CONSTANT\n"
"DCL SAMP[0..1], CONSTANT\n"
"TEX TEMP[0], IN[0], SAMP[0], 2D\n"
"TEX TEMP[1], TEMP[0].%s, SAMP[1], 1D\n"
"MOV OUT[0], TEMP[1]\n"
"END\n";
#endif

View File

@ -0,0 +1,136 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef ASM_UTIL_H
#define ASM_UTIL_H
static const char pass_through_depth_asm[] =
"FRAG1.1\n"
"DCL IN[0], POSITION, LINEAR\n"
"DCL OUT[0].z, POSITION, CONSTANT\n"
"0: MOV OUT[0].z, IN[0].zzzz\n"
"1: END\n";
/* μnew = μmask */
static const char set_mask_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL SAMP[0], CONSTANT\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"0: TEX OUT[0], IN[0], SAMP[0], 2D\n"/*umask*/
"1: END\n";
/* μnew = 1 (1 μmask)*(1 μprev) */
static const char union_mask_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL IN[1], POSITION, LINEAR\n"
"DCL CONST[0], CONSTANT\n"
"DCL SAMP[0..1], CONSTANT\n"
"DCL TEMP[0..3], CONSTANT\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"0: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/
"1: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/
"2: SUB TEMP[2], CONST[0], TEMP[0]\n"
"3: SUB TEMP[3], CONST[0], TEMP[1]\n"
"4: MUL TEMP[0].w, TEMP[2].wwww, TEMP[3].wwww\n"
"5: SUB OUT[0], CONST[0], TEMP[0]\n"
"6: END\n";
/* μnew = μmask *μprev */
static const char intersect_mask_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL IN[1], POSITION, LINEAR\n"
"DCL CONST[0], CONSTANT\n"
"DCL SAMP[0..1], CONSTANT\n"
"DCL TEMP[0..1], CONSTANT\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"0: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/
"1: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/
"2: MUL OUT[0], TEMP[0].wwww, TEMP[1].wwww\n"
"3: END\n";
/* μnew = μprev*(1 μmask) */
static const char subtract_mask_asm[] =
"FRAG1.1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
"DCL IN[1], POSITION, LINEAR\n"
"DCL CONST[0], CONSTANT\n"
"DCL SAMP[0..1], CONSTANT\n"
"DCL TEMP[0..2], CONSTANT\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"0: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/
"1: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/
"2: SUB TEMP[2], CONST[0], TEMP[1]\n"
"3: MUL OUT[0], TEMP[2].wwww, TEMP[0].wwww\n"
"4: END\n";
static const char vs_plain_asm[] =
"VERT1.1\n"
"DCL IN[0]\n"
"DCL OUT[0], POSITION\n"
"DCL TEMP[0]\n"
"DCL CONST[0..1]\n"
"0: MUL TEMP[0], IN[0], CONST[0]\n"
"1: ADD TEMP[0], TEMP[0], CONST[1]\n"
"2: MOV OUT[0], TEMP[0]\n"
"3: END\n";
static const char vs_clear_asm[] =
"VERT1.1\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], COLOR\n"
"DCL TEMP[0]\n"
"DCL CONST[0..1]\n"
"0: MUL TEMP[0], IN[0], CONST[0]\n"
"1: ADD TEMP[0], TEMP[0], CONST[1]\n"
"2: MOV OUT[0], TEMP[0]\n"
"3: MOV OUT[1], IN[1]\n"
"4: END\n";
static const char vs_texture_asm[] =
"VERT1.1\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], GENERIC\n"
"DCL TEMP[0]\n"
"DCL CONST[0..1]\n"
"0: MUL TEMP[0], IN[0], CONST[0]\n"
"1: ADD TEMP[0], TEMP[0], CONST[1]\n"
"2: MOV OUT[0], TEMP[0]\n"
"3: MOV OUT[1], IN[1]\n"
"4: END\n";
#endif

View File

@ -0,0 +1,704 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "bezier.h"
#include "matrix.h"
#include "polygon.h"
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <math.h>
static const float flatness = 0.5;
static INLINE void split_left(struct bezier *bez, VGfloat t, struct bezier* left)
{
left->x1 = bez->x1;
left->y1 = bez->y1;
left->x2 = bez->x1 + t * (bez->x2 - bez->x1);
left->y2 = bez->y1 + t * (bez->y2 - bez->y1);
left->x3 = bez->x2 + t * (bez->x3 - bez->x2);
left->y3 = bez->y2 + t * (bez->y3 - bez->y2);
bez->x3 = bez->x3 + t * (bez->x4 - bez->x3);
bez->y3 = bez->y3 + t * (bez->y4 - bez->y3);
bez->x2 = left->x3 + t * (bez->x3 - left->x3);
bez->y2 = left->y3 + t * (bez->y3 - left->y3);
left->x3 = left->x2 + t * (left->x3 - left->x2);
left->y3 = left->y2 + t * (left->y3 - left->y2);
left->x4 = bez->x1 = left->x3 + t * (bez->x2 - left->x3);
left->y4 = bez->y1 = left->y3 + t * (bez->y2 - left->y3);
}
static INLINE void split(struct bezier *bez,
struct bezier *first_half,
struct bezier *second_half)
{
double c = (bez->x2 + bez->x3) * 0.5;
first_half->x2 = (bez->x1 + bez->x2) * 0.5;
second_half->x3 = (bez->x3 + bez->x4) * 0.5;
first_half->x1 = bez->x1;
second_half->x4 = bez->x4;
first_half->x3 = (first_half->x2 + c) * 0.5;
second_half->x2 = (second_half->x3 + c) * 0.5;
first_half->x4 = second_half->x1 =
(first_half->x3 + second_half->x2) * 0.5;
c = (bez->y2 + bez->y3) / 2;
first_half->y2 = (bez->y1 + bez->y2) * 0.5;
second_half->y3 = (bez->y3 + bez->y4) * 0.5;
first_half->y1 = bez->y1;
second_half->y4 = bez->y4;
first_half->y3 = (first_half->y2 + c) * 0.5;
second_half->y2 = (second_half->y3 + c) * 0.5;
first_half->y4 = second_half->y1 =
(first_half->y3 + second_half->y2) * 0.5;
}
struct polygon * bezier_to_polygon(struct bezier *bez)
{
struct polygon *poly = polygon_create(64);
polygon_vertex_append(poly, bez->x1, bez->y1);
bezier_add_to_polygon(bez, poly);
return poly;
}
void bezier_add_to_polygon(const struct bezier *bez,
struct polygon *poly)
{
struct bezier beziers[32];
struct bezier *b;
beziers[0] = *bez;
b = beziers;
while (b >= beziers) {
double y4y1 = b->y4 - b->y1;
double x4x1 = b->x4 - b->x1;
double l = ABS(x4x1) + ABS(y4y1);
double d;
if (l > 1.f) {
d = ABS((x4x1)*(b->y1 - b->y2) - (y4y1)*(b->x1 - b->x2))
+ ABS((x4x1)*(b->y1 - b->y3) - (y4y1)*(b->x1 - b->x3));
} else {
d = ABS(b->x1 - b->x2) + ABS(b->y1 - b->y2) +
ABS(b->x1 - b->x3) + ABS(b->y1 - b->y3);
l = 1.;
}
if (d < flatness*l || b == beziers + 31) {
/* good enough, we pop it off and add the endpoint */
polygon_vertex_append(poly, b->x4, b->y4);
--b;
} else {
/* split, second half of the bezier goes lower into the stack */
split(b, b+1, b);
++b;
}
}
}
static void add_if_close(struct bezier *bez, VGfloat *length, VGfloat error)
{
struct bezier left, right; /* bez poly splits */
VGfloat len = 0.0; /* arc length */
VGfloat chord; /* chord length */
len = len + line_length(bez->x1, bez->y1, bez->x2, bez->y2);
len = len + line_length(bez->x2, bez->y2, bez->x3, bez->y3);
len = len + line_length(bez->x3, bez->y3, bez->x4, bez->y4);
chord = line_length(bez->x1, bez->y1, bez->x4, bez->y4);
if ((len-chord) > error) {
split(bez, &left, &right); /* split in two */
add_if_close(&left, length, error); /* try left side */
add_if_close(&right, length, error); /* try right side */
return;
}
*length = *length + len;
return;
}
float bezier_length(struct bezier *bez, float error)
{
VGfloat length = 0.f;
add_if_close(bez, &length, error);
return length;
}
void bezier_init(struct bezier *bez,
float x1, float y1,
float x2, float y2,
float x3, float y3,
float x4, float y4)
{
bez->x1 = x1;
bez->y1 = y1;
bez->x2 = x2;
bez->y2 = y2;
bez->x3 = x3;
bez->y3 = y3;
bez->x4 = x4;
bez->y4 = y4;
#if 0
debug_printf("bezier in [%f, %f, %f, %f, %f, %f]\n",
x1, y1, x2, y2, x3, y3, x4, y4);
#endif
}
static INLINE void bezier_init2v(struct bezier *bez,
float *pt1,
float *pt2,
float *pt3,
float *pt4)
{
bez->x1 = pt1[0];
bez->y1 = pt1[1];
bez->x2 = pt2[0];
bez->y2 = pt2[1];
bez->x3 = pt3[0];
bez->y3 = pt3[1];
bez->x4 = pt4[0];
bez->y4 = pt4[1];
}
void bezier_transform(struct bezier *bez,
struct matrix *matrix)
{
assert(matrix_is_affine(matrix));
matrix_map_point(matrix, bez->x1, bez->y1, &bez->x1, &bez->y1);
matrix_map_point(matrix, bez->x2, bez->y2, &bez->x2, &bez->y2);
matrix_map_point(matrix, bez->x3, bez->y3, &bez->x3, &bez->y3);
matrix_map_point(matrix, bez->x4, bez->y4, &bez->x4, &bez->y4);
}
static INLINE void bezier_point_at(const struct bezier *bez, float t, float *pt)
{
float a, b, c, d;
float m_t;
m_t = 1. - t;
b = m_t * m_t;
c = t * t;
d = c * t;
a = b * m_t;
b *= 3. * t;
c *= 3. * m_t;
pt[0] = a*bez->x1 + b*bez->x2 + c*bez->x3 + d*bez->x4;
pt[1] = a*bez->y1 + b*bez->y2 + c*bez->y3 + d*bez->y4;
}
static INLINE void bezier_normal_at(const struct bezier *bez, float t, float *norm)
{
float m_t = 1. - t;
float a = m_t * m_t;
float b = t * m_t;
float c = t * t;
norm[0] = (bez->y2-bez->y1) * a + (bez->y3-bez->y2) * b + (bez->y4-bez->y3) * c;
norm[1] = -(bez->x2-bez->x1) * a - (bez->x3-bez->x2) * b - (bez->x4-bez->x3) * c;
}
enum shift_result {
Ok,
Discard,
Split,
Circle
};
static enum shift_result good_offset(const struct bezier *b1,
const struct bezier *b2,
float offset, float threshold)
{
const float o2 = offset*offset;
const float max_dist_line = threshold*offset*offset;
const float max_dist_normal = threshold*offset;
const float spacing = 0.25;
for (float i = spacing; i < 0.99; i += spacing) {
float p1[2],p2[2], d, l;
float normal[2];
bezier_point_at(b1, i, p1);
bezier_point_at(b2, i, p2);
d = (p1[0] - p2[0])*(p1[0] - p2[0]) + (p1[1] - p2[1])*(p1[1] - p2[1]);
if (ABS(d - o2) > max_dist_line)
return Split;
bezier_normal_at(b1, i, normal);
l = ABS(normal[0]) + ABS(normal[1]);
if (l != 0.) {
d = ABS(normal[0]*(p1[1] - p2[1]) - normal[1]*(p1[0] - p2[0]) ) / l;
if (d > max_dist_normal)
return Split;
}
}
return Ok;
}
static INLINE void shift_line_by_normal(float *l, float offset)
{
float norm[4];
float tx, ty;
line_normal(l, norm);
line_normalize(norm);
tx = (norm[2] - norm[0]) * offset;
ty = (norm[3] - norm[1]) * offset;
l[0] += tx; l[1] += ty;
l[2] += tx; l[3] += ty;
}
static INLINE VGboolean is_bezier_line(float (*points)[2], int count)
{
float dx13 = points[2][0] - points[0][0];
float dy13 = points[2][1] - points[0][1];
float dx12 = points[1][0] - points[0][0];
float dy12 = points[1][1] - points[0][1];
debug_assert(count > 2);
if (count == 3) {
return floatsEqual(dx12 * dy13, dx13 * dy12);
} else if (count == 4) {
float dx14 = points[3][0] - points[0][0];
float dy14 = points[3][1] - points[0][1];
return (floatsEqual(dx12 * dy13, dx13 * dy12) &&
floatsEqual(dx12 * dy14, dx14 * dy12));
}
return VG_FALSE;
}
static INLINE void compute_pt_normal(float *pt1, float *pt2, float *res)
{
float line[4];
float normal[4];
line[0] = 0.f; line[1] = 0.f;
line[2] = pt2[0] - pt1[0];
line[3] = pt2[1] - pt1[1];
line_normal(line, normal);
line_normalize(normal);
res[0] = normal[2];
res[1] = normal[3];
}
static enum shift_result shift(const struct bezier *orig,
struct bezier *shifted,
float offset, float threshold)
{
int map[4];
VGboolean p1_p2_equal = (orig->x1 == orig->x2 && orig->y1 == orig->y2);
VGboolean p2_p3_equal = (orig->x2 == orig->x3 && orig->y2 == orig->y3);
VGboolean p3_p4_equal = (orig->x3 == orig->x4 && orig->y3 == orig->y4);
float points[4][2];
int np = 0;
float bounds[4];
float points_shifted[4][2];
float prev_normal[2];
points[np][0] = orig->x1;
points[np][1] = orig->y1;
map[0] = 0;
++np;
if (!p1_p2_equal) {
points[np][0] = orig->x2;
points[np][1] = orig->y2;
++np;
}
map[1] = np - 1;
if (!p2_p3_equal) {
points[np][0] = orig->x3;
points[np][1] = orig->y3;
++np;
}
map[2] = np - 1;
if (!p3_p4_equal) {
points[np][0] = orig->x4;
points[np][1] = orig->y4;
++np;
}
map[3] = np - 1;
if (np == 1)
return Discard;
/* We need to specialcase lines of 3 or 4 points due to numerical
instability in intersection code below */
if (np > 2 && is_bezier_line(points, np)) {
float l[4] = { points[0][0], points[0][1],
points[np-1][0], points[np-1][1] };
float ctrl1[2], ctrl2[2];
if (floatsEqual(points[0][0], points[np-1][0]) &&
floatsEqual(points[0][1], points[np-1][1]))
return Discard;
shift_line_by_normal(l, offset);
line_point_at(l, 0.33, ctrl1);
line_point_at(l, 0.66, ctrl2);
bezier_init(shifted, l[0], l[1],
ctrl1[0], ctrl1[1], ctrl2[0], ctrl2[1],
l[2], l[3]);
return Ok;
}
bezier_bounds(orig, bounds);
if (np == 4 && bounds[2] < .1*offset && bounds[3] < .1*offset) {
float l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) +
(orig->y1 - orig->y2)*(orig->y1 - orig->y1) *
(orig->x3 - orig->x4)*(orig->x3 - orig->x4) +
(orig->y3 - orig->y4)*(orig->y3 - orig->y4);
float dot = (orig->x1 - orig->x2)*(orig->x3 - orig->x4) +
(orig->y1 - orig->y2)*(orig->y3 - orig->y4);
if (dot < 0 && dot*dot < 0.8*l)
/* the points are close and reverse dirction. Approximate the whole
thing by a semi circle */
return Circle;
}
compute_pt_normal(points[0], points[1], prev_normal);
points_shifted[0][0] = points[0][0] + offset * prev_normal[0];
points_shifted[0][1] = points[0][1] + offset * prev_normal[1];
for (int i = 1; i < np - 1; ++i) {
float normal_sum[2], r;
float next_normal[2];
compute_pt_normal(points[i], points[i + 1], next_normal);
normal_sum[0] = prev_normal[0] + next_normal[0];
normal_sum[1] = prev_normal[1] + next_normal[1];
r = 1.0 + prev_normal[0] * next_normal[0]
+ prev_normal[1] * next_normal[1];
if (floatsEqual(r + 1, 1)) {
points_shifted[i][0] = points[i][0] + offset * prev_normal[0];
points_shifted[i][1] = points[i][1] + offset * prev_normal[1];
} else {
float k = offset / r;
points_shifted[i][0] = points[i][0] + k * normal_sum[0];
points_shifted[i][1] = points[i][1] + k * normal_sum[1];
}
prev_normal[0] = next_normal[0];
prev_normal[1] = next_normal[1];
}
points_shifted[np - 1][0] = points[np - 1][0] + offset * prev_normal[0];
points_shifted[np - 1][1] = points[np - 1][1] + offset * prev_normal[1];
bezier_init2v(shifted,
points_shifted[map[0]], points_shifted[map[1]],
points_shifted[map[2]], points_shifted[map[3]]);
return good_offset(orig, shifted, offset, threshold);
}
static VGboolean make_circle(const struct bezier *b, float offset, struct bezier *o)
{
float normals[3][2];
float dist;
float angles[2];
float sign = 1.f;
int i;
float circle[3][2];
normals[0][0] = b->y2 - b->y1;
normals[0][1] = b->x1 - b->x2;
dist = sqrt(normals[0][0]*normals[0][0] + normals[0][1]*normals[0][1]);
if (floatsEqual(dist + 1, 1.f))
return VG_FALSE;
normals[0][0] /= dist;
normals[0][1] /= dist;
normals[2][0] = b->y4 - b->y3;
normals[2][1] = b->x3 - b->x4;
dist = sqrt(normals[2][0]*normals[2][0] + normals[2][1]*normals[2][1]);
if (floatsEqual(dist + 1, 1.f))
return VG_FALSE;
normals[2][0] /= dist;
normals[2][1] /= dist;
normals[1][0] = b->x1 - b->x2 - b->x3 + b->x4;
normals[1][1] = b->y1 - b->y2 - b->y3 + b->y4;
dist = -1*sqrt(normals[1][0]*normals[1][0] + normals[1][1]*normals[1][1]);
normals[1][0] /= dist;
normals[1][1] /= dist;
for (i = 0; i < 2; ++i) {
float cos_a = normals[i][0]*normals[i+1][0] + normals[i][1]*normals[i+1][1];
if (cos_a > 1.)
cos_a = 1.;
if (cos_a < -1.)
cos_a = -1;
angles[i] = acos(cos_a)/M_PI;
}
if (angles[0] + angles[1] > 1.) {
/* more than 180 degrees */
normals[1][0] = -normals[1][0];
normals[1][1] = -normals[1][1];
angles[0] = 1. - angles[0];
angles[1] = 1. - angles[1];
sign = -1.;
}
circle[0][0] = b->x1 + normals[0][0]*offset;
circle[0][1] = b->y1 + normals[0][1]*offset;
circle[1][0] = 0.5*(b->x1 + b->x4) + normals[1][0]*offset;
circle[1][1] = 0.5*(b->y1 + b->y4) + normals[1][1]*offset;
circle[2][0] = b->x4 + normals[2][0]*offset;
circle[2][1] = b->y4 + normals[2][1]*offset;
for (i = 0; i < 2; ++i) {
float kappa = 2.*KAPPA * sign * offset * angles[i];
o->x1 = circle[i][0];
o->y1 = circle[i][1];
o->x2 = circle[i][0] - normals[i][1]*kappa;
o->y2 = circle[i][1] + normals[i][0]*kappa;
o->x3 = circle[i+1][0] + normals[i+1][1]*kappa;
o->y3 = circle[i+1][1] - normals[i+1][0]*kappa;
o->x4 = circle[i+1][0];
o->y4 = circle[i+1][1];
++o;
}
return VG_TRUE;
}
int bezier_translate_by_normal(struct bezier *bez,
struct bezier *curves,
int max_curves,
float normal_len,
float threshold)
{
struct bezier beziers[10];
struct bezier *b, *o;
/* fixme: this should really be floatsEqual */
if (bez->x1 == bez->x2 && bez->x1 == bez->x3 && bez->x1 == bez->x4 &&
bez->y1 == bez->y2 && bez->y1 == bez->y3 && bez->y1 == bez->y4)
return 0;
--max_curves;
redo:
beziers[0] = *bez;
b = beziers;
o = curves;
while (b >= beziers) {
int stack_segments = b - beziers + 1;
enum shift_result res;
if ((stack_segments == 10) || (o - curves == max_curves - stack_segments)) {
threshold *= 1.5;
if (threshold > 2.)
goto give_up;
goto redo;
}
res = shift(b, o, normal_len, threshold);
if (res == Discard) {
--b;
} else if (res == Ok) {
++o;
--b;
continue;
} else if (res == Circle && max_curves - (o - curves) >= 2) {
/* add semi circle */
if (make_circle(b, normal_len, o))
o += 2;
--b;
} else {
split(b, b+1, b);
++b;
}
}
give_up:
while (b >= beziers) {
enum shift_result res = shift(b, o, normal_len, threshold);
/* if res isn't Ok or Split then *o is undefined */
if (res == Ok || res == Split)
++o;
--b;
}
debug_assert(o - curves <= max_curves);
return o - curves;
}
void bezier_bounds(const struct bezier *bez,
float *bounds/*x/y/width/height*/)
{
float xmin = bez->x1;
float xmax = bez->x1;
float ymin = bez->y1;
float ymax = bez->y1;
if (bez->x2 < xmin)
xmin = bez->x2;
else if (bez->x2 > xmax)
xmax = bez->x2;
if (bez->x3 < xmin)
xmin = bez->x3;
else if (bez->x3 > xmax)
xmax = bez->x3;
if (bez->x4 < xmin)
xmin = bez->x4;
else if (bez->x4 > xmax)
xmax = bez->x4;
if (bez->y2 < ymin)
ymin = bez->y2;
else if (bez->y2 > ymax)
ymax = bez->y2;
if (bez->y3 < ymin)
ymin = bez->y3;
else if (bez->y3 > ymax)
ymax = bez->y3;
if (bez->y4 < ymin)
ymin = bez->y4;
else if (bez->y4 > ymax)
ymax = bez->y4;
bounds[0] = xmin; /* x */
bounds[1] = ymin; /* y */
bounds[2] = xmax - xmin; /* width */
bounds[3] = ymax - ymin; /* height */
}
void bezier_start_tangent(const struct bezier *bez,
float *tangent)
{
tangent[0] = bez->x1;
tangent[1] = bez->y1;
tangent[2] = bez->x2;
tangent[3] = bez->y2;
if (null_line(tangent)) {
tangent[0] = bez->x1;
tangent[1] = bez->y1;
tangent[2] = bez->x3;
tangent[3] = bez->y3;
}
if (null_line(tangent)) {
tangent[0] = bez->x1;
tangent[1] = bez->y1;
tangent[2] = bez->x4;
tangent[3] = bez->y4;
}
}
static INLINE VGfloat bezier_t_at_length(struct bezier *bez,
VGfloat at_length,
VGfloat error)
{
VGfloat len = bezier_length(bez, error);
VGfloat t = 1.0;
VGfloat last_bigger = 1.;
if (at_length > len || floatsEqual(at_length, len))
return t;
if (floatIsZero(at_length))
return 0.f;
t *= 0.5;
while (1) {
struct bezier right = *bez;
struct bezier left;
VGfloat tmp_len;
split_left(&right, t, &left);
tmp_len = bezier_length(&left, error);
if (ABS(tmp_len - at_length) < error)
break;
if (tmp_len < at_length) {
t += (last_bigger - t)*.5;
} else {
last_bigger = t;
t -= t*.5;
}
}
return t;
}
void bezier_point_at_length(struct bezier *bez,
float length,
float *point,
float *normal)
{
/* ~0.000001 seems to be required to pass G2080x tests */
VGfloat t = bezier_t_at_length(bez, length, 0.000001);
bezier_point_at(bez, t, point);
bezier_normal_at(bez, t, normal);
vector_unit(normal);
}
void bezier_point_at_t(struct bezier *bez, float t,
float *point, float *normal)
{
bezier_point_at(bez, t, point);
bezier_normal_at(bez, t, normal);
vector_unit(normal);
}
void bezier_exact_bounds(const struct bezier *bez,
float *bounds/*x/y/width/height*/)
{
struct polygon *poly = polygon_create(64);
polygon_vertex_append(poly, bez->x1, bez->y1);
bezier_add_to_polygon(bez, poly);
polygon_bounding_rect(poly, bounds);
polygon_destroy(poly);
}

View File

@ -0,0 +1,81 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef BEZIER_H
#define BEZIER_H
struct polygon;
struct matrix;
struct bezier {
float x1, y1;
float x2, y2;
float x3, y3;
float x4, y4;
};
#define BEZIER_DEFAULT_ERROR 0.01
/* kappa as being l of a circle with r = 1, we can emulate any
* circle of radius r by using the formula
* l = r . kappa
* More at:
* http://www.whizkidtech.redprince.net/bezier/circle/ */
#define KAPPA 0.5522847498
void bezier_init(struct bezier *bez,
float x1, float y1,
float x2, float y2,
float x3, float y3,
float x4, float y4);
struct polygon *bezier_to_polygon(struct bezier *bez);
void bezier_add_to_polygon(const struct bezier *bez,
struct polygon *poly);
float bezier_length(struct bezier *bez, float error);
void bezier_transform(struct bezier *bez,
struct matrix *mat);
int bezier_translate_by_normal(struct bezier *b,
struct bezier *curves,
int max_curves,
float normal_len,
float threshold);
void bezier_bounds(const struct bezier *bez,
float *bounds/*x/y/width/height*/);
void bezier_exact_bounds(const struct bezier *bez,
float *bounds/*x/y/width/height*/);
void bezier_start_tangent(const struct bezier *bez,
float *tangent);
void bezier_point_at_length(struct bezier *bez, float length,
float *point, float *normal);
void bezier_point_at_t(struct bezier *bez, float t,
float *point, float *normal);
#endif

View File

@ -0,0 +1,654 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "image.h"
#include "vg_translate.h"
#include "vg_context.h"
#include "matrix.h"
#include "renderer.h"
#include "util_array.h"
#include "api_consts.h"
#include "shaders_cache.h"
#include "shader.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_inlines.h"
#include "util/u_blit.h"
#include "util/u_tile.h"
#include "util/u_memory.h"
#include "util/u_math.h"
static enum pipe_format vg_format_to_pipe(VGImageFormat format)
{
switch(format) {
case VG_sRGB_565:
return PIPE_FORMAT_R5G6B5_UNORM;
case VG_sRGBA_5551:
return PIPE_FORMAT_A1R5G5B5_UNORM;
case VG_sRGBA_4444:
return PIPE_FORMAT_A4R4G4B4_UNORM;
case VG_sL_8:
case VG_lL_8:
return PIPE_FORMAT_L8_UNORM;
case VG_BW_1:
return PIPE_FORMAT_A8R8G8B8_UNORM;
case VG_A_8:
return PIPE_FORMAT_A8_UNORM;
#ifdef OPENVG_VERSION_1_1
case VG_A_1:
case VG_A_4:
return PIPE_FORMAT_A8_UNORM;
#endif
default:
return PIPE_FORMAT_A8R8G8B8_UNORM;
}
}
static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc)
{
src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
dst_loc[2] = src_loc[2];
dst_loc[3] = src_loc[3];
}
static void vg_copy_texture(struct vg_context *ctx,
struct pipe_texture *dst, VGint dx, VGint dy,
struct pipe_texture *src, VGint sx, VGint sy,
VGint width, VGint height)
{
VGfloat dst_loc[4], src_loc[4];
VGfloat dst_bounds[4], src_bounds[4];
VGfloat src_shift[4], dst_shift[4], shift[4];
dst_loc[0] = dx;
dst_loc[1] = dy;
dst_loc[2] = width;
dst_loc[3] = height;
dst_bounds[0] = 0.f;
dst_bounds[1] = 0.f;
dst_bounds[2] = dst->width[0];
dst_bounds[3] = dst->height[0];
src_loc[0] = sx;
src_loc[1] = sy;
src_loc[2] = width;
src_loc[3] = height;
src_bounds[0] = 0.f;
src_bounds[1] = 0.f;
src_bounds[2] = src->width[0];
src_bounds[3] = src->height[0];
vg_bound_rect(src_loc, src_bounds, src_shift);
vg_bound_rect(dst_loc, dst_bounds, dst_shift);
shift[0] = src_shift[0] - dst_shift[0];
shift[1] = src_shift[1] - dst_shift[1];
if (shift[0] < 0)
vg_shift_rectx(src_loc, src_bounds, -shift[0]);
else
vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
if (shift[1] < 0)
vg_shift_recty(src_loc, src_bounds, -shift[1]);
else
vg_shift_recty(dst_loc, dst_bounds, shift[1]);
vg_sync_size(src_loc, dst_loc);
if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
dst_loc[2] >= 0 && dst_loc[3] >= 0) {
renderer_copy_texture(ctx->renderer,
src,
src_loc[0],
src_loc[1] + src_loc[3],
src_loc[0] + src_loc[2],
src_loc[1],
dst,
dst_loc[0],
dst_loc[1] + dst_loc[3],
dst_loc[0] + dst_loc[2],
dst_loc[1]);
}
}
void vg_copy_surface(struct vg_context *ctx,
struct pipe_surface *dst, VGint dx, VGint dy,
struct pipe_surface *src, VGint sx, VGint sy,
VGint width, VGint height)
{
VGfloat dst_loc[4], src_loc[4];
VGfloat dst_bounds[4], src_bounds[4];
VGfloat src_shift[4], dst_shift[4], shift[4];
dst_loc[0] = dx;
dst_loc[1] = dy;
dst_loc[2] = width;
dst_loc[3] = height;
dst_bounds[0] = 0.f;
dst_bounds[1] = 0.f;
dst_bounds[2] = dst->width;
dst_bounds[3] = dst->height;
src_loc[0] = sx;
src_loc[1] = sy;
src_loc[2] = width;
src_loc[3] = height;
src_bounds[0] = 0.f;
src_bounds[1] = 0.f;
src_bounds[2] = src->width;
src_bounds[3] = src->height;
vg_bound_rect(src_loc, src_bounds, src_shift);
vg_bound_rect(dst_loc, dst_bounds, dst_shift);
shift[0] = src_shift[0] - dst_shift[0];
shift[1] = src_shift[1] - dst_shift[1];
if (shift[0] < 0)
vg_shift_rectx(src_loc, src_bounds, -shift[0]);
else
vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
if (shift[1] < 0)
vg_shift_recty(src_loc, src_bounds, -shift[1]);
else
vg_shift_recty(dst_loc, dst_bounds, shift[1]);
vg_sync_size(src_loc, dst_loc);
if (src_loc[2] > 0 && src_loc[3] > 0 &&
dst_loc[2] > 0 && dst_loc[3] > 0) {
if (src == dst)
renderer_copy_surface(ctx->renderer,
src,
src_loc[0],
src->height - (src_loc[1] + src_loc[3]),
src_loc[0] + src_loc[2],
src->height - src_loc[1],
dst,
dst_loc[0],
dst->height - (dst_loc[1] + dst_loc[3]),
dst_loc[0] + dst_loc[2],
dst->height - dst_loc[1],
0, 0);
else
renderer_copy_surface(ctx->renderer,
src,
src_loc[0],
src->height - src_loc[1],
src_loc[0] + src_loc[2],
src->height - (src_loc[1] + src_loc[3]),
dst,
dst_loc[0],
dst->height - (dst_loc[1] + dst_loc[3]),
dst_loc[0] + dst_loc[2],
dst->height - dst_loc[1],
0, 0);
}
}
static struct pipe_texture *image_texture(struct vg_image *img)
{
struct pipe_texture *tex = img->texture;
return tex;
}
static void image_cleari(struct vg_image *img, VGint clear_colori,
VGint x, VGint y, VGint width, VGint height)
{
VGint *clearbuf;
VGint i;
VGfloat dwidth, dheight;
clearbuf = malloc(sizeof(VGint)*width*height);
for (i = 0; i < width*height; ++i)
clearbuf[i] = clear_colori;
dwidth = MIN2(width, img->width);
dheight = MIN2(height, img->height);
image_sub_data(img, clearbuf, width * sizeof(VGint),
VG_sRGBA_8888,
x, y, dwidth, dheight);
free(clearbuf);
}
struct vg_image * image_create(VGImageFormat format,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *image = CALLOC_STRUCT(vg_image);
enum pipe_format pformat = vg_format_to_pipe(format);
struct pipe_texture pt, *newtex;
struct pipe_screen *screen = ctx->pipe->screen;
vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
image->format = format;
image->width = width;
image->height = height;
image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
image->sampler.normalized_coords = 1;
assert(screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_SAMPLER, 0));
memset(&pt, 0, sizeof(pt));
pt.target = PIPE_TEXTURE_2D;
pt.format = pformat;
pf_get_block(pformat, &pt.block);
pt.last_level = 0;
pt.width[0] = width;
pt.height[0] = height;
pt.depth[0] = 1;
pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
newtex = screen->texture_create(screen, &pt);
debug_assert(newtex);
image->texture = newtex;
vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
image_cleari(image, 0, 0, 0, image->width, image->height);
return image;
}
void image_destroy(struct vg_image *img)
{
struct vg_context *ctx = vg_current_context();
vg_context_remove_object(ctx, VG_OBJECT_IMAGE, img);
if (img->parent) {
/* remove img from the parent child array */
int idx;
struct vg_image **array =
(struct vg_image **)img->parent->children_array->data;
for (idx = 0; idx < img->parent->children_array->num_elements; ++idx) {
struct vg_image *child = array[idx];
if (child == img) {
break;
}
}
debug_assert(idx < img->parent->children_array->num_elements);
array_remove_element(img->parent->children_array, idx);
}
if (img->children_array && img->children_array->num_elements) {
/* reparent the children */
VGint i;
struct vg_image *parent = img->parent;
struct vg_image **children =
(struct vg_image **)img->children_array->data;
if (!parent) {
VGint min_x = children[0]->x;
parent = children[0];
for (i = 1; i < img->children_array->num_elements; ++i) {
struct vg_image *child = children[i];
if (child->x < min_x) {
parent = child;
}
}
}
for (i = 0; i < img->children_array->num_elements; ++i) {
struct vg_image *child = children[i];
if (child != parent) {
child->parent = parent;
if (!parent->children_array) {
parent->children_array = array_create(
sizeof(struct vg_image*));
}
array_append_data(parent->children_array,
&child, 1);
} else
child->parent = NULL;
}
array_destroy(img->children_array);
}
pipe_texture_reference(&img->texture, NULL);
free(img);
}
void image_clear(struct vg_image *img,
VGint x, VGint y, VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
VGfloat *clear_colorf = ctx->state.vg.clear_color;
VGubyte r, g, b ,a;
VGint clear_colori;
/* FIXME: this is very nasty */
r = float_to_ubyte(clear_colorf[0]);
g = float_to_ubyte(clear_colorf[1]);
b = float_to_ubyte(clear_colorf[2]);
a = float_to_ubyte(clear_colorf[3]);
clear_colori = r << 24 | g << 16 | b << 8 | a;
image_cleari(img, clear_colori, x, y, width, height);
}
void image_sub_data(struct vg_image *image,
const void * data,
VGint dataStride,
VGImageFormat dataFormat,
VGint x, VGint y,
VGint width, VGint height)
{
const VGint yStep = 1;
VGubyte *src = (VGubyte *)data;
VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
VGfloat *df = (VGfloat*)temp;
VGint i;
struct vg_context *ctx = vg_current_context();
struct pipe_screen *screen = ctx->pipe->screen;
struct pipe_texture *texture = image_texture(image);
VGint xoffset = 0, yoffset = 0;
if (x < 0) {
xoffset -= x;
width += x;
x = 0;
}
if (y < 0) {
yoffset -= y;
height += y;
y = 0;
}
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (x > image->width || y > image->width) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
if (x + width > image->width) {
width = image->width - x;
}
if (y + height > image->height) {
height = image->height - y;
}
{ /* upload color_data */
struct pipe_transfer *transfer = screen->get_tex_transfer(
screen, texture, 0, 0, 0,
PIPE_TRANSFER_WRITE, 0, 0, texture->width[0], texture->height[0]);
src += (dataStride * yoffset);
for (i = 0; i < height; i++) {
_vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp);
pipe_put_tile_rgba(transfer, x+image->x, y+image->y, width, 1, df);
y += yStep;
src += dataStride;
}
screen->tex_transfer_destroy(transfer);
}
}
void image_get_sub_data(struct vg_image * image,
void * data,
VGint dataStride,
VGImageFormat dataFormat,
VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
VGfloat *df = (VGfloat*)temp;
VGint y = 0, yStep = 1;
VGint i;
VGubyte *dst = (VGubyte *)data;
{
struct pipe_transfer *transfer =
screen->get_tex_transfer(screen,
image->texture, 0, 0, 0,
PIPE_TRANSFER_READ,
0, 0,
image->x + image->width,
image->y + image->height);
/* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) {
#if 0
debug_printf("%d-%d == %d\n", sy, height, y);
#endif
pipe_get_tile_rgba(transfer, sx+image->x, y, width, 1, df);
y += yStep;
_vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst);
dst += dataStride;
}
screen->tex_transfer_destroy(transfer);
}
}
struct vg_image * image_child_image(struct vg_image *parent,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_image *image = CALLOC_STRUCT(vg_image);
vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
image->x = parent->x + x;
image->y = parent->y + y;
image->width = width;
image->height = height;
image->parent = parent;
image->texture = 0;
pipe_texture_reference(&image->texture,
parent->texture);
image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
image->sampler.normalized_coords = 1;
if (!parent->children_array)
parent->children_array = array_create(
sizeof(struct vg_image*));
array_append_data(parent->children_array,
&image, 1);
vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
return image;
}
void image_copy(struct vg_image *dst, VGint dx, VGint dy,
struct vg_image *src, VGint sx, VGint sy,
VGint width, VGint height,
VGboolean dither)
{
struct vg_context *ctx = vg_current_context();
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
/* make sure rendering has completed */
ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy,
src->texture, src->x + sx, src->y + sy, width, height);
}
void image_draw(struct vg_image *img)
{
struct vg_context *ctx = vg_current_context();
VGfloat x1, y1;
VGfloat x2, y2;
VGfloat x3, y3;
VGfloat x4, y4;
struct matrix *matrix;
x1 = 0;
y1 = 0;
x2 = img->width;
y2 = 0;
x3 = img->width;
y3 = img->height;
x4 = 0;
y4 = img->height;
matrix = &ctx->state.vg.image_user_to_surface_matrix;
matrix_map_point(matrix, x1, y1, &x1, &y1);
matrix_map_point(matrix, x2, y2, &x2, &y2);
matrix_map_point(matrix, x3, y3, &x3, &y3);
matrix_map_point(matrix, x4, y4, &x4, &y4);
shader_set_drawing_image(ctx->shader, VG_TRUE);
shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
shader_set_image(ctx->shader, img);
shader_bind(ctx->shader);
renderer_texture_quad(ctx->renderer, image_texture(img),
img->x, img->y, img->x + img->width, img->y + img->height,
x1, y1, x2, y2, x3, y3, x4, y4);
}
void image_set_pixels(VGint dx, VGint dy,
struct vg_image *src, VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *surf;
struct st_renderbuffer *strb = ctx->draw_buffer->strb;
/* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
surf = screen->get_tex_surface(screen, image_texture(src), 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ);
vg_copy_surface(ctx, strb->surface, dx, dy,
surf, sx+src->x, sy+src->y, width, height);
screen->tex_surface_destroy(surf);
}
void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *surf;
struct st_renderbuffer *strb = ctx->draw_buffer->strb;
/* flip the y coordinates */
/*dy = dst->height - dy - height;*/
/* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
surf = screen->get_tex_surface(screen, image_texture(dst), 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE |
PIPE_BUFFER_USAGE_GPU_READ);
vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
strb->surface, sx, sy, width, height);
pipe_surface_reference(&surf, NULL);
}
VGboolean vg_image_overlaps(struct vg_image *dst,
struct vg_image *src)
{
if (dst == src || dst->parent == src ||
dst == src->parent)
return VG_TRUE;
if (dst->parent && dst->parent == src->parent) {
VGfloat left1 = dst->x;
VGfloat left2 = src->x;
VGfloat right1 = dst->x + dst->width;
VGfloat right2 = src->x + src->width;
VGfloat bottom1 = dst->y;
VGfloat bottom2 = src->y;
VGfloat top1 = dst->y + dst->height;
VGfloat top2 = src->y + src->height;
return !(left2 > right1 || right2 < left1 ||
top2 > bottom1 || bottom2 < top1);
}
return VG_FALSE;
}
VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers,
struct pipe_texture **textures)
{
img->sampler.min_img_filter = image_sampler_filter(img->base.ctx);
img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx);
samplers[3] = &img->sampler;
textures[3] = img->texture;
return 1;
}
VGint image_sampler_filter(struct vg_context *ctx)
{
switch(ctx->state.vg.image_quality) {
case VG_IMAGE_QUALITY_NONANTIALIASED:
return PIPE_TEX_FILTER_NEAREST;
break;
case VG_IMAGE_QUALITY_FASTER:
return PIPE_TEX_FILTER_NEAREST;
break;
case VG_IMAGE_QUALITY_BETTER:
/*return PIPE_TEX_FILTER_ANISO;*/
return PIPE_TEX_FILTER_LINEAR;
break;
default:
debug_printf("Unknown image quality");
}
return PIPE_TEX_FILTER_NEAREST;
}

View File

@ -0,0 +1,104 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef IMAGES_H
#define IMAGES_H
#include "vg_context.h"
#include "pipe/p_state.h"
struct pipe_texture;
struct array;
struct vg_context;
struct pipe_surface;
struct vg_image {
struct vg_object base;
VGImageFormat format;
VGint x, y;
VGint width, height;
struct vg_image *parent;
struct pipe_texture *texture;
struct pipe_sampler_state sampler;
struct array *children_array;
};
struct vg_image *image_create(VGImageFormat format,
VGint width, VGint height);
void image_destroy(struct vg_image *img);
void image_clear(struct vg_image *img,
VGint x, VGint y, VGint width, VGint height);
void image_sub_data(struct vg_image *image,
const void * data,
VGint dataStride,
VGImageFormat dataFormat,
VGint x, VGint y,
VGint width, VGint height);
void image_get_sub_data(struct vg_image * image,
void * data,
VGint dataStride,
VGImageFormat dataFormat,
VGint x, VGint y,
VGint width, VGint height);
struct vg_image *image_child_image(struct vg_image *parent,
VGint x, VGint y,
VGint width, VGint height);
void image_copy(struct vg_image *dst, VGint dx, VGint dy,
struct vg_image *src, VGint sx, VGint sy,
VGint width, VGint height,
VGboolean dither);
void image_draw(struct vg_image *img);
void image_set_pixels(VGint dx, VGint dy,
struct vg_image *src, VGint sx, VGint sy,
VGint width, VGint height);
void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
VGint sx, VGint sy,
VGint width, VGint height);
VGint image_bind_samplers(struct vg_image *dst, struct pipe_sampler_state **samplers,
struct pipe_texture **textures);
VGboolean vg_image_overlaps(struct vg_image *dst,
struct vg_image *src);
VGint image_sampler_filter(struct vg_context *ctx);
void vg_copy_surface(struct vg_context *ctx,
struct pipe_surface *dst, VGint dx, VGint dy,
struct pipe_surface *src, VGint sx, VGint sy,
VGint width, VGint height);
#endif

View File

@ -0,0 +1,690 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "mask.h"
#include "path.h"
#include "image.h"
#include "shaders_cache.h"
#include "renderer.h"
#include "asm_util.h"
#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
struct vg_mask_layer {
struct vg_object base;
VGint width;
VGint height;
struct pipe_texture *texture;
};
static INLINE struct pipe_surface *
alpha_mask_surface(struct vg_context *ctx, int usage)
{
struct pipe_screen *screen = ctx->pipe->screen;
struct st_framebuffer *stfb = ctx->draw_buffer;
return screen->get_tex_surface(screen,
stfb->alpha_mask,
0, 0, 0,
usage);
}
static INLINE VGboolean
intersect_rectangles(VGint dwidth, VGint dheight,
VGint swidth, VGint sheight,
VGint tx, VGint ty,
VGint twidth, VGint theight,
VGint *offsets,
VGint *location)
{
if (tx + twidth <= 0 || tx >= dwidth)
return VG_FALSE;
if (ty + theight <= 0 || ty >= dheight)
return VG_FALSE;
offsets[0] = 0;
offsets[1] = 0;
location[0] = tx;
location[1] = ty;
if (tx < 0) {
offsets[0] -= tx;
location[0] = 0;
location[2] = MIN2(tx + swidth, MIN2(dwidth, tx + twidth));
offsets[2] = location[2];
} else {
offsets[2] = MIN2(twidth, MIN2(dwidth - tx, swidth ));
location[2] = offsets[2];
}
if (ty < 0) {
offsets[1] -= ty;
location[1] = 0;
location[3] = MIN2(ty + sheight, MIN2(dheight, ty + theight));
offsets[3] = location[3];
} else {
offsets[3] = MIN2(theight, MIN2(dheight - ty, sheight));
location[3] = offsets[3];
}
return VG_TRUE;
}
#if DEBUG_MASKS
static void read_alpha_mask(void * data, VGint dataStride,
VGImageFormat dataFormat,
VGint sx, VGint sy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->alpha_mask;
struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
VGfloat *df = (VGfloat*)temp;
VGint y = (fb->height - sy) - 1, yStep = -1;
VGint i;
VGubyte *dst = (VGubyte *)data;
VGint xoffset = 0, yoffset = 0;
/* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
if (sx < 0) {
xoffset = -sx;
xoffset *= _vega_size_for_format(dataFormat);
width += sx;
sx = 0;
}
if (sy < 0) {
yoffset = -sy;
height += sy;
sy = 0;
y = (fb->height - sy) - 1;
yoffset *= dataStride;
}
{
struct pipe_surface *surf;
surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ);
/* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) {
#if 0
debug_printf("%d-%d == %d\n", sy, height, y);
#endif
pipe_get_tile_rgba(surf, sx, y, width, 1, df);
y += yStep;
_vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
dst + yoffset + xoffset);
dst += dataStride;
}
pipe_surface_reference(&surf, NULL);
}
}
void save_alpha_to_file(const char *filename)
{
struct vg_context *ctx = vg_current_context();
struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
VGint *data;
int i, j;
data = malloc(sizeof(int) * fb->width * fb->height);
read_alpha_mask(data, fb->width * sizeof(int),
VG_sRGBA_8888,
0, 0, fb->width, fb->height);
fprintf(stderr, "/*---------- start */\n");
fprintf(stderr, "const int image_width = %d;\n",
fb->width);
fprintf(stderr, "const int image_height = %d;\n",
fb->height);
fprintf(stderr, "const int image_data = {\n");
for (i = 0; i < fb->height; ++i) {
for (j = 0; j < fb->width; ++j) {
int rgba = data[i * fb->height + j];
int argb = 0;
argb = (rgba >> 8);
argb |= ((rgba & 0xff) << 24);
fprintf(stderr, "0x%x, ", argb);
}
fprintf(stderr, "\n");
}
fprintf(stderr, "};\n");
fprintf(stderr, "/*---------- end */\n");
}
#endif
static void setup_mask_framebuffer(struct pipe_surface *surf,
VGint surf_width, VGint surf_height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_framebuffer_state fb;
memset(&fb, 0, sizeof(fb));
fb.width = surf_width;
fb.height = surf_height;
fb.nr_cbufs = 1;
fb.cbufs[0] = surf;
{
VGint i;
for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
fb.cbufs[i] = 0;
}
cso_set_framebuffer(ctx->cso_context, &fb);
}
/* setup shader constants */
static void setup_mask_operation(VGMaskOperation operation)
{
struct vg_context *ctx = vg_current_context();
struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
const VGint param_bytes = 4 * sizeof(VGfloat);
const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f};
void *shader = 0;
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization.
*/
pipe_buffer_reference(&cbuf->buffer, NULL);
cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1,
PIPE_BUFFER_USAGE_CONSTANT,
param_bytes);
if (cbuf->buffer) {
st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
0, param_bytes, ones);
}
ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
switch (operation) {
case VG_UNION_MASK: {
if (!ctx->mask.union_fs) {
ctx->mask.union_fs = shader_create_from_text(ctx->pipe,
union_mask_asm,
200,
PIPE_SHADER_FRAGMENT);
}
shader = ctx->mask.union_fs->driver;
}
break;
case VG_INTERSECT_MASK: {
if (!ctx->mask.intersect_fs) {
ctx->mask.intersect_fs = shader_create_from_text(ctx->pipe,
intersect_mask_asm,
200,
PIPE_SHADER_FRAGMENT);
}
shader = ctx->mask.intersect_fs->driver;
}
break;
case VG_SUBTRACT_MASK: {
if (!ctx->mask.subtract_fs) {
ctx->mask.subtract_fs = shader_create_from_text(ctx->pipe,
subtract_mask_asm,
200,
PIPE_SHADER_FRAGMENT);
}
shader = ctx->mask.subtract_fs->driver;
}
break;
case VG_SET_MASK: {
if (!ctx->mask.set_fs) {
ctx->mask.set_fs = shader_create_from_text(ctx->pipe,
set_mask_asm,
200,
PIPE_SHADER_FRAGMENT);
}
shader = ctx->mask.set_fs->driver;
}
break;
default:
assert(0);
break;
}
cso_set_fragment_shader_handle(ctx->cso_context, shader);
}
static void setup_mask_samplers(struct pipe_texture *umask)
{
struct vg_context *ctx = vg_current_context();
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
struct st_framebuffer *fb_buffers = ctx->draw_buffer;
struct pipe_texture *uprev = NULL;
struct pipe_sampler_state sampler;
uprev = fb_buffers->blend_texture;
sampler = ctx->mask.sampler;
sampler.normalized_coords = 1;
samplers[0] = NULL;
samplers[1] = NULL;
samplers[2] = NULL;
textures[0] = NULL;
textures[1] = NULL;
textures[2] = NULL;
samplers[0] = &sampler;
samplers[1] = &ctx->mask.sampler;
textures[0] = umask;
textures[1] = uprev;
cso_set_samplers(ctx->cso_context, 2,
(const struct pipe_sampler_state **)samplers);
cso_set_sampler_textures(ctx->cso_context, 2, textures);
}
/* setup shader constants */
static void setup_mask_fill(const VGfloat color[4])
{
struct vg_context *ctx = vg_current_context();
struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
const VGint param_bytes = 4 * sizeof(VGfloat);
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization.
*/
pipe_buffer_reference(&cbuf->buffer, NULL);
cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1,
PIPE_BUFFER_USAGE_CONSTANT,
param_bytes);
if (cbuf->buffer) {
st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, 0, param_bytes, color);
}
ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
cso_set_fragment_shader_handle(ctx->cso_context,
shaders_cache_fill(ctx->sc,
VEGA_SOLID_FILL_SHADER));
}
static void setup_mask_viewport()
{
struct vg_context *ctx = vg_current_context();
vg_set_viewport(ctx, VEGA_Y0_TOP);
}
static void setup_mask_blend()
{
struct vg_context *ctx = vg_current_context();
struct pipe_blend_state blend;
memset(&blend, 0, sizeof(struct pipe_blend_state));
blend.blend_enable = 1;
blend.colormask |= PIPE_MASK_R;
blend.colormask |= PIPE_MASK_G;
blend.colormask |= PIPE_MASK_B;
blend.colormask |= PIPE_MASK_A;
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
cso_set_blend(ctx->cso_context, &blend);
}
static void surface_fill(struct pipe_surface *surf,
int surf_width, int surf_height,
int x, int y, int width, int height,
const VGfloat color[4])
{
struct vg_context *ctx = vg_current_context();
if (x < 0) {
width += x;
x = 0;
}
if (y < 0) {
height += y;
y = 0;
}
cso_save_framebuffer(ctx->cso_context);
cso_save_blend(ctx->cso_context);
cso_save_fragment_shader(ctx->cso_context);
cso_save_viewport(ctx->cso_context);
setup_mask_blend();
setup_mask_fill(color);
setup_mask_framebuffer(surf, surf_width, surf_height);
setup_mask_viewport();
renderer_draw_quad(ctx->renderer, x, y,
x + width, y + height, 0.0f/*depth should be disabled*/);
/* make sure rendering has completed */
ctx->pipe->flush(ctx->pipe,
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
NULL);
#if DEBUG_MASKS
save_alpha_to_file(0);
#endif
cso_restore_blend(ctx->cso_context);
cso_restore_framebuffer(ctx->cso_context);
cso_restore_fragment_shader(ctx->cso_context);
cso_restore_viewport(ctx->cso_context);
}
static void mask_using_texture(struct pipe_texture *texture,
VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct pipe_surface *surface =
alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_GPU_WRITE);
VGint offsets[4], loc[4];
if (!surface)
return;
if (!intersect_rectangles(surface->width, surface->height,
texture->width[0], texture->height[0],
x, y, width, height,
offsets, loc))
return;
#if 0
debug_printf("Offset = [%d, %d, %d, %d]\n", offsets[0],
offsets[1], offsets[2], offsets[3]);
debug_printf("Locati = [%d, %d, %d, %d]\n", loc[0],
loc[1], loc[2], loc[3]);
#endif
/* prepare our blend surface */
vg_prepare_blend_surface_from_mask(ctx);
cso_save_samplers(ctx->cso_context);
cso_save_sampler_textures(ctx->cso_context);
cso_save_framebuffer(ctx->cso_context);
cso_save_blend(ctx->cso_context);
cso_save_fragment_shader(ctx->cso_context);
cso_save_viewport(ctx->cso_context);
setup_mask_samplers(texture);
setup_mask_blend();
setup_mask_operation(operation);
setup_mask_framebuffer(surface, surface->width, surface->height);
setup_mask_viewport();
/* render the quad to propagate the rendering from stencil */
renderer_draw_texture(ctx->renderer, texture,
offsets[0], offsets[1],
offsets[0] + offsets[2], offsets[1] + offsets[3],
loc[0], loc[1], loc[0] + loc[2], loc[1] + loc[3]);
/* make sure rendering has completed */
ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
cso_restore_blend(ctx->cso_context);
cso_restore_framebuffer(ctx->cso_context);
cso_restore_fragment_shader(ctx->cso_context);
cso_restore_samplers(ctx->cso_context);
cso_restore_sampler_textures(ctx->cso_context);
cso_restore_viewport(ctx->cso_context);
pipe_surface_reference(&surface, NULL);
}
#ifdef OPENVG_VERSION_1_1
struct vg_mask_layer * mask_layer_create(VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct vg_mask_layer *mask = 0;
mask = CALLOC_STRUCT(vg_mask_layer);
vg_init_object(&mask->base, ctx, VG_OBJECT_MASK);
mask->width = width;
mask->height = height;
{
struct pipe_texture pt;
struct pipe_screen *screen = ctx->pipe->screen;
memset(&pt, 0, sizeof(pt));
pt.target = PIPE_TEXTURE_2D;
pt.format = PIPE_FORMAT_A8R8G8B8_UNORM;
pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &pt.block);
pt.last_level = 0;
pt.width[0] = width;
pt.height[0] = height;
pt.depth[0] = 1;
pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
pt.compressed = 0;
mask->texture = screen->texture_create(screen, &pt);
}
vg_context_add_object(ctx, VG_OBJECT_MASK, mask);
return mask;
}
void mask_layer_destroy(struct vg_mask_layer *layer)
{
struct vg_context *ctx = vg_current_context();
vg_context_remove_object(ctx, VG_OBJECT_MASK, layer);
pipe_texture_release(&layer->texture);
free(layer);
}
void mask_layer_fill(struct vg_mask_layer *layer,
VGint x, VGint y,
VGint width, VGint height,
VGfloat value)
{
struct vg_context *ctx = vg_current_context();
VGfloat alpha_color[4] = {0, 0, 0, 0};
struct pipe_surface *surface;
alpha_color[3] = value;
surface = ctx->pipe->screen->get_tex_surface(
ctx->pipe->screen, layer->texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
surface_fill(surface,
layer->width, layer->height,
x, y, width, height, alpha_color);
ctx->pipe->screen->tex_surface_release(ctx->pipe->screen, &surface);
}
void mask_copy(struct vg_mask_layer *layer,
VGint sx, VGint sy,
VGint dx, VGint dy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
struct st_framebuffer *fb_buffers = ctx->draw_buffer;
renderer_copy_texture(ctx->renderer,
layer->texture,
sx, sy,
sx + width, sy + height,
fb_buffers->alpha_mask,
dx, dy,
dx + width, dy + height);
}
static void mask_layer_render_to(struct vg_mask_layer *layer,
struct path *path,
VGbitfield paint_modes)
{
struct vg_context *ctx = vg_current_context();
const VGfloat fill_color[4] = {1.f, 1.f, 1.f, 1.f};
struct pipe_screen *screen = ctx->pipe->screen;
struct pipe_surface *surface;
surface = screen->get_tex_surface(screen, layer->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
cso_save_framebuffer(ctx->cso_context);
cso_save_fragment_shader(ctx->cso_context);
cso_save_viewport(ctx->cso_context);
setup_mask_blend();
setup_mask_fill(fill_color);
setup_mask_framebuffer(surface, layer->width, layer->height);
setup_mask_viewport();
if (paint_modes & VG_FILL_PATH) {
struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
path_fill(path, mat);
}
if (paint_modes & VG_STROKE_PATH){
path_stroke(path);
}
/* make sure rendering has completed */
ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
cso_restore_framebuffer(ctx->cso_context);
cso_restore_fragment_shader(ctx->cso_context);
cso_restore_viewport(ctx->cso_context);
ctx->state.dirty |= BLEND_DIRTY;
screen->tex_surface_release(ctx->pipe->screen, &surface);
}
void mask_render_to(struct path *path,
VGbitfield paint_modes,
VGMaskOperation operation)
{
struct vg_context *ctx = vg_current_context();
struct st_framebuffer *fb_buffers = ctx->draw_buffer;
struct vg_mask_layer *temp_layer;
VGint width, height;
width = fb_buffers->alpha_mask->width[0];
height = fb_buffers->alpha_mask->width[0];
temp_layer = mask_layer_create(width, height);
mask_layer_render_to(temp_layer, path, paint_modes);
mask_using_layer(temp_layer, 0, 0, width, height,
operation);
mask_layer_destroy(temp_layer);
}
void mask_using_layer(struct vg_mask_layer *layer,
VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height)
{
mask_using_texture(layer->texture, operation,
x, y, width, height);
}
VGint mask_layer_width(struct vg_mask_layer *layer)
{
return layer->width;
}
VGint mask_layer_height(struct vg_mask_layer *layer)
{
return layer->height;
}
#endif
void mask_using_image(struct vg_image *image,
VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height)
{
mask_using_texture(image->texture, operation,
x, y, width, height);
}
void mask_fill(VGint x, VGint y, VGint width, VGint height,
VGfloat value)
{
struct vg_context *ctx = vg_current_context();
VGfloat alpha_color[4] = {.0f, .0f, .0f, value};
struct pipe_surface *surf = alpha_mask_surface(
ctx, PIPE_BUFFER_USAGE_GPU_WRITE);
#if DEBUG_MASKS
debug_printf("mask_fill(%d, %d, %d, %d) with rgba(%f, %f, %f, %f)\n",
x, y, width, height,
alpha_color[0], alpha_color[1],
alpha_color[2], alpha_color[3]);
debug_printf("XXX %f === %f \n",
alpha_color[3], value);
#endif
surface_fill(surf, surf->width, surf->height,
x, y, width, height, alpha_color);
pipe_surface_reference(&surf, NULL);
}
VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
struct pipe_texture **textures)
{
struct vg_context *ctx = vg_current_context();
if (ctx->state.vg.masking) {
struct st_framebuffer *fb_buffers = ctx->draw_buffer;
samplers[1] = &ctx->mask.sampler;
textures[1] = fb_buffers->alpha_mask;
return 1;
} else
return 0;
}

View File

@ -0,0 +1,68 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef MASK_H
#define MASK_H
#include "vg_context.h"
struct path;
struct vg_image;
struct pipe_texture;
struct vg_mask_layer *mask_layer_create(VGint width, VGint height);
void mask_layer_destroy(struct vg_mask_layer *layer);
void mask_layer_fill(struct vg_mask_layer *layer,
VGint x, VGint y,
VGint width, VGint height,
VGfloat value);
VGint mask_layer_width(struct vg_mask_layer *layer);
VGint mask_layer_height(struct vg_mask_layer *layer);
void mask_copy(struct vg_mask_layer *layer,
VGint sx, VGint sy,
VGint dx, VGint dy,
VGint width, VGint height);
void mask_render_to(struct path *path,
VGbitfield paint_modes,
VGMaskOperation operation);
void mask_using_layer(struct vg_mask_layer *layer,
VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height);
void mask_using_image(struct vg_image *image,
VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height);
void mask_fill(VGint x, VGint y,
VGint width, VGint height,
VGfloat value);
VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
struct pipe_texture **textures);
#endif

View File

@ -0,0 +1,462 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef MATRIX_H
#define MATRIX_H
#include "VG/openvg.h"
#include "pipe/p_compiler.h"
#include "util/u_math.h"
#include <stdio.h>
#include <math.h>
#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
#define floatIsZero(x) (floatsEqual((x) + 1, 1))
#define ABS(x) (fabsf(x))
#define DEGREES_TO_RADIANS(d) (0.0174532925199 * (d))
#define FLT_TO_INT(flt) float_to_int_floor(((VGuint*)&(flt))[0])
static INLINE VGint float_to_int_floor(VGuint bits)
{
int sign = (bits >> 31) ? -1 : 1;
int exp = ((bits >> 23) & 255) - 127;
int mant = bits & 0x007fffff;
int sh = 23 - exp;
/* abs(value) >= 2^31 -> clamp. */
if (exp >= 31)
return (VGint)((sign < 0) ? 0x80000000u : 0x7fffffffu);
/* abs(value) < 1 -> return -1 or 0. */
if (exp < 0)
return (sign < 0 && (exp > -127 || mant != 0)) ? -1 : 0;
/* abs(value) >= 2^23 -> shift left. */
mant |= 0x00800000;
if (sh <= 0)
return sign * (mant << -sh);
/* Negative -> add a rounding term. */
if (sign < 0)
mant += (1 << sh) - 1;
/* Shift right to obtain the result. */
return sign * (mant >> sh);
}
struct matrix {
VGfloat m[9];
};
static INLINE void matrix_init(struct matrix *mat,
const VGfloat *val)
{
memcpy(mat->m, val, sizeof(VGfloat) * 9);
}
static INLINE void matrix_inits(struct matrix *mat,
VGfloat m11, VGfloat m12, VGfloat m13,
VGfloat m21, VGfloat m22, VGfloat m23,
VGfloat m31, VGfloat m32, VGfloat m33)
{
mat->m[0] = m11; mat->m[1] = m12; mat->m[2] = m13;
mat->m[3] = m21; mat->m[4] = m22; mat->m[5] = m23;
mat->m[6] = m31; mat->m[7] = m32; mat->m[8] = m33;
}
static INLINE void matrix_load_identity(struct matrix *matrix)
{
static const VGfloat identity[9] = {1.f, 0.f, 0.f,
0.f, 1.f, 0.f,
0.f, 0.f, 1.f};
memcpy(matrix->m, identity, sizeof(identity));
}
static INLINE VGboolean matrix_is_identity(struct matrix *matrix)
{
return floatsEqual(matrix->m[0], 1) && floatIsZero(matrix->m[1]) &&
floatIsZero(matrix->m[2]) &&
floatIsZero(matrix->m[3]) && floatsEqual(matrix->m[4], 1) &&
floatIsZero(matrix->m[5]) &&
floatIsZero(matrix->m[6]) && floatIsZero(matrix->m[7]) &&
floatIsZero(matrix->m[8]);
}
static INLINE VGboolean matrix_is_affine(struct matrix *matrix)
{
return floatIsZero(matrix->m[2]) && floatIsZero(matrix->m[5])
&& floatsEqual(matrix->m[8], 1);
}
static INLINE void matrix_make_affine(struct matrix *matrix)
{
matrix->m[2] = 0.f;
matrix->m[5] = 0.f;
matrix->m[8] = 1.f;
}
static INLINE void matrix_mult(struct matrix *dst,
struct matrix *src)
{
VGfloat m11 = dst->m[0]*src->m[0] + dst->m[3]*src->m[1] + dst->m[6]*src->m[2];
VGfloat m12 = dst->m[0]*src->m[3] + dst->m[3]*src->m[4] + dst->m[6]*src->m[5];
VGfloat m13 = dst->m[0]*src->m[6] + dst->m[3]*src->m[7] + dst->m[6]*src->m[8];
VGfloat m21 = dst->m[1]*src->m[0] + dst->m[4]*src->m[1] + dst->m[7]*src->m[2];
VGfloat m22 = dst->m[1]*src->m[3] + dst->m[4]*src->m[4] + dst->m[7]*src->m[5];
VGfloat m23 = dst->m[1]*src->m[6] + dst->m[4]*src->m[7] + dst->m[7]*src->m[8];
VGfloat m31 = dst->m[2]*src->m[0] + dst->m[5]*src->m[1] + dst->m[8]*src->m[2];
VGfloat m32 = dst->m[2]*src->m[3] + dst->m[5]*src->m[4] + dst->m[8]*src->m[5];
VGfloat m33 = dst->m[2]*src->m[6] + dst->m[5]*src->m[7] + dst->m[8]*src->m[8];
dst->m[0] = m11; dst->m[1] = m21; dst->m[2] = m31;
dst->m[3] = m12; dst->m[4] = m22; dst->m[5] = m32;
dst->m[6] = m13; dst->m[7] = m23; dst->m[8] = m33;
}
static INLINE void matrix_map_point(struct matrix *mat,
VGfloat x, VGfloat y,
VGfloat *out_x, VGfloat *out_y)
{
/* to be able to do matrix_map_point(m, x, y, &x, &y) use
* temporaries */
VGfloat tmp_x = x, tmp_y = y;
*out_x = mat->m[0]*tmp_x + mat->m[3]*tmp_y + mat->m[6];
*out_y = mat->m[1]*tmp_x + mat->m[4]*tmp_y + mat->m[7];
if (!matrix_is_affine(mat)) {
VGfloat w = 1/(mat->m[2]*tmp_x + mat->m[5]*tmp_y + mat->m[8]);
*out_x *= w;
*out_y *= w;
}
}
static INLINE void matrix_translate(struct matrix *dst,
VGfloat tx, VGfloat ty)
{
if (!matrix_is_affine(dst)) {
struct matrix trans_matrix;
matrix_load_identity(&trans_matrix);
trans_matrix.m[6] = tx;
trans_matrix.m[7] = ty;
matrix_mult(dst, &trans_matrix);
} else {
dst->m[6] += tx*dst->m[0] + ty*dst->m[3];
dst->m[7] += ty*dst->m[4] + tx*dst->m[1];
}
}
static INLINE void matrix_scale(struct matrix *dst,
VGfloat sx, VGfloat sy)
{
if (!matrix_is_affine(dst)) {
struct matrix scale_matrix;
matrix_load_identity(&scale_matrix);
scale_matrix.m[0] = sx;
scale_matrix.m[4] = sy;
matrix_mult(dst, &scale_matrix);
} else {
dst->m[0] *= sx; dst->m[1] *= sx;
dst->m[3] *= sy; dst->m[4] *= sy;
}
}
static INLINE void matrix_shear(struct matrix *dst,
VGfloat shx, VGfloat shy)
{
struct matrix shear_matrix;
matrix_load_identity(&shear_matrix);
shear_matrix.m[1] = shy;
shear_matrix.m[3] = shx;
matrix_mult(dst, &shear_matrix);
}
static INLINE void matrix_rotate(struct matrix *dst,
VGfloat angle)
{
struct matrix mat;
float sin_val = 0;
float cos_val = 0;
if (floatsEqual(angle, 90) || floatsEqual(angle, -270))
sin_val = 1.f;
else if (floatsEqual(angle, 270) || floatsEqual(angle, -90))
sin_val = -1.f;
else if (floatsEqual(angle, 180))
cos_val = -1.f;
else {
float radians = DEGREES_TO_RADIANS(angle);
sin_val = sin(radians);
cos_val = cos(radians);
}
if (!matrix_is_affine(dst)) {
matrix_load_identity(&mat);
mat.m[0] = cos_val; mat.m[1] = sin_val;
mat.m[3] = -sin_val; mat.m[4] = cos_val;
matrix_mult(dst, &mat);
} else {
VGfloat m11 = cos_val*dst->m[0] + sin_val*dst->m[3];
VGfloat m12 = cos_val*dst->m[1] + sin_val*dst->m[4];
VGfloat m21 = -sin_val*dst->m[0] + cos_val*dst->m[3];
VGfloat m22 = -sin_val*dst->m[1] + cos_val*dst->m[4];
dst->m[0] = m11; dst->m[1] = m12;
dst->m[3] = m21; dst->m[4] = m22;
}
}
static INLINE VGfloat matrix_determinant(struct matrix *mat)
{
return mat->m[0]*(mat->m[8]*mat->m[4]-mat->m[7]*mat->m[5]) -
mat->m[3]*(mat->m[8]*mat->m[1]-mat->m[7]*mat->m[2])+
mat->m[6]*(mat->m[5]*mat->m[1]-mat->m[4]*mat->m[2]);
}
static INLINE void matrix_adjoint(struct matrix *mat)
{
VGfloat h[9];
h[0] = mat->m[4]*mat->m[8] - mat->m[5]*mat->m[7];
h[3] = mat->m[5]*mat->m[6] - mat->m[3]*mat->m[8];
h[6] = mat->m[3]*mat->m[7] - mat->m[4]*mat->m[6];
h[1] = mat->m[2]*mat->m[7] - mat->m[1]*mat->m[8];
h[4] = mat->m[0]*mat->m[8] - mat->m[2]*mat->m[6];
h[7] = mat->m[1]*mat->m[6] - mat->m[0]*mat->m[7];
h[2] = mat->m[1]*mat->m[5] - mat->m[2]*mat->m[4];
h[5] = mat->m[2]*mat->m[3] - mat->m[0]*mat->m[5];
h[8] = mat->m[0]*mat->m[4] - mat->m[1]*mat->m[3];
memcpy(mat->m, h, sizeof(VGfloat) * 9);
}
static INLINE void matrix_divs(struct matrix *mat,
VGfloat s)
{
mat->m[0] /= s;
mat->m[1] /= s;
mat->m[2] /= s;
mat->m[3] /= s;
mat->m[4] /= s;
mat->m[5] /= s;
mat->m[6] /= s;
mat->m[7] /= s;
mat->m[8] /= s;
}
static INLINE VGboolean matrix_invert(struct matrix *mat)
{
VGfloat det = matrix_determinant(mat);
if (floatIsZero(det))
return VG_FALSE;
matrix_adjoint(mat);
matrix_divs(mat, det);
return VG_TRUE;
}
static INLINE VGboolean matrix_is_invertible(struct matrix *mat)
{
return !floatIsZero(matrix_determinant(mat));
}
static INLINE VGboolean matrix_square_to_quad(VGfloat dx0, VGfloat dy0,
VGfloat dx1, VGfloat dy1,
VGfloat dx3, VGfloat dy3,
VGfloat dx2, VGfloat dy2,
struct matrix *mat)
{
VGfloat ax = dx0 - dx1 + dx2 - dx3;
VGfloat ay = dy0 - dy1 + dy2 - dy3;
if (floatIsZero(ax) && floatIsZero(ay)) {
/* affine case */
matrix_inits(mat,
dx1 - dx0, dy1 - dy0, 0,
dx2 - dx1, dy2 - dy1, 0,
dx0, dy0, 1);
} else {
VGfloat a, b, c, d, e, f, g, h;
VGfloat ax1 = dx1 - dx2;
VGfloat ax2 = dx3 - dx2;
VGfloat ay1 = dy1 - dy2;
VGfloat ay2 = dy3 - dy2;
/* determinants */
VGfloat gtop = ax * ay2 - ax2 * ay;
VGfloat htop = ax1 * ay - ax * ay1;
VGfloat bottom = ax1 * ay2 - ax2 * ay1;
if (!bottom)
return VG_FALSE;
g = gtop / bottom;
h = htop / bottom;
a = dx1 - dx0 + g * dx1;
b = dx3 - dx0 + h * dx3;
c = dx0;
d = dy1 - dy0 + g * dy1;
e = dy3 - dy0 + h * dy3;
f = dy0;
matrix_inits(mat,
a, d, g,
b, e, h,
c, f, 1.f);
}
return VG_TRUE;
}
static INLINE VGboolean matrix_quad_to_square(VGfloat sx0, VGfloat sy0,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
VGfloat sx3, VGfloat sy3,
struct matrix *mat)
{
if (!matrix_square_to_quad(sx0, sy0, sx1, sy1,
sx2, sy2, sx3, sy3,
mat))
return VG_FALSE;
return matrix_invert(mat);
}
static INLINE VGboolean matrix_quad_to_quad(VGfloat dx0, VGfloat dy0,
VGfloat dx1, VGfloat dy1,
VGfloat dx2, VGfloat dy2,
VGfloat dx3, VGfloat dy3,
VGfloat sx0, VGfloat sy0,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
VGfloat sx3, VGfloat sy3,
struct matrix *mat)
{
struct matrix sqr_to_qd;
if (!matrix_square_to_quad(dx0, dy0, dx1, dy1,
dx2, dy2, dx3, dy3,
mat))
return VG_FALSE;
if (!matrix_quad_to_square(sx0, sy0, sx1, sy1,
sx2, sy2, sx3, sy3,
&sqr_to_qd))
return VG_FALSE;
matrix_mult(mat, &sqr_to_qd);
return VG_TRUE;
}
static INLINE VGboolean null_line(const VGfloat *l)
{
return floatsEqual(l[0], l[2]) && floatsEqual(l[1], l[3]);
}
static INLINE void line_normal(float *l, float *norm)
{
norm[0] = l[0];
norm[1] = l[1];
norm[2] = l[0] + (l[3] - l[1]);
norm[3] = l[1] - (l[2] - l[0]);
}
static INLINE void line_normalize(float *l)
{
float x = l[2] - l[0];
float y = l[3] - l[1];
float len = sqrt(x*x + y*y);
l[2] = l[0] + x/len;
l[3] = l[1] + y/len;
}
static INLINE VGfloat line_length(VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2)
{
VGfloat x = x2 - x1;
VGfloat y = y2 - y1;
return sqrt(x*x + y*y);
}
static INLINE VGfloat line_lengthv(const VGfloat *l)
{
VGfloat x = l[2] - l[0];
VGfloat y = l[3] - l[1];
return sqrt(x*x + y*y);
}
static INLINE void line_point_at(float *l, float t, float *pt)
{
float dx = l[2] - l[0];
float dy = l[3] - l[1];
pt[0] = l[0] + dx * t;
pt[1] = l[1] + dy * t;
}
static INLINE void vector_unit(float *vec)
{
float len = sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
vec[0] /= len;
vec[1] /= len;
}
static INLINE void line_normal_vector(float *line, float *vec)
{
VGfloat normal[4];
line_normal(line, normal);
vec[0] = normal[2] - normal[0];
vec[1] = normal[3] - normal[1];
vector_unit(vec);
}
#endif

View File

@ -0,0 +1,699 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "paint.h"
#include "shaders_cache.h"
#include "matrix.h"
#include "image.h"
#include "st_inlines.h"
#include "pipe/p_compiler.h"
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "cso_cache/cso_context.h"
struct vg_paint {
struct vg_object base;
VGPaintType type;
struct {
VGfloat color[4];
VGint colori[4];
} solid;
struct {
VGColorRampSpreadMode spread;
VGuint color_data[1024];
struct {
VGfloat coords[4];
VGint coordsi[4];
} linear;
struct {
VGfloat vals[5];
VGint valsi[5];
} radial;
struct pipe_texture *texture;
struct pipe_sampler_state sampler;
VGfloat *ramp_stops;
VGint *ramp_stopsi;
VGint num_stops;
VGboolean color_ramps_premultiplied;
} gradient;
struct {
struct pipe_texture *texture;
VGTilingMode tiling_mode;
struct pipe_sampler_state sampler;
} pattern;
struct pipe_constant_buffer cbuf;
struct pipe_shader_state fs_state;
void *fs;
};
static INLINE VGuint mix_pixels(VGuint p1, VGuint a, VGuint p2, VGuint b)
{
VGuint t = (p1 & 0xff00ff) * a + (p2 & 0xff00ff) * b;
t >>= 8; t &= 0xff00ff;
p1 = ((p1 >> 8) & 0xff00ff) * a + ((p2 >> 8) & 0xff00ff) * b;
p1 &= 0xff00ff00; p1 |= t;
return p1;
}
static INLINE VGuint float4_to_argb(const VGfloat *clr)
{
return float_to_ubyte(clr[3]) << 24 |
float_to_ubyte(clr[0]) << 16 |
float_to_ubyte(clr[1]) << 8 |
float_to_ubyte(clr[2]) << 0;
}
static INLINE void create_gradient_data(const VGfloat *ramp_stops,
VGint num,
VGuint *data,
VGint size)
{
VGint i;
VGint pos = 0;
VGfloat fpos = 0, incr = 1.f / size;
VGuint last_color;
while (fpos < ramp_stops[0]) {
data[pos] = float4_to_argb(ramp_stops + 1);
fpos += incr;
++pos;
}
for (i = 0; i < num - 1; ++i) {
VGint rcur = 5 * i;
VGint rnext = 5 * (i + 1);
VGfloat delta = 1.f/(ramp_stops[rnext] - ramp_stops[rcur]);
while (fpos < ramp_stops[rnext] && pos < size) {
VGint dist = 256 * ((fpos - ramp_stops[rcur]) * delta);
VGint idist = 256 - dist;
VGuint current_color = float4_to_argb(ramp_stops + rcur + 1);
VGuint next_color = float4_to_argb(ramp_stops + rnext + 1);
data[pos] = mix_pixels(current_color, idist,
next_color, dist);
fpos += incr;
++pos;
}
}
last_color = float4_to_argb(ramp_stops + ((num - 1) * 5 + 1));
while (pos < size) {
data[pos] = last_color;
++pos;
}
data[size-1] = last_color;
}
static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p)
{
struct pipe_context *pipe = p->base.ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_texture *tex = 0;
struct pipe_texture templ;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_1D;
templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
templ.last_level = 0;
templ.width[0] = 1024;
templ.height[0] = 1;
templ.depth[0] = 1;
pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &templ.block);
templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
tex = screen->texture_create(screen, &templ);
{ /* upload color_data */
struct pipe_transfer *transfer =
st_no_flush_get_tex_transfer(p->base.ctx, tex, 0, 0, 0,
PIPE_TRANSFER_WRITE, 0, 0, 1024, 1);
void *map = screen->transfer_map(screen, transfer);
memcpy(map, p->gradient.color_data, sizeof(VGint)*1024);
screen->transfer_unmap(screen, transfer);
screen->tex_transfer_destroy(transfer);
}
return tex;
}
struct vg_paint * paint_create(struct vg_context *ctx)
{
struct vg_paint *paint = CALLOC_STRUCT(vg_paint);
const VGfloat default_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
const VGfloat def_ling[] = {0.0f, 0.0f, 1.0f, 0.0f};
const VGfloat def_radg[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
vg_init_object(&paint->base, ctx, VG_OBJECT_PAINT);
vg_context_add_object(ctx, VG_OBJECT_PAINT, paint);
paint->type = VG_PAINT_TYPE_COLOR;
memcpy(paint->solid.color, default_color,
4 * sizeof(VGfloat));
paint->gradient.spread = VG_COLOR_RAMP_SPREAD_PAD;
memcpy(paint->gradient.linear.coords, def_ling,
4 * sizeof(VGfloat));
memcpy(paint->gradient.radial.vals, def_radg,
5 * sizeof(VGfloat));
paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
paint->gradient.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
paint->gradient.sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
paint->gradient.sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
paint->gradient.sampler.normalized_coords = 1;
memcpy(&paint->pattern.sampler,
&paint->gradient.sampler,
sizeof(struct pipe_sampler_state));
return paint;
}
void paint_destroy(struct vg_paint *paint)
{
struct vg_context *ctx = paint->base.ctx;
if (paint->pattern.texture)
pipe_texture_reference(&paint->pattern.texture, NULL);
if (ctx)
vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint);
free(paint->gradient.ramp_stopsi);
free(paint->gradient.ramp_stops);
free(paint);
}
void paint_set_color(struct vg_paint *paint,
const VGfloat *color)
{
paint->solid.color[0] = color[0];
paint->solid.color[1] = color[1];
paint->solid.color[2] = color[2];
paint->solid.color[3] = color[3];
paint->solid.colori[0] = FLT_TO_INT(color[0]);
paint->solid.colori[1] = FLT_TO_INT(color[1]);
paint->solid.colori[2] = FLT_TO_INT(color[2]);
paint->solid.colori[3] = FLT_TO_INT(color[3]);
}
static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer)
{
VGfloat *map = (VGfloat*)buffer;
memcpy(buffer, paint->solid.color, 4 * sizeof(VGfloat));
map[4] = 0.f;
map[5] = 1.f;
map[6] = 2.f;
map[7] = 4.f;
}
static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *buffer)
{
struct vg_context *ctx = paint->base.ctx;
VGfloat *map = (VGfloat*)buffer;
map[0] = paint->gradient.linear.coords[2] - paint->gradient.linear.coords[0];
map[1] = paint->gradient.linear.coords[3] - paint->gradient.linear.coords[1];
map[2] = 1.f / (map[0] * map[0] + map[1] * map[1]);
map[3] = 1.f;
map[4] = 0.f;
map[5] = 1.f;
map[6] = 2.f;
map[7] = 4.f;
{
struct matrix mat;
struct matrix inv;
matrix_load_identity(&mat);
matrix_translate(&mat, -paint->gradient.linear.coords[0], -paint->gradient.linear.coords[1]);
memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
sizeof(struct matrix));
matrix_invert(&inv);
matrix_mult(&inv, &mat);
memcpy(&mat, &inv,
sizeof(struct matrix));
map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
}
#if 0
debug_printf("Coords (%f, %f, %f, %f)\n",
map[0], map[1], map[2], map[3]);
#endif
}
static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *buffer)
{
VGfloat *radialCoords = paint->gradient.radial.vals;
struct vg_context *ctx = paint->base.ctx;
VGfloat *map = (VGfloat*)buffer;
map[0] = radialCoords[0] - radialCoords[2];
map[1] = radialCoords[1] - radialCoords[3];
map[2] = -map[0] * map[0] - map[1] * map[1] +
radialCoords[4] * radialCoords[4];
map[3] = 1.f;
map[4] = 0.f;
map[5] = 1.f;
map[6] = 2.f;
map[7] = 4.f;
{
struct matrix mat;
struct matrix inv;
matrix_load_identity(&mat);
matrix_translate(&mat, -radialCoords[2], -radialCoords[3]);
memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
sizeof(struct matrix));
matrix_invert(&inv);
matrix_mult(&inv, &mat);
memcpy(&mat, &inv,
sizeof(struct matrix));
map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
}
#if 0
debug_printf("Coords (%f, %f, %f, %f)\n",
map[0], map[1], map[2], map[3]);
#endif
}
static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer)
{
struct vg_context *ctx = paint->base.ctx;
VGfloat *map = (VGfloat *)buffer;
memcpy(map, paint->solid.color, 4 * sizeof(VGfloat));
map[4] = 0.f;
map[5] = 1.f;
map[6] = paint->pattern.texture->width[0];
map[7] = paint->pattern.texture->height[0];
{
struct matrix mat;
memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix,
sizeof(struct matrix));
matrix_invert(&mat);
{
struct matrix pm;
memcpy(&pm, &ctx->state.vg.path_user_to_surface_matrix,
sizeof(struct matrix));
matrix_invert(&pm);
matrix_mult(&pm, &mat);
memcpy(&mat, &pm, sizeof(struct matrix));
}
map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
}
}
void paint_set_type(struct vg_paint *paint, VGPaintType type)
{
paint->type = type;
}
void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops,
int num)
{
const VGfloat default_stops[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
VGint i;
const VGint num_stops = num / 5;
VGfloat last_coord;
paint->gradient.num_stops = num;
if (num) {
free(paint->gradient.ramp_stops);
paint->gradient.ramp_stops = malloc(sizeof(VGfloat)*num);
memcpy(paint->gradient.ramp_stops, stops, sizeof(VGfloat)*num);
} else
return;
/* stops must be in increasing order. the last stop is 1.0. if the
* first one is bigger than 1 then the whole sequence is invalid*/
if (stops[0] > 1) {
stops = default_stops;
num = 10;
}
last_coord = stops[0];
for (i = 1; i < num_stops; ++i) {
VGint idx = 5 * i;
VGfloat coord = stops[idx];
if (!floatsEqual(last_coord, coord) && coord < last_coord) {
stops = default_stops;
num = 10;
break;
}
last_coord = coord;
}
create_gradient_data(stops, num / 5, paint->gradient.color_data,
1024);
if (paint->gradient.texture) {
pipe_texture_reference(&paint->gradient.texture, NULL);
paint->gradient.texture = 0;
}
paint->gradient.texture = create_gradient_texture(paint);
}
void paint_set_colori(struct vg_paint *p,
VGuint rgba)
{
p->solid.color[0] = ((rgba >> 24) & 0xff) / 255.f;
p->solid.color[1] = ((rgba >> 16) & 0xff) / 255.f;
p->solid.color[2] = ((rgba >> 8) & 0xff) / 255.f;
p->solid.color[3] = ((rgba >> 0) & 0xff) / 255.f;
}
VGuint paint_colori(struct vg_paint *p)
{
#define F2B(f) (float_to_ubyte(f))
return ((F2B(p->solid.color[0]) << 24) |
(F2B(p->solid.color[1]) << 16) |
(F2B(p->solid.color[2]) << 8) |
(F2B(p->solid.color[3]) << 0));
#undef F2B
}
void paint_set_linear_gradient(struct vg_paint *paint,
const VGfloat *coords)
{
memcpy(paint->gradient.linear.coords, coords, sizeof(VGfloat) * 4);
}
void paint_set_spread_mode(struct vg_paint *paint,
VGint mode)
{
paint->gradient.spread = mode;
switch(mode) {
case VG_COLOR_RAMP_SPREAD_PAD:
paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
break;
case VG_COLOR_RAMP_SPREAD_REPEAT:
paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
break;
case VG_COLOR_RAMP_SPREAD_REFLECT:
paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
break;
}
}
VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint)
{
return paint->gradient.spread;
}
void paint_set_radial_gradient(struct vg_paint *paint,
const VGfloat *values)
{
memcpy(paint->gradient.radial.vals, values, sizeof(VGfloat) * 5);
}
void paint_set_pattern(struct vg_paint *paint,
struct vg_image *img)
{
if (paint->pattern.texture)
pipe_texture_reference(&paint->pattern.texture, NULL);
paint->pattern.texture = 0;
pipe_texture_reference(&paint->pattern.texture,
img->texture);
}
void paint_set_pattern_tiling(struct vg_paint *paint,
VGTilingMode mode)
{
paint->pattern.tiling_mode = mode;
switch(mode) {
case VG_TILE_FILL:
paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
break;
case VG_TILE_PAD:
paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
break;
case VG_TILE_REPEAT:
paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
break;
case VG_TILE_REFLECT:
paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
break;
default:
debug_assert("!Unknown tiling mode");
}
}
void paint_get_color(struct vg_paint *paint,
VGfloat *color)
{
color[0] = paint->solid.color[0];
color[1] = paint->solid.color[1];
color[2] = paint->solid.color[2];
color[3] = paint->solid.color[3];
}
void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops,
int num)
{
memcpy(stops, paint->gradient.ramp_stops, sizeof(VGfloat)*num);
}
void paint_linear_gradient(struct vg_paint *paint,
VGfloat *coords)
{
memcpy(coords, paint->gradient.linear.coords, sizeof(VGfloat)*4);
}
void paint_radial_gradient(struct vg_paint *paint,
VGfloat *coords)
{
memcpy(coords, paint->gradient.radial.vals, sizeof(VGfloat)*5);
}
int paint_num_ramp_stops(struct vg_paint *paint)
{
return paint->gradient.num_stops;
}
VGPaintType paint_type(struct vg_paint *paint)
{
return paint->type;
}
void paint_set_coloriv(struct vg_paint *paint,
const VGint *color)
{
paint->solid.color[0] = color[0];
paint->solid.color[1] = color[1];
paint->solid.color[2] = color[2];
paint->solid.color[3] = color[3];
paint->solid.colori[0] = color[0];
paint->solid.colori[1] = color[1];
paint->solid.colori[2] = color[2];
paint->solid.colori[3] = color[3];
}
void paint_get_coloriv(struct vg_paint *paint,
VGint *color)
{
color[0] = paint->solid.colori[0];
color[1] = paint->solid.colori[1];
color[2] = paint->solid.colori[2];
color[3] = paint->solid.colori[3];
}
void paint_set_color_ramp_premultiplied(struct vg_paint *paint,
VGboolean set)
{
paint->gradient.color_ramps_premultiplied = set;
}
VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint)
{
return paint->gradient.color_ramps_premultiplied;
}
void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops,
int num)
{
if (num) {
free(paint->gradient.ramp_stopsi);
paint->gradient.ramp_stopsi = malloc(sizeof(VGint)*num);
memcpy(paint->gradient.ramp_stopsi, stops, sizeof(VGint)*num);
}
}
void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops,
int num)
{
memcpy(stops, paint->gradient.ramp_stopsi, sizeof(VGint)*num);
}
void paint_set_linear_gradienti(struct vg_paint *paint,
const VGint *coords)
{
memcpy(paint->gradient.linear.coordsi, coords, sizeof(VGint) * 4);
}
void paint_linear_gradienti(struct vg_paint *paint,
VGint *coords)
{
memcpy(coords, paint->gradient.linear.coordsi, sizeof(VGint)*4);
}
void paint_set_radial_gradienti(struct vg_paint *paint,
const VGint *values)
{
memcpy(paint->gradient.radial.valsi, values, sizeof(VGint) * 5);
}
void paint_radial_gradienti(struct vg_paint *paint,
VGint *coords)
{
memcpy(coords, paint->gradient.radial.valsi, sizeof(VGint)*5);
}
VGTilingMode paint_pattern_tiling(struct vg_paint *paint)
{
return paint->pattern.tiling_mode;
}
VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
struct pipe_texture **textures)
{
struct vg_context *ctx = vg_current_context();
switch(paint->type) {
case VG_PAINT_TYPE_LINEAR_GRADIENT:
case VG_PAINT_TYPE_RADIAL_GRADIENT: {
if (paint->gradient.texture) {
paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx);
paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx);
samplers[0] = &paint->gradient.sampler;
textures[0] = paint->gradient.texture;
return 1;
}
}
break;
case VG_PAINT_TYPE_PATTERN: {
memcpy(paint->pattern.sampler.border_color,
ctx->state.vg.tile_fill_color,
sizeof(VGfloat) * 4);
paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx);
paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx);
samplers[0] = &paint->pattern.sampler;
textures[0] = paint->pattern.texture;
return 1;
}
break;
default:
samplers[0] = &paint->pattern.sampler; /* dummy */
textures[0] = 0;
return 0;
break;
}
return 0;
}
void paint_resolve_type(struct vg_paint *paint)
{
if (paint->type == VG_PAINT_TYPE_PATTERN &&
!paint->pattern.texture) {
paint->type = VG_PAINT_TYPE_COLOR;
}
}
VGint paint_constant_buffer_size(struct vg_paint *paint)
{
switch(paint->type) {
case VG_PAINT_TYPE_COLOR:
return 8 * sizeof(VGfloat);/*4 color + 4 constants (0.f,1.f,2.f,4.f)*/
break;
case VG_PAINT_TYPE_LINEAR_GRADIENT:
return 20 * sizeof(VGfloat);
break;
case VG_PAINT_TYPE_RADIAL_GRADIENT:
return 20 * sizeof(VGfloat);
break;
case VG_PAINT_TYPE_PATTERN:
return 20 * sizeof(VGfloat);
break;
default:
debug_printf("Uknown paint type: %d\n", paint->type);
}
return 0;
}
void paint_fill_constant_buffer(struct vg_paint *paint,
void *buffer)
{
switch(paint->type) {
case VG_PAINT_TYPE_COLOR:
paint_color_buffer(paint, buffer);
break;
case VG_PAINT_TYPE_LINEAR_GRADIENT:
paint_linear_gradient_buffer(paint, buffer);
break;
case VG_PAINT_TYPE_RADIAL_GRADIENT:
paint_radial_gradient_buffer(paint, buffer);
break;
case VG_PAINT_TYPE_PATTERN:
paint_pattern_buffer(paint, buffer);
break;
default:
abort();
}
}

View File

@ -0,0 +1,118 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef PAINT_H
#define PAINT_H
#include "vg_context.h"
#include "VG/openvg.h"
#include "pipe/p_state.h"
struct vg_paint;
struct vg_image;
struct pipe_sampler_state;
struct pipe_texture;
struct vg_paint *paint_create(struct vg_context *ctx);
void paint_destroy(struct vg_paint *paint);
void paint_set_color(struct vg_paint *paint,
const VGfloat *color);
void paint_get_color(struct vg_paint *paint,
VGfloat *color);
void paint_set_coloriv(struct vg_paint *paint,
const VGint *color);
void paint_get_coloriv(struct vg_paint *paint,
VGint *color);
void paint_set_colori(struct vg_paint *paint,
VGuint rgba);
VGuint paint_colori(struct vg_paint *paint);
void paint_set_type(struct vg_paint *paint, VGPaintType type);
VGPaintType paint_type(struct vg_paint *paint);
void paint_resolve_type(struct vg_paint *paint);
void paint_set_linear_gradient(struct vg_paint *paint,
const VGfloat *coords);
void paint_linear_gradient(struct vg_paint *paint,
VGfloat *coords);
void paint_set_linear_gradienti(struct vg_paint *paint,
const VGint *coords);
void paint_linear_gradienti(struct vg_paint *paint,
VGint *coords);
void paint_set_radial_gradient(struct vg_paint *paint,
const VGfloat *values);
void paint_radial_gradient(struct vg_paint *paint,
VGfloat *coords);
void paint_set_radial_gradienti(struct vg_paint *paint,
const VGint *values);
void paint_radial_gradienti(struct vg_paint *paint,
VGint *coords);
void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops,
int num);
void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops,
int num);
void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops,
int num);
void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops,
int num);
int paint_num_ramp_stops(struct vg_paint *paint);
void paint_set_spread_mode(struct vg_paint *paint,
VGint mode);
VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint);
void paint_set_pattern(struct vg_paint *paint,
struct vg_image *img);
void paint_set_pattern_tiling(struct vg_paint *paint,
VGTilingMode mode);
VGTilingMode paint_pattern_tiling(struct vg_paint *paint);
void paint_set_color_ramp_premultiplied(struct vg_paint *paint,
VGboolean set);
VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint);
VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
struct pipe_texture **textures);
VGint paint_constant_buffer_size(struct vg_paint *paint);
void paint_fill_constant_buffer(struct vg_paint *paint,
void *buffer);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,126 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef _PATH_H
#define _PATH_H
#include "VG/openvg.h"
struct path;
struct polygon;
struct matrix;
enum fill_rule {
ODD_EVEN_FILL,
WINDING_FILL
};
struct path_for_each_data {
VGubyte segment;
/* all coords are absolute, even if segment is relative */
const VGfloat *coords;
VGfloat sx, sy, ox, oy, px, py;
void *user_data;
};
typedef VGboolean (*path_for_each_cb)(struct path *p,
struct path_for_each_data *data);
struct path *path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias,
VGint segmentCapacityHint,
VGint coordCapacityHint,
VGbitfield capabilities);
void path_destroy(struct path *p);
VGbitfield path_capabilities(struct path *p);
void path_set_capabilities(struct path *p, VGbitfield bf);
void path_append_data(struct path *p,
VGint numSegments,
const VGubyte * pathSegments,
const void * pathData);
void path_append_path(struct path *dst,
struct path *src);
VGint path_num_segments(struct path *p);
void path_bounding_rect(struct path *p, float *x, float *y,
float *w, float *h);
float path_length(struct path *p, int start_segment, int num_segments);
void path_set_fill_rule(enum fill_rule fill);
enum fill_rule path_fill_rule(enum fill_rule fill);
VGboolean path_is_empty(struct path *p);
VGbyte path_datatype_size(struct path *p);
VGPathDatatype path_datatype(struct path *p);
VGfloat path_scale(struct path *p);
VGfloat path_bias(struct path *p);
VGint path_num_coords(struct path *p);
void path_modify_coords(struct path *p,
VGint startIndex,
VGint numSegments,
const void * pathData);
struct path *path_create_stroke(struct path *p,
struct matrix *m);
void path_for_each_segment(struct path *path,
path_for_each_cb cb,
void *user_data);
void path_transform(struct path *dst, struct path *src);
VGboolean path_interpolate(struct path *dst,
struct path *start, struct path *end,
VGfloat amount);
void path_clear(struct path *p, VGbitfield capabilities);
void path_render(struct path *p, VGbitfield paintModes);
void path_fill(struct path *p, struct matrix *mat);
void path_stroke(struct path *p);
void path_move_to(struct path *p, float x, float y);
void path_line_to(struct path *p, float x, float y);
void path_cubic_to(struct path *p, float px1, float py1,
float px2, float py2,
float x, float y);
void path_point(struct path *p, VGint startSegment, VGint numSegments,
VGfloat distance, VGfloat *point, VGfloat *normal);
void vg_float_to_datatype(VGPathDatatype datatype,
VGubyte *common_data,
const VGfloat *data,
VGint num_coords);
#endif

View File

@ -0,0 +1,109 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef PATH_UTILS_H
#define PATH_UTILS_H
#include "VG/openvg.h"
#define SEGMENT_COMMAND(command) /* Extract segment type */ \
((command) & 0x1e)
#define SEGMENT_ABS_REL(command) /* Extract absolute/relative bit */ \
((command) & 0x1)
static INLINE VGint size_for_datatype(VGPathDatatype datatype)
{
switch(datatype) {
case VG_PATH_DATATYPE_S_8:
return 1;
case VG_PATH_DATATYPE_S_16:
return 2;
case VG_PATH_DATATYPE_S_32:
return 4;
case VG_PATH_DATATYPE_F:
return 4;
default:
assert(!"unknown datatype");
}
return 0;
}
static INLINE VGint num_elements_for_segments(const VGubyte *segments,
VGint num_segments)
{
VGint i;
VGint count = 0;
for (i = 0; i < num_segments; ++i) {
VGubyte segment = segments[i];
VGint command = SEGMENT_COMMAND(segment);
switch(command) {
case VG_CLOSE_PATH:
break;
case VG_MOVE_TO:
count += 2;
break;
case VG_LINE_TO:
count += 2;
break;
case VG_HLINE_TO:
count += 1;
break;
case VG_VLINE_TO:
count += 1;
break;
case VG_QUAD_TO:
count += 4;
break;
case VG_CUBIC_TO:
count += 6;
break;
case VG_SQUAD_TO:
count += 2;
break;
case VG_SCUBIC_TO:
count += 4;
break;
case VG_SCCWARC_TO:
count += 5;
break;
case VG_SCWARC_TO:
count += 5;
break;
case VG_LCCWARC_TO:
count += 5;
break;
case VG_LCWARC_TO:
count += 5;
break;
default:
assert(!"Unknown segment!");
}
}
return count;
}
#endif

View File

@ -0,0 +1,550 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "polygon.h"
#include "matrix.h" /*for floatsEqual*/
#include "vg_context.h"
#include "vg_state.h"
#include "paint.h"
#include "renderer.h"
#include "util_array.h"
#include "VG/openvg.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
#include "pipe/p_screen.h"
#include "util/u_draw_quad.h"
#include "util/u_math.h"
#include <string.h>
#include <stdlib.h>
#define DEBUG_POLYGON 0
#define COMPONENTS 2
struct polygon
{
VGfloat *data;
VGint size;
VGint num_verts;
VGboolean dirty;
struct pipe_buffer *vbuf;
struct pipe_screen *screen;
};
static float *ptr_to_vertex(float *data, int idx)
{
return data + (idx * COMPONENTS);
}
#if 0
static void polygon_print(struct polygon *poly)
{
int i;
float *vert;
debug_printf("Polygon %p, size = %d\n", poly, poly->num_verts);
for (i = 0; i < poly->num_verts; ++i) {
vert = ptr_to_vertex(poly->data, i);
debug_printf("%f, %f, ", vert[0], vert[1]);
}
debug_printf("\nend\n");
}
#endif
struct polygon * polygon_create(int size)
{
struct polygon *poly = (struct polygon*)malloc(sizeof(struct polygon));
poly->data = malloc(sizeof(float) * COMPONENTS * size);
poly->size = size;
poly->num_verts = 0;
poly->dirty = VG_TRUE;
poly->vbuf = NULL;
return poly;
}
struct polygon * polygon_create_from_data(float *data, int size)
{
struct polygon *poly = polygon_create(size);
memcpy(poly->data, data, sizeof(float) * COMPONENTS * size);
poly->num_verts = size;
poly->dirty = VG_TRUE;
poly->vbuf = NULL;
return poly;
}
void polygon_destroy(struct polygon *poly)
{
if (poly->vbuf)
pipe_buffer_reference(&poly->vbuf, NULL);
free(poly->data);
free(poly);
}
void polygon_resize(struct polygon *poly, int new_size)
{
float *data = (float*)malloc(sizeof(float) * COMPONENTS * new_size);
int size = MIN2(sizeof(float) * COMPONENTS * new_size,
sizeof(float) * COMPONENTS * poly->size);
memcpy(data, poly->data, size);
free(poly->data);
poly->data = data;
poly->size = new_size;
poly->dirty = VG_TRUE;
}
int polygon_size(struct polygon *poly)
{
return poly->size;
}
int polygon_vertex_count(struct polygon *poly)
{
return poly->num_verts;
}
float * polygon_data(struct polygon *poly)
{
return poly->data;
}
void polygon_vertex_append(struct polygon *p,
float x, float y)
{
float *vert;
#if DEBUG_POLYGON
debug_printf("Append vertex [%f, %f]\n", x, y);
#endif
if (p->num_verts >= p->size) {
polygon_resize(p, p->size * 2);
}
vert = ptr_to_vertex(p->data, p->num_verts);
vert[0] = x;
vert[1] = y;
++p->num_verts;
p->dirty = VG_TRUE;
}
void polygon_set_vertex(struct polygon *p, int idx,
float x, float y)
{
float *vert;
if (idx >= p->num_verts) {
/*fixme: error reporting*/
abort();
return;
}
vert = ptr_to_vertex(p->data, idx);
vert[0] = x;
vert[1] = y;
p->dirty = VG_TRUE;
}
void polygon_vertex(struct polygon *p, int idx,
float *vertex)
{
float *vert;
if (idx >= p->num_verts) {
/*fixme: error reporting*/
abort();
return;
}
vert = ptr_to_vertex(p->data, idx);
vertex[0] = vert[0];
vertex[1] = vert[1];
}
void polygon_bounding_rect(struct polygon *p,
float *rect)
{
int i;
float minx, miny, maxx, maxy;
float *vert = ptr_to_vertex(p->data, 0);
minx = vert[0];
maxx = vert[0];
miny = vert[1];
maxy = vert[1];
for (i = 1; i < p->num_verts; ++i) {
vert = ptr_to_vertex(p->data, i);
minx = MIN2(vert[0], minx);
miny = MIN2(vert[1], miny);
maxx = MAX2(vert[0], maxx);
maxy = MAX2(vert[1], maxy);
}
rect[0] = minx;
rect[1] = miny;
rect[2] = maxx - minx;
rect[3] = maxy - miny;
}
int polygon_contains_point(struct polygon *p,
float x, float y)
{
return 0;
}
void polygon_append_polygon(struct polygon *dst,
struct polygon *src)
{
if (dst->num_verts + src->num_verts >= dst->size) {
polygon_resize(dst, dst->num_verts + src->num_verts * 1.5);
}
memcpy(ptr_to_vertex(dst->data, dst->num_verts),
src->data, src->num_verts * COMPONENTS * sizeof(VGfloat));
dst->num_verts += src->num_verts;
}
VGboolean polygon_is_closed(struct polygon *p)
{
VGfloat start[2], end[2];
polygon_vertex(p, 0, start);
polygon_vertex(p, p->num_verts - 1, end);
return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
}
static void set_blend_for_fill(struct pipe_blend_state *blend)
{
memset(blend, 0, sizeof(struct pipe_blend_state));
blend->colormask = 0; /*disable colorwrites*/
blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
}
static void draw_polygon(struct vg_context *ctx,
struct polygon *poly)
{
int vert_size;
struct pipe_context *pipe;
struct pipe_vertex_buffer vbuffer;
struct pipe_vertex_element velement;
vert_size = poly->num_verts * COMPONENTS * sizeof(float);
/*polygon_print(poly);*/
pipe = ctx->pipe;
if (poly->vbuf == NULL || poly->dirty) {
if (poly->vbuf) {
pipe_buffer_reference(&poly->vbuf,
NULL);
}
poly->screen = pipe->screen;
poly->vbuf= pipe_user_buffer_create(poly->screen,
poly->data,
vert_size);
poly->dirty = VG_FALSE;
}
/* tell pipe about the vertex buffer */
memset(&vbuffer, 0, sizeof(vbuffer));
vbuffer.buffer = poly->vbuf;
vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
vbuffer.buffer_offset = 0;
vbuffer.max_index = poly->num_verts - 1;
pipe->set_vertex_buffers(pipe, 1, &vbuffer);
/* tell pipe about the vertex attributes */
velement.src_offset = 0;
velement.vertex_buffer_index = 0;
velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
velement.nr_components = COMPONENTS;
pipe->set_vertex_elements(pipe, 1, &velement);
/* draw */
pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN,
0, poly->num_verts);
}
void polygon_fill(struct polygon *poly, struct vg_context *ctx)
{
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_blend_state blend;
VGfloat bounds[4];
VGfloat min_x, min_y, max_x, max_y;
assert(poly);
polygon_bounding_rect(poly, bounds);
min_x = bounds[0];
min_y = bounds[1];
max_x = bounds[0] + bounds[2];
max_y = bounds[1] + bounds[3];
#if DEBUG_POLYGON
debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
min_x, min_y, max_x, max_y);
#endif
set_blend_for_fill(&blend);
memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
cso_save_blend(ctx->cso_context);
cso_save_depth_stencil_alpha(ctx->cso_context);
dsa.stencil[0].enabled = 1;
if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
dsa.stencil[0].writemask = 1;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = ~0;
cso_set_blend(ctx->cso_context, &blend);
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
draw_polygon(ctx, poly);
} else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
struct pipe_screen *screen = ctx->pipe->screen;
if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
/* front */
dsa.stencil[0].writemask = ~0;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = ~0;
/* back */
dsa.stencil[1].enabled = 1;
dsa.stencil[1].writemask = ~0;
dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
dsa.stencil[1].ref_value = 0;
dsa.stencil[1].valuemask = ~0;
cso_set_blend(ctx->cso_context, &blend);
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
draw_polygon(ctx, poly);
} else {
struct pipe_rasterizer_state raster;
memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
cso_save_rasterizer(ctx->cso_context);
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = ~0;
raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
cso_set_blend(ctx->cso_context, &blend);
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
cso_set_rasterizer(ctx->cso_context, &raster);
draw_polygon(ctx, poly);
raster.cull_mode = raster.front_winding;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
cso_set_rasterizer(ctx->cso_context, &raster);
draw_polygon(ctx, poly);
cso_restore_rasterizer(ctx->cso_context);
}
}
/* restore color writes */
cso_restore_blend(ctx->cso_context);
/* setup stencil ops */
dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
dsa.stencil[1].enabled = 0;
memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
sizeof(struct pipe_depth_state));
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
/* render the quad to propagate the rendering from stencil */
renderer_draw_quad(ctx->renderer, min_x, min_y,
max_x, max_y, 0.0f/*depth should be disabled*/);
cso_restore_depth_stencil_alpha(ctx->cso_context);
}
void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
{
struct array *polys = polyarray->array;
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_blend_state blend;
VGfloat min_x = polyarray->min_x;
VGfloat min_y = polyarray->min_y;
VGfloat max_x = polyarray->max_x;
VGfloat max_y = polyarray->max_y;
VGint i;
#if DEBUG_POLYGON
debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
__FUNCTION__,
min_x, min_y, max_x, max_y);
#endif
set_blend_for_fill(&blend);
memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
cso_save_blend(ctx->cso_context);
cso_save_depth_stencil_alpha(ctx->cso_context);
dsa.stencil[0].enabled = 1;
if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
dsa.stencil[0].writemask = 1;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = ~0;
cso_set_blend(ctx->cso_context, &blend);
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
for (i = 0; i < polys->num_elements; ++i) {
struct polygon *poly = (((struct polygon**)polys->data)[i]);
draw_polygon(ctx, poly);
}
} else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
struct pipe_screen *screen = ctx->pipe->screen;
if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
/* front */
dsa.stencil[0].writemask = ~0;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = ~0;
/* back */
dsa.stencil[1].enabled = 1;
dsa.stencil[1].writemask = ~0;
dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
dsa.stencil[1].ref_value = 0;
dsa.stencil[1].valuemask = ~0;
cso_set_blend(ctx->cso_context, &blend);
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
for (i = 0; i < polys->num_elements; ++i) {
struct polygon *poly = (((struct polygon**)polys->data)[i]);
draw_polygon(ctx, poly);
}
} else {
struct pipe_rasterizer_state raster;
memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
cso_save_rasterizer(ctx->cso_context);
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = ~0;
raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
cso_set_blend(ctx->cso_context, &blend);
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
cso_set_rasterizer(ctx->cso_context, &raster);
for (i = 0; i < polys->num_elements; ++i) {
struct polygon *poly = (((struct polygon**)polys->data)[i]);
draw_polygon(ctx, poly);
}
raster.cull_mode = raster.front_winding;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
cso_set_rasterizer(ctx->cso_context, &raster);
for (i = 0; i < polys->num_elements; ++i) {
struct polygon *poly = (((struct polygon**)polys->data)[i]);
draw_polygon(ctx, poly);
}
cso_restore_rasterizer(ctx->cso_context);
}
}
/* restore color writes */
cso_restore_blend(ctx->cso_context);
/* setup stencil ops */
dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].ref_value = 0;
dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
dsa.stencil[1].enabled = 0;
memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
sizeof(struct pipe_depth_state));
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
/* render the quad to propagate the rendering from stencil */
renderer_draw_quad(ctx->renderer, min_x, min_y,
max_x, max_y, 0.0f/*depth should be disabled*/);
cso_restore_depth_stencil_alpha(ctx->cso_context);
}

View File

@ -0,0 +1,75 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef POLYGON_H
#define POLYGON_H
#include "VG/openvg.h"
struct polygon;
struct vg_context;
struct vg_paint;
struct array;
struct polygon *polygon_create(int size);
struct polygon *polygon_create_from_data(float *data, int size);
void polygon_destroy(struct polygon *poly);
void polygon_resize(struct polygon *poly, int new_size);
int polygon_size(struct polygon *poly);
int polygon_vertex_count(struct polygon *poly);
float * polygon_data(struct polygon *poly);
void polygon_vertex_append(struct polygon *p,
float x, float y);
void polygon_append_polygon(struct polygon *dst,
struct polygon *src);
void polygon_set_vertex(struct polygon *p, int idx,
float x, float y);
void polygon_vertex(struct polygon *p, int idx,
float *vertex);
void polygon_bounding_rect(struct polygon *p,
float *rect);
int polygon_contains_point(struct polygon *p,
float x, float y);
VGboolean polygon_is_closed(struct polygon *p);
void polygon_fill(struct polygon *p, struct vg_context *pipe);
/* TODO: make a file/module around this struct
*/
struct polygon_array {
struct array *array;
VGfloat min_x, max_x;
VGfloat min_y, max_y;
};
void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx);
#endif

View File

@ -0,0 +1,592 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "renderer.h"
#include "vg_context.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
#include "pipe/p_screen.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_draw_quad.h"
#include "util/u_simple_shaders.h"
#include "util/u_memory.h"
#include "cso_cache/cso_context.h"
struct renderer {
struct pipe_context *pipe;
struct vg_context *owner;
struct cso_context *cso;
void *fs;
VGfloat vertices[4][2][4];
};
static void setup_shaders(struct renderer *ctx)
{
struct pipe_context *pipe = ctx->pipe;
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe);
}
static struct pipe_buffer *
setup_vertex_data(struct renderer *ctx,
float x0, float y0, float x1, float y1, float z)
{
ctx->vertices[0][0][0] = x0;
ctx->vertices[0][0][1] = y0;
ctx->vertices[0][0][2] = z;
ctx->vertices[0][1][0] = 0.0f; /*s*/
ctx->vertices[0][1][1] = 0.0f; /*t*/
ctx->vertices[1][0][0] = x1;
ctx->vertices[1][0][1] = y0;
ctx->vertices[1][0][2] = z;
ctx->vertices[1][1][0] = 1.0f; /*s*/
ctx->vertices[1][1][1] = 0.0f; /*t*/
ctx->vertices[2][0][0] = x1;
ctx->vertices[2][0][1] = y1;
ctx->vertices[2][0][2] = z;
ctx->vertices[2][1][0] = 1.0f;
ctx->vertices[2][1][1] = 1.0f;
ctx->vertices[3][0][0] = x0;
ctx->vertices[3][0][1] = y1;
ctx->vertices[3][0][2] = z;
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
return pipe_user_buffer_create( ctx->pipe->screen,
ctx->vertices,
sizeof(ctx->vertices) );
}
static struct pipe_buffer *
setup_vertex_data_tex(struct renderer *ctx,
float x0, float y0, float x1, float y1,
float s0, float t0, float s1, float t1,
float z)
{
ctx->vertices[0][0][0] = x0;
ctx->vertices[0][0][1] = y0;
ctx->vertices[0][0][2] = z;
ctx->vertices[0][1][0] = s0; /*s*/
ctx->vertices[0][1][1] = t0; /*t*/
ctx->vertices[1][0][0] = x1;
ctx->vertices[1][0][1] = y0;
ctx->vertices[1][0][2] = z;
ctx->vertices[1][1][0] = s1; /*s*/
ctx->vertices[1][1][1] = t0; /*t*/
ctx->vertices[2][0][0] = x1;
ctx->vertices[2][0][1] = y1;
ctx->vertices[2][0][2] = z;
ctx->vertices[2][1][0] = s1;
ctx->vertices[2][1][1] = t1;
ctx->vertices[3][0][0] = x0;
ctx->vertices[3][0][1] = y1;
ctx->vertices[3][0][2] = z;
ctx->vertices[3][1][0] = s0;
ctx->vertices[3][1][1] = t1;
return pipe_user_buffer_create( ctx->pipe->screen,
ctx->vertices,
sizeof(ctx->vertices) );
}
static struct pipe_buffer *
setup_vertex_data_qtex(struct renderer *ctx,
float x0, float y0, float x1, float y1,
float x2, float y2, float x3, float y3,
float s0, float t0, float s1, float t1,
float z)
{
ctx->vertices[0][0][0] = x0;
ctx->vertices[0][0][1] = y0;
ctx->vertices[0][0][2] = z;
ctx->vertices[0][1][0] = s0; /*s*/
ctx->vertices[0][1][1] = t0; /*t*/
ctx->vertices[1][0][0] = x1;
ctx->vertices[1][0][1] = y1;
ctx->vertices[1][0][2] = z;
ctx->vertices[1][1][0] = s1; /*s*/
ctx->vertices[1][1][1] = t0; /*t*/
ctx->vertices[2][0][0] = x2;
ctx->vertices[2][0][1] = y2;
ctx->vertices[2][0][2] = z;
ctx->vertices[2][1][0] = s1;
ctx->vertices[2][1][1] = t1;
ctx->vertices[3][0][0] = x3;
ctx->vertices[3][0][1] = y3;
ctx->vertices[3][0][2] = z;
ctx->vertices[3][1][0] = s0;
ctx->vertices[3][1][1] = t1;
return pipe_user_buffer_create( ctx->pipe->screen,
ctx->vertices,
sizeof(ctx->vertices) );
}
struct renderer * renderer_create(struct vg_context *owner)
{
VGint i;
struct renderer *renderer = CALLOC_STRUCT(renderer);
if (!renderer)
return NULL;
renderer->owner = owner;
renderer->pipe = owner->pipe;
renderer->cso = owner->cso_context;
setup_shaders(renderer);
/* init vertex data that doesn't change */
for (i = 0; i < 4; i++) {
renderer->vertices[i][0][3] = 1.0f; /* w */
renderer->vertices[i][1][2] = 0.0f; /* r */
renderer->vertices[i][1][3] = 1.0f; /* q */
}
return renderer;
}
void renderer_destroy(struct renderer *ctx)
{
#if 0
if (ctx->fs) {
cso_delete_fragment_shader(ctx->cso, ctx->fs);
ctx->fs = NULL;
}
#endif
free(ctx);
}
void renderer_draw_quad(struct renderer *r,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2,
VGfloat depth)
{
struct pipe_buffer *buf;
buf = setup_vertex_data(r, x1, y1, x2, y2, depth);
if (buf) {
util_draw_vertex_buffer(r->pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
pipe_buffer_reference( &buf,
NULL );
}
}
void renderer_draw_texture(struct renderer *r,
struct pipe_texture *tex,
VGfloat x1offset, VGfloat y1offset,
VGfloat x2offset, VGfloat y2offset,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2)
{
struct pipe_context *pipe = r->pipe;
struct pipe_buffer *buf;
VGfloat s0, t0, s1, t1;
assert(tex->width[0] != 0);
assert(tex->height[0] != 0);
s0 = x1offset / tex->width[0];
s1 = x2offset / tex->width[0];
t0 = y1offset / tex->height[0];
t1 = y2offset / tex->height[0];
cso_save_vertex_shader(r->cso);
/* shaders */
cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
/* draw quad */
buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
s0, t0, s1, t1, 0.0f);
if (buf) {
util_draw_vertex_buffer(pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
pipe_buffer_reference( &buf,
NULL );
}
cso_restore_vertex_shader(r->cso);
}
void renderer_copy_texture(struct renderer *ctx,
struct pipe_texture *src,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
struct pipe_texture *dst,
VGfloat dx1, VGfloat dy1,
VGfloat dx2, VGfloat dy2)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_buffer *buf;
struct pipe_surface *dst_surf = screen->get_tex_surface(
screen, dst, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
struct pipe_framebuffer_state fb;
float s0, t0, s1, t1;
assert(src->width[0] != 0);
assert(src->height[0] != 0);
assert(dst->width[0] != 0);
assert(dst->height[0] != 0);
#if 0
debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
#endif
#if 1
s0 = sx1 / src->width[0];
s1 = sx2 / src->width[0];
t0 = sy1 / src->height[0];
t1 = sy2 / src->height[0];
#else
s0 = 0;
s1 = 1;
t0 = 0;
t1 = 1;
#endif
assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_samplers(ctx->cso);
cso_save_sampler_textures(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
cso_save_viewport(ctx->cso);
/* set misc state we care about */
{
struct pipe_blend_state blend;
memset(&blend, 0, sizeof(blend));
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.colormask = PIPE_MASK_RGBA;
cso_set_blend(ctx->cso, &blend);
}
/* sampler */
{
struct pipe_sampler_state sampler;
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.normalized_coords = 1;
cso_single_sampler(ctx->cso, 0, &sampler);
cso_single_sampler_done(ctx->cso);
}
vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
/* texture */
cso_set_sampler_textures(ctx->cso, 1, &src);
/* shaders */
cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
/* drawing dest */
memset(&fb, 0, sizeof(fb));
fb.width = dst_surf->width;
fb.height = dst_surf->height;
fb.nr_cbufs = 1;
fb.cbufs[0] = dst_surf;
{
VGint i;
for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
fb.cbufs[i] = 0;
}
cso_set_framebuffer(ctx->cso, &fb);
/* draw quad */
buf = setup_vertex_data_tex(ctx,
dx1, dy1,
dx2, dy2,
s0, t0, s1, t1,
0.0f);
if (buf) {
util_draw_vertex_buffer(ctx->pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
pipe_buffer_reference( &buf,
NULL );
}
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_samplers(ctx->cso);
cso_restore_sampler_textures(ctx->cso);
cso_restore_framebuffer(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
cso_restore_viewport(ctx->cso);
pipe_surface_reference(&dst_surf, NULL);
}
void renderer_copy_surface(struct renderer *ctx,
struct pipe_surface *src,
int srcX0, int srcY0,
int srcX1, int srcY1,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, unsigned filter)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_buffer *buf;
struct pipe_texture texTemp, *tex;
struct pipe_surface *texSurf;
struct pipe_framebuffer_state fb;
struct st_framebuffer *stfb = ctx->owner->draw_buffer;
const int srcW = abs(srcX1 - srcX0);
const int srcH = abs(srcY1 - srcY0);
const int srcLeft = MIN2(srcX0, srcX1);
const int srcTop = MIN2(srcY0, srcY1);
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
if (srcLeft != srcX0) {
/* left-right flip */
int tmp = dstX0;
dstX0 = dstX1;
dstX1 = tmp;
}
if (srcTop != srcY0) {
/* up-down flip */
int tmp = dstY0;
dstY0 = dstY1;
dstY1 = tmp;
}
assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_SAMPLER, 0));
assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_SAMPLER, 0));
assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
/*
* XXX for now we're always creating a temporary texture.
* Strictly speaking that's not always needed.
*/
/* create temp texture */
memset(&texTemp, 0, sizeof(texTemp));
texTemp.target = PIPE_TEXTURE_2D;
texTemp.format = src->format;
texTemp.last_level = 0;
texTemp.width[0] = srcW;
texTemp.height[0] = srcH;
texTemp.depth[0] = 1;
pf_get_block(src->format, &texTemp.block);
tex = screen->texture_create(screen, &texTemp);
if (!tex)
return;
texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* load temp texture */
pipe->surface_copy(pipe,
texSurf, 0, 0, /* dest */
src, srcLeft, srcTop, /* src */
srcW, srcH); /* size */
/* free the surface, update the texture if necessary.*/
screen->tex_surface_destroy(texSurf);
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_samplers(ctx->cso);
cso_save_sampler_textures(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
cso_save_viewport(ctx->cso);
/* set misc state we care about */
{
struct pipe_blend_state blend;
memset(&blend, 0, sizeof(blend));
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.colormask = PIPE_MASK_RGBA;
cso_set_blend(ctx->cso, &blend);
}
vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
/* sampler */
{
struct pipe_sampler_state sampler;
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.normalized_coords = 1;
cso_single_sampler(ctx->cso, 0, &sampler);
cso_single_sampler_done(ctx->cso);
}
/* texture */
cso_set_sampler_textures(ctx->cso, 1, &tex);
/* shaders */
cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
/* drawing dest */
if (stfb->strb->surface != dst) {
memset(&fb, 0, sizeof(fb));
fb.width = dst->width;
fb.height = dst->height;
fb.nr_cbufs = 1;
fb.cbufs[0] = dst;
fb.zsbuf = stfb->dsrb->surface;
cso_set_framebuffer(ctx->cso, &fb);
}
/* draw quad */
buf = setup_vertex_data(ctx,
(float) dstX0, (float) dstY0,
(float) dstX1, (float) dstY1, z);
if (buf) {
util_draw_vertex_buffer(ctx->pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
pipe_buffer_reference( &buf,
NULL );
}
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_samplers(ctx->cso);
cso_restore_sampler_textures(ctx->cso);
cso_restore_framebuffer(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
cso_restore_viewport(ctx->cso);
pipe_texture_reference(&tex, NULL);
}
void renderer_texture_quad(struct renderer *r,
struct pipe_texture *tex,
VGfloat x1offset, VGfloat y1offset,
VGfloat x2offset, VGfloat y2offset,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2,
VGfloat x3, VGfloat y3,
VGfloat x4, VGfloat y4)
{
struct pipe_context *pipe = r->pipe;
struct pipe_buffer *buf;
VGfloat s0, t0, s1, t1;
assert(tex->width[0] != 0);
assert(tex->height[0] != 0);
s0 = x1offset / tex->width[0];
s1 = x2offset / tex->width[0];
t0 = y1offset / tex->height[0];
t1 = y2offset / tex->height[0];
cso_save_vertex_shader(r->cso);
/* shaders */
cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
/* draw quad */
buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
s0, t0, s1, t1, 0.0f);
if (buf) {
util_draw_vertex_buffer(pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
pipe_buffer_reference(&buf,
NULL);
}
cso_restore_vertex_shader(r->cso);
}

View File

@ -0,0 +1,76 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef RENDERER_H
#define RENDERER_H
#include "VG/openvg.h"
struct renderer;
struct vg_context;
struct pipe_texture;
struct pipe_surface;
struct renderer *renderer_create(struct vg_context *owner);
void renderer_destroy(struct renderer *);
void renderer_draw_quad(struct renderer *,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2,
VGfloat depth);
void renderer_draw_texture(struct renderer *,
struct pipe_texture *texture,
VGfloat x1offset, VGfloat y1offset,
VGfloat x2offset, VGfloat y2offset,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2);
void renderer_texture_quad(struct renderer *,
struct pipe_texture *texture,
VGfloat x1offset, VGfloat y1offset,
VGfloat x2offset, VGfloat y2offset,
VGfloat x1, VGfloat y1,
VGfloat x2, VGfloat y2,
VGfloat x3, VGfloat y3,
VGfloat x4, VGfloat y4);
void renderer_copy_texture(struct renderer *r,
struct pipe_texture *src,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
struct pipe_texture *dst,
VGfloat dx1, VGfloat dy1,
VGfloat dx2, VGfloat dy2);
void renderer_copy_surface(struct renderer *r,
struct pipe_surface *src,
int sx1, int sy1,
int sx2, int sy2,
struct pipe_surface *dst,
int dx1, int dy1,
int dx2, int dy2,
float z, unsigned filter);
#endif

View File

@ -0,0 +1,310 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "shader.h"
#include "vg_context.h"
#include "shaders_cache.h"
#include "paint.h"
#include "mask.h"
#include "image.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#define MAX_CONSTANTS 20
struct shader {
struct vg_context *context;
VGboolean masking;
struct vg_paint *paint;
struct vg_image *image;
VGboolean drawing_image;
VGImageMode image_mode;
float constants[MAX_CONSTANTS];
struct pipe_constant_buffer cbuf;
struct pipe_shader_state fs_state;
void *fs;
};
struct shader * shader_create(struct vg_context *ctx)
{
struct shader *shader = 0;
shader = CALLOC_STRUCT(shader);
shader->context = ctx;
return shader;
}
void shader_destroy(struct shader *shader)
{
free(shader);
}
void shader_set_masking(struct shader *shader, VGboolean set)
{
shader->masking = set;
}
VGboolean shader_is_masking(struct shader *shader)
{
return shader->masking;
}
void shader_set_paint(struct shader *shader, struct vg_paint *paint)
{
shader->paint = paint;
}
struct vg_paint * shader_paint(struct shader *shader)
{
return shader->paint;
}
static void setup_constant_buffer(struct shader *shader)
{
struct vg_context *ctx = shader->context;
struct pipe_context *pipe = shader->context->pipe;
struct pipe_constant_buffer *cbuf = &shader->cbuf;
VGint param_bytes = paint_constant_buffer_size(shader->paint);
float temp_buf[MAX_CONSTANTS];
assert(param_bytes <= sizeof(temp_buf));
paint_fill_constant_buffer(shader->paint, temp_buf);
if (cbuf->buffer == NULL ||
memcmp(temp_buf, shader->constants, param_bytes) != 0)
{
pipe_buffer_reference(&cbuf->buffer, NULL);
memcpy(shader->constants, temp_buf, param_bytes);
cbuf->buffer = pipe_user_buffer_create(pipe->screen,
&shader->constants,
sizeof(shader->constants));
}
ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
}
static VGint blend_bind_samplers(struct vg_context *ctx,
struct pipe_sampler_state **samplers,
struct pipe_texture **textures)
{
VGBlendMode bmode = ctx->state.vg.blend_mode;
if (bmode == VG_BLEND_MULTIPLY ||
bmode == VG_BLEND_SCREEN ||
bmode == VG_BLEND_DARKEN ||
bmode == VG_BLEND_LIGHTEN) {
struct st_framebuffer *stfb = ctx->draw_buffer;
vg_prepare_blend_surface(ctx);
samplers[2] = &ctx->blend_sampler;
textures[2] = stfb->blend_texture;
if (!samplers[0] || !textures[0]) {
samplers[1] = samplers[2];
textures[1] = textures[2];
}
if (!samplers[1] || !textures[1]) {
samplers[1] = samplers[0];
textures[1] = textures[0];
}
return 1;
}
return 0;
}
static void setup_samplers(struct shader *shader)
{
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
struct vg_context *ctx = shader->context;
/* a little wonky: we use the num as a boolean that just says
* whether any sampler/textures have been set. the actual numbering
* for samplers is always the same:
* 0 - paint sampler/texture for gradient/pattern
* 1 - mask sampler/texture
* 2 - blend sampler/texture
* 3 - image sampler/texture
* */
VGint num = 0;
samplers[0] = NULL;
samplers[1] = NULL;
samplers[2] = NULL;
samplers[3] = NULL;
textures[0] = NULL;
textures[1] = NULL;
textures[2] = NULL;
textures[3] = NULL;
num += paint_bind_samplers(shader->paint, samplers, textures);
num += mask_bind_samplers(samplers, textures);
num += blend_bind_samplers(ctx, samplers, textures);
if (shader->drawing_image && shader->image)
num += image_bind_samplers(shader->image, samplers, textures);
if (num) {
cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers);
cso_set_sampler_textures(ctx->cso_context, 4, textures);
}
}
static INLINE VGboolean is_format_bw(struct shader *shader)
{
#if 0
struct vg_context *ctx = shader->context;
struct st_framebuffer *stfb = ctx->draw_buffer;
#endif
if (shader->drawing_image && shader->image) {
if (shader->image->format == VG_BW_1)
return VG_TRUE;
}
return VG_FALSE;
}
static void setup_shader_program(struct shader *shader)
{
struct vg_context *ctx = shader->context;
VGint shader_id = 0;
VGBlendMode blend_mode = ctx->state.vg.blend_mode;
VGboolean black_white = is_format_bw(shader);
/* 1st stage: fill */
if (!shader->drawing_image ||
(shader->image_mode == VG_DRAW_IMAGE_MULTIPLY || shader->image_mode == VG_DRAW_IMAGE_STENCIL)) {
switch(paint_type(shader->paint)) {
case VG_PAINT_TYPE_COLOR:
shader_id |= VEGA_SOLID_FILL_SHADER;
break;
case VG_PAINT_TYPE_LINEAR_GRADIENT:
shader_id |= VEGA_LINEAR_GRADIENT_SHADER;
break;
case VG_PAINT_TYPE_RADIAL_GRADIENT:
shader_id |= VEGA_RADIAL_GRADIENT_SHADER;
break;
case VG_PAINT_TYPE_PATTERN:
shader_id |= VEGA_PATTERN_SHADER;
break;
default:
abort();
}
}
/* second stage image */
if (shader->drawing_image) {
switch(shader->image_mode) {
case VG_DRAW_IMAGE_NORMAL:
shader_id |= VEGA_IMAGE_NORMAL_SHADER;
break;
case VG_DRAW_IMAGE_MULTIPLY:
shader_id |= VEGA_IMAGE_MULTIPLY_SHADER;
break;
case VG_DRAW_IMAGE_STENCIL:
shader_id |= VEGA_IMAGE_STENCIL_SHADER;
break;
default:
debug_printf("Unknown image mode!");
}
}
if (shader->masking)
shader_id |= VEGA_MASK_SHADER;
switch(blend_mode) {
case VG_BLEND_MULTIPLY:
shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
break;
case VG_BLEND_SCREEN:
shader_id |= VEGA_BLEND_SCREEN_SHADER;
break;
case VG_BLEND_DARKEN:
shader_id |= VEGA_BLEND_DARKEN_SHADER;
break;
case VG_BLEND_LIGHTEN:
shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
break;
default:
/* handled by pipe_blend_state */
break;
}
if (black_white)
shader_id |= VEGA_BW_SHADER;
shader->fs = shaders_cache_fill(ctx->sc, shader_id);
cso_set_fragment_shader_handle(ctx->cso_context, shader->fs);
}
void shader_bind(struct shader *shader)
{
/* first resolve the real paint type */
paint_resolve_type(shader->paint);
setup_constant_buffer(shader);
setup_samplers(shader);
setup_shader_program(shader);
}
void shader_set_image_mode(struct shader *shader, VGImageMode image_mode)
{
shader->image_mode = image_mode;
}
VGImageMode shader_image_mode(struct shader *shader)
{
return shader->image_mode;
}
void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image)
{
shader->drawing_image = drawing_image;
}
VGboolean shader_drawing_image(struct shader *shader)
{
return shader->drawing_image;
}
void shader_set_image(struct shader *shader, struct vg_image *img)
{
shader->image = img;
}

View File

@ -0,0 +1,56 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SHADER_H
#define SHADER_H
#include "VG/openvg.h"
struct shader;
struct vg_paint;
struct vg_context;
struct vg_image;
struct shader *shader_create(struct vg_context *context);
void shader_destroy(struct shader *shader);
void shader_set_masking(struct shader *shader, VGboolean set);
VGboolean shader_is_masking(struct shader *shader);
void shader_set_paint(struct shader *shader, struct vg_paint *paint);
struct vg_paint *shader_paint(struct shader *shader);
void shader_set_image_mode(struct shader *shader, VGImageMode image_mode);
VGImageMode shader_image_mode(struct shader *shader);
void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image);
VGboolean shader_drawing_image(struct shader *shader);
void shader_set_image(struct shader *shader, struct vg_image *img);
void shader_bind(struct shader *shader);
#endif

View File

@ -0,0 +1,439 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "shaders_cache.h"
#include "vg_context.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_screen.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_build.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_text.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_debug.h"
#include "cso_cache/cso_hash.h"
#include "cso_cache/cso_context.h"
#include "VG/openvg.h"
#include "asm_fill.h"
/* Essentially we construct an ubber-shader based on the state
* of the pipeline. The stages are:
* 1) Fill (mandatory, solid color/gradient/pattern/image draw)
* 2) Image composition (image mode multiply and stencil)
* 3) Mask
* 4) Extended blend (multiply/screen/darken/lighten)
* 5) Premultiply/Unpremultiply
* 6) Color transform (to black and white)
*/
#define SHADER_STAGES 6
struct cached_shader {
void *driver_shader;
struct pipe_shader_state state;
};
struct shaders_cache {
struct vg_context *pipe;
struct cso_hash *hash;
};
static INLINE struct tgsi_token *tokens_from_assembly(const char *txt, int num_tokens)
{
struct tgsi_token *tokens;
tokens = (struct tgsi_token *) MALLOC(num_tokens * sizeof(tokens[0]));
tgsi_text_translate(txt, tokens, num_tokens);
#if DEBUG_SHADERS
tgsi_dump(tokens, 0);
#endif
return tokens;
}
#define ALL_FILLS (VEGA_SOLID_FILL_SHADER | \
VEGA_LINEAR_GRADIENT_SHADER | \
VEGA_RADIAL_GRADIENT_SHADER | \
VEGA_PATTERN_SHADER | \
VEGA_IMAGE_NORMAL_SHADER)
/*
static const char max_shader_preamble[] =
"FRAG1.1\n"
"DCL IN[0], POSITION, LINEAR\n"
"DCL IN[1], GENERIC[0], PERSPECTIVE\n"
"DCL OUT[0], COLOR, CONSTANT\n"
"DCL CONST[0..9], CONSTANT\n"
"DCL TEMP[0..9], CONSTANT\n"
"DCL SAMP[0..9], CONSTANT\n";
max_shader_preamble strlen == 175
*/
#define MAX_PREAMBLE 175
static INLINE VGint range_min(VGint min, VGint current)
{
if (min < 0)
min = current;
else
min = MIN2(min, current);
return min;
}
static INLINE VGint range_max(VGint max, VGint current)
{
return MAX2(max, current);
}
static void
create_preamble(char *txt,
const struct shader_asm_info *shaders[SHADER_STAGES],
int num_shaders)
{
VGboolean declare_input = VG_FALSE;
VGint start_const = -1, end_const = 0;
VGint start_temp = -1, end_temp = 0;
VGint start_sampler = -1, end_sampler = 0;
VGint i;
VGint num_consts, num_temps, num_samplers;
for (i = 0; i < num_shaders; ++i) {
if (shaders[i]->num_consts)
start_const = range_min(start_const, shaders[i]->start_const);
if (shaders[i]->num_temps)
start_temp = range_min(start_temp, shaders[i]->start_temp);
if (shaders[i]->num_samplers)
start_sampler = range_min(start_sampler, shaders[i]->start_sampler);
end_const = range_max(end_const, shaders[i]->start_const +
shaders[i]->num_consts);
end_temp = range_max(end_temp, shaders[i]->start_temp +
shaders[i]->num_temps);
end_sampler = range_max(end_sampler, shaders[i]->start_sampler +
shaders[i]->num_samplers);
if (shaders[i]->needs_position)
declare_input = VG_TRUE;
}
/* if they're still unitialized, initialize them */
if (start_const < 0)
start_const = 0;
if (start_temp < 0)
start_temp = 0;
if (start_sampler < 0)
start_sampler = 0;
num_consts = end_const - start_const;
num_temps = end_temp - start_temp;
num_samplers = end_sampler - start_sampler;
/* end exclusive */
--end_const;
--end_temp;
--end_sampler;
sprintf(txt, "FRAG1.1\n");
if (declare_input) {
sprintf(txt + strlen(txt), "DCL IN[0], POSITION, LINEAR\n");
sprintf(txt + strlen(txt), "DCL IN[1], GENERIC[0], PERSPECTIVE\n");
}
/* we always have a color output */
sprintf(txt + strlen(txt), "DCL OUT[0], COLOR, CONSTANT\n");
if (num_consts > 1)
sprintf(txt + strlen(txt), "DCL CONST[%d..%d], CONSTANT\n", start_const, end_const);
else if (num_consts == 1)
sprintf(txt + strlen(txt), "DCL CONST[%d], CONSTANT\n", start_const);
if (num_temps > 1)
sprintf(txt + strlen(txt), "DCL TEMP[%d..%d], CONSTANT\n", start_temp, end_temp);
else if (num_temps > 1)
sprintf(txt + strlen(txt), "DCL TEMP[%d], CONSTANT\n", start_temp);
if (num_samplers > 1)
sprintf(txt + strlen(txt), "DCL SAMP[%d..%d], CONSTANT\n", start_sampler, end_sampler);
else if (num_samplers == 1)
sprintf(txt + strlen(txt), "DCL SAMP[%d], CONSTANT\n", start_sampler);
}
static void *
combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders,
struct pipe_context *pipe,
struct pipe_shader_state *shader)
{
char *combined_txt;
int combined_len = MAX_PREAMBLE;
int combined_tokens = 0;
int i = 0;
int current_shader = 0;
int current_len;
for (i = 0; i < num_shaders; ++i) {
combined_len += strlen(shaders[i]->txt);
combined_tokens += shaders[i]->num_tokens;
}
/* add for the %s->TEMP[0] substitutions */
combined_len += num_shaders * 7 /*TEMP[0]*/ + 4 /*"END\n"*/;
combined_txt = (char*)malloc(combined_len);
combined_txt[0] = '\0';
create_preamble(combined_txt, shaders, num_shaders);
while (current_shader < num_shaders) {
const char temp[] = "TEMP[0]";
const char out[] = "OUT[0]";
const char *subst = temp;
current_len = strlen(combined_txt);
/* if the last shader then output */
if (current_shader + 1 == num_shaders)
subst = out;
snprintf(combined_txt + current_len,
combined_len - current_len,
shaders[current_shader]->txt,
subst);
++current_shader;
}
current_len = strlen(combined_txt);
snprintf(combined_txt + current_len,
combined_len - current_len,
"END\n");
debug_printf("Combined shader is : \n%s\n",
combined_txt);
shader->tokens = tokens_from_assembly(
combined_txt, combined_tokens);
free(combined_txt);
return pipe->create_fs_state(pipe, shader);
}
static void *
create_shader(struct pipe_context *pipe,
int id,
struct pipe_shader_state *shader)
{
int idx = 0;
const struct shader_asm_info * shaders[SHADER_STAGES];
/* the shader has to have a fill */
debug_assert(id & ALL_FILLS);
/* first stage */
if (id & VEGA_SOLID_FILL_SHADER) {
debug_assert(idx == 0);
shaders[idx] = &shaders_asm[0];
debug_assert(shaders_asm[0].id == VEGA_SOLID_FILL_SHADER);
++idx;
}
if ((id & VEGA_LINEAR_GRADIENT_SHADER)) {
debug_assert(idx == 0);
shaders[idx] = &shaders_asm[1];
debug_assert(shaders_asm[1].id == VEGA_LINEAR_GRADIENT_SHADER);
++idx;
}
if ((id & VEGA_RADIAL_GRADIENT_SHADER)) {
debug_assert(idx == 0);
shaders[idx] = &shaders_asm[2];
debug_assert(shaders_asm[2].id == VEGA_RADIAL_GRADIENT_SHADER);
++idx;
}
if ((id & VEGA_PATTERN_SHADER)) {
debug_assert(idx == 0);
debug_assert(shaders_asm[3].id == VEGA_PATTERN_SHADER);
shaders[idx] = &shaders_asm[3];
++idx;
}
if ((id & VEGA_IMAGE_NORMAL_SHADER)) {
debug_assert(idx == 0);
debug_assert(shaders_asm[4].id == VEGA_IMAGE_NORMAL_SHADER);
shaders[idx] = &shaders_asm[4];
++idx;
}
/* second stage */
if ((id & VEGA_IMAGE_MULTIPLY_SHADER)) {
debug_assert(shaders_asm[5].id == VEGA_IMAGE_MULTIPLY_SHADER);
shaders[idx] = &shaders_asm[5];
++idx;
} else if ((id & VEGA_IMAGE_STENCIL_SHADER)) {
debug_assert(shaders_asm[6].id == VEGA_IMAGE_STENCIL_SHADER);
shaders[idx] = &shaders_asm[6];
++idx;
}
/* third stage */
if ((id & VEGA_MASK_SHADER)) {
debug_assert(idx == 1);
debug_assert(shaders_asm[7].id == VEGA_MASK_SHADER);
shaders[idx] = &shaders_asm[7];
++idx;
}
/* fourth stage */
if ((id & VEGA_BLEND_MULTIPLY_SHADER)) {
debug_assert(shaders_asm[8].id == VEGA_BLEND_MULTIPLY_SHADER);
shaders[idx] = &shaders_asm[8];
++idx;
} else if ((id & VEGA_BLEND_SCREEN_SHADER)) {
debug_assert(shaders_asm[9].id == VEGA_BLEND_SCREEN_SHADER);
shaders[idx] = &shaders_asm[9];
++idx;
} else if ((id & VEGA_BLEND_DARKEN_SHADER)) {
debug_assert(shaders_asm[10].id == VEGA_BLEND_DARKEN_SHADER);
shaders[idx] = &shaders_asm[10];
++idx;
} else if ((id & VEGA_BLEND_LIGHTEN_SHADER)) {
debug_assert(shaders_asm[11].id == VEGA_BLEND_LIGHTEN_SHADER);
shaders[idx] = &shaders_asm[11];
++idx;
}
/* fifth stage */
if ((id & VEGA_PREMULTIPLY_SHADER)) {
debug_assert(shaders_asm[12].id == VEGA_PREMULTIPLY_SHADER);
shaders[idx] = &shaders_asm[12];
++idx;
} else if ((id & VEGA_UNPREMULTIPLY_SHADER)) {
debug_assert(shaders_asm[13].id == VEGA_UNPREMULTIPLY_SHADER);
shaders[idx] = &shaders_asm[13];
++idx;
}
/* sixth stage */
if ((id & VEGA_BW_SHADER)) {
debug_assert(shaders_asm[14].id == VEGA_BW_SHADER);
shaders[idx] = &shaders_asm[14];
++idx;
}
return combine_shaders(shaders, idx, pipe, shader);
}
/*************************************************/
struct shaders_cache * shaders_cache_create(struct vg_context *vg)
{
struct shaders_cache *sc = CALLOC_STRUCT(shaders_cache);
sc->pipe = vg;
sc->hash = cso_hash_create();
return sc;
}
void shaders_cache_destroy(struct shaders_cache *sc)
{
struct cso_hash_iter iter = cso_hash_first_node(sc->hash);
while (!cso_hash_iter_is_null(iter)) {
struct cached_shader *cached =
(struct cached_shader *)cso_hash_iter_data(iter);
cso_delete_fragment_shader(sc->pipe->cso_context,
cached->driver_shader);
iter = cso_hash_erase(sc->hash, iter);
}
cso_hash_delete(sc->hash);
free(sc);
}
void * shaders_cache_fill(struct shaders_cache *sc,
int shader_key)
{
VGint key = shader_key;
struct cached_shader *cached;
struct cso_hash_iter iter = cso_hash_find(sc->hash, key);
if (cso_hash_iter_is_null(iter)) {
cached = CALLOC_STRUCT(cached_shader);
cached->driver_shader = create_shader(sc->pipe->pipe, key, &cached->state);
cso_hash_insert(sc->hash, key, cached);
return cached->driver_shader;
}
cached = (struct cached_shader *)cso_hash_iter_data(iter);
assert(cached->driver_shader);
return cached->driver_shader;
}
struct vg_shader * shader_create_from_text(struct pipe_context *pipe,
const char *txt, int num_tokens,
int type)
{
struct vg_shader *shader = (struct vg_shader *)malloc(
sizeof(struct vg_shader));
struct tgsi_token *tokens = tokens_from_assembly(txt, num_tokens);
struct pipe_shader_state state;
debug_assert(type == PIPE_SHADER_VERTEX ||
type == PIPE_SHADER_FRAGMENT);
state.tokens = tokens;
shader->type = type;
shader->tokens = tokens;
if (type == PIPE_SHADER_FRAGMENT)
shader->driver = pipe->create_fs_state(pipe, &state);
else
shader->driver = pipe->create_vs_state(pipe, &state);
return shader;
}
void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader)
{
if (shader->type == PIPE_SHADER_FRAGMENT)
cso_delete_fragment_shader(ctx->cso_context, shader->driver);
else
cso_delete_vertex_shader(ctx->cso_context, shader->driver);
free(shader->tokens);
free(shader);
}

View File

@ -0,0 +1,77 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SHADERS_CACHE_H
#define SHADERS_CACHE_H
struct vg_context;
struct pipe_context;
struct tgsi_token;
struct shaders_cache;
enum VegaShaderType {
VEGA_SOLID_FILL_SHADER = 1 << 0,
VEGA_LINEAR_GRADIENT_SHADER = 1 << 1,
VEGA_RADIAL_GRADIENT_SHADER = 1 << 2,
VEGA_PATTERN_SHADER = 1 << 3,
VEGA_IMAGE_NORMAL_SHADER = 1 << 4,
VEGA_IMAGE_MULTIPLY_SHADER = 1 << 5,
VEGA_IMAGE_STENCIL_SHADER = 1 << 6,
VEGA_MASK_SHADER = 1 << 7,
VEGA_BLEND_MULTIPLY_SHADER = 1 << 8,
VEGA_BLEND_SCREEN_SHADER = 1 << 9,
VEGA_BLEND_DARKEN_SHADER = 1 << 10,
VEGA_BLEND_LIGHTEN_SHADER = 1 << 11,
VEGA_PREMULTIPLY_SHADER = 1 << 12,
VEGA_UNPREMULTIPLY_SHADER = 1 << 13,
VEGA_BW_SHADER = 1 << 14
};
struct vg_shader {
void *driver;
struct tgsi_token *tokens;
int type;/* PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT */
};
struct shaders_cache *shaders_cache_create(struct vg_context *pipe);
void shaders_cache_destroy(struct shaders_cache *sc);
void *shaders_cache_fill(struct shaders_cache *sc,
int shader_key);
struct vg_shader *shader_create_from_text(struct pipe_context *pipe,
const char *txt, int num_tokens,
int type);
void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader);
#endif

View File

@ -0,0 +1,159 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* Functions for checking if buffers/textures are referenced when we need
* to read/write from/to them. Flush when needed.
*/
#ifndef ST_INLINES_H
#define ST_INLINES_H
#include "vg_context.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_state.h"
static INLINE struct pipe_transfer *
st_cond_flush_get_tex_transfer(struct vg_context *st,
struct pipe_texture *pt,
unsigned int face,
unsigned int level,
unsigned int zslice,
enum pipe_transfer_usage usage,
unsigned int x, unsigned int y,
unsigned int w, unsigned int h)
{
struct pipe_screen *screen = st->pipe->screen;
struct pipe_context *pipe = st->pipe;
unsigned referenced =
pipe->is_texture_referenced(pipe, pt, face, level);
if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
usage == PIPE_TRANSFER_WRITE ||
usage == PIPE_TRANSFER_READ_WRITE))
vgFlush();
return screen->get_tex_transfer(screen, pt, face, level, zslice, usage,
x, y, w, h);
}
static INLINE struct pipe_transfer *
st_no_flush_get_tex_transfer(struct vg_context *st,
struct pipe_texture *pt,
unsigned int face,
unsigned int level,
unsigned int zslice,
enum pipe_transfer_usage usage,
unsigned int x, unsigned int y,
unsigned int w, unsigned int h)
{
struct pipe_screen *screen = st->pipe->screen;
return screen->get_tex_transfer(screen, pt, face, level,
zslice, usage, x, y, w, h);
}
static INLINE void *
st_cond_flush_pipe_buffer_map(struct vg_context *st,
struct pipe_buffer *buf,
unsigned int map_flags)
{
struct pipe_context *pipe = st->pipe;
unsigned int referenced = pipe->is_buffer_referenced(pipe, buf);
if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
(map_flags & PIPE_BUFFER_USAGE_CPU_WRITE)))
vgFlush();
return pipe_buffer_map(pipe->screen, buf, map_flags);
}
static INLINE void *
st_no_flush_pipe_buffer_map(struct vg_context *st,
struct pipe_buffer *buf,
unsigned int map_flags)
{
return pipe_buffer_map(st->pipe->screen, buf, map_flags);
}
static INLINE void
st_cond_flush_pipe_buffer_write(struct vg_context *st,
struct pipe_buffer *buf,
unsigned int offset,
unsigned int size,
const void * data)
{
struct pipe_context *pipe = st->pipe;
if (pipe->is_buffer_referenced(pipe, buf))
vgFlush();
pipe_buffer_write(pipe->screen, buf, offset, size, data);
}
static INLINE void
st_no_flush_pipe_buffer_write(struct vg_context *st,
struct pipe_buffer *buf,
unsigned int offset,
unsigned int size,
const void * data)
{
pipe_buffer_write(st->pipe->screen, buf, offset, size, data);
}
static INLINE void
st_cond_flush_pipe_buffer_read(struct vg_context *st,
struct pipe_buffer *buf,
unsigned int offset,
unsigned int size,
void * data)
{
struct pipe_context *pipe = st->pipe;
if (pipe->is_buffer_referenced(pipe, buf) & PIPE_REFERENCED_FOR_WRITE)
vgFlush();
pipe_buffer_read(pipe->screen, buf, offset, size, data);
}
static INLINE void
st_no_flush_pipe_buffer_read(struct vg_context *st,
struct pipe_buffer *buf,
unsigned int offset,
unsigned int size,
void * data)
{
pipe_buffer_read(st->pipe->screen, buf, offset, size, data);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef STROKER_H
#define STROKER_H
#include "VG/openvg.h"
#include "api_consts.h"
struct path;
struct vg_state;
struct array;
struct stroker {
void (*begin)(struct stroker *stroker);
void (*process_subpath)(struct stroker *stroker);
void (*end)(struct stroker *stroker);
struct array *segments;
struct array *control_points;
struct path *path;
VGfloat back1_x, back1_y;
VGfloat back2_x, back2_y;
VGfloat stroke_width;
VGfloat miter_limit;
VGCapStyle cap_style;
VGJoinStyle join_style;
VGPathCommand last_cmd;
};
struct dash_stroker {
struct stroker base;
struct stroker stroker;
VGfloat dash_pattern[VEGA_MAX_DASH_COUNT];
VGint dash_pattern_num;
VGfloat dash_phase;
VGboolean dash_phase_reset;
};
void stroker_init(struct stroker *stroker,
struct vg_state *state);
void dash_stroker_init(struct stroker *stroker,
struct vg_state *state);
void dash_stroker_cleanup(struct dash_stroker *stroker);
void stroker_cleanup(struct stroker *stroker);
void stroker_begin(struct stroker *stroker);
void stroker_move_to(struct stroker *stroker, VGfloat x, VGfloat y);
void stroker_line_to(struct stroker *stroker, VGfloat x, VGfloat y);
void stroker_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1,
VGfloat px2, VGfloat py2,
VGfloat x, VGfloat y);
void stroker_end(struct stroker *stroker);
void stroker_emit_move_to(struct stroker *stroker, VGfloat x, VGfloat y);
void stroker_emit_line_to(struct stroker *stroker, VGfloat x, VGfloat y);
void stroker_emit_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1,
VGfloat px2, VGfloat py2,
VGfloat x, VGfloat y);
#endif

View File

@ -0,0 +1,122 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef UTIL_ARRAY_H
#define UTIL_ARRAY_H
#include "util/u_memory.h"
#define DEFAULT_ARRAY_SIZE 256
struct array {
VGint datatype_size;
void *data;
VGint size;
VGint num_elements;
};
static INLINE struct array *array_create(VGint datatype_size)
{
struct array *array = CALLOC_STRUCT(array);
array->datatype_size = datatype_size;
array->size = DEFAULT_ARRAY_SIZE;
array->data = malloc(array->size * array->datatype_size);
return array;
}
static INLINE struct array *array_create_size(VGint datatype_size, VGint size)
{
struct array *array = CALLOC_STRUCT(array);
array->datatype_size = datatype_size;
array->size = size;
array->data = malloc(array->size * array->datatype_size);
return array;
}
static INLINE void array_destroy(struct array *array)
{
if (array)
free(array->data);
free(array);
}
static INLINE void array_resize(struct array *array, int num)
{
VGint size = array->datatype_size * num;
void *data = malloc(size);
memcpy(data, array->data, array->size * array->datatype_size);
free(array->data);
array->data = data;
array->size = num;
array->num_elements = (array->num_elements > num) ? num :
array->num_elements;
}
static INLINE void array_append_data(struct array *array,
const void *data, int num_elements)
{
VGbyte *adata;
while (array->num_elements + num_elements > array->size) {
array_resize(array, (array->num_elements + num_elements) * 1.5);
}
adata = (VGbyte *)array->data;
memcpy(adata + (array->num_elements * array->datatype_size), data,
num_elements * array->datatype_size);
array->num_elements += num_elements;
}
static INLINE void array_change_data(struct array *array,
const void *data,
int start_idx,
int num_elements)
{
VGbyte *adata = (VGbyte *)array->data;
memcpy(adata + (start_idx * array->datatype_size), data,
num_elements * array->datatype_size);
}
static INLINE void array_remove_element(struct array *array,
int idx)
{
VGbyte *adata = (VGbyte *)array->data;
memmove(adata + (idx * array->datatype_size),
adata + ((idx + 1) * array->datatype_size),
(array->num_elements - idx - 1) * array->datatype_size);
--array->num_elements;
}
static INLINE void array_reset(struct array *array)
{
array->num_elements = 0;
}
#endif

View File

@ -0,0 +1,543 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "vg_context.h"
#include "paint.h"
#include "renderer.h"
#include "shaders_cache.h"
#include "shader.h"
#include "asm_util.h"
#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "cso_cache/cso_context.h"
#include "util/u_simple_shaders.h"
#include "util/u_memory.h"
#include "util/u_blit.h"
struct vg_context *_vg_context = 0;
struct vg_context * vg_current_context(void)
{
return _vg_context;
}
static void init_clear(struct vg_context *st)
{
struct pipe_context *pipe = st->pipe;
/* rasterizer state: bypass clipping */
memset(&st->clear.raster, 0, sizeof(st->clear.raster));
st->clear.raster.gl_rasterization_rules = 1;
/* fragment shader state: color pass-through program */
st->clear.fs =
util_make_fragment_passthrough_shader(pipe);
}
void vg_set_current_context(struct vg_context *ctx)
{
_vg_context = ctx;
}
struct vg_context * vg_create_context(struct pipe_context *pipe,
const void *visual,
struct vg_context *share)
{
struct vg_context *ctx;
ctx = CALLOC_STRUCT(vg_context);
ctx->pipe = pipe;
vg_init_state(&ctx->state.vg);
ctx->state.dirty = ALL_DIRTY;
ctx->cso_context = cso_create_context(pipe);
init_clear(ctx);
ctx->default_paint = paint_create(ctx);
ctx->state.vg.stroke_paint = ctx->default_paint;
ctx->state.vg.fill_paint = ctx->default_paint;
ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->mask.sampler.normalized_coords = 0;
ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->blend_sampler.normalized_coords = 0;
vg_set_error(ctx, VG_NO_ERROR);
ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create();
ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create();
ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create();
ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create();
ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create();
ctx->renderer = renderer_create(ctx);
ctx->sc = shaders_cache_create(ctx);
ctx->shader = shader_create(ctx);
ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context);
return ctx;
}
void vg_destroy_context(struct vg_context *ctx)
{
struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
struct pipe_constant_buffer *vsbuf = &ctx->vs_const_buffer;
util_destroy_blit(ctx->blit);
renderer_destroy(ctx->renderer);
shaders_cache_destroy(ctx->sc);
shader_destroy(ctx->shader);
paint_destroy(ctx->default_paint);
if (cbuf && cbuf->buffer)
pipe_buffer_reference(&cbuf->buffer, NULL);
if (vsbuf && vsbuf->buffer)
pipe_buffer_reference(&vsbuf->buffer, NULL);
if (ctx->clear.fs) {
cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
ctx->clear.fs = NULL;
}
if (ctx->plain_vs) {
vg_shader_destroy(ctx, ctx->plain_vs);
ctx->plain_vs = NULL;
}
if (ctx->clear_vs) {
vg_shader_destroy(ctx, ctx->clear_vs);
ctx->clear_vs = NULL;
}
if (ctx->texture_vs) {
vg_shader_destroy(ctx, ctx->texture_vs);
ctx->texture_vs = NULL;
}
if (ctx->pass_through_depth_fs)
vg_shader_destroy(ctx, ctx->pass_through_depth_fs);
if (ctx->mask.union_fs)
vg_shader_destroy(ctx, ctx->mask.union_fs);
if (ctx->mask.intersect_fs)
vg_shader_destroy(ctx, ctx->mask.intersect_fs);
if (ctx->mask.subtract_fs)
vg_shader_destroy(ctx, ctx->mask.subtract_fs);
if (ctx->mask.set_fs)
vg_shader_destroy(ctx, ctx->mask.set_fs);
cso_release_all(ctx->cso_context);
cso_destroy_context(ctx->cso_context);
cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]);
cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]);
cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]);
cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]);
cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]);
free(ctx);
}
void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
{
obj->type = type;
obj->ctx = ctx;
}
VGboolean vg_context_is_object_valid(struct vg_context *ctx,
enum vg_object_type type,
void *ptr)
{
if (ctx) {
struct cso_hash *hash = ctx->owned_objects[type];
if (!hash)
return VG_FALSE;
return cso_hash_contains(hash, (unsigned)(long)ptr);
}
return VG_FALSE;
}
void vg_context_add_object(struct vg_context *ctx,
enum vg_object_type type,
void *ptr)
{
if (ctx) {
struct cso_hash *hash = ctx->owned_objects[type];
if (!hash)
return;
cso_hash_insert(hash, (unsigned)(long)ptr, ptr);
}
}
void vg_context_remove_object(struct vg_context *ctx,
enum vg_object_type type,
void *ptr)
{
if (ctx) {
struct cso_hash *hash = ctx->owned_objects[type];
if (!hash)
return;
cso_hash_take(hash, (unsigned)(long)ptr);
}
}
static void update_clip_state(struct vg_context *ctx)
{
struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa;
struct vg_state *state = &ctx->state.vg;
memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
if (state->scissoring) {
struct pipe_blend_state *blend = &ctx->state.g3d.blend;
struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/
dsa->depth.func = PIPE_FUNC_ALWAYS;
dsa->depth.enabled = 1;
cso_save_blend(ctx->cso_context);
cso_save_fragment_shader(ctx->cso_context);
/* set a passthrough shader */
if (!ctx->pass_through_depth_fs)
ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe,
pass_through_depth_asm,
40,
PIPE_SHADER_FRAGMENT);
cso_set_fragment_shader_handle(ctx->cso_context,
ctx->pass_through_depth_fs->driver);
cso_set_depth_stencil_alpha(ctx->cso_context, dsa);
ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
/* disable color writes */
blend->colormask = 0; /*disable colorwrites*/
cso_set_blend(ctx->cso_context, blend);
/* enable scissoring */
for (int i = 0; i < state->scissor_rects_num; ++i) {
const float x = state->scissor_rects[i * 4 + 0].f;
const float y = state->scissor_rects[i * 4 + 1].f;
const float width = state->scissor_rects[i * 4 + 2].f;
const float height = state->scissor_rects[i * 4 + 3].f;
VGfloat minx, miny, maxx, maxy;
minx = 0;
miny = 0;
maxx = fb->width;
maxy = fb->height;
if (x > minx)
minx = x;
if (y > miny)
miny = y;
if (x + width < maxx)
maxx = x + width;
if (y + height < maxy)
maxy = y + height;
/* check for null space */
if (minx >= maxx || miny >= maxy)
minx = miny = maxx = maxy = 0;
/*glClear(GL_DEPTH_BUFFER_BIT);*/
renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f);
}
blend->colormask = 1; /*enable colorwrites*/
cso_restore_blend(ctx->cso_context);
cso_restore_fragment_shader(ctx->cso_context);
dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
dsa->depth.func = PIPE_FUNC_GEQUAL;
}
}
void vg_validate_state(struct vg_context *ctx)
{
if ((ctx->state.dirty & BLEND_DIRTY)) {
struct pipe_blend_state *blend = &ctx->state.g3d.blend;
memset(blend, 0, sizeof(struct pipe_blend_state));
blend->blend_enable = 1;
blend->colormask |= PIPE_MASK_R;
blend->colormask |= PIPE_MASK_G;
blend->colormask |= PIPE_MASK_B;
blend->colormask |= PIPE_MASK_A;
switch (ctx->state.vg.blend_mode) {
case VG_BLEND_SRC:
blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
break;
case VG_BLEND_SRC_OVER:
blend->rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
break;
case VG_BLEND_DST_OVER:
blend->rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
blend->alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
break;
case VG_BLEND_SRC_IN:
blend->rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
blend->alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
break;
case VG_BLEND_DST_IN:
blend->rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
blend->alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
break;
case VG_BLEND_MULTIPLY:
case VG_BLEND_SCREEN:
case VG_BLEND_DARKEN:
case VG_BLEND_LIGHTEN:
blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
break;
case VG_BLEND_ADDITIVE:
blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
break;
default:
assert(!"not implemented blend mode");
}
cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend);
}
if ((ctx->state.dirty & RASTERIZER_DIRTY)) {
struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer;
memset(raster, 0, sizeof(struct pipe_rasterizer_state));
raster->gl_rasterization_rules = 1;
cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer);
}
if ((ctx->state.dirty & VIEWPORT_DIRTY)) {
struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
const VGint param_bytes = 8 * sizeof(VGfloat);
VGfloat vs_consts[8] = {
2.f/fb->width, 2.f/fb->height, 1, 1,
-1, -1, 0, 0
};
struct pipe_constant_buffer *cbuf = &ctx->vs_const_buffer;
vg_set_viewport(ctx, VEGA_Y0_BOTTOM);
pipe_buffer_reference(&cbuf->buffer, NULL);
cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 16,
PIPE_BUFFER_USAGE_CONSTANT,
param_bytes);
if (cbuf->buffer) {
st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
0, param_bytes, vs_consts);
}
ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, cbuf);
}
if ((ctx->state.dirty & VS_DIRTY)) {
cso_set_vertex_shader_handle(ctx->cso_context,
vg_plain_vs(ctx));
}
/* must be last because it renders to the depth buffer*/
if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) {
update_clip_state(ctx);
cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa);
}
shader_set_masking(ctx->shader, ctx->state.vg.masking);
shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
ctx->state.dirty = NONE_DIRTY;
}
VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
{
struct vg_object *obj = ptr;
if (ptr && is_aligned(obj) && obj->type == type)
return VG_TRUE;
else
return VG_FALSE;
}
void vg_set_error(struct vg_context *ctx,
VGErrorCode code)
{
/*vgGetError returns the oldest error code provided by
* an API call on the current context since the previous
* call to vgGetError on that context (or since the creation
of the context).*/
if (ctx->_error == VG_NO_ERROR)
ctx->_error = code;
}
void vg_prepare_blend_surface(struct vg_context *ctx)
{
struct pipe_surface *dest_surface = NULL;
struct pipe_context *pipe = ctx->pipe;
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->strb;
/* first finish all pending rendering */
vgFinish();
dest_surface = pipe->screen->get_tex_surface(pipe->screen,
stfb->blend_texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* flip it, because we want to use it as a sampler */
util_blit_pixels_tex(ctx->blit,
strb->texture,
0, strb->height,
strb->width, 0,
dest_surface,
0, 0,
strb->width, strb->height,
0.0, PIPE_TEX_MIPFILTER_NEAREST);
if (dest_surface)
pipe_surface_reference(&dest_surface, NULL);
/* make sure it's complete */
vgFinish();
}
void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
{
struct pipe_surface *dest_surface = NULL;
struct pipe_context *pipe = ctx->pipe;
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->strb;
vg_validate_state(ctx);
/* first finish all pending rendering */
vgFinish();
dest_surface = pipe->screen->get_tex_surface(pipe->screen,
stfb->blend_texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
/* flip it, because we want to use it as a sampler */
util_blit_pixels_tex(ctx->blit,
stfb->alpha_mask,
0, strb->height,
strb->width, 0,
dest_surface,
0, 0,
strb->width, strb->height,
0.0, PIPE_TEX_MIPFILTER_NEAREST);
/* make sure it's complete */
vgFinish();
if (dest_surface)
pipe_surface_reference(&dest_surface, NULL);
}
void * vg_plain_vs(struct vg_context *ctx)
{
if (!ctx->plain_vs) {
ctx->plain_vs = shader_create_from_text(ctx->pipe,
vs_plain_asm,
200,
PIPE_SHADER_VERTEX);
}
return ctx->plain_vs->driver;
}
void * vg_clear_vs(struct vg_context *ctx)
{
if (!ctx->clear_vs) {
ctx->clear_vs = shader_create_from_text(ctx->pipe,
vs_clear_asm,
200,
PIPE_SHADER_VERTEX);
}
return ctx->clear_vs->driver;
}
void * vg_texture_vs(struct vg_context *ctx)
{
if (!ctx->texture_vs) {
ctx->texture_vs = shader_create_from_text(ctx->pipe,
vs_texture_asm,
200,
PIPE_SHADER_VERTEX);
}
return ctx->texture_vs->driver;
}
void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation)
{
struct pipe_viewport_state viewport;
struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
viewport.scale[0] = fb->width / 2.f;
viewport.scale[1] = fb->height / y_scale;
viewport.scale[2] = 1.0;
viewport.scale[3] = 1.0;
viewport.translate[0] = fb->width / 2.f;
viewport.translate[1] = fb->height / 2.f;
viewport.translate[2] = 0.0;
viewport.translate[3] = 0.0;
cso_set_viewport(ctx->cso_context, &viewport);
}

View File

@ -0,0 +1,292 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef VG_CONTEXT_H
#define VG_CONTEXT_H
#include "vg_state.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
#include "util/u_pointer.h"
#include "util/u_math.h"
#include "cso_cache/cso_hash.h"
#include "cso_cache/cso_context.h"
struct renderer;
struct shaders_cache;
struct shader;
struct vg_shader;
struct st_renderbuffer {
enum pipe_format format;
struct pipe_surface *surface;
struct pipe_texture *texture;
VGint width, height;
};
struct st_framebuffer {
VGint init_width, init_height;
struct st_renderbuffer *strb;
struct st_renderbuffer *dsrb;
struct pipe_texture *alpha_mask;
struct pipe_texture *blend_texture;
void *privateData;
};
enum vg_object_type {
VG_OBJECT_UNKNOWN = 0,
VG_OBJECT_PAINT,
VG_OBJECT_IMAGE,
VG_OBJECT_MASK,
VG_OBJECT_FONT,
VG_OBJECT_PATH,
VG_OBJECT_LAST
};
enum dirty_state {
NONE_DIRTY = 0<<0,
BLEND_DIRTY = 1<<1,
RASTERIZER_DIRTY = 1<<2,
VIEWPORT_DIRTY = 1<<3,
VS_DIRTY = 1<<4,
DEPTH_STENCIL_DIRTY = 1<<5,
ALL_DIRTY = BLEND_DIRTY | RASTERIZER_DIRTY |
VIEWPORT_DIRTY | VS_DIRTY | DEPTH_STENCIL_DIRTY
};
struct vg_context
{
struct pipe_context *pipe;
struct {
struct vg_state vg;
struct {
struct pipe_blend_state blend;
struct pipe_rasterizer_state rasterizer;
struct pipe_shader_state vs_state;
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_framebuffer_state fb;
} g3d;
VGbitfield dirty;
} state;
VGErrorCode _error;
struct st_framebuffer *draw_buffer;
struct cso_hash *owned_objects[VG_OBJECT_LAST];
struct {
struct pipe_shader_state vert_shader;
struct pipe_shader_state frag_shader;
struct pipe_rasterizer_state raster;
void *fs;
float vertices[4][2][4]; /**< vertex pos + color */
} clear;
struct {
struct pipe_constant_buffer cbuf;
struct pipe_sampler_state sampler;
struct vg_shader *union_fs;
struct vg_shader *intersect_fs;
struct vg_shader *subtract_fs;
struct vg_shader *set_fs;
} mask;
struct vg_shader *pass_through_depth_fs;
struct cso_context *cso_context;
struct pipe_buffer *stencil_quad;
VGfloat stencil_vertices[4][2][4];
struct renderer *renderer;
struct shaders_cache *sc;
struct shader *shader;
struct pipe_sampler_state blend_sampler;
struct {
struct pipe_constant_buffer buffer;
void *color_matrix_fs;
} filter;
struct vg_paint *default_paint;
struct blit_state *blit;
struct vg_shader *plain_vs;
struct vg_shader *clear_vs;
struct vg_shader *texture_vs;
struct pipe_constant_buffer vs_const_buffer;
};
struct vg_object {
enum vg_object_type type;
struct vg_context *ctx;
};
void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type);
VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type);
struct vg_context *vg_create_context(struct pipe_context *pipe,
const void *visual,
struct vg_context *share);
void vg_destroy_context(struct vg_context *ctx);
struct vg_context *vg_current_context(void);
void vg_set_current_context(struct vg_context *ctx);
VGboolean vg_context_is_object_valid(struct vg_context *ctx,
enum vg_object_type type,
void *ptr);
void vg_context_add_object(struct vg_context *ctx,
enum vg_object_type type,
void *ptr);
void vg_context_remove_object(struct vg_context *ctx,
enum vg_object_type type,
void *ptr);
void vg_validate_state(struct vg_context *ctx);
void vg_set_error(struct vg_context *ctx,
VGErrorCode code);
void vg_prepare_blend_surface(struct vg_context *ctx);
void vg_prepare_blend_surface_from_mask(struct vg_context *ctx);
static INLINE VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
{
void *aligned = align_pointer(ptr, alignment);
return (ptr == aligned) ? VG_TRUE : VG_FALSE;
}
static INLINE VGboolean is_aligned(const void *ptr)
{
return is_aligned_to(ptr, 4);
}
static INLINE void vg_shift_rectx(VGfloat coords[4],
const VGfloat *bounds,
const VGfloat shift)
{
coords[0] += shift;
coords[2] -= shift;
if (bounds) {
coords[2] = MIN2(coords[2], bounds[2]);
/* bound x/y + width/height */
if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
coords[2] = (bounds[0] + bounds[2]) - coords[0];
}
}
}
static INLINE void vg_shift_recty(VGfloat coords[4],
const VGfloat *bounds,
const VGfloat shift)
{
coords[1] += shift;
coords[3] -= shift;
if (bounds) {
coords[3] = MIN2(coords[3], bounds[3]);
if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
coords[3] = (bounds[1] + bounds[3]) - coords[1];
}
}
}
static INLINE void vg_bound_rect(VGfloat coords[4],
const VGfloat bounds[4],
VGfloat shift[4])
{
/* if outside the bounds */
if (coords[0] > (bounds[0] + bounds[2]) ||
coords[1] > (bounds[1] + bounds[3]) ||
(coords[0] + coords[2]) < bounds[0] ||
(coords[1] + coords[3]) < bounds[1]) {
coords[0] = 0.f;
coords[1] = 0.f;
coords[2] = 0.f;
coords[3] = 0.f;
shift[0] = 0.f;
shift[1] = 0.f;
return;
}
/* bound x */
if (coords[0] < bounds[0]) {
shift[0] = bounds[0] - coords[0];
coords[2] -= shift[0];
coords[0] = bounds[0];
} else
shift[0] = 0.f;
/* bound y */
if (coords[1] < bounds[1]) {
shift[1] = bounds[1] - coords[1];
coords[3] -= shift[1];
coords[1] = bounds[1];
} else
shift[1] = 0.f;
shift[2] = bounds[2] - coords[2];
shift[3] = bounds[3] - coords[3];
/* bound width/height */
coords[2] = MIN2(coords[2], bounds[2]);
coords[3] = MIN2(coords[3], bounds[3]);
/* bound x/y + width/height */
if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
coords[2] = (bounds[0] + bounds[2]) - coords[0];
}
if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
coords[3] = (bounds[1] + bounds[3]) - coords[1];
}
/* if outside the bounds */
if ((coords[0] + coords[2]) < bounds[0] ||
(coords[1] + coords[3]) < bounds[1]) {
coords[0] = 0.f;
coords[1] = 0.f;
coords[2] = 0.f;
coords[3] = 0.f;
return;
}
}
void *vg_plain_vs(struct vg_context *ctx);
void *vg_clear_vs(struct vg_context *ctx);
void *vg_texture_vs(struct vg_context *ctx);
typedef enum {
VEGA_Y0_TOP,
VEGA_Y0_BOTTOM
} VegaOrientation;
void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation);
#endif

View File

@ -0,0 +1,124 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "vg_state.h"
#include <string.h>
void vg_init_state(struct vg_state *state)
{
state->matrix_mode = VG_MATRIX_PATH_USER_TO_SURFACE;
state->fill_rule = VG_EVEN_ODD;
state->image_quality = VG_IMAGE_QUALITY_FASTER;
state->rendering_quality = VG_RENDERING_QUALITY_BETTER;
state->blend_mode = VG_BLEND_SRC_OVER;
state->image_mode = VG_DRAW_IMAGE_NORMAL;
memset(state->scissor_rects, 0, sizeof(state->scissor_rects));
state->scissor_rects_num = 0;
state->color_transform = VG_FALSE;
state->color_transform_values[0] = 1.0f;
state->color_transform_values[1] = 1.0f;
state->color_transform_values[2] = 1.0f;
state->color_transform_values[3] = 1.0f;
state->color_transform_values[4] = 0.0f;
state->color_transform_values[5] = 0.0f;
state->color_transform_values[6] = 0.0f;
state->color_transform_values[7] = 0.0f;
/* Stroke parameters */
state->stroke.line_width.f = 1.0f;
state->stroke.line_width.i = 1;
state->stroke.cap_style = VG_CAP_BUTT;
state->stroke.join_style = VG_JOIN_MITER;
state->stroke.miter_limit.f = 4.0f;
state->stroke.miter_limit.i = 4;
state->stroke.dash_pattern_num = 0;
state->stroke.dash_phase.f = 0.0f;
state->stroke.dash_phase.i = 0;
state->stroke.dash_phase_reset = VG_FALSE;
/* Edge fill color for VG_TILE_FILL tiling mode */
state->tile_fill_color[0] = 0.0f;
state->tile_fill_color[1] = 0.0f;
state->tile_fill_color[2] = 0.0f;
state->tile_fill_color[3] = 0.0f;
/* Color for vgClear */
state->clear_color[0] = 0.0f;
state->clear_color[1] = 0.0f;
state->clear_color[2] = 0.0f;
state->clear_color[3] = 0.0f;
/* Glyph origin */
state->glyph_origin[0].f = 0.0f;
state->glyph_origin[1].f = 0.0f;
state->glyph_origin[0].i = 0;
state->glyph_origin[1].i = 0;
/* Enable/disable alpha masking and scissoring */
state->masking = VG_FALSE;
state->scissoring = VG_FALSE;
/* Pixel layout information */
state->pixel_layout = VG_PIXEL_LAYOUT_UNKNOWN;
state->screen_layout = VG_PIXEL_LAYOUT_UNKNOWN;
/* Source format selection for image filters */
state->filter_format_linear = VG_FALSE;
state->filter_format_premultiplied = VG_FALSE;
/* Destination write enable mask for image filters */
state->filter_channel_mask = (VG_RED | VG_GREEN | VG_BLUE | VG_ALPHA);
matrix_load_identity(&state->path_user_to_surface_matrix);
matrix_load_identity(&state->image_user_to_surface_matrix);
matrix_load_identity(&state->fill_paint_to_user_matrix);
matrix_load_identity(&state->stroke_paint_to_user_matrix);
matrix_load_identity(&state->glyph_user_to_surface_matrix);
}
struct matrix *vg_state_matrix(struct vg_state *state)
{
switch(state->matrix_mode) {
case VG_MATRIX_PATH_USER_TO_SURFACE:
return &state->path_user_to_surface_matrix;
case VG_MATRIX_IMAGE_USER_TO_SURFACE:
return &state->image_user_to_surface_matrix;
case VG_MATRIX_FILL_PAINT_TO_USER:
return &state->fill_paint_to_user_matrix;
case VG_MATRIX_STROKE_PAINT_TO_USER:
return &state->stroke_paint_to_user_matrix;
#ifdef OPENVG_VERSION_1_1
case VG_MATRIX_GLYPH_USER_TO_SURFACE:
return &state->glyph_user_to_surface_matrix;
#endif
default:
break;
}
return NULL;
}

View File

@ -0,0 +1,109 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef VG_STATE_H
#define VG_STATE_H
#include "VG/openvg.h"
#include "api_consts.h"
#include "matrix.h"
struct vg_value
{
VGfloat f;
VGint i;
};
struct vg_state {
/* Mode settings */
VGMatrixMode matrix_mode;
VGFillRule fill_rule;
VGImageQuality image_quality;
VGRenderingQuality rendering_quality;
VGBlendMode blend_mode;
VGImageMode image_mode;
/* Scissoring rectangles */
struct vg_value scissor_rects[32*4];
VGint scissor_rects_num;
/* Color Transformation */
VGboolean color_transform;
VGfloat color_transform_values[8];
/* Stroke parameters */
struct {
struct vg_value line_width;
VGCapStyle cap_style;
VGJoinStyle join_style;
struct vg_value miter_limit;
struct vg_value dash_pattern[VEGA_MAX_DASH_COUNT];
VGint dash_pattern_num;
struct vg_value dash_phase;
VGboolean dash_phase_reset;
} stroke;
/* Edge fill color for VG_TILE_FILL tiling mode */
VGfloat tile_fill_color[4];
VGint tile_fill_colori[4];
/* Color for vgClear */
VGfloat clear_color[4];
VGint clear_colori[4];
/* Glyph origin */
struct vg_value glyph_origin[2];
/* Enable/disable alpha masking and scissoring */
VGboolean masking;
VGboolean scissoring;
/* Pixel layout information */
VGPixelLayout pixel_layout;
VGPixelLayout screen_layout;
/* Source format selection for image filters */
VGboolean filter_format_linear;
VGboolean filter_format_premultiplied;
/* Destination write enable mask for image filters */
VGbitfield filter_channel_mask;
struct matrix path_user_to_surface_matrix;
struct matrix image_user_to_surface_matrix;
struct matrix fill_paint_to_user_matrix;
struct matrix stroke_paint_to_user_matrix;
struct matrix glyph_user_to_surface_matrix;
struct vg_paint *stroke_paint;
struct vg_paint *fill_paint;
};
void vg_init_state(struct vg_state *state);
struct matrix * vg_state_matrix(struct vg_state *state);
#endif

View File

@ -0,0 +1,406 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "vg_context.h"
#include "vg_tracker.h"
#include "mask.h"
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
#include "pipe/p_screen.h"
#include "util/u_memory.h"
#include "util/u_math.h"
static struct pipe_texture *
create_texture(struct pipe_context *pipe, enum pipe_format format,
VGint width, VGint height)
{
struct pipe_texture templ;
memset(&templ, 0, sizeof(templ));
if (format != PIPE_FORMAT_NONE) {
templ.format = format;
}
else {
templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
}
templ.target = PIPE_TEXTURE_2D;
pf_get_block(templ.format, &templ.block);
templ.width[0] = width;
templ.height[0] = height;
templ.depth[0] = 1;
templ.last_level = 0;
if (pf_get_component_bits(format, PIPE_FORMAT_COMP_S)) {
templ.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
} else {
templ.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_RENDER_TARGET |
PIPE_TEXTURE_USAGE_SAMPLER);
}
return pipe->screen->texture_create(pipe->screen, &templ);
}
/**
* Allocate a renderbuffer for a an on-screen window (not a user-created
* renderbuffer). The window system code determines the format.
*/
static struct st_renderbuffer *
st_new_renderbuffer_fb(enum pipe_format format)
{
struct st_renderbuffer *strb;
strb = CALLOC_STRUCT(st_renderbuffer);
if (!strb) {
/*_vega_error(NULL, VG_OUT_OF_MEMORY, "creating renderbuffer");*/
return NULL;
}
strb->format = format;
return strb;
}
/**
* This is called to allocate the original drawing surface, and
* during window resize.
*/
static VGboolean
st_renderbuffer_alloc_storage(struct vg_context * ctx,
struct st_renderbuffer *strb,
VGuint width, VGuint height)
{
struct pipe_context *pipe = ctx->pipe;
unsigned surface_usage;
/* Free the old surface and texture
*/
pipe_surface_reference(&strb->surface, NULL);
pipe_texture_reference(&strb->texture, NULL);
/* Probably need dedicated flags for surface usage too:
*/
surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE);
strb->texture = create_texture(pipe, strb->format,
width, height);
if (!strb->texture)
return FALSE;
strb->surface = pipe->screen->get_tex_surface(pipe->screen,
strb->texture,
0, 0, 0,
surface_usage);
strb->width = width;
strb->height = height;
assert(strb->surface->width == width);
assert(strb->surface->height == height);
return strb->surface != NULL;
}
struct vg_context * st_create_context(struct pipe_context *pipe,
const void *visual,
struct vg_context *share)
{
struct vg_context *ctx = vg_create_context(pipe, visual, share);
/*debug_printf("--------- CREATE CONTEXT %p\n", ctx);*/
return ctx;
}
void st_destroy_context(struct vg_context *st)
{
/*debug_printf("--------- DESTROY CONTEXT %p\n", st);*/
vg_destroy_context(st);
}
void st_copy_context_state(struct vg_context *dst, struct vg_context *src,
uint mask)
{
fprintf(stderr, "FIXME: %s\n", __FUNCTION__);
}
void st_get_framebuffer_dimensions(struct st_framebuffer *stfb,
uint *width,
uint *height)
{
*width = stfb->strb->width;
*height = stfb->strb->height;
}
struct st_framebuffer * st_create_framebuffer(const void *visual,
enum pipe_format colorFormat,
enum pipe_format depthFormat,
enum pipe_format stencilFormat,
uint width, uint height,
void *privateData)
{
struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer);
if (stfb) {
struct st_renderbuffer *rb =
st_new_renderbuffer_fb(colorFormat);
stfb->strb = rb;
#if 0
if (doubleBuffer) {
struct st_renderbuffer *rb =
st_new_renderbuffer_fb(colorFormat);
}
#endif
/* we want to combine the depth/stencil */
if (stencilFormat == depthFormat)
stfb->dsrb = st_new_renderbuffer_fb(stencilFormat);
else
stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_S8Z24_UNORM);
/*### currently we always allocate it but it's possible it's
not necessary if EGL_ALPHA_MASK_SIZE was 0
*/
stfb->alpha_mask = 0;
stfb->init_width = width;
stfb->init_height = height;
stfb->privateData = privateData;
}
return stfb;
}
static void setup_new_alpha_mask(struct vg_context *ctx,
struct st_framebuffer *stfb,
uint width, uint height)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_texture *old_texture = stfb->alpha_mask;
/*
we use PIPE_FORMAT_A8R8G8B8_UNORM because we want to render to
this texture and use it as a sampler, so while this wastes some
space it makes both of those a lot simpler
*/
stfb->alpha_mask =
create_texture(pipe, PIPE_FORMAT_A8R8G8B8_UNORM, width, height);
if (!stfb->alpha_mask) {
if (old_texture)
pipe_texture_reference(&old_texture, NULL);
return;
}
vg_validate_state(ctx);
/* alpha mask starts with 1.f alpha */
mask_fill(0, 0, width, height, 1.f);
/* if we had an old surface copy it over */
if (old_texture) {
struct pipe_surface *surface = pipe->screen->get_tex_surface(
pipe->screen,
stfb->alpha_mask,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
struct pipe_surface *old_surface = pipe->screen->get_tex_surface(
pipe->screen,
old_texture,
0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ);
pipe->surface_copy(pipe,
surface,
0, 0,
old_surface,
0, 0,
MIN2(old_surface->width, width),
MIN2(old_surface->height, height));
if (surface)
pipe_surface_reference(&surface, NULL);
if (old_surface)
pipe_surface_reference(&old_surface, NULL);
}
/* Free the old texture
*/
if (old_texture)
pipe_texture_reference(&old_texture, NULL);
}
void st_resize_framebuffer(struct st_framebuffer *stfb,
uint width, uint height)
{
struct vg_context *ctx = vg_current_context();
struct st_renderbuffer *strb = stfb->strb;
struct pipe_framebuffer_state *state;
if (!ctx)
return;
state = &ctx->state.g3d.fb;
/* If this is a noop, exit early and don't do the clear, etc below.
*/
if (strb->width == width &&
strb->height == height &&
state->zsbuf)
return;
if (strb->width != width || strb->height != height)
st_renderbuffer_alloc_storage(ctx, strb,
width, height);
if (stfb->dsrb->width != width || stfb->dsrb->height != height)
st_renderbuffer_alloc_storage(ctx, stfb->dsrb,
width, height);
{
VGuint i;
memset(state, 0, sizeof(struct pipe_framebuffer_state));
state->width = width;
state->height = height;
state->nr_cbufs = 1;
state->cbufs[0] = strb->surface;
for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
state->cbufs[i] = 0;
state->zsbuf = stfb->dsrb->surface;
cso_set_framebuffer(ctx->cso_context, state);
}
ctx->state.dirty |= VIEWPORT_DIRTY;
ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/
ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL,
NULL, 0.0, 0);
/* we need all the other state already set */
setup_new_alpha_mask(ctx, stfb, width, height);
pipe_texture_reference( &stfb->blend_texture, NULL );
stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_A8R8G8B8_UNORM,
width, height);
}
void st_set_framebuffer_surface(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_surface *surf)
{
struct st_renderbuffer *rb = stfb->strb;
/* unreference existing surfaces */
pipe_surface_reference( &rb->surface, NULL );
pipe_texture_reference( &rb->texture, NULL );
/* reference new ones */
pipe_surface_reference( &rb->surface, surf );
pipe_texture_reference( &rb->texture, surf->texture );
rb->width = surf->width;
rb->height = surf->height;
}
int st_get_framebuffer_surface(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_surface **surf)
{
struct st_renderbuffer *rb = stfb->strb;
*surf = rb->surface;
return VG_TRUE;
}
int st_get_framebuffer_texture(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_texture **tex)
{
struct st_renderbuffer *rb = stfb->strb;
*tex = rb->texture;
return VG_TRUE;
}
void * st_framebuffer_private(struct st_framebuffer *stfb)
{
return stfb->privateData;
}
void st_unreference_framebuffer(struct st_framebuffer *stfb)
{
/* FIXME */
}
void st_make_current(struct vg_context *st,
struct st_framebuffer *draw,
struct st_framebuffer *read)
{
vg_set_current_context(st);
if (st) {
st->draw_buffer = draw;
}
}
void st_flush(struct vg_context *st, uint pipeFlushFlags,
struct pipe_fence_handle **fence)
{
st->pipe->flush(st->pipe, pipeFlushFlags, fence);
}
void st_finish(struct vg_context *st)
{
struct pipe_fence_handle *fence = NULL;
st_flush(st, PIPE_FLUSH_RENDER_CACHE, &fence);
st->pipe->screen->fence_finish(st->pipe->screen, fence, 0);
st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
}
void st_notify_swapbuffers(struct st_framebuffer *stfb)
{
struct vg_context *ctx = vg_current_context();
if (ctx && ctx->draw_buffer == stfb) {
st_flush(ctx,
PIPE_FLUSH_RENDER_CACHE |
PIPE_FLUSH_SWAPBUFFERS |
PIPE_FLUSH_FRAME,
NULL);
}
}
void st_notify_swapbuffers_complete(struct st_framebuffer *stfb)
{
}
int
st_set_teximage(struct pipe_texture *pt, int target)
{
return 0;
}

View File

@ -0,0 +1,102 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef VG_TRACKER_H
#define VG_TRACKER_H
#include "VG/openvg.h"
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#define ST_SURFACE_FRONT_LEFT 0
#define ST_SURFACE_BACK_LEFT 1
#define ST_SURFACE_FRONT_RIGHT 2
#define ST_SURFACE_BACK_RIGHT 3
#define ST_SURFACE_DEPTH 8
struct vg_context;
struct st_framebuffer;
struct pipe_context;
struct pipe_fence_handle;
struct pipe_surface;
struct vg_context *st_create_context(struct pipe_context *pipe,
const void *visual,
struct vg_context *share);
void st_destroy_context( struct vg_context *st );
void st_copy_context_state(struct vg_context *dst, struct vg_context *src,
uint mask);
struct st_framebuffer *st_create_framebuffer(const void *visual,
enum pipe_format colorFormat,
enum pipe_format depthFormat,
enum pipe_format stencilFormat,
uint width, uint height,
void *privateData);
void st_resize_framebuffer(struct st_framebuffer *stfb,
uint width, uint height);
void st_set_framebuffer_surface(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_surface *surf);
void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
uint *width, uint *height);
int st_set_teximage(struct pipe_texture *pt, int target);
int st_get_framebuffer_surface(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_surface **surf);
int st_get_framebuffer_texture(struct st_framebuffer *stfb,
uint surfIndex, struct pipe_texture **tex);
void *st_framebuffer_private(struct st_framebuffer *stfb);
void st_unreference_framebuffer(struct st_framebuffer *stfb);
void st_make_current(struct vg_context *st,
struct st_framebuffer *draw,
struct st_framebuffer *read);
void st_flush(struct vg_context *st, uint pipeFlushFlags,
struct pipe_fence_handle **fence);
void st_finish(struct vg_context *st);
void st_notify_swapbuffers(struct st_framebuffer *stfb);
void st_notify_swapbuffers_complete(struct st_framebuffer *stfb);
/** Generic function type */
typedef void (*st_proc)();
st_proc st_get_proc_address(const char *procname);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef VG_TRANSLATE_H
#define VG_TRANSLATE_H
#include "VG/openvg.h"
#include "vg_context.h"
/*FIXME: we really should be using translate module
* but pipe_format can't express some of the VG formats
* (the premultiplied ones) so currently it won't work */
void _vega_pack_rgba_span_float(struct vg_context *ctx,
VGuint n, VGfloat rgba[][4],
VGImageFormat dstFormat,
void *dstAddr);
void _vega_unpack_float_span_rgba(struct vg_context *ctx,
VGuint n,
VGuint offset,
const void * data,
VGImageFormat dataFormat,
VGfloat rgba[][4]);
VGint _vega_size_for_format(VGImageFormat format);
#endif

View File

@ -0,0 +1,450 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "VG/openvg.h"
#include "VG/vgu.h"
#include "matrix.h"
#include "path.h"
#include "util/u_debug.h"
#include "util/u_pointer.h"
#include <math.h>
#include <assert.h>
static VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
{
void *aligned = align_pointer(ptr, alignment);
return (ptr == aligned) ? VG_TRUE : VG_FALSE;
}
static VGboolean is_aligned(const void *ptr)
{
return is_aligned_to(ptr, 4);
}
static void vgu_append_float_coords(VGPath path,
const VGubyte *cmds,
VGint num_cmds,
const VGfloat *coords,
VGint num_coords)
{
VGubyte common_data[40 * sizeof(VGfloat)];
struct path *p = (struct path *)path;
vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords);
vgAppendPathData(path, num_cmds, cmds, common_data);
}
VGUErrorCode vguLine(VGPath path,
VGfloat x0, VGfloat y0,
VGfloat x1, VGfloat y1)
{
static const VGubyte cmds[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS};
VGfloat coords[4];
VGbitfield caps;
if (path == VG_INVALID_HANDLE) {
return VGU_BAD_HANDLE_ERROR;
}
caps = vgGetPathCapabilities(path);
if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
return VGU_PATH_CAPABILITY_ERROR;
}
coords[0] = x0;
coords[1] = y0;
coords[2] = x1;
coords[3] = y1;
vgu_append_float_coords(path, cmds, 2, coords, 4);
return VGU_NO_ERROR;
}
VGUErrorCode vguPolygon(VGPath path,
const VGfloat * points,
VGint count,
VGboolean closed)
{
VGubyte *cmds;
VGfloat *coords;
VGbitfield caps;
VGint i;
if (path == VG_INVALID_HANDLE) {
return VGU_BAD_HANDLE_ERROR;
}
if (!points || count <= 0 || !is_aligned(points)) {
return VGU_ILLEGAL_ARGUMENT_ERROR;
}
caps = vgGetPathCapabilities(path);
if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
return VGU_PATH_CAPABILITY_ERROR;
}
cmds = malloc(sizeof(VGubyte) * count + 1);
coords = malloc(sizeof(VGfloat) * count * 2);
cmds[0] = VG_MOVE_TO_ABS;
coords[0] = points[0];
coords[1] = points[1];
for (i = 1; i < count; ++i) {
cmds[i] = VG_LINE_TO_ABS;
coords[2*i + 0] = points[2*i + 0];
coords[2*i + 1] = points[2*i + 1];
}
if (closed) {
cmds[i] = VG_CLOSE_PATH;
++i;
}
vgu_append_float_coords(path, cmds, i, coords, 2*i);
free(cmds);
free(coords);
return VGU_NO_ERROR;
}
VGUErrorCode vguRect(VGPath path,
VGfloat x, VGfloat y,
VGfloat width, VGfloat height)
{
static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_VLINE_TO_REL,
VG_HLINE_TO_REL,
VG_CLOSE_PATH
};
VGfloat coords[5];
VGbitfield caps;
if (path == VG_INVALID_HANDLE) {
return VGU_BAD_HANDLE_ERROR;
}
caps = vgGetPathCapabilities(path);
if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
return VGU_PATH_CAPABILITY_ERROR;
}
if (width <= 0 || height <= 0) {
return VGU_ILLEGAL_ARGUMENT_ERROR;
}
coords[0] = x;
coords[1] = y;
coords[2] = width;
coords[3] = height;
coords[4] = -width;
vgu_append_float_coords(path, cmds, 5, coords, 5);
return VGU_NO_ERROR;
}
VGUErrorCode vguRoundRect(VGPath path,
VGfloat x, VGfloat y,
VGfloat width,
VGfloat height,
VGfloat arcWidth,
VGfloat arcHeight)
{
static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_CLOSE_PATH
};
VGfloat c[26];
VGbitfield caps;
if (path == VG_INVALID_HANDLE) {
return VGU_BAD_HANDLE_ERROR;
}
caps = vgGetPathCapabilities(path);
if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
return VGU_PATH_CAPABILITY_ERROR;
}
if (width <= 0 || height <= 0) {
return VGU_ILLEGAL_ARGUMENT_ERROR;
}
c[0] = x + arcWidth/2; c[1] = y;
c[2] = width - arcWidth;
c[3] = arcWidth/2; c[4] = arcHeight/2; c[5] = 0;
c[6] = arcWidth/2; c[7] = arcHeight/2;
c[8] = height - arcHeight;
c[9] = arcWidth/2; c[10] = arcHeight/2; c[11] = 0;
c[12] = -arcWidth/2; c[13] = arcHeight/2;
c[14] = -(width - arcWidth);
c[15] = arcWidth/2; c[16] = arcHeight/2; c[17] = 0;
c[18] = -arcWidth/2; c[19] = -arcHeight/2;
c[20] = -(height - arcHeight);
c[21] = arcWidth/2; c[22] = arcHeight/2; c[23] = 0;
c[24] = arcWidth/2; c[25] = -arcHeight/2;
vgu_append_float_coords(path, cmds, 10, c, 26);
return VGU_NO_ERROR;
}
VGUErrorCode vguEllipse(VGPath path,
VGfloat cx, VGfloat cy,
VGfloat width,
VGfloat height)
{
static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
VG_SCCWARC_TO_REL,
VG_SCCWARC_TO_REL,
VG_CLOSE_PATH
};
VGfloat coords[12];
VGbitfield caps;
if (path == VG_INVALID_HANDLE) {
return VGU_BAD_HANDLE_ERROR;
}
caps = vgGetPathCapabilities(path);
if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
return VGU_PATH_CAPABILITY_ERROR;
}
if (width <= 0 || height <= 0) {
return VGU_ILLEGAL_ARGUMENT_ERROR;
}
coords[0] = cx + width/2; coords[1] = cy;
coords[2] = width/2; coords[3] = height/2; coords[4] = 0;
coords[5] = -width; coords[6] = 0;
coords[7] = width/2; coords[8] = height/2; coords[9] = 0;
coords[10] = width; coords[11] = 0;
vgu_append_float_coords(path, cmds, 4, coords, 11);
return VGU_NO_ERROR;
}
VGUErrorCode vguArc(VGPath path,
VGfloat x, VGfloat y,
VGfloat width, VGfloat height,
VGfloat startAngle,
VGfloat angleExtent,
VGUArcType arcType)
{
VGubyte cmds[11];
VGfloat coords[40];
VGbitfield caps;
VGfloat last = startAngle + angleExtent;
VGint i, c = 0;
if (path == VG_INVALID_HANDLE) {
return VGU_BAD_HANDLE_ERROR;
}
caps = vgGetPathCapabilities(path);
if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
return VGU_PATH_CAPABILITY_ERROR;
}
if (width <= 0 || height <= 0) {
return VGU_ILLEGAL_ARGUMENT_ERROR;
}
if (arcType != VGU_ARC_OPEN &&
arcType != VGU_ARC_CHORD &&
arcType != VGU_ARC_PIE) {
return VGU_ILLEGAL_ARGUMENT_ERROR;
}
cmds[c] = VG_MOVE_TO_ABS; ++c;
coords[0] = x+cos(DEGREES_TO_RADIANS(startAngle))*width/2;
coords[1] = y+sin(DEGREES_TO_RADIANS(startAngle))*height/2;
#ifdef DEBUG_VGUARC
debug_printf("start [%f, %f]\n", coords[0], coords[1]);
#endif
i = 2;
if (angleExtent > 0) {
VGfloat angle = startAngle + 180;
while (angle < last) {
cmds[c] = VG_SCCWARC_TO_ABS; ++c;
coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle))*width/2;
coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle))*height/2;
#ifdef DEBUG_VGUARC
debug_printf("1 [%f, %f]\n", coords[i+3],
coords[i+4]);
#endif
i += 5;
angle += 180;
}
cmds[c] = VG_SCCWARC_TO_ABS; ++c;
coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
coords[i+3] = x+cos(DEGREES_TO_RADIANS(last))*width/2;
coords[i+4] = y+sin(DEGREES_TO_RADIANS(last))*height/2;
#ifdef DEBUG_VGUARC
debug_printf("2 [%f, %f]\n", coords[i+3],
coords[i+4]);
#endif
i += 5;
} else {
VGfloat angle = startAngle - 180;
while (angle > last) {
cmds[c] = VG_SCWARC_TO_ABS; ++c;
coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle)) * width/2;
coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle)) * height/2;
#ifdef DEBUG_VGUARC
debug_printf("3 [%f, %f]\n", coords[i+3],
coords[i+4]);
#endif
angle -= 180;
i += 5;
}
cmds[c] = VG_SCWARC_TO_ABS; ++c;
coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
coords[i+3] = x + cos(DEGREES_TO_RADIANS(last)) * width/2;
coords[i+4] = y + sin(DEGREES_TO_RADIANS(last)) * height/2;
#ifdef DEBUG_VGUARC
debug_printf("4 [%f, %f]\n", coords[i+3],
coords[i+4]);
#endif
i += 5;
}
if (arcType == VGU_ARC_PIE) {
cmds[c] = VG_LINE_TO_ABS; ++c;
coords[i] = x; coords[i + 1] = y;
i += 2;
}
if (arcType == VGU_ARC_PIE || arcType == VGU_ARC_CHORD) {
cmds[c] = VG_CLOSE_PATH;
++c;
}
assert(c < 11);
vgu_append_float_coords(path, cmds, c, coords, i);
return VGU_NO_ERROR;
}
VGUErrorCode vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
VGfloat sx3, VGfloat sy3,
VGfloat * matrix)
{
struct matrix mat;
if (!matrix || !is_aligned(matrix))
return VGU_ILLEGAL_ARGUMENT_ERROR;
if (!matrix_quad_to_square(sx0, sy0,
sx1, sy1,
sx2, sy2,
sx3, sy3,
&mat))
return VGU_BAD_WARP_ERROR;
if (!matrix_is_invertible(&mat))
return VGU_BAD_WARP_ERROR;
memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
return VGU_NO_ERROR;
}
VGUErrorCode vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0,
VGfloat dx1, VGfloat dy1,
VGfloat dx2, VGfloat dy2,
VGfloat dx3, VGfloat dy3,
VGfloat * matrix)
{
struct matrix mat;
if (!matrix || !is_aligned(matrix))
return VGU_ILLEGAL_ARGUMENT_ERROR;
if (!matrix_square_to_quad(dx0, dy0,
dx1, dy1,
dx2, dy2,
dx3, dy3,
&mat))
return VGU_BAD_WARP_ERROR;
if (!matrix_is_invertible(&mat))
return VGU_BAD_WARP_ERROR;
memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
return VGU_NO_ERROR;
}
VGUErrorCode vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0,
VGfloat dx1, VGfloat dy1,
VGfloat dx2, VGfloat dy2,
VGfloat dx3, VGfloat dy3,
VGfloat sx0, VGfloat sy0,
VGfloat sx1, VGfloat sy1,
VGfloat sx2, VGfloat sy2,
VGfloat sx3, VGfloat sy3,
VGfloat * matrix)
{
struct matrix mat;
if (!matrix || !is_aligned(matrix))
return VGU_ILLEGAL_ARGUMENT_ERROR;
if (!matrix_quad_to_quad(dx0, dy0,
dx1, dy1,
dx2, dy2,
dx3, dy3,
sx0, sy0,
sx1, sy1,
sx2, sy2,
sx3, sy3,
&mat))
return VGU_BAD_WARP_ERROR;
memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
return VGU_NO_ERROR;
}