OpenVG 1.0 State Tracker
Import of the OpenVG 1.0 state tracker for Gallium.
This commit is contained in:
parent
fbceedd2de
commit
544dd4b11f
|
@ -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>
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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)
|
|
@ -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
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue