зеркало из https://github.com/mozilla/pjs.git
Merge from org.mozilla.cvs.cairo branch.
- Cairo 1.1.1 - Updated thebes, gfx/src/thebes - Fixes to plugins with thebes gfx under linux - Native theme fixes with thebes rendering (NOTE: widget changes only enabled when building with thebes, otherwise all old code)
This commit is contained in:
Родитель
04ff4a140c
Коммит
8994df8c7d
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -3932,6 +3932,7 @@ AC_SUBST(MOC)
|
|||
if test "$MOZ_ENABLE_CAIRO_GFX"
|
||||
then
|
||||
AC_DEFINE(MOZ_THEBES)
|
||||
AC_DEFINE(MOZ_CAIRO_GFX)
|
||||
fi
|
||||
|
||||
if test "$MOZ_ENABLE_GTK" \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Snapshots of cairo, libpixman, and glitz for mozilla usage. Where possible,
|
||||
Snapshots of cairo and glitz for mozilla usage. Where possible,
|
||||
these should be official releases from the cairo project as-is. If
|
||||
changes are necessary, they should be documented below and the patch
|
||||
file included in this directory.
|
||||
|
@ -10,29 +10,10 @@ http://www.cairographics.org/.
|
|||
|
||||
VERSIONS:
|
||||
|
||||
cairo 0.9.1
|
||||
libpixman 0.1.5
|
||||
glitz 0.4.0
|
||||
cairo 1.1.1 (cvs)
|
||||
glitz 0.5.0
|
||||
|
||||
***** NOTE FOR VISUAL C++ 6.0 *****
|
||||
|
||||
VC6 cannot build pixman correctly for various reasons. There is a static
|
||||
win32 pixman library provided in libpixman/src/pixman-vc71.lib that will
|
||||
be used instead of building on all Win32/Visual C++ builds. Building with
|
||||
VC7.1, gcc/mingw, or anything else other than VC6 is fine.
|
||||
|
||||
PATCHES:
|
||||
|
||||
stdint.h - select between inttypes.h, stdint.h, and mozstdint.h.
|
||||
|
||||
dash-dos.diff - prevent DOS attack with dasharray.
|
||||
|
||||
alphablend.diff - check for AlphaBlend usability at runtime (win32)
|
||||
|
||||
feature-tests.diff - change #if to #ifdef, and change
|
||||
cairo-features.h.in to #define things based on mozilla configure
|
||||
tests
|
||||
|
||||
allow-null-surface.diff - allow creating a cairo_t with a NULL
|
||||
target surface
|
||||
atsui-empty.diff - prevent OS-X crash with empty string
|
||||
VC6 cannot build pixman from cairo. Therefore, VC6 builds are not supported
|
||||
if cairo is enabled. Please upgrade to VC7.1/8.
|
||||
|
|
|
@ -43,6 +43,8 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
VISIBILITY_FLAGS =
|
||||
|
||||
MODULE = cairo
|
||||
LIBRARY_NAME = mozcairo
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
@ -79,6 +81,7 @@ CSRCS = \
|
|||
cairo-pen.c \
|
||||
cairo-polygon.c \
|
||||
cairo-region.c \
|
||||
cairo-scaled-font.c \
|
||||
cairo-slope.c \
|
||||
cairo-spline.c \
|
||||
cairo-surface.c \
|
||||
|
@ -87,7 +90,7 @@ CSRCS = \
|
|||
cairo-wideint.c \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = cairo.h cairo-features.h
|
||||
EXPORTS = cairo.h cairo-features.h cairo-platform.h
|
||||
|
||||
|
||||
ifeq ($(MOZ_GFX_TOOLKIT),windows)
|
||||
|
|
|
@ -100,27 +100,19 @@ _arc_max_angle_for_tolerance_normalized (double tolerance)
|
|||
return angle;
|
||||
}
|
||||
|
||||
/* XXX: The computation here if bogus. Correct math (with proof!) is
|
||||
* available in _cairo_pen_vertices_needed. */
|
||||
static int
|
||||
_arc_segments_needed (double angle,
|
||||
double radius,
|
||||
cairo_matrix_t *ctm,
|
||||
double tolerance)
|
||||
{
|
||||
double l1, l2, lmax;
|
||||
double max_angle;
|
||||
double major_axis, max_angle;
|
||||
|
||||
_cairo_matrix_compute_eigen_values (ctm, &l1, &l2);
|
||||
|
||||
l1 = fabs (l1);
|
||||
l2 = fabs (l2);
|
||||
if (l1 > l2)
|
||||
lmax = l1;
|
||||
else
|
||||
lmax = l2;
|
||||
|
||||
max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / (radius * lmax));
|
||||
/* the error is amplified by at most the length of the
|
||||
* major axis of the circle; see cairo-pen.c for a more detailed analysis
|
||||
* of this. */
|
||||
major_axis = _cairo_matrix_transformed_circle_major_axis (ctm, radius);
|
||||
max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / major_axis);
|
||||
|
||||
return (int) ceil (angle / max_angle);
|
||||
}
|
||||
|
|
|
@ -38,35 +38,85 @@
|
|||
#include "cairo-atsui.h"
|
||||
#include "cairoint.h"
|
||||
#include "cairo.h"
|
||||
#if 0
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
|
||||
* here so we can use older SDKs.
|
||||
*/
|
||||
#ifndef FixedToFloat
|
||||
#define fixed1 ((Fixed) 0x00010000L)
|
||||
#define FixedToFloat(a) ((float)(a) / fixed1)
|
||||
#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1))
|
||||
#endif
|
||||
typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
|
||||
typedef struct _cairo_atsui_font cairo_atsui_font_t;
|
||||
|
||||
typedef struct {
|
||||
static cairo_status_t _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
||||
ATSUFontID font_id,
|
||||
ATSUStyle style,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font_out);
|
||||
|
||||
struct _cairo_atsui_font {
|
||||
cairo_scaled_font_t base;
|
||||
|
||||
cairo_matrix_t scale;
|
||||
ATSUStyle style;
|
||||
ATSUStyle unscaled_style;
|
||||
ATSUFontID fontID;
|
||||
} cairo_atsui_font_t;
|
||||
};
|
||||
|
||||
|
||||
struct _cairo_atsui_font_face {
|
||||
cairo_font_face_t base;
|
||||
ATSUFontID font_id;
|
||||
};
|
||||
|
||||
static void
|
||||
_cairo_atsui_font_face_destroy (void *abstract_face)
|
||||
{
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_face_scaled_font_create (void *abstract_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font)
|
||||
{
|
||||
cairo_atsui_font_face_t *font_face = abstract_face;
|
||||
OSStatus err;
|
||||
ATSUAttributeTag styleTags[] = { kATSUFontTag };
|
||||
ATSUAttributeValuePtr styleValues[] = { &font_face->font_id };
|
||||
ByteCount styleSizes[] = { sizeof(ATSUFontID) };
|
||||
ATSUStyle style;
|
||||
|
||||
err = ATSUCreateStyle (&style);
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(styleTags) / sizeof(styleTags[0]),
|
||||
styleTags, styleSizes, styleValues);
|
||||
|
||||
return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
|
||||
font_matrix, ctm, options, font);
|
||||
}
|
||||
|
||||
static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
|
||||
_cairo_atsui_font_face_destroy,
|
||||
_cairo_atsui_font_face_scaled_font_create
|
||||
};
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
|
||||
{
|
||||
cairo_atsui_font_face_t *font_face;
|
||||
|
||||
font_face = malloc (sizeof (cairo_atsui_font_face_t));
|
||||
if (!font_face) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
font_face->font_id = font_id;
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_atsui_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
typedef struct cairo_ATSUI_glyph_path_callback_info_t {
|
||||
cairo_path_fixed_t *path;
|
||||
cairo_matrix_t scale;
|
||||
} cairo_ATSUI_glyph_path_callback_info_t;
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend;
|
||||
|
||||
static CGAffineTransform
|
||||
CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
|
||||
|
@ -82,7 +132,6 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
|
|||
ATSUStyle style;
|
||||
OSStatus err;
|
||||
|
||||
|
||||
// Set the style's size
|
||||
CGAffineTransform theTransform =
|
||||
CGAffineTransformMakeWithCairoFontScale(scale);
|
||||
|
@ -103,6 +152,86 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
|
|||
return style;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
|
||||
{
|
||||
ATSFontRef atsFont;
|
||||
ATSFontMetrics metrics;
|
||||
OSStatus err;
|
||||
|
||||
atsFont = FMGetATSFontRefFromFont(font->fontID);
|
||||
|
||||
if (atsFont) {
|
||||
err =
|
||||
ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault,
|
||||
&metrics);
|
||||
|
||||
if (err == noErr) {
|
||||
cairo_font_extents_t extents;
|
||||
|
||||
extents.ascent = metrics.ascent;
|
||||
extents.descent = metrics.descent;
|
||||
extents.height = metrics.capHeight;
|
||||
extents.max_x_advance = metrics.maxAdvanceWidth;
|
||||
|
||||
// The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
|
||||
extents.max_y_advance = 0.0;
|
||||
|
||||
_cairo_scaled_font_set_metrics (&font->base, &extents);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
||||
ATSUFontID font_id,
|
||||
ATSUStyle style,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font_out)
|
||||
{
|
||||
cairo_atsui_font_t *font = NULL;
|
||||
cairo_matrix_t scale;
|
||||
OSStatus err;
|
||||
cairo_status_t status;
|
||||
|
||||
font = malloc(sizeof(cairo_atsui_font_t));
|
||||
|
||||
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
|
||||
&cairo_atsui_scaled_font_backend);
|
||||
|
||||
cairo_matrix_multiply(&scale, font_matrix, ctm);
|
||||
font->style = CreateSizedCopyOfStyle(style, &scale);
|
||||
|
||||
Fixed theSize = FloatToFixed(1.0);
|
||||
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
|
||||
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
|
||||
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(theFontStyleTags) /
|
||||
sizeof(ATSUAttributeTag), theFontStyleTags,
|
||||
theFontStyleSizes, theFontStyleValues);
|
||||
|
||||
font->unscaled_style = style;
|
||||
|
||||
font->fontID = font_id;
|
||||
font->scale = scale;
|
||||
|
||||
*font_out = &font->base;
|
||||
|
||||
status = _cairo_atsui_font_set_metrics (font);
|
||||
if (status) {
|
||||
cairo_scaled_font_destroy (&font->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
||||
|
@ -111,12 +240,10 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
|||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font_out)
|
||||
{
|
||||
cairo_atsui_font_t *font = NULL;
|
||||
ATSUStyle style;
|
||||
ATSUFontID fontID;
|
||||
OSStatus err;
|
||||
Boolean isItalic, isBold;
|
||||
cairo_matrix_t scale;
|
||||
const char *family = toy_face->family;
|
||||
|
||||
err = ATSUCreateStyle(&style);
|
||||
|
@ -173,43 +300,19 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
|||
kFontNoLanguageCode, &fontID);
|
||||
}
|
||||
|
||||
|
||||
ATSUAttributeTag styleTags[] =
|
||||
{ kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
|
||||
ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
|
||||
ByteCount styleSizes[] =
|
||||
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
|
||||
|
||||
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(styleTags) / sizeof(styleTags[0]),
|
||||
styleTags, styleSizes, styleValues);
|
||||
|
||||
font = malloc(sizeof(cairo_atsui_font_t));
|
||||
|
||||
_cairo_scaled_font_init(&font->base, toy_face, font_matrix, ctm, options,
|
||||
&cairo_atsui_scaled_font_backend);
|
||||
|
||||
cairo_matrix_multiply(&scale, font_matrix, ctm);
|
||||
font->style = CreateSizedCopyOfStyle(style, &scale);
|
||||
|
||||
Fixed theSize = FloatToFixed(1.0);
|
||||
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
|
||||
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
|
||||
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(theFontStyleTags) /
|
||||
sizeof(ATSUAttributeTag), theFontStyleTags,
|
||||
theFontStyleSizes, theFontStyleValues);
|
||||
|
||||
font->unscaled_style = style;
|
||||
|
||||
font->fontID = fontID;
|
||||
font->scale = scale;
|
||||
|
||||
*font_out = &font->base;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
|
||||
font_matrix, ctm, options, font_out);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -226,73 +329,195 @@ _cairo_atsui_font_fini(void *abstract_font)
|
|||
ATSUDisposeStyle(font->unscaled_style);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_cairo_atsui_font_get_glyph_cache_key(void *abstract_font,
|
||||
cairo_glyph_cache_key_t *key)
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
cairo_text_extents_t extents;
|
||||
OSStatus err;
|
||||
GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
ATSGlyphIdealMetrics metricsH, metricsV;
|
||||
ATSUStyle style;
|
||||
ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
|
||||
const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag };
|
||||
const ByteCount theSizes[] = { sizeof(verticalType) };
|
||||
ATSUAttributeValuePtr theValues[] = { &verticalType };
|
||||
|
||||
ATSUCreateAndCopyStyle(font->unscaled_style, &style);
|
||||
|
||||
err = ATSUGlyphGetIdealMetrics(style,
|
||||
1, &theGlyph, 0, &metricsH);
|
||||
err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues);
|
||||
err = ATSUGlyphGetIdealMetrics(style,
|
||||
1, &theGlyph, 0, &metricsV);
|
||||
|
||||
extents.x_bearing = metricsH.sideBearing.x;
|
||||
extents.y_bearing = metricsV.advance.y;
|
||||
extents.width =
|
||||
metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x;
|
||||
extents.height =
|
||||
-metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y;
|
||||
extents.x_advance = metricsH.advance.x;
|
||||
extents.y_advance = 0;
|
||||
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
&font->base,
|
||||
&extents);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static OSStatus
|
||||
_move_to (const Float32Point *point,
|
||||
void *callback_data)
|
||||
{
|
||||
cairo_path_fixed_t *path = callback_data;
|
||||
|
||||
_cairo_path_fixed_close_path (path);
|
||||
_cairo_path_fixed_move_to (path,
|
||||
_cairo_fixed_from_double(point->x),
|
||||
_cairo_fixed_from_double(point->y));
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static OSStatus
|
||||
_line_to (const Float32Point *point,
|
||||
void *callback_data)
|
||||
{
|
||||
cairo_path_fixed_t *path = callback_data;
|
||||
|
||||
_cairo_path_fixed_line_to (path,
|
||||
_cairo_fixed_from_double(point->x),
|
||||
_cairo_fixed_from_double(point->y));
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static OSStatus
|
||||
_curve_to (const Float32Point *point1,
|
||||
const Float32Point *point2,
|
||||
const Float32Point *point3,
|
||||
void *callback_data)
|
||||
{
|
||||
cairo_path_fixed_t *path = callback_data;
|
||||
|
||||
_cairo_path_fixed_curve_to (path,
|
||||
_cairo_fixed_from_double(point1->x),
|
||||
_cairo_fixed_from_double(point1->y),
|
||||
_cairo_fixed_from_double(point2->x),
|
||||
_cairo_fixed_from_double(point2->y),
|
||||
_cairo_fixed_from_double(point3->x),
|
||||
_cairo_fixed_from_double(point3->y));
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static OSStatus
|
||||
_close_path (void *callback_data)
|
||||
|
||||
{
|
||||
cairo_path_fixed_t *path = callback_data;
|
||||
|
||||
_cairo_path_fixed_close_path (path);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
static ATSCubicMoveToUPP moveProc = NULL;
|
||||
static ATSCubicLineToUPP lineProc = NULL;
|
||||
static ATSCubicCurveToUPP curveProc = NULL;
|
||||
static ATSCubicClosePathUPP closePathProc = NULL;
|
||||
OSStatus err;
|
||||
cairo_path_fixed_t *path;
|
||||
|
||||
path = _cairo_path_fixed_create ();
|
||||
if (!path)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (moveProc == NULL) {
|
||||
moveProc = NewATSCubicMoveToUPP(_move_to);
|
||||
lineProc = NewATSCubicLineToUPP(_line_to);
|
||||
curveProc = NewATSCubicCurveToUPP(_curve_to);
|
||||
closePathProc = NewATSCubicClosePathUPP(_close_path);
|
||||
}
|
||||
|
||||
err = ATSUGlyphGetCubicPaths(scaled_font->style,
|
||||
_cairo_scaled_glyph_index (scaled_glyph),
|
||||
moveProc,
|
||||
lineProc,
|
||||
curveProc,
|
||||
closePathProc, (void *)path, &err);
|
||||
|
||||
_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_scaled_glyph_init (void *abstract_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_glyph_info_t info)
|
||||
{
|
||||
cairo_atsui_font_t *scaled_font = abstract_font;
|
||||
cairo_status_t status;
|
||||
|
||||
if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
|
||||
status = _cairo_atsui_font_init_glyph_metrics (scaled_font, scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
|
||||
status = _cairo_atsui_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_atsui_font_text_to_glyphs (void *abstract_font,
|
||||
double x,
|
||||
double y,
|
||||
const char *utf8,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs)
|
||||
{
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
size_t i;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
uint16_t *utf16;
|
||||
int n16;
|
||||
OSStatus err;
|
||||
ATSUTextLayout textLayout;
|
||||
ATSLayoutRecord *layoutRecords;
|
||||
ItemCount glyphCount, charCount;
|
||||
UniChar *theText;
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
ItemCount glyphCount;
|
||||
int i;
|
||||
|
||||
// liberal estimate of size
|
||||
charCount = strlen(utf8);
|
||||
|
||||
if (charCount == 0) {
|
||||
*glyphs = NULL;
|
||||
*num_glyphs = 0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Set the text in the text layout object, so we can measure it
|
||||
theText = (UniChar *) malloc(charCount * sizeof(UniChar));
|
||||
|
||||
#if 1
|
||||
for (i = 0; i < charCount; i++) {
|
||||
theText[i] = utf8[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
size_t inBytes = charCount, outBytes = charCount;
|
||||
iconv_t converter = iconv_open("UTF-8", "UTF-16");
|
||||
charCount = iconv(converter, utf8, &inBytes, theText, &outBytes);
|
||||
#endif
|
||||
status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
err = ATSUCreateTextLayout(&textLayout);
|
||||
|
||||
err = ATSUSetTextPointerLocation(textLayout,
|
||||
theText, 0, charCount, charCount);
|
||||
|
||||
err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
|
||||
|
||||
// Set the style for all of the text
|
||||
err = ATSUSetRunStyle(textLayout,
|
||||
font->unscaled_style, kATSUFromTextBeginning, kATSUToTextEnd);
|
||||
font->style, kATSUFromTextBeginning, kATSUToTextEnd);
|
||||
|
||||
// Get the glyphs from the text layout object
|
||||
err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
|
||||
0,
|
||||
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
|
||||
(void *)
|
||||
&layoutRecords,
|
||||
(void *)&layoutRecords,
|
||||
&glyphCount);
|
||||
|
||||
*num_glyphs = glyphCount - 1;
|
||||
|
||||
|
||||
*glyphs =
|
||||
(cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t)));
|
||||
if (*glyphs == NULL) {
|
||||
|
@ -301,148 +526,21 @@ _cairo_atsui_font_text_to_glyphs(void *abstract_font,
|
|||
|
||||
for (i = 0; i < *num_glyphs; i++) {
|
||||
(*glyphs)[i].index = layoutRecords[i].glyphID;
|
||||
(*glyphs)[i].x = FixedToFloat(layoutRecords[i].realPos);
|
||||
(*glyphs)[i].y = 0;
|
||||
(*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos);
|
||||
(*glyphs)[i].y = y;
|
||||
}
|
||||
|
||||
|
||||
free(theText);
|
||||
free (utf16);
|
||||
|
||||
ATSUDirectReleaseLayoutDataArrayPtr(NULL,
|
||||
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
|
||||
(void *) &layoutRecords);
|
||||
|
||||
ATSUDisposeTextLayout(textLayout);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_font_extents(void *abstract_font,
|
||||
cairo_font_extents_t * extents)
|
||||
{
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
ATSFontRef atsFont;
|
||||
ATSFontMetrics metrics;
|
||||
OSStatus err;
|
||||
|
||||
// TODO - test this
|
||||
|
||||
atsFont = FMGetATSFontRefFromFont(font->fontID);
|
||||
|
||||
if (atsFont) {
|
||||
err =
|
||||
ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault,
|
||||
&metrics);
|
||||
|
||||
if (err == noErr) {
|
||||
extents->ascent = metrics.ascent;
|
||||
extents->descent = metrics.descent;
|
||||
extents->height = metrics.capHeight;
|
||||
extents->max_x_advance = metrics.maxAdvanceWidth;
|
||||
|
||||
// The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
|
||||
extents->max_y_advance = 0.0;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return CAIRO_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_glyph_extents(void *abstract_font,
|
||||
cairo_glyph_t * glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t * extents)
|
||||
{
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
OSStatus err;
|
||||
|
||||
assert(num_glyphs == 1);
|
||||
|
||||
GlyphID theGlyph = glyphs[0].index;
|
||||
|
||||
ATSGlyphIdealMetrics metricsH, metricsV;
|
||||
ATSUStyle style;
|
||||
|
||||
ATSUCreateAndCopyStyle(font->unscaled_style, &style);
|
||||
|
||||
err = ATSUGlyphGetIdealMetrics(style,
|
||||
1, &theGlyph, 0, &metricsH);
|
||||
|
||||
ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
|
||||
const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag };
|
||||
const ByteCount theSizes[] = { sizeof(verticalType) };
|
||||
ATSUAttributeValuePtr theValues[] = { &verticalType };
|
||||
|
||||
err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues);
|
||||
|
||||
err = ATSUGlyphGetIdealMetrics(style,
|
||||
1, &theGlyph, 0, &metricsV);
|
||||
|
||||
extents->x_bearing = metricsH.sideBearing.x;
|
||||
extents->y_bearing = metricsV.advance.y;
|
||||
extents->width =
|
||||
metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x;
|
||||
extents->height =
|
||||
-metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y;
|
||||
extents->x_advance = metricsH.advance.x;
|
||||
extents->y_advance = 0;
|
||||
|
||||
ATSUDisposeStyle(style);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_glyph_bbox(void *abstract_font,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs, cairo_box_t *bbox)
|
||||
{
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
cairo_fixed_t x1, y1, x2, y2;
|
||||
int i;
|
||||
|
||||
bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16;
|
||||
bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16;
|
||||
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
GlyphID theGlyph = glyphs[i].index;
|
||||
|
||||
ATSGlyphScreenMetrics metrics;
|
||||
ATSUGlyphGetScreenMetrics(font->style,
|
||||
1, &theGlyph, 0, true, true, &metrics);
|
||||
|
||||
x1 = _cairo_fixed_from_double(glyphs[i].x + metrics.topLeft.x);
|
||||
y1 = _cairo_fixed_from_double(glyphs[i].y - metrics.topLeft.y);
|
||||
x2 = x1 + _cairo_fixed_from_double(metrics.height);
|
||||
y2 = y1 + _cairo_fixed_from_double(metrics.width);
|
||||
|
||||
if (x1 < bbox->p1.x)
|
||||
bbox->p1.x = x1;
|
||||
|
||||
if (y1 < bbox->p1.y)
|
||||
bbox->p1.y = y1;
|
||||
|
||||
if (x2 > bbox->p2.x)
|
||||
bbox->p2.x = x2;
|
||||
|
||||
if (y2 > bbox->p2.y)
|
||||
bbox->p2.y = y2;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
static cairo_int_status_t
|
||||
_cairo_atsui_font_show_glyphs (void *abstract_font,
|
||||
cairo_operator_t operator,
|
||||
cairo_pattern_t *pattern,
|
||||
|
@ -537,166 +635,12 @@ _cairo_atsui_font_show_glyphs(void *abstract_font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static OSStatus MyATSCubicMoveToCallback(const Float32Point * pt,
|
||||
void *callBackDataPtr)
|
||||
{
|
||||
cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
|
||||
double scaledPt[2];
|
||||
cairo_fixed_t x, y;
|
||||
|
||||
scaledPt[0] = pt->x;
|
||||
scaledPt[1] = pt->y;
|
||||
|
||||
cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
|
||||
|
||||
x = _cairo_fixed_from_double(scaledPt[0]);
|
||||
y = _cairo_fixed_from_double(scaledPt[1]);
|
||||
|
||||
_cairo_path_fixed_close_path(info->path);
|
||||
_cairo_path_fixed_move_to(info->path, x, y);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
static OSStatus MyATSCubicLineToCallback(const Float32Point * pt,
|
||||
void *callBackDataPtr)
|
||||
{
|
||||
cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
|
||||
double scaledPt[2];
|
||||
cairo_fixed_t x, y;
|
||||
|
||||
scaledPt[0] = pt->x;
|
||||
scaledPt[1] = pt->y;
|
||||
|
||||
cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
|
||||
|
||||
x = _cairo_fixed_from_double(scaledPt[0]);
|
||||
y = _cairo_fixed_from_double(scaledPt[1]);
|
||||
|
||||
_cairo_path_fixed_line_to(info->path, x, y);
|
||||
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
static OSStatus MyATSCubicCurveToCallback(const Float32Point * pt1,
|
||||
const Float32Point * pt2,
|
||||
const Float32Point * pt3,
|
||||
void *callBackDataPtr)
|
||||
{
|
||||
cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
|
||||
double scaledPt[2];
|
||||
cairo_fixed_t x0, y0;
|
||||
cairo_fixed_t x1, y1;
|
||||
cairo_fixed_t x2, y2;
|
||||
|
||||
|
||||
scaledPt[0] = pt1->x;
|
||||
scaledPt[1] = pt1->y;
|
||||
|
||||
cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
|
||||
|
||||
x0 = _cairo_fixed_from_double(scaledPt[0]);
|
||||
y0 = _cairo_fixed_from_double(scaledPt[1]);
|
||||
|
||||
|
||||
scaledPt[0] = pt2->x;
|
||||
scaledPt[1] = pt2->y;
|
||||
|
||||
cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
|
||||
|
||||
x1 = _cairo_fixed_from_double(scaledPt[0]);
|
||||
y1 = _cairo_fixed_from_double(scaledPt[1]);
|
||||
|
||||
|
||||
scaledPt[0] = pt3->x;
|
||||
scaledPt[1] = pt3->y;
|
||||
|
||||
cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
|
||||
|
||||
x2 = _cairo_fixed_from_double(scaledPt[0]);
|
||||
y2 = _cairo_fixed_from_double(scaledPt[1]);
|
||||
|
||||
|
||||
_cairo_path_fixed_curve_to(info->path, x0, y0, x1, y1, x2, y2);
|
||||
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
static OSStatus MyCubicClosePathProc(void *callBackDataPtr)
|
||||
{
|
||||
cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
|
||||
|
||||
|
||||
_cairo_path_fixed_close_path(info->path);
|
||||
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_glyph_path(void *abstract_font,
|
||||
cairo_glyph_t *glyphs, int num_glyphs,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
int i;
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
OSStatus err;
|
||||
cairo_ATSUI_glyph_path_callback_info_t info;
|
||||
|
||||
|
||||
static ATSCubicMoveToUPP moveProc = NULL;
|
||||
static ATSCubicLineToUPP lineProc = NULL;
|
||||
static ATSCubicCurveToUPP curveProc = NULL;
|
||||
static ATSCubicClosePathUPP closePathProc = NULL;
|
||||
|
||||
|
||||
if (moveProc == NULL) {
|
||||
moveProc = NewATSCubicMoveToUPP(MyATSCubicMoveToCallback);
|
||||
lineProc = NewATSCubicLineToUPP(MyATSCubicLineToCallback);
|
||||
curveProc = NewATSCubicCurveToUPP(MyATSCubicCurveToCallback);
|
||||
closePathProc = NewATSCubicClosePathUPP(MyCubicClosePathProc);
|
||||
}
|
||||
|
||||
|
||||
info.path = path;
|
||||
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
GlyphID theGlyph = glyphs[i].index;
|
||||
|
||||
|
||||
cairo_matrix_init(&info.scale,
|
||||
1.0, 0.0,
|
||||
0.0, 1.0, glyphs[i].x, glyphs[i].y);
|
||||
|
||||
|
||||
err = ATSUGlyphGetCubicPaths(font->style,
|
||||
theGlyph,
|
||||
moveProc,
|
||||
lineProc,
|
||||
curveProc,
|
||||
closePathProc, (void *) &info, &err);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
|
||||
_cairo_atsui_font_create_toy,
|
||||
_cairo_atsui_font_fini,
|
||||
_cairo_atsui_font_font_extents,
|
||||
_cairo_atsui_font_scaled_glyph_init,
|
||||
_cairo_atsui_font_text_to_glyphs,
|
||||
_cairo_atsui_font_glyph_extents,
|
||||
_cairo_atsui_font_glyph_bbox,
|
||||
NULL, /* ucs4_to_index */
|
||||
_cairo_atsui_font_show_glyphs,
|
||||
_cairo_atsui_font_glyph_path,
|
||||
_cairo_atsui_font_get_glyph_cache_key,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Calum Robinson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Calum Robinson
|
||||
*
|
||||
* Contributor(s):
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_ATSUI_H
|
||||
#define CAIRO_ATSUI_H
|
||||
|
||||
#include <cairo.h>
|
||||
|
||||
#if CAIRO_HAS_ATSUI_FONT
|
||||
|
||||
/* ATSUI platform-specific font interface */
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#else /* CAIRO_HAS_ATSUI_FONT */
|
||||
# error Cairo was not compiled with support for the atsui font backend
|
||||
#endif /* CAIRO_HAS_ATSUI_FONT */
|
||||
|
||||
#endif /* CAIRO_ATSUI_H */
|
|
@ -0,0 +1,125 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Red Hat, Inc.
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
* Graydon Hoare <graydon@redhat.com>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_CACHE_PRIVATE_H
|
||||
#define CAIRO_CACHE_PRIVATE_H
|
||||
|
||||
typedef struct _cairo_cache cairo_cache_t;
|
||||
|
||||
/**
|
||||
* cairo_cache_entry_t:
|
||||
*
|
||||
* A #cairo_cache_entry_t contains both a key and a value for
|
||||
* cairo_cache_t. User-derived types for cairo_cache_entry_t must
|
||||
* have a cairo_cache_entry_t as their first field. For example:
|
||||
*
|
||||
* typedef _my_entry {
|
||||
* cairo_cache_entry_t base;
|
||||
* ... Remainder of key and value fields here ..
|
||||
* } my_entry_t;
|
||||
*
|
||||
* which then allows a pointer to my_entry_t to be passed to any of
|
||||
* the cairo_cache functions as follows without requiring a cast:
|
||||
*
|
||||
* _cairo_cache_insert (cache, &my_entry->base, size);
|
||||
*
|
||||
* IMPORTANT: The caller is responsible for initializing
|
||||
* my_entry->base.hash with a hash code derived from the key. The
|
||||
* essential property of the hash code is that keys_equal must never
|
||||
* return %TRUE for two keys that have different hashes. The best hash
|
||||
* code will reduce the frequency of two keys with the same code for
|
||||
* which keys_equal returns %FALSE.
|
||||
*
|
||||
* The user must also initialize my_entry->base.size to indicate
|
||||
* the size of the current entry. What units to use for size is
|
||||
* entirely up to the caller, (though the same units must be used for
|
||||
* the max_size parameter passed to _cairo_cache_create()). If all
|
||||
* entries are close to the same size, the simplest thing to do is to
|
||||
* just use units of "entries", (eg. set size==1 in all entries and
|
||||
* set max_size to the number of entries which you want to be saved
|
||||
* in the cache).
|
||||
*
|
||||
* Which parts of the entry make up the "key" and which part make up
|
||||
* the value are entirely up to the caller, (as determined by the
|
||||
* computation going into base.hash as well as the keys_equal
|
||||
* function). A few of the cairo_cache functions accept an entry which
|
||||
* will be used exclusively as a "key", (indicated by a parameter name
|
||||
* of key). In these cases, the value-related fields of the entry need
|
||||
* not be initialized if so desired.
|
||||
**/
|
||||
typedef struct _cairo_cache_entry {
|
||||
unsigned long hash;
|
||||
unsigned long size;
|
||||
} cairo_cache_entry_t;
|
||||
|
||||
typedef cairo_bool_t
|
||||
(*cairo_cache_keys_equal_func_t) (void *key_a, void *key_b);
|
||||
|
||||
typedef void
|
||||
(*cairo_cache_callback_func_t) (void *entry,
|
||||
void *closure);
|
||||
|
||||
cairo_private cairo_cache_t *
|
||||
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
|
||||
cairo_destroy_func_t entry_destroy,
|
||||
unsigned long max_size);
|
||||
|
||||
cairo_private void
|
||||
_cairo_cache_destroy (cairo_cache_t *cache);
|
||||
|
||||
cairo_private void
|
||||
_cairo_cache_freeze (cairo_cache_t *cache);
|
||||
|
||||
cairo_private void
|
||||
_cairo_cache_thaw (cairo_cache_t *cache);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_cache_lookup (cairo_cache_t *cache,
|
||||
cairo_cache_entry_t *key,
|
||||
cairo_cache_entry_t **entry_return);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_cache_insert (cairo_cache_t *cache,
|
||||
cairo_cache_entry_t *entry);
|
||||
|
||||
cairo_private void
|
||||
_cairo_cache_foreach (cairo_cache_t *cache,
|
||||
cairo_cache_callback_func_t cache_callback,
|
||||
void *closure);
|
||||
|
||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* This file is Copyright © 2004 Red Hat, Inc.
|
||||
* Copyright © 2004 Red Hat, Inc.
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -30,481 +31,343 @@
|
|||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Keith Packard
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
* Graydon Hoare <graydon@redhat.com>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
/*
|
||||
* This structure, and accompanying table, is borrowed/modified from the
|
||||
* file xserver/render/glyph.c in the freedesktop.org x server, with
|
||||
* permission (and suggested modification of doubling sizes) by Keith
|
||||
* Packard.
|
||||
*/
|
||||
struct _cairo_cache {
|
||||
cairo_hash_table_t *hash_table;
|
||||
|
||||
static const cairo_cache_arrangement_t cache_arrangements [] = {
|
||||
{ 16, 43, 41 },
|
||||
{ 32, 73, 71 },
|
||||
{ 64, 151, 149 },
|
||||
{ 128, 283, 281 },
|
||||
{ 256, 571, 569 },
|
||||
{ 512, 1153, 1151 },
|
||||
{ 1024, 2269, 2267 },
|
||||
{ 2048, 4519, 4517 },
|
||||
{ 4096, 9013, 9011 },
|
||||
{ 8192, 18043, 18041 },
|
||||
{ 16384, 36109, 36107 },
|
||||
{ 32768, 72091, 72089 },
|
||||
{ 65536, 144409, 144407 },
|
||||
{ 131072, 288361, 288359 },
|
||||
{ 262144, 576883, 576881 },
|
||||
{ 524288, 1153459, 1153457 },
|
||||
{ 1048576, 2307163, 2307161 },
|
||||
{ 2097152, 4613893, 4613891 },
|
||||
{ 4194304, 9227641, 9227639 },
|
||||
{ 8388608, 18455029, 18455027 },
|
||||
{ 16777216, 36911011, 36911009 },
|
||||
{ 33554432, 73819861, 73819859 },
|
||||
{ 67108864, 147639589, 147639587 },
|
||||
{ 134217728, 295279081, 295279079 },
|
||||
{ 268435456, 590559793, 590559791 }
|
||||
cairo_destroy_func_t entry_destroy;
|
||||
|
||||
unsigned long max_size;
|
||||
unsigned long size;
|
||||
|
||||
int freeze_count;
|
||||
};
|
||||
|
||||
#define N_CACHE_SIZES (sizeof(cache_arrangements)/sizeof(cache_arrangements[0]))
|
||||
|
||||
/*
|
||||
* Entries 'e' are poiners, in one of 3 states:
|
||||
*
|
||||
* e == NULL: The entry has never had anything put in it
|
||||
* e != DEAD_ENTRY: The entry has an active value in it currently
|
||||
* e == DEAD_ENTRY: The entry *had* a value in it at some point, but the
|
||||
* entry has been killed. Lookups requesting free space can
|
||||
* reuse these entries; lookups requesting a precise match
|
||||
* should neither return these entries nor stop searching when
|
||||
* seeing these entries.
|
||||
*
|
||||
* We expect keys will not be destroyed frequently, so our table does not
|
||||
* contain any explicit shrinking code nor any chain-coalescing code for
|
||||
* entries randomly deleted by memory pressure (except during rehashing, of
|
||||
* course). These assumptions are potentially bad, but they make the
|
||||
* implementation straightforward.
|
||||
*
|
||||
* Revisit later if evidence appears that we're using excessive memory from
|
||||
* a mostly-dead table.
|
||||
*
|
||||
* Generally you do not need to worry about freeing cache entries; the
|
||||
* cache will expire entries randomly as it experiences memory pressure.
|
||||
* If max_memory is set, entries are not expired, and must be explicitely
|
||||
* removed.
|
||||
*
|
||||
* This table is open-addressed with double hashing. Each table size is a
|
||||
* prime chosen to be a little more than double the high water mark for a
|
||||
* given arrangement, so the tables should remain < 50% full. The table
|
||||
* size makes for the "first" hash modulus; a second prime (2 less than the
|
||||
* first prime) serves as the "second" hash modulus, which is co-prime and
|
||||
* thus guarantees a complete permutation of table indices.
|
||||
*
|
||||
*/
|
||||
|
||||
#define DEAD_ENTRY ((cairo_cache_entry_base_t *) 1)
|
||||
#define NULL_ENTRY_P(cache, i) ((cache)->entries[i] == NULL)
|
||||
#define DEAD_ENTRY_P(cache, i) ((cache)->entries[i] == DEAD_ENTRY)
|
||||
#define LIVE_ENTRY_P(cache, i) \
|
||||
(!((NULL_ENTRY_P((cache),(i))) || (DEAD_ENTRY_P((cache),(i)))))
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define _cache_sane_state(c)
|
||||
#else
|
||||
static void
|
||||
_cache_sane_state (cairo_cache_t *cache)
|
||||
{
|
||||
assert (cache != NULL);
|
||||
assert (cache->entries != NULL);
|
||||
assert (cache->backend != NULL);
|
||||
assert (cache->arrangement != NULL);
|
||||
/* Cannot check this, a single object may larger */
|
||||
/* assert (cache->used_memory <= cache->max_memory); */
|
||||
assert (cache->live_entries <= cache->arrangement->size);
|
||||
}
|
||||
#endif
|
||||
_cairo_cache_remove (cairo_cache_t *cache,
|
||||
cairo_cache_entry_t *entry);
|
||||
|
||||
static void
|
||||
_entry_destroy (cairo_cache_t *cache, unsigned long i)
|
||||
{
|
||||
_cache_sane_state (cache);
|
||||
_cairo_cache_shrink_to_accomodate (cairo_cache_t *cache,
|
||||
unsigned long additional);
|
||||
|
||||
if (LIVE_ENTRY_P(cache, i))
|
||||
{
|
||||
cairo_cache_entry_base_t *entry = cache->entries[i];
|
||||
assert(cache->live_entries > 0);
|
||||
assert(cache->used_memory >= entry->memory);
|
||||
|
||||
cache->live_entries--;
|
||||
cache->used_memory -= entry->memory;
|
||||
cache->backend->destroy_entry (cache, entry);
|
||||
cache->entries[i] = DEAD_ENTRY;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_cache_entry_base_t **
|
||||
_cache_lookup (cairo_cache_t *cache,
|
||||
void *key,
|
||||
int (*predicate)(void*,void*,void*))
|
||||
{
|
||||
|
||||
cairo_cache_entry_base_t **probe;
|
||||
unsigned long hash;
|
||||
unsigned long table_size, i, idx, step;
|
||||
|
||||
_cache_sane_state (cache);
|
||||
assert (key != NULL);
|
||||
|
||||
table_size = cache->arrangement->size;
|
||||
hash = cache->backend->hash (cache, key);
|
||||
idx = hash % table_size;
|
||||
step = 0;
|
||||
|
||||
for (i = 0; i < table_size; ++i)
|
||||
{
|
||||
#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
cache->probes++;
|
||||
#endif
|
||||
assert(idx < table_size);
|
||||
probe = cache->entries + idx;
|
||||
|
||||
/*
|
||||
* There are two lookup modes: searching for a free slot and searching
|
||||
* for an exact entry.
|
||||
*/
|
||||
|
||||
if (predicate != NULL)
|
||||
{
|
||||
/* We are looking up an exact entry. */
|
||||
if (*probe == NULL)
|
||||
{
|
||||
/* Found an empty spot, there can't be a match */
|
||||
break;
|
||||
}
|
||||
else if (*probe != DEAD_ENTRY
|
||||
&& (*probe)->hashcode == hash
|
||||
&& predicate (cache, key, *probe))
|
||||
{
|
||||
return probe;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are just looking for a free slot. */
|
||||
if (*probe == NULL
|
||||
|| *probe == DEAD_ENTRY)
|
||||
{
|
||||
return probe;
|
||||
}
|
||||
}
|
||||
|
||||
if (step == 0) {
|
||||
step = hash % cache->arrangement->rehash;
|
||||
if (step == 0)
|
||||
step = 1;
|
||||
}
|
||||
|
||||
idx += step;
|
||||
if (idx >= table_size)
|
||||
idx -= table_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* The table should not have permitted you to get here if you were just
|
||||
* looking for a free slot: there should have been room.
|
||||
*/
|
||||
assert(predicate != NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static cairo_cache_entry_base_t **
|
||||
_find_available_entry_for (cairo_cache_t *cache,
|
||||
void *key)
|
||||
{
|
||||
return _cache_lookup (cache, key, NULL);
|
||||
}
|
||||
|
||||
static cairo_cache_entry_base_t **
|
||||
_find_exact_live_entry_for (cairo_cache_t *cache,
|
||||
void *key)
|
||||
{
|
||||
return _cache_lookup (cache, key, cache->backend->keys_equal);
|
||||
}
|
||||
|
||||
static const cairo_cache_arrangement_t *
|
||||
_find_cache_arrangement (unsigned long proposed_size)
|
||||
{
|
||||
unsigned long idx;
|
||||
|
||||
for (idx = 0; idx < N_CACHE_SIZES; ++idx)
|
||||
if (cache_arrangements[idx].high_water_mark >= proposed_size)
|
||||
return &cache_arrangements[idx];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_resize_cache (cairo_cache_t *cache, unsigned long proposed_size)
|
||||
_cairo_cache_init (cairo_cache_t *cache,
|
||||
cairo_cache_keys_equal_func_t keys_equal,
|
||||
cairo_destroy_func_t entry_destroy,
|
||||
unsigned long max_size)
|
||||
{
|
||||
cairo_cache_t tmp;
|
||||
cairo_cache_entry_base_t **e;
|
||||
unsigned long new_size, i;
|
||||
|
||||
tmp = *cache;
|
||||
tmp.arrangement = _find_cache_arrangement (proposed_size);
|
||||
assert(tmp.arrangement != NULL);
|
||||
if (tmp.arrangement == cache->arrangement)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
new_size = tmp.arrangement->size;
|
||||
tmp.entries = calloc (new_size, sizeof (cairo_cache_entry_base_t *));
|
||||
if (tmp.entries == NULL)
|
||||
cache->hash_table = _cairo_hash_table_create (keys_equal);
|
||||
if (cache->hash_table == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
for (i = 0; i < cache->arrangement->size; ++i) {
|
||||
if (LIVE_ENTRY_P(cache, i)) {
|
||||
e = _find_available_entry_for (&tmp, cache->entries[i]);
|
||||
assert (e != NULL);
|
||||
*e = cache->entries[i];
|
||||
}
|
||||
}
|
||||
free (cache->entries);
|
||||
cache->entries = tmp.entries;
|
||||
cache->arrangement = tmp.arrangement;
|
||||
cache->entry_destroy = entry_destroy;
|
||||
|
||||
cache->max_size = max_size;
|
||||
cache->size = 0;
|
||||
|
||||
cache->freeze_count = 0;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
static double
|
||||
_load_factor (cairo_cache_t *cache)
|
||||
static void
|
||||
_cairo_cache_fini (cairo_cache_t *cache)
|
||||
{
|
||||
return ((double) cache->live_entries)
|
||||
/ ((double) cache->arrangement->size);
|
||||
}
|
||||
#endif
|
||||
cairo_cache_entry_t *entry;
|
||||
|
||||
/* Find a random in the cache matching the given predicate. We use the
|
||||
* same algorithm as the probing algorithm to walk over the entries in
|
||||
* the hash table in a pseudo-random order. Walking linearly would
|
||||
* favor entries following gaps in the hash table. We could also
|
||||
* call rand() repeatedly, which works well for almost-full tables,
|
||||
* but degrades when the table is almost empty, or predicate
|
||||
* returns false for most entries.
|
||||
*/
|
||||
static cairo_cache_entry_base_t **
|
||||
_random_entry (cairo_cache_t *cache,
|
||||
int (*predicate)(void*))
|
||||
{
|
||||
cairo_cache_entry_base_t **probe;
|
||||
unsigned long hash;
|
||||
unsigned long table_size, i, idx, step;
|
||||
/* We have to manually remove all entries from the cache ourselves
|
||||
* rather than relying on _cairo_hash_table_destroy() to do that
|
||||
* since otherwise the cache->entry_destroy callback would not get
|
||||
* called on each entry. */
|
||||
|
||||
_cache_sane_state (cache);
|
||||
|
||||
table_size = cache->arrangement->size;
|
||||
hash = rand ();
|
||||
idx = hash % table_size;
|
||||
step = 0;
|
||||
|
||||
for (i = 0; i < table_size; ++i)
|
||||
{
|
||||
assert(idx < table_size);
|
||||
probe = cache->entries + idx;
|
||||
|
||||
if (LIVE_ENTRY_P(cache, idx)
|
||||
&& (!predicate || predicate (*probe)))
|
||||
return probe;
|
||||
|
||||
if (step == 0) {
|
||||
step = hash % cache->arrangement->rehash;
|
||||
if (step == 0)
|
||||
step = 1;
|
||||
while (1) {
|
||||
entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
_cairo_cache_remove (cache, entry);
|
||||
}
|
||||
|
||||
idx += step;
|
||||
if (idx >= table_size)
|
||||
idx -= table_size;
|
||||
_cairo_hash_table_destroy (cache->hash_table);
|
||||
cache->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_cache_create:
|
||||
* @keys_equal: a function to return %TRUE if two keys are equal
|
||||
* @entry_destroy: destroy notifier for cache entries
|
||||
* @max_size: the maximum size for this cache
|
||||
*
|
||||
* Creates a new cache using the keys_equal() function to determine
|
||||
* the equality of entries.
|
||||
*
|
||||
* Data is provided to the cache in the form of user-derived version
|
||||
* of cairo_cache_entry_t. A cache entry must be able to hold hash
|
||||
* code, a size, and the key/value pair being stored in the
|
||||
* cache. Sometimes only the key will be necessary, (as in
|
||||
* _cairo_cache_lookup()), and in these cases the value portion of the
|
||||
* entry need not be initialized.
|
||||
*
|
||||
* The units for max_size can be chosen by the caller, but should be
|
||||
* consistent with the units of the size field of cache entries. When
|
||||
* adding an entry with _cairo_cache_insert() if the total size of
|
||||
* entries in the cache would exceed max_size then entries will be
|
||||
* removed at random until the new entry would fit or the cache is
|
||||
* empty. Then the new entry is inserted.
|
||||
*
|
||||
* There are cases in which the automatic removal of entries is
|
||||
* undesired. If the cache entries have reference counts, then it is a
|
||||
* simple matter to use the reference counts to ensure that entries
|
||||
* continue to live even after being ejected from the cache. However,
|
||||
* in some cases the memory overhead of adding a reference count to
|
||||
* the entry would be objectionable. In such cases, the
|
||||
* _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
|
||||
* used to establish a window during which no automatic removal of
|
||||
* entries will occur.
|
||||
*
|
||||
* Return value:
|
||||
**/
|
||||
cairo_cache_t *
|
||||
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
|
||||
cairo_destroy_func_t entry_destroy,
|
||||
unsigned long max_size)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_cache_t *cache;
|
||||
|
||||
cache = malloc (sizeof (cairo_cache_t));
|
||||
if (cache == NULL)
|
||||
return NULL;
|
||||
|
||||
status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size);
|
||||
if (status) {
|
||||
free (cache);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* public API follows */
|
||||
|
||||
cairo_status_t
|
||||
_cairo_cache_init (cairo_cache_t *cache,
|
||||
const cairo_cache_backend_t *backend,
|
||||
unsigned long max_memory)
|
||||
{
|
||||
assert (backend != NULL);
|
||||
|
||||
if (cache != NULL){
|
||||
cache->arrangement = &cache_arrangements[0];
|
||||
cache->max_memory = max_memory;
|
||||
cache->used_memory = 0;
|
||||
cache->live_entries = 0;
|
||||
|
||||
#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
cache->hits = 0;
|
||||
cache->misses = 0;
|
||||
cache->probes = 0;
|
||||
#endif
|
||||
|
||||
cache->backend = backend;
|
||||
cache->entries = calloc (cache->arrangement->size,
|
||||
sizeof(cairo_cache_entry_base_t *));
|
||||
|
||||
if (cache->entries == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
_cache_sane_state (cache);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_cache_destroy:
|
||||
* @cache: a cache to destroy
|
||||
*
|
||||
* Immediately destroys the given cache, freeing all resources
|
||||
* associated with it. As part of this process, the entry_destroy()
|
||||
* function, (as passed to _cairo_cache_create()), will be called for
|
||||
* each entry in the cache.
|
||||
**/
|
||||
void
|
||||
_cairo_cache_destroy (cairo_cache_t *cache)
|
||||
{
|
||||
unsigned long i;
|
||||
if (cache == NULL)
|
||||
return;
|
||||
_cairo_cache_fini (cache);
|
||||
|
||||
_cache_sane_state (cache);
|
||||
|
||||
for (i = 0; i < cache->arrangement->size; ++i)
|
||||
_entry_destroy (cache, i);
|
||||
|
||||
free (cache->entries);
|
||||
cache->entries = NULL;
|
||||
cache->backend->destroy_cache (cache);
|
||||
free (cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_cache_freeze:
|
||||
* @cache: a cache with some precious entries in it (or about to be
|
||||
* added)
|
||||
*
|
||||
* Disable the automatic ejection of entries from the cache. For as
|
||||
* long as the cache is "frozen", calls to _cairo_cache_insert() will
|
||||
* add new entries to the cache regardless of how large the cache
|
||||
* grows. See _cairo_cache_thaw().
|
||||
*
|
||||
* NOTE: Multiple calls to _cairo_cache_freeze() will stack, in that
|
||||
* the cache will remain "frozen" until a corresponding number of
|
||||
* calls are made to _cairo_cache_thaw().
|
||||
**/
|
||||
void
|
||||
_cairo_cache_shrink_to (cairo_cache_t *cache,
|
||||
unsigned long max_memory)
|
||||
_cairo_cache_freeze (cairo_cache_t *cache)
|
||||
{
|
||||
unsigned long idx;
|
||||
/* Make some entries die if we're under memory pressure. */
|
||||
while (cache->live_entries > 0 && cache->used_memory > max_memory) {
|
||||
idx = _random_entry (cache, NULL) - cache->entries;
|
||||
assert (idx < cache->arrangement->size);
|
||||
_entry_destroy (cache, idx);
|
||||
}
|
||||
assert (cache->freeze_count >= 0);
|
||||
|
||||
cache->freeze_count++;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
/**
|
||||
* _cairo_cache_thaw:
|
||||
* @cache: a cache, just after the entries in it have become less
|
||||
* precious
|
||||
*
|
||||
* Cancels the effects of _cairo_cache_freeze().
|
||||
*
|
||||
* When a number of calls to _cairo_cache_thaw() is made corresponding
|
||||
* to the number of calls to _cairo_cache_freeze() the cache will no
|
||||
* longer be "frozen". If the cache had grown larger than max_size
|
||||
* while frozen, entries will immediately be ejected (by random) from
|
||||
* the cache until the cache is smaller than max_size. Also, the
|
||||
* automatic ejection of entries on _cairo_cache_insert() will resume.
|
||||
**/
|
||||
void
|
||||
_cairo_cache_thaw (cairo_cache_t *cache)
|
||||
{
|
||||
assert (cache->freeze_count > 0);
|
||||
|
||||
cache->freeze_count--;
|
||||
|
||||
if (cache->freeze_count == 0)
|
||||
_cairo_cache_shrink_to_accomodate (cache, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_cache_lookup:
|
||||
* @cache: a cache
|
||||
* @key: the key of interest
|
||||
* @entry_return: pointer for return value
|
||||
*
|
||||
* Performs a lookup in @cache looking for an entry which has a key
|
||||
* that matches @key, (as determined by the keys_equal() function
|
||||
* passed to _cairo_cache_create()).
|
||||
*
|
||||
* Return value: %TRUE if there is an entry in the cache that matches
|
||||
* @key, (which will now be in *entry_return). %FALSE otherwise, (in
|
||||
* which case *entry_return will be %NULL).
|
||||
**/
|
||||
cairo_bool_t
|
||||
_cairo_cache_lookup (cairo_cache_t *cache,
|
||||
void *key,
|
||||
void **entry_return,
|
||||
int *created_entry)
|
||||
cairo_cache_entry_t *key,
|
||||
cairo_cache_entry_t **entry_return)
|
||||
{
|
||||
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_cache_entry_base_t **slot = NULL, *new_entry;
|
||||
|
||||
_cache_sane_state (cache);
|
||||
|
||||
#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
if ((cache->hits + cache->misses) % 0xffff == 0)
|
||||
printf("cache %p stats: size %ld, live %ld, load %.2f\n"
|
||||
" mem %ld/%ld, hit %ld, miss %ld\n"
|
||||
" probe %ld, %.2f probe/access\n",
|
||||
cache,
|
||||
cache->arrangement->size,
|
||||
cache->live_entries,
|
||||
_load_factor (cache),
|
||||
cache->used_memory,
|
||||
cache->max_memory,
|
||||
cache->hits,
|
||||
cache->misses,
|
||||
cache->probes,
|
||||
((double) cache->probes)
|
||||
/ ((double) (cache->hits +
|
||||
cache->misses + 1)));
|
||||
#endif
|
||||
|
||||
/* See if we have an entry in the table already. */
|
||||
slot = _find_exact_live_entry_for (cache, key);
|
||||
if (slot != NULL) {
|
||||
#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
cache->hits++;
|
||||
#endif
|
||||
*entry_return = *slot;
|
||||
if (created_entry)
|
||||
*created_entry = 0;
|
||||
return status;
|
||||
return _cairo_hash_table_lookup (cache->hash_table,
|
||||
(cairo_hash_entry_t *) key,
|
||||
(cairo_hash_entry_t **) entry_return);
|
||||
}
|
||||
|
||||
#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
cache->misses++;
|
||||
#endif
|
||||
|
||||
/* Build the new entry. */
|
||||
status = cache->backend->create_entry (cache, key,
|
||||
(void **)&new_entry);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* Store the hash value in case the backend forgot. */
|
||||
new_entry->hashcode = cache->backend->hash (cache, key);
|
||||
|
||||
if (cache->live_entries && cache->max_memory)
|
||||
_cairo_cache_shrink_to (cache, cache->max_memory);
|
||||
|
||||
/* Can't assert this; new_entry->memory may be larger than max_memory */
|
||||
/* assert(cache->max_memory >= (cache->used_memory + new_entry->memory)); */
|
||||
|
||||
/* Make room in the table for a new slot. */
|
||||
status = _resize_cache (cache, cache->live_entries + 1);
|
||||
if (status != CAIRO_STATUS_SUCCESS) {
|
||||
cache->backend->destroy_entry (cache, new_entry);
|
||||
return status;
|
||||
}
|
||||
|
||||
slot = _find_available_entry_for (cache, key);
|
||||
assert(slot != NULL);
|
||||
|
||||
/* Store entry in slot and increment statistics. */
|
||||
*slot = new_entry;
|
||||
cache->live_entries++;
|
||||
cache->used_memory += new_entry->memory;
|
||||
|
||||
_cache_sane_state (cache);
|
||||
|
||||
*entry_return = new_entry;
|
||||
if (created_entry)
|
||||
*created_entry = 1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_cache_remove (cairo_cache_t *cache,
|
||||
void *key)
|
||||
/**
|
||||
* _cairo_cache_remove_random:
|
||||
* @cache: a cache
|
||||
*
|
||||
* Remove a random entry from the cache.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if an entry was successfully
|
||||
* removed. CAIRO_INT_STATUS_CACHE_EMPTY if there are no entries that
|
||||
* can be removed.
|
||||
**/
|
||||
static cairo_int_status_t
|
||||
_cairo_cache_remove_random (cairo_cache_t *cache)
|
||||
{
|
||||
cairo_cache_entry_base_t **slot;
|
||||
cairo_cache_entry_t *entry;
|
||||
|
||||
_cache_sane_state (cache);
|
||||
entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
|
||||
if (entry == NULL)
|
||||
return CAIRO_INT_STATUS_CACHE_EMPTY;
|
||||
|
||||
/* See if we have an entry in the table already. */
|
||||
slot = _find_exact_live_entry_for (cache, key);
|
||||
if (slot != NULL)
|
||||
_entry_destroy (cache, slot - cache->entries);
|
||||
_cairo_cache_remove (cache, entry);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void *
|
||||
_cairo_cache_random_entry (cairo_cache_t *cache,
|
||||
int (*predicate)(void*))
|
||||
/**
|
||||
* _cairo_cache_shrink_to_accomodate:
|
||||
* @cache: a cache
|
||||
* @additional: additional size requested in bytes
|
||||
*
|
||||
* If cache is not frozen, eject entries randomly until the size of
|
||||
* the cache is at least @additional bytes less than
|
||||
* cache->max_size. That is, make enough room to accomodate a new
|
||||
* entry of size @additional.
|
||||
**/
|
||||
static void
|
||||
_cairo_cache_shrink_to_accomodate (cairo_cache_t *cache,
|
||||
unsigned long additional)
|
||||
{
|
||||
cairo_cache_entry_base_t **slot = _random_entry (cache, predicate);
|
||||
cairo_int_status_t status;
|
||||
|
||||
return slot ? *slot : NULL;
|
||||
if (cache->freeze_count)
|
||||
return;
|
||||
|
||||
while (cache->size + additional > cache->max_size) {
|
||||
status = _cairo_cache_remove_random (cache);
|
||||
if (status) {
|
||||
if (status == CAIRO_INT_STATUS_CACHE_EMPTY)
|
||||
return;
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_cache_insert:
|
||||
* @cache: a cache
|
||||
* @entry: an entry to be inserted
|
||||
*
|
||||
* Insert @entry into the cache. If an entry exists in the cache with
|
||||
* a matching key, then the old entry will be removed first, (and the
|
||||
* entry_destroy() callback will be called on it).
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful or
|
||||
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_cache_insert (cairo_cache_t *cache,
|
||||
cairo_cache_entry_t *entry)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_cache_shrink_to_accomodate (cache, entry->size);
|
||||
|
||||
status = _cairo_hash_table_insert (cache->hash_table,
|
||||
(cairo_hash_entry_t *) entry);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
cache->size += entry->size;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_cache_remove:
|
||||
* @cache: a cache
|
||||
* @entry: an entry that exists in the cache
|
||||
*
|
||||
* Remove an existing entry from the cache.
|
||||
*
|
||||
* (NOTE: If any caller wanted access to a non-static version of this
|
||||
* function, an improved version would require only a key rather than
|
||||
* an entry. Fixing that would require fixing _cairo_hash_table_remove
|
||||
* to return (a copy of?) the entry being removed.)
|
||||
**/
|
||||
static void
|
||||
_cairo_cache_remove (cairo_cache_t *cache,
|
||||
cairo_cache_entry_t *entry)
|
||||
{
|
||||
cache->size -= entry->size;
|
||||
|
||||
_cairo_hash_table_remove (cache->hash_table,
|
||||
(cairo_hash_entry_t *) entry);
|
||||
|
||||
if (cache->entry_destroy)
|
||||
cache->entry_destroy (entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_cache_foreach:
|
||||
* @cache: a cache
|
||||
* @cache_callback: function to be called for each entry
|
||||
* @closure: additional argument to be passed to @cache_callback
|
||||
*
|
||||
* Call @cache_callback for each entry in the cache, in a
|
||||
* non-specified order.
|
||||
**/
|
||||
void
|
||||
_cairo_cache_foreach (cairo_cache_t *cache,
|
||||
cairo_cache_callback_func_t cache_callback,
|
||||
void *closure)
|
||||
{
|
||||
_cairo_hash_table_foreach (cache->hash_table,
|
||||
cache_callback,
|
||||
closure);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
|
|
|
@ -60,7 +60,6 @@ void
|
|||
cairo_debug_reset_static_data (void)
|
||||
{
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
_cairo_xlib_surface_reset_static_data ();
|
||||
_cairo_xlib_screen_reset_static_data ();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#ifndef CAIRO_FEATURES_H
|
||||
#define CAIRO_FEATURES_H
|
||||
|
||||
#include "cairo-platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define CAIRO_BEGIN_DECLS extern "C" {
|
||||
# define CAIRO_END_DECLS }
|
||||
|
@ -45,11 +47,11 @@
|
|||
# define CAIRO_END_DECLS
|
||||
#endif
|
||||
|
||||
#define CAIRO_VERSION_MAJOR 0
|
||||
#define CAIRO_VERSION_MINOR 9
|
||||
#define CAIRO_VERSION_MAJOR 1
|
||||
#define CAIRO_VERSION_MINOR 1
|
||||
#define CAIRO_VERSION_MICRO 1
|
||||
|
||||
#define CAIRO_VERSION_STRING "0.9.1"
|
||||
#define CAIRO_VERSION_STRING "1.1.1"
|
||||
|
||||
@PS_SURFACE_FEATURE@
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ _cairo_fixed_from_int (int i)
|
|||
cairo_fixed_t
|
||||
_cairo_fixed_from_double (double d)
|
||||
{
|
||||
return (cairo_fixed_t) (d * 65536);
|
||||
return (cairo_fixed_t) floor (d * 65536 + 0.5);
|
||||
}
|
||||
|
||||
cairo_fixed_t
|
||||
|
@ -84,7 +84,7 @@ _cairo_fixed_integer_floor (cairo_fixed_t f)
|
|||
int
|
||||
_cairo_fixed_integer_ceil (cairo_fixed_t f)
|
||||
{
|
||||
if (f >= 0)
|
||||
if (f > 0)
|
||||
return ((f - 1)>>16) + 1;
|
||||
else
|
||||
return - (-f >> 16);
|
||||
|
|
|
@ -85,6 +85,10 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
|
|||
if (font_face->ref_count == (unsigned int)-1)
|
||||
return font_face;
|
||||
|
||||
/* We would normally assert (font_face->ref_count >0) here but we
|
||||
* can't get away with that due to the zombie case as documented
|
||||
* in _cairo_ft_font_face_destroy. */
|
||||
|
||||
font_face->ref_count++;
|
||||
|
||||
return font_face;
|
||||
|
@ -107,6 +111,8 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
|
|||
if (font_face->ref_count == (unsigned int)-1)
|
||||
return;
|
||||
|
||||
assert (font_face->ref_count > 0);
|
||||
|
||||
if (--(font_face->ref_count) > 0)
|
||||
return;
|
||||
|
||||
|
@ -407,544 +413,6 @@ static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
|
|||
_cairo_toy_font_face_scaled_font_create
|
||||
};
|
||||
|
||||
/* cairo_scaled_font_t */
|
||||
|
||||
static const cairo_scaled_font_t _cairo_scaled_font_nil = {
|
||||
{ 0 }, /* hash_entry */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
-1, /* ref_count */
|
||||
NULL, /* font_face */
|
||||
{ 1., 0., 0., 1., 0, 0}, /* font_matrix */
|
||||
{ 1., 0., 0., 1., 0, 0}, /* ctm */
|
||||
{ 1., 0., 0., 1., 0, 0}, /* scale */
|
||||
{ CAIRO_ANTIALIAS_DEFAULT, /* options */
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
||||
CAIRO_HINT_STYLE_DEFAULT,
|
||||
CAIRO_HINT_METRICS_DEFAULT} ,
|
||||
CAIRO_SCALED_FONT_BACKEND_DEFAULT,
|
||||
};
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_set_error:
|
||||
* @scaled_font: a scaled_font
|
||||
* @status: a status value indicating an error, (eg. not
|
||||
* CAIRO_STATUS_SUCCESS)
|
||||
*
|
||||
* Sets scaled_font->status to @status and calls _cairo_error;
|
||||
*
|
||||
* All assignments of an error status to scaled_font->status should happen
|
||||
* through _cairo_scaled_font_set_error() or else _cairo_error() should be
|
||||
* called immediately after the assignment.
|
||||
*
|
||||
* The purpose of this function is to allow the user to set a
|
||||
* breakpoint in _cairo_error() to generate a stack trace for when the
|
||||
* user causes cairo to detect an error.
|
||||
**/
|
||||
void
|
||||
_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
|
||||
cairo_status_t status)
|
||||
{
|
||||
scaled_font->status = status;
|
||||
|
||||
_cairo_error (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_status:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Checks whether an error has previously occurred for this
|
||||
* scaled_font.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS or another error such as
|
||||
* %CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_scaled_font_status (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
return scaled_font->status;
|
||||
}
|
||||
|
||||
/* Here we keep a unique mapping from
|
||||
* cairo_font_face_t/matrix/ctm/options => cairo_scaled_font_t.
|
||||
*
|
||||
* Here are the things that we want to map:
|
||||
*
|
||||
* a) All otherwise referenced cairo_scaled_font_t's
|
||||
* b) Some number of not otherwise referenced cairo_scaled_font_t's
|
||||
*
|
||||
* The implementation uses a hash table which covers (a)
|
||||
* completely. Then, for (b) we have an array of otherwise
|
||||
* unreferenced fonts (holdovers) which are expired in
|
||||
* least-recently-used order.
|
||||
*
|
||||
* The cairo_scaled_font_create code gets to treat this like a regular
|
||||
* hash table. All of the magic for the little holdover cache is in
|
||||
* cairo_scaled_font_reference and cairo_scaled_font_destroy.
|
||||
*/
|
||||
|
||||
/* This defines the size of the holdover array ... that is, the number
|
||||
* of scaled fonts we keep around even when not otherwise referenced
|
||||
*/
|
||||
#define CAIRO_SCALED_FONT_MAX_HOLDOVERS 24
|
||||
|
||||
typedef struct _cairo_scaled_font_map {
|
||||
cairo_hash_table_t *hash_table;
|
||||
cairo_scaled_font_t *holdovers[CAIRO_SCALED_FONT_MAX_HOLDOVERS];
|
||||
int num_holdovers;
|
||||
} cairo_scaled_font_map_t;
|
||||
|
||||
static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
|
||||
|
||||
CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex);
|
||||
|
||||
static int
|
||||
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b);
|
||||
|
||||
static cairo_scaled_font_map_t *
|
||||
_cairo_scaled_font_map_lock (void)
|
||||
{
|
||||
CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex);
|
||||
|
||||
if (cairo_scaled_font_map == NULL)
|
||||
{
|
||||
cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t));
|
||||
if (cairo_scaled_font_map == NULL)
|
||||
goto CLEANUP_MUTEX_LOCK;
|
||||
|
||||
cairo_scaled_font_map->hash_table =
|
||||
_cairo_hash_table_create (_cairo_scaled_font_keys_equal);
|
||||
|
||||
if (cairo_scaled_font_map->hash_table == NULL)
|
||||
goto CLEANUP_SCALED_FONT_MAP;
|
||||
|
||||
cairo_scaled_font_map->num_holdovers = 0;
|
||||
}
|
||||
|
||||
return cairo_scaled_font_map;
|
||||
|
||||
CLEANUP_SCALED_FONT_MAP:
|
||||
free (cairo_scaled_font_map);
|
||||
CLEANUP_MUTEX_LOCK:
|
||||
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_scaled_font_map_unlock (void)
|
||||
{
|
||||
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_scaled_font_map_destroy (void)
|
||||
{
|
||||
int i;
|
||||
cairo_scaled_font_map_t *font_map = cairo_scaled_font_map;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
|
||||
if (font_map == NULL)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
|
||||
|
||||
for (i = 0; i < font_map->num_holdovers; i++) {
|
||||
scaled_font = font_map->holdovers[i];
|
||||
/* We should only get here through the reset_static_data path
|
||||
* and there had better not be any active references at that
|
||||
* point. */
|
||||
assert (scaled_font->ref_count == 0);
|
||||
_cairo_hash_table_remove (font_map->hash_table,
|
||||
&scaled_font->hash_entry);
|
||||
_cairo_scaled_font_fini (scaled_font);
|
||||
free (scaled_font);
|
||||
}
|
||||
|
||||
_cairo_hash_table_destroy (font_map->hash_table);
|
||||
|
||||
free (cairo_scaled_font_map);
|
||||
cairo_scaled_font_map = NULL;
|
||||
}
|
||||
|
||||
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
|
||||
*
|
||||
* Not necessarily better than a lot of other hashes, but should be OK, and
|
||||
* well tested with binary data.
|
||||
*/
|
||||
|
||||
#define FNV_32_PRIME ((uint32_t)0x01000193)
|
||||
#define FNV1_32_INIT ((uint32_t)0x811c9dc5)
|
||||
|
||||
static uint32_t
|
||||
_hash_bytes_fnv (unsigned char *buffer,
|
||||
int len,
|
||||
uint32_t hval)
|
||||
{
|
||||
while (len--) {
|
||||
hval *= FNV_32_PRIME;
|
||||
hval ^= *buffer++;
|
||||
}
|
||||
|
||||
return hval;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options)
|
||||
{
|
||||
uint32_t hash = FNV1_32_INIT;
|
||||
|
||||
scaled_font->status = CAIRO_STATUS_SUCCESS;
|
||||
scaled_font->font_face = font_face;
|
||||
scaled_font->font_matrix = *font_matrix;
|
||||
scaled_font->ctm = *ctm;
|
||||
scaled_font->options = *options;
|
||||
|
||||
/* We do a bytewise hash on the font matrices, ignoring the
|
||||
* translation values. */
|
||||
hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx),
|
||||
sizeof(double) * 4,
|
||||
hash);
|
||||
hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->ctm.xx),
|
||||
sizeof(double) * 4,
|
||||
hash);
|
||||
|
||||
hash ^= (unsigned long) scaled_font->font_face;
|
||||
|
||||
hash ^= cairo_font_options_hash (&scaled_font->options);
|
||||
|
||||
scaled_font->hash_entry.hash = hash;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b)
|
||||
{
|
||||
cairo_scaled_font_t *key_a = abstract_key_a;
|
||||
cairo_scaled_font_t *key_b = abstract_key_b;
|
||||
|
||||
return (key_a->font_face == key_b->font_face &&
|
||||
memcmp ((unsigned char *)(&key_a->font_matrix.xx),
|
||||
(unsigned char *)(&key_b->font_matrix.xx),
|
||||
sizeof(double) * 4) == 0 &&
|
||||
memcmp ((unsigned char *)(&key_a->ctm.xx),
|
||||
(unsigned char *)(&key_b->ctm.xx),
|
||||
sizeof(double) * 4) == 0 &&
|
||||
cairo_font_options_equal (&key_a->options, &key_b->options));
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
const cairo_scaled_font_backend_t *backend)
|
||||
{
|
||||
scaled_font->ref_count = 1;
|
||||
|
||||
_cairo_scaled_font_init_key (scaled_font, font_face,
|
||||
font_matrix, ctm, options);
|
||||
|
||||
cairo_font_face_reference (font_face);
|
||||
|
||||
cairo_matrix_multiply (&scaled_font->scale,
|
||||
&scaled_font->font_matrix,
|
||||
&scaled_font->ctm);
|
||||
|
||||
scaled_font->backend = backend;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
if (scaled_font->font_face)
|
||||
cairo_font_face_destroy (scaled_font->font_face);
|
||||
|
||||
scaled_font->backend->fini (scaled_font);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_create:
|
||||
* @font_face: a #cairo_font_face_t
|
||||
* @font_matrix: font space to user space transformation matrix for the
|
||||
* font. In the simplest case of a N point font, this matrix is
|
||||
* just a scale by N, but it can also be used to shear the font
|
||||
* or stretch it unequally along the two axes. See
|
||||
* cairo_set_font_matrix().
|
||||
* @ctm: user to device transformation matrix with which the font will
|
||||
* be used.
|
||||
* @options: options to use when getting metrics for the font and
|
||||
* rendering with it.
|
||||
*
|
||||
* Creates a #cairo_scaled_font_t object from a font face and matrices that
|
||||
* describe the size of the font and the environment in which it will
|
||||
* be used.
|
||||
*
|
||||
* Return value: a newly created #cairo_scaled_font_t. Destroy with
|
||||
* cairo_scaled_font_destroy()
|
||||
**/
|
||||
cairo_scaled_font_t *
|
||||
cairo_scaled_font_create (cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_scaled_font_map_t *font_map;
|
||||
cairo_scaled_font_t key, *scaled_font = NULL;
|
||||
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
if (font_map == NULL)
|
||||
goto UNWIND;
|
||||
|
||||
_cairo_scaled_font_init_key (&key, font_face,
|
||||
font_matrix, ctm, options);
|
||||
|
||||
/* Return existing scaled_font if it exists in the hash table. */
|
||||
if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
|
||||
(cairo_hash_entry_t**) &scaled_font))
|
||||
{
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
return cairo_scaled_font_reference (scaled_font);
|
||||
}
|
||||
|
||||
/* Otherwise create it and insert it into the hash table. */
|
||||
status = font_face->backend->scaled_font_create (font_face, font_matrix,
|
||||
ctm, options, &scaled_font);
|
||||
if (status)
|
||||
goto UNWIND_FONT_MAP_LOCK;
|
||||
|
||||
status = _cairo_hash_table_insert (font_map->hash_table,
|
||||
&scaled_font->hash_entry);
|
||||
if (status)
|
||||
goto UNWIND_SCALED_FONT_CREATE;
|
||||
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
|
||||
return scaled_font;
|
||||
|
||||
UNWIND_SCALED_FONT_CREATE:
|
||||
/* We can't call _cairo_scaled_font_destroy here since it expects
|
||||
* that the font has already been successfully inserted into the
|
||||
* hash table. */
|
||||
_cairo_scaled_font_fini (scaled_font);
|
||||
free (scaled_font);
|
||||
UNWIND_FONT_MAP_LOCK:
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
UNWIND:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_reference:
|
||||
* @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case
|
||||
* this function does nothing)
|
||||
*
|
||||
* Increases the reference count on @scaled_font by one. This prevents
|
||||
* @scaled_font from being destroyed until a matching call to
|
||||
* cairo_scaled_font_destroy() is made.
|
||||
**/
|
||||
cairo_scaled_font_t *
|
||||
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
if (scaled_font == NULL)
|
||||
return NULL;
|
||||
|
||||
if (scaled_font->ref_count == (unsigned int)-1)
|
||||
return scaled_font;
|
||||
|
||||
/* If the original reference count is 0, then this font must have
|
||||
* been found in font_map->holdovers, (which means this caching is
|
||||
* actually working). So now we remove it from the holdovers
|
||||
* array. */
|
||||
if (scaled_font->ref_count == 0) {
|
||||
cairo_scaled_font_map_t *font_map;
|
||||
int i;
|
||||
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
{
|
||||
for (i = 0; i < font_map->num_holdovers; i++)
|
||||
if (font_map->holdovers[i] == scaled_font)
|
||||
break;
|
||||
assert (i < font_map->num_holdovers);
|
||||
|
||||
font_map->num_holdovers--;
|
||||
memmove (&font_map->holdovers[i],
|
||||
&font_map->holdovers[i+1],
|
||||
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
|
||||
}
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
}
|
||||
|
||||
scaled_font->ref_count++;
|
||||
|
||||
return scaled_font;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_destroy:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Decreases the reference count on @font by one. If the result
|
||||
* is zero, then @font and all associated resources are freed.
|
||||
* See cairo_scaled_font_reference().
|
||||
**/
|
||||
void
|
||||
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_scaled_font_map_t *font_map;
|
||||
|
||||
if (scaled_font == NULL)
|
||||
return;
|
||||
|
||||
if (scaled_font->ref_count == (unsigned int)-1)
|
||||
return;
|
||||
|
||||
if (--(scaled_font->ref_count) > 0)
|
||||
return;
|
||||
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
assert (font_map != NULL);
|
||||
{
|
||||
/* Rather than immediately destroying this object, we put it into
|
||||
* the font_map->holdovers array in case it will get used again
|
||||
* soon. To make room for it, we do actually destroy the
|
||||
* least-recently-used holdover.
|
||||
*/
|
||||
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
|
||||
cairo_scaled_font_t *lru;
|
||||
|
||||
lru = font_map->holdovers[0];
|
||||
assert (lru->ref_count == 0);
|
||||
|
||||
_cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
|
||||
|
||||
_cairo_scaled_font_fini (lru);
|
||||
free (lru);
|
||||
|
||||
font_map->num_holdovers--;
|
||||
memmove (&font_map->holdovers[0],
|
||||
&font_map->holdovers[1],
|
||||
font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
|
||||
}
|
||||
|
||||
font_map->holdovers[font_map->num_holdovers] = scaled_font;
|
||||
font_map->num_holdovers++;
|
||||
}
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
const char *utf8,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs)
|
||||
{
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
return scaled_font->backend->text_to_glyphs (scaled_font, utf8, glyphs, num_glyphs);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
return scaled_font->backend->glyph_extents (scaled_font, glyphs, num_glyphs, extents);
|
||||
}
|
||||
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_box_t *bbox)
|
||||
{
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
return scaled_font->backend->glyph_bbox (scaled_font, glyphs, num_glyphs, bbox);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t operator,
|
||||
cairo_pattern_t *pattern,
|
||||
cairo_surface_t *surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
status = _cairo_surface_show_glyphs (scaled_font, operator, pattern,
|
||||
surface,
|
||||
source_x, source_y,
|
||||
dest_x, dest_y,
|
||||
width, height,
|
||||
glyphs, num_glyphs);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
/* Surface display routine either does not exist or failed. */
|
||||
return scaled_font->backend->show_glyphs (scaled_font, operator, pattern,
|
||||
surface,
|
||||
source_x, source_y,
|
||||
dest_x, dest_y,
|
||||
width, height,
|
||||
glyphs, num_glyphs);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
return scaled_font->backend->glyph_path (scaled_font, glyphs, num_glyphs, path);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_cache_key_t *key)
|
||||
{
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
scaled_font->backend->get_glyph_cache_key (scaled_font, key);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *extents)
|
||||
{
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
return scaled_font->backend->font_extents (scaled_font, extents);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
|
||||
const cairo_unscaled_font_backend_t *backend)
|
||||
|
@ -978,307 +446,11 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
|
|||
free (unscaled_font);
|
||||
}
|
||||
|
||||
/* Public font API follows. */
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_extents:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
* @extents: a #cairo_font_extents_t which to store the retrieved extents.
|
||||
*
|
||||
* Gets the metrics for a #cairo_scaled_font_t.
|
||||
**/
|
||||
void
|
||||
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *extents)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
double font_scale_x, font_scale_y;
|
||||
|
||||
if (scaled_font->status) {
|
||||
_cairo_scaled_font_set_error (scaled_font, scaled_font->status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = _cairo_scaled_font_font_extents (scaled_font, extents);
|
||||
if (status) {
|
||||
_cairo_scaled_font_set_error (scaled_font, status);
|
||||
return;
|
||||
}
|
||||
|
||||
_cairo_matrix_compute_scale_factors (&scaled_font->font_matrix,
|
||||
&font_scale_x, &font_scale_y,
|
||||
/* XXX */ 1);
|
||||
|
||||
/*
|
||||
* The font responded in unscaled units, scale by the font
|
||||
* matrix scale factors to get to user space
|
||||
*/
|
||||
|
||||
extents->ascent *= font_scale_y;
|
||||
extents->descent *= font_scale_y;
|
||||
extents->height *= font_scale_y;
|
||||
extents->max_x_advance *= font_scale_x;
|
||||
extents->max_y_advance *= font_scale_y;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_font_glyph_extents:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
* @glyphs: an array of glyph IDs with X and Y offsets.
|
||||
* @num_glyphs: the number of glyphs in the @glyphs array
|
||||
* @extents: a #cairo_text_extents_t which to store the retrieved extents.
|
||||
*
|
||||
* cairo_font_glyph_extents() gets the overall metrics for a string of
|
||||
* glyphs. The X and Y offsets in @glyphs are taken from an origin of 0,0.
|
||||
**/
|
||||
void
|
||||
cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_glyph_t origin_glyph;
|
||||
cairo_text_extents_t origin_extents;
|
||||
int i;
|
||||
double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
|
||||
double x_pos = 0.0, y_pos = 0.0;
|
||||
int set = 0;
|
||||
|
||||
if (scaled_font->status) {
|
||||
_cairo_scaled_font_set_error (scaled_font, scaled_font->status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!num_glyphs)
|
||||
{
|
||||
extents->x_bearing = 0.0;
|
||||
extents->y_bearing = 0.0;
|
||||
extents->width = 0.0;
|
||||
extents->height = 0.0;
|
||||
extents->x_advance = 0.0;
|
||||
extents->y_advance = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
double x, y;
|
||||
double wm, hm;
|
||||
|
||||
origin_glyph = glyphs[i];
|
||||
origin_glyph.x = 0.0;
|
||||
origin_glyph.y = 0.0;
|
||||
status = _cairo_scaled_font_glyph_extents (scaled_font,
|
||||
&origin_glyph, 1,
|
||||
&origin_extents);
|
||||
|
||||
/*
|
||||
* Transform font space metrics into user space metrics
|
||||
* by running the corners through the font matrix and
|
||||
* expanding the bounding box as necessary
|
||||
*/
|
||||
x = origin_extents.x_bearing;
|
||||
y = origin_extents.y_bearing;
|
||||
cairo_matrix_transform_point (&scaled_font->font_matrix,
|
||||
&x, &y);
|
||||
|
||||
for (hm = 0.0; hm <= 1.0; hm += 1.0)
|
||||
for (wm = 0.0; wm <= 1.0; wm += 1.0)
|
||||
{
|
||||
x = origin_extents.x_bearing + origin_extents.width * wm;
|
||||
y = origin_extents.y_bearing + origin_extents.height * hm;
|
||||
cairo_matrix_transform_point (&scaled_font->font_matrix,
|
||||
&x, &y);
|
||||
x += glyphs[i].x;
|
||||
y += glyphs[i].y;
|
||||
if (!set)
|
||||
{
|
||||
min_x = max_x = x;
|
||||
min_y = max_y = y;
|
||||
set = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x < min_x) min_x = x;
|
||||
if (x > max_x) max_x = x;
|
||||
if (y < min_y) min_y = y;
|
||||
if (y > max_y) max_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
x = origin_extents.x_advance;
|
||||
y = origin_extents.y_advance;
|
||||
cairo_matrix_transform_point (&scaled_font->font_matrix,
|
||||
&x, &y);
|
||||
x_pos = glyphs[i].x + x;
|
||||
y_pos = glyphs[i].y + y;
|
||||
}
|
||||
|
||||
extents->x_bearing = min_x - glyphs[0].x;
|
||||
extents->y_bearing = min_y - glyphs[0].y;
|
||||
extents->width = max_x - min_x;
|
||||
extents->height = max_y - min_y;
|
||||
extents->x_advance = x_pos - glyphs[0].x;
|
||||
extents->y_advance = y_pos - glyphs[0].y;
|
||||
}
|
||||
|
||||
/* Now we implement functions to access a default global image & metrics
|
||||
* cache.
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
_cairo_glyph_cache_hash (void *cache, void *key)
|
||||
{
|
||||
cairo_glyph_cache_key_t *in;
|
||||
in = (cairo_glyph_cache_key_t *) key;
|
||||
return
|
||||
((unsigned long) in->unscaled)
|
||||
^ ((unsigned long) in->scale.xx)
|
||||
^ ((unsigned long) in->scale.yx)
|
||||
^ ((unsigned long) in->scale.xy)
|
||||
^ ((unsigned long) in->scale.yy)
|
||||
^ (in->flags * 1451) /* 1451 is just an abitrary prime */
|
||||
^ in->index;
|
||||
}
|
||||
|
||||
int
|
||||
_cairo_glyph_cache_keys_equal (void *cache,
|
||||
void *k1,
|
||||
void *k2)
|
||||
{
|
||||
cairo_glyph_cache_key_t *a, *b;
|
||||
a = (cairo_glyph_cache_key_t *) k1;
|
||||
b = (cairo_glyph_cache_key_t *) k2;
|
||||
return (a->index == b->index)
|
||||
&& (a->unscaled == b->unscaled)
|
||||
&& (a->flags == b->flags)
|
||||
&& (a->scale.xx == b->scale.xx)
|
||||
&& (a->scale.yx == b->scale.yx)
|
||||
&& (a->scale.xy == b->scale.xy)
|
||||
&& (a->scale.yy == b->scale.yy);
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_image_glyph_cache_create_entry (void *cache,
|
||||
void *key,
|
||||
void **return_value)
|
||||
{
|
||||
cairo_glyph_cache_key_t *k = (cairo_glyph_cache_key_t *) key;
|
||||
cairo_image_glyph_cache_entry_t *im;
|
||||
cairo_status_t status;
|
||||
|
||||
im = calloc (1, sizeof (cairo_image_glyph_cache_entry_t));
|
||||
if (im == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
im->key = *k;
|
||||
status = im->key.unscaled->backend->create_glyph (im->key.unscaled,
|
||||
im);
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS) {
|
||||
free (im);
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_unscaled_font_reference (im->key.unscaled);
|
||||
|
||||
im->key.base.memory =
|
||||
sizeof (cairo_image_glyph_cache_entry_t)
|
||||
+ (im->image ?
|
||||
sizeof (cairo_image_surface_t)
|
||||
+ 28 * sizeof (int) /* rough guess at size of pixman image structure */
|
||||
+ (im->image->height * im->image->stride) : 0);
|
||||
|
||||
*return_value = im;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_image_glyph_cache_destroy_entry (void *cache,
|
||||
void *value)
|
||||
{
|
||||
cairo_image_glyph_cache_entry_t *im;
|
||||
|
||||
im = (cairo_image_glyph_cache_entry_t *) value;
|
||||
_cairo_unscaled_font_destroy (im->key.unscaled);
|
||||
cairo_surface_destroy (&(im->image->base));
|
||||
free (im);
|
||||
}
|
||||
|
||||
static void
|
||||
_image_glyph_cache_destroy_cache (void *cache)
|
||||
{
|
||||
free (cache);
|
||||
}
|
||||
|
||||
static const cairo_cache_backend_t cairo_image_cache_backend = {
|
||||
_cairo_glyph_cache_hash,
|
||||
_cairo_glyph_cache_keys_equal,
|
||||
_image_glyph_cache_create_entry,
|
||||
_image_glyph_cache_destroy_entry,
|
||||
_image_glyph_cache_destroy_cache
|
||||
};
|
||||
|
||||
CAIRO_MUTEX_DECLARE(_global_image_glyph_cache_mutex);
|
||||
|
||||
static cairo_cache_t *
|
||||
_global_image_glyph_cache = NULL;
|
||||
|
||||
void
|
||||
_cairo_lock_global_image_glyph_cache()
|
||||
{
|
||||
CAIRO_MUTEX_LOCK (_global_image_glyph_cache_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_unlock_global_image_glyph_cache()
|
||||
{
|
||||
if (_global_image_glyph_cache) {
|
||||
_cairo_cache_shrink_to (_global_image_glyph_cache,
|
||||
CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT);
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (_global_image_glyph_cache_mutex);
|
||||
}
|
||||
|
||||
cairo_cache_t *
|
||||
_cairo_get_global_image_glyph_cache ()
|
||||
{
|
||||
if (_global_image_glyph_cache == NULL) {
|
||||
_global_image_glyph_cache = malloc (sizeof (cairo_cache_t));
|
||||
|
||||
if (_global_image_glyph_cache == NULL)
|
||||
goto FAIL;
|
||||
|
||||
if (_cairo_cache_init (_global_image_glyph_cache,
|
||||
&cairo_image_cache_backend,
|
||||
0))
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
return _global_image_glyph_cache;
|
||||
|
||||
FAIL:
|
||||
if (_global_image_glyph_cache)
|
||||
free (_global_image_glyph_cache);
|
||||
_global_image_glyph_cache = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_font_reset_static_data (void)
|
||||
{
|
||||
_cairo_scaled_font_map_destroy ();
|
||||
|
||||
_cairo_lock_global_image_glyph_cache();
|
||||
_cairo_cache_destroy (_global_image_glyph_cache);
|
||||
_global_image_glyph_cache = NULL;
|
||||
_cairo_unlock_global_image_glyph_cache();
|
||||
|
||||
CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex);
|
||||
_cairo_hash_table_destroy (cairo_toy_font_face_hash_table);
|
||||
cairo_toy_font_face_hash_table = NULL;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -49,21 +49,21 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_font_face_t *
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_ft_font_options_substitute (const cairo_font_options_t *options,
|
||||
FcPattern *pattern);
|
||||
|
||||
cairo_font_face_t *
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
||||
int load_flags);
|
||||
|
||||
FT_Face
|
||||
cairo_public FT_Face
|
||||
cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
|
|
@ -35,6 +35,9 @@ typedef struct _cairo_glitz_surface {
|
|||
pixman_region16_t *clip;
|
||||
} cairo_glitz_surface_t;
|
||||
|
||||
static const cairo_surface_backend_t *
|
||||
_cairo_glitz_surface_get_backend (void);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
@ -81,7 +84,8 @@ _cairo_glitz_surface_create_similar (void *abstract_src,
|
|||
|
||||
drawable = glitz_surface_get_drawable (src->surface);
|
||||
|
||||
gformat = glitz_find_standard_format (drawable,
|
||||
gformat =
|
||||
glitz_find_standard_format (drawable,
|
||||
_glitz_format_from_content (content));
|
||||
if (!gformat) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
@ -356,7 +360,9 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
|
|||
else if (_cairo_surface_is_image (src))
|
||||
{
|
||||
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
|
||||
cairo_content_t content = _cairo_content_from_format (image_src->format);
|
||||
cairo_content_t content;
|
||||
|
||||
content = _cairo_content_from_format (image_src->format);
|
||||
|
||||
clone = (cairo_glitz_surface_t *)
|
||||
_cairo_glitz_surface_create_similar (surface, content,
|
||||
|
@ -430,12 +436,14 @@ _glitz_operator (cairo_operator_t op)
|
|||
case CAIRO_OPERATOR_ADD:
|
||||
return GLITZ_OPERATOR_ADD;
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
/* XXX: OVER is definitely not the right thing here, (but it
|
||||
* is what the original glitz backend code has always
|
||||
* done). Cairo's SATURATE operator is the native GL
|
||||
* compositing mode, (from my understanding). So why isn't
|
||||
* there a GLITZ_OPERATOR_SATURATE for us to use here? */
|
||||
return GLITZ_OPERATOR_OVER;
|
||||
/* XXX: This line should never be reached. Glitz backend should bail
|
||||
out earlier if saturate operator is used. OpenGL can't do saturate
|
||||
with pre-multiplied colors. Solid colors can still be done as we
|
||||
can just un-pre-multiply them. However, support for that will have
|
||||
to be added to glitz. */
|
||||
|
||||
/* fall-through */
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
|
@ -454,11 +462,54 @@ _glitz_operator (cairo_operator_t op)
|
|||
static glitz_status_t
|
||||
_glitz_ensure_target (glitz_surface_t *surface)
|
||||
{
|
||||
if (glitz_surface_get_attached_drawable (surface) ||
|
||||
CAIRO_GLITZ_FEATURE_OK (surface, FRAMEBUFFER_OBJECT))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (!glitz_surface_get_attached_drawable (surface))
|
||||
{
|
||||
glitz_drawable_format_t *target_format, templ;
|
||||
glitz_format_t *format;
|
||||
glitz_drawable_t *drawable, *target;
|
||||
unsigned int width, height;
|
||||
unsigned long mask;
|
||||
|
||||
drawable = glitz_surface_get_drawable (surface);
|
||||
format = glitz_surface_get_format (surface);
|
||||
width = glitz_surface_get_width (surface);
|
||||
height = glitz_surface_get_height (surface);
|
||||
|
||||
if (format->type != GLITZ_FORMAT_TYPE_COLOR)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
templ.color = format->color;
|
||||
templ.depth_size = 0;
|
||||
templ.stencil_size = 0;
|
||||
templ.doublebuffer = 0;
|
||||
templ.samples = 1;
|
||||
|
||||
mask =
|
||||
GLITZ_FORMAT_RED_SIZE_MASK |
|
||||
GLITZ_FORMAT_GREEN_SIZE_MASK |
|
||||
GLITZ_FORMAT_BLUE_SIZE_MASK |
|
||||
GLITZ_FORMAT_ALPHA_SIZE_MASK |
|
||||
GLITZ_FORMAT_DEPTH_SIZE_MASK |
|
||||
GLITZ_FORMAT_STENCIL_SIZE_MASK |
|
||||
GLITZ_FORMAT_DOUBLEBUFFER_MASK |
|
||||
GLITZ_FORMAT_SAMPLES_MASK;
|
||||
|
||||
target_format = glitz_find_drawable_format (drawable, mask, &templ, 0);
|
||||
if (!target_format)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
target = glitz_create_drawable (drawable, target_format,
|
||||
width, height);
|
||||
if (!target)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
glitz_surface_attach (surface, target,
|
||||
GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
|
||||
|
||||
glitz_drawable_destroy (target);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct _cairo_glitz_surface_attributes {
|
||||
|
@ -970,7 +1021,8 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
{
|
||||
_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
|
||||
|
||||
status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base, dst,
|
||||
status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base,
|
||||
dst,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
&src, &attributes);
|
||||
|
@ -1218,8 +1270,6 @@ _cairo_glitz_surface_get_extents (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
|
||||
|
||||
#define CAIRO_GLITZ_AREA_AVAILABLE 0
|
||||
#define CAIRO_GLITZ_AREA_DIVIDED 1
|
||||
#define CAIRO_GLITZ_AREA_OCCUPIED 2
|
||||
|
@ -1530,6 +1580,56 @@ _cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root)
|
|||
_cairo_glitz_area_destroy (root->area);
|
||||
}
|
||||
|
||||
typedef struct _cairo_glitz_surface_font_private {
|
||||
cairo_glitz_root_area_t root;
|
||||
glitz_surface_t *surface;
|
||||
} cairo_glitz_surface_font_private_t;
|
||||
|
||||
typedef struct _cairo_glitz_surface_glyph_private {
|
||||
cairo_glitz_area_t *area;
|
||||
cairo_bool_t locked;
|
||||
cairo_point_double_t p1, p2;
|
||||
} cairo_glitz_surface_glyph_private_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area,
|
||||
void *closure)
|
||||
{
|
||||
cairo_glitz_surface_glyph_private_t *glyph_private = closure;
|
||||
|
||||
glyph_private->area = area;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area,
|
||||
void *closure)
|
||||
{
|
||||
cairo_glitz_surface_glyph_private_t *glyph_private = closure;
|
||||
|
||||
glyph_private->area = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_glitz_glyph_compare (cairo_glitz_area_t *area,
|
||||
void *closure1,
|
||||
void *closure2)
|
||||
{
|
||||
cairo_glitz_surface_glyph_private_t *glyph_private = closure1;
|
||||
|
||||
if (glyph_private->locked)
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = {
|
||||
_cairo_glitz_glyph_move_in,
|
||||
_cairo_glitz_glyph_move_out,
|
||||
_cairo_glitz_glyph_compare
|
||||
};
|
||||
|
||||
#define GLYPH_CACHE_TEXTURE_SIZE 512
|
||||
#define GLYPH_CACHE_MAX_LEVEL 64
|
||||
#define GLYPH_CACHE_MAX_HEIGHT 72
|
||||
|
@ -1549,266 +1649,170 @@ _cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root)
|
|||
WRITE_VEC2 (ptr, _vx1, _vy2); \
|
||||
WRITE_VEC2 (ptr, (p1)->x, (p1)->y)
|
||||
|
||||
typedef struct _cairo_glitz_glyph_cache {
|
||||
cairo_cache_t base;
|
||||
cairo_glitz_root_area_t root;
|
||||
glitz_surface_t *surface;
|
||||
} cairo_glitz_glyph_cache_t;
|
||||
|
||||
typedef struct {
|
||||
cairo_glyph_cache_key_t key;
|
||||
int ref_count;
|
||||
cairo_glyph_size_t size;
|
||||
cairo_glitz_area_t *area;
|
||||
cairo_bool_t locked;
|
||||
cairo_point_double_t p1, p2;
|
||||
} cairo_glitz_glyph_cache_entry_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area,
|
||||
void *closure)
|
||||
_cairo_glitz_surface_font_init (cairo_glitz_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_format_t format)
|
||||
{
|
||||
cairo_glitz_glyph_cache_entry_t *entry = closure;
|
||||
|
||||
entry->area = area;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area,
|
||||
void *closure)
|
||||
{
|
||||
cairo_glitz_glyph_cache_entry_t *entry = closure;
|
||||
|
||||
entry->area = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_glitz_glyph_compare (cairo_glitz_area_t *area,
|
||||
void *closure1,
|
||||
void *closure2)
|
||||
{
|
||||
cairo_glitz_glyph_cache_entry_t *entry = closure1;
|
||||
|
||||
if (entry->locked)
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = {
|
||||
_cairo_glitz_glyph_move_in,
|
||||
_cairo_glitz_glyph_move_out,
|
||||
_cairo_glitz_glyph_compare
|
||||
};
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_glyph_cache_create_entry (void *abstract_cache,
|
||||
void *abstract_key,
|
||||
void **return_entry)
|
||||
{
|
||||
cairo_glitz_glyph_cache_entry_t *entry;
|
||||
cairo_glyph_cache_key_t *key = abstract_key;
|
||||
|
||||
cairo_status_t status;
|
||||
cairo_cache_t *im_cache;
|
||||
cairo_image_glyph_cache_entry_t *im;
|
||||
|
||||
unsigned long entry_memory = 0;
|
||||
|
||||
entry = malloc (sizeof (cairo_glitz_glyph_cache_entry_t));
|
||||
if (!entry)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_lock_global_image_glyph_cache ();
|
||||
|
||||
im_cache = _cairo_get_global_image_glyph_cache ();
|
||||
if (im_cache == NULL) {
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
free (entry);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = _cairo_cache_lookup (im_cache, key, (void **) (&im), NULL);
|
||||
if (status != CAIRO_STATUS_SUCCESS || im == NULL) {
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
free (entry);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (im->image)
|
||||
entry_memory = im->image->width * im->image->stride;
|
||||
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
|
||||
entry->ref_count = 1;
|
||||
entry->key = *key;
|
||||
entry->key.base.memory = entry_memory;
|
||||
entry->area = NULL;
|
||||
entry->locked = FALSE;
|
||||
|
||||
_cairo_unscaled_font_reference (entry->key.unscaled);
|
||||
|
||||
*return_entry = entry;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_glitz_glyph_cache_destroy_entry (void *abstract_cache,
|
||||
void *abstract_entry)
|
||||
{
|
||||
cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
|
||||
|
||||
entry->ref_count--;
|
||||
if (entry->ref_count)
|
||||
return;
|
||||
|
||||
if (entry->area)
|
||||
_cairo_glitz_area_move_out (entry->area);
|
||||
|
||||
_cairo_unscaled_font_destroy (entry->key.unscaled);
|
||||
|
||||
free (entry);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_glitz_glyph_cache_entry_reference (void *abstract_entry)
|
||||
{
|
||||
cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
|
||||
|
||||
entry->ref_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_glitz_glyph_cache_destroy_cache (void *abstract_cache)
|
||||
{
|
||||
cairo_glitz_glyph_cache_t *cache = abstract_cache;
|
||||
|
||||
_cairo_glitz_root_area_fini (&cache->root);
|
||||
|
||||
glitz_surface_destroy (cache->surface);
|
||||
}
|
||||
|
||||
static const cairo_cache_backend_t _cairo_glitz_glyph_cache_backend = {
|
||||
_cairo_glyph_cache_hash,
|
||||
_cairo_glyph_cache_keys_equal,
|
||||
_cairo_glitz_glyph_cache_create_entry,
|
||||
_cairo_glitz_glyph_cache_destroy_entry,
|
||||
_cairo_glitz_glyph_cache_destroy_cache
|
||||
};
|
||||
|
||||
static cairo_glitz_glyph_cache_t *_cairo_glitz_glyph_caches = NULL;
|
||||
|
||||
static cairo_glitz_glyph_cache_t *
|
||||
_cairo_glitz_get_glyph_cache (cairo_glitz_surface_t *surface)
|
||||
{
|
||||
cairo_glitz_glyph_cache_t *cache;
|
||||
cairo_glitz_surface_font_private_t *font_private;
|
||||
glitz_drawable_t *drawable;
|
||||
glitz_format_t *format;
|
||||
|
||||
/*
|
||||
* FIXME: caches should be thread specific, display specific and screen
|
||||
* specific.
|
||||
*/
|
||||
|
||||
if (_cairo_glitz_glyph_caches)
|
||||
return _cairo_glitz_glyph_caches;
|
||||
glitz_format_t *surface_format = NULL;
|
||||
cairo_int_status_t status;
|
||||
|
||||
drawable = glitz_surface_get_drawable (surface->surface);
|
||||
|
||||
format = glitz_find_standard_format (drawable, GLITZ_STANDARD_A8);
|
||||
if (!format)
|
||||
return NULL;
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_A8:
|
||||
surface_format =
|
||||
glitz_find_standard_format (drawable, GLITZ_STANDARD_A8);
|
||||
break;
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
surface_format =
|
||||
glitz_find_standard_format (drawable, GLITZ_STANDARD_ARGB32);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cache = malloc (sizeof (cairo_glitz_glyph_cache_t));
|
||||
if (!cache)
|
||||
return NULL;
|
||||
if (!surface_format)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
cache->surface =
|
||||
glitz_surface_create (drawable, format,
|
||||
font_private = malloc (sizeof (cairo_glitz_surface_font_private_t));
|
||||
if (!font_private)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
font_private->surface = glitz_surface_create (drawable, surface_format,
|
||||
GLYPH_CACHE_TEXTURE_SIZE,
|
||||
GLYPH_CACHE_TEXTURE_SIZE,
|
||||
0, NULL);
|
||||
if (cache->surface == NULL)
|
||||
if (font_private->surface == NULL)
|
||||
{
|
||||
free (cache);
|
||||
return NULL;
|
||||
free (font_private);
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (_cairo_glitz_root_area_init (&cache->root,
|
||||
if (format == CAIRO_FORMAT_ARGB32)
|
||||
glitz_surface_set_component_alpha (font_private->surface, 1);
|
||||
|
||||
status = _cairo_glitz_root_area_init (&font_private->root,
|
||||
GLYPH_CACHE_MAX_LEVEL,
|
||||
GLYPH_CACHE_TEXTURE_SIZE,
|
||||
GLYPH_CACHE_TEXTURE_SIZE,
|
||||
&_cairo_glitz_area_funcs))
|
||||
&_cairo_glitz_area_funcs);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
glitz_surface_destroy (cache->surface);
|
||||
free (cache);
|
||||
return NULL;
|
||||
glitz_surface_destroy (font_private->surface);
|
||||
free (font_private);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (_cairo_cache_init (&cache->base,
|
||||
&_cairo_glitz_glyph_cache_backend,
|
||||
CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT))
|
||||
{
|
||||
_cairo_glitz_root_area_fini (&cache->root);
|
||||
glitz_surface_destroy (cache->surface);
|
||||
free (cache);
|
||||
return NULL;
|
||||
scaled_font->surface_private = font_private;
|
||||
scaled_font->surface_backend = _cairo_glitz_surface_get_backend ();
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_glitz_glyph_caches = cache;
|
||||
static void
|
||||
_cairo_glitz_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_glitz_surface_font_private_t *font_private;
|
||||
|
||||
return cache;
|
||||
font_private = scaled_font->surface_private;
|
||||
if (font_private)
|
||||
{
|
||||
_cairo_glitz_root_area_fini (&font_private->root);
|
||||
glitz_surface_destroy (font_private->surface);
|
||||
free (font_private);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_glitz_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_glitz_surface_glyph_private_t *glyph_private;
|
||||
|
||||
glyph_private = scaled_glyph->surface_private;
|
||||
if (glyph_private)
|
||||
{
|
||||
if (glyph_private->area)
|
||||
_cairo_glitz_area_move_out (glyph_private->area);
|
||||
|
||||
free (glyph_private);
|
||||
}
|
||||
}
|
||||
|
||||
#define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536)
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_cache_glyph (cairo_glitz_glyph_cache_t *cache,
|
||||
cairo_glitz_glyph_cache_entry_t *entry,
|
||||
cairo_image_glyph_cache_entry_t *image_entry)
|
||||
_cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
|
||||
cairo_glitz_surface_font_private_t *font_private;
|
||||
cairo_glitz_surface_glyph_private_t *glyph_private;
|
||||
glitz_point_fixed_t p1, p2;
|
||||
glitz_pixel_format_t pf;
|
||||
glitz_buffer_t *buffer;
|
||||
pixman_format_t *format;
|
||||
int am, rm, gm, bm;
|
||||
cairo_int_status_t status;
|
||||
|
||||
entry->size = image_entry->size;
|
||||
glyph_private = scaled_glyph->surface_private;
|
||||
if (glyph_private == NULL)
|
||||
{
|
||||
glyph_private = malloc (sizeof (cairo_glitz_surface_glyph_private_t));
|
||||
if (!glyph_private)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (entry->size.width > GLYPH_CACHE_MAX_WIDTH ||
|
||||
entry->size.height > GLYPH_CACHE_MAX_HEIGHT)
|
||||
glyph_private->area = NULL;
|
||||
glyph_private->locked = FALSE;
|
||||
|
||||
scaled_glyph->surface_private = (void *) glyph_private;
|
||||
}
|
||||
|
||||
if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH ||
|
||||
glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if ((entry->size.width == 0 && entry->size.height == 0) ||
|
||||
!image_entry->image)
|
||||
if (scaled_font->surface_private == NULL)
|
||||
{
|
||||
entry->area = &_empty_area;
|
||||
status = _cairo_glitz_surface_font_init (surface, scaled_font,
|
||||
glyph_surface->format);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
font_private = scaled_font->surface_private;
|
||||
|
||||
if (glyph_surface->width == 0 || glyph_surface->height == 0)
|
||||
{
|
||||
glyph_private->area = &_empty_area;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
format = pixman_image_get_format (image_entry->image->pixman_image);
|
||||
format = pixman_image_get_format (glyph_surface->pixman_image);
|
||||
if (!format)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (_cairo_glitz_area_find (cache->root.area,
|
||||
entry->size.width,
|
||||
entry->size.height,
|
||||
FALSE, entry))
|
||||
if (_cairo_glitz_area_find (font_private->root.area,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height,
|
||||
FALSE, glyph_private))
|
||||
{
|
||||
if (_cairo_glitz_area_find (cache->root.area,
|
||||
entry->size.width,
|
||||
entry->size.height,
|
||||
TRUE, entry))
|
||||
if (_cairo_glitz_area_find (font_private->root.area,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height,
|
||||
TRUE, glyph_private))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
buffer = glitz_buffer_create_for_data (image_entry->image->data);
|
||||
buffer = glitz_buffer_create_for_data (glyph_surface->data);
|
||||
if (!buffer)
|
||||
{
|
||||
_cairo_glitz_area_move_out (entry->area);
|
||||
_cairo_glitz_area_move_out (glyph_private->area);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -1819,32 +1823,32 @@ _cairo_glitz_cache_glyph (cairo_glitz_glyph_cache_t *cache,
|
|||
pf.masks.green_mask = gm;
|
||||
pf.masks.blue_mask = bm;
|
||||
|
||||
pf.bytes_per_line = image_entry->image->stride;
|
||||
pf.bytes_per_line = glyph_surface->stride;
|
||||
pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP;
|
||||
pf.xoffset = 0;
|
||||
pf.skip_lines = 0;
|
||||
|
||||
glitz_set_pixels (cache->surface,
|
||||
entry->area->x,
|
||||
entry->area->y,
|
||||
entry->size.width,
|
||||
entry->size.height,
|
||||
glitz_set_pixels (font_private->surface,
|
||||
glyph_private->area->x,
|
||||
glyph_private->area->y,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height,
|
||||
&pf, buffer);
|
||||
|
||||
glitz_buffer_destroy (buffer);
|
||||
|
||||
p1.x = entry->area->x << 16;
|
||||
p1.y = entry->area->y << 16;
|
||||
p2.x = (entry->area->x + entry->size.width) << 16;
|
||||
p2.y = (entry->area->y + entry->size.height) << 16;
|
||||
p1.x = glyph_private->area->x << 16;
|
||||
p1.y = glyph_private->area->y << 16;
|
||||
p2.x = (glyph_private->area->x + glyph_surface->width) << 16;
|
||||
p2.y = (glyph_private->area->y + glyph_surface->height) << 16;
|
||||
|
||||
glitz_surface_translate_point (cache->surface, &p1, &p1);
|
||||
glitz_surface_translate_point (cache->surface, &p2, &p2);
|
||||
glitz_surface_translate_point (font_private->surface, &p1, &p1);
|
||||
glitz_surface_translate_point (font_private->surface, &p2, &p2);
|
||||
|
||||
entry->p1.x = FIXED_TO_FLOAT (p1.x);
|
||||
entry->p1.y = FIXED_TO_FLOAT (p1.y);
|
||||
entry->p2.x = FIXED_TO_FLOAT (p2.x);
|
||||
entry->p2.y = FIXED_TO_FLOAT (p2.y);
|
||||
glyph_private->p1.x = FIXED_TO_FLOAT (p1.x);
|
||||
glyph_private->p1.y = FIXED_TO_FLOAT (p1.y);
|
||||
glyph_private->p2.x = FIXED_TO_FLOAT (p2.x);
|
||||
glyph_private->p2.y = FIXED_TO_FLOAT (p2.y);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1866,16 +1870,16 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
int num_glyphs)
|
||||
{
|
||||
cairo_glitz_surface_attributes_t attributes;
|
||||
cairo_glitz_surface_glyph_private_t *glyph_private;
|
||||
cairo_glitz_surface_t *dst = abstract_surface;
|
||||
cairo_glitz_surface_t *src;
|
||||
cairo_glitz_glyph_cache_t *cache;
|
||||
cairo_glitz_glyph_cache_entry_t *stack_entries[N_STACK_BUF];
|
||||
cairo_glitz_glyph_cache_entry_t **entries;
|
||||
cairo_glyph_cache_key_t key;
|
||||
cairo_scaled_glyph_t *stack_scaled_glyphs[N_STACK_BUF];
|
||||
cairo_scaled_glyph_t **scaled_glyphs;
|
||||
glitz_float_t stack_vertices[N_STACK_BUF * 16];
|
||||
glitz_float_t *vertices;
|
||||
glitz_buffer_t *buffer;
|
||||
cairo_int_status_t status;
|
||||
int x_offset, y_offset;
|
||||
int i, cached_glyphs = 0;
|
||||
int remaining_glyps = num_glyphs;
|
||||
glitz_float_t x1, y1, x2, y2;
|
||||
|
@ -1892,6 +1896,10 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
};
|
||||
|
||||
if (scaled_font->surface_backend != NULL &&
|
||||
scaled_font->surface_backend != _cairo_glitz_surface_get_backend ())
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (op == CAIRO_OPERATOR_SATURATE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
|
@ -1916,12 +1924,12 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
if (!data)
|
||||
goto FAIL1;
|
||||
|
||||
entries = (cairo_glitz_glyph_cache_entry_t **) data;
|
||||
scaled_glyphs = (cairo_scaled_glyph_t **) data;
|
||||
vertices = (glitz_float_t *) (data + num_glyphs * sizeof (void *));
|
||||
}
|
||||
else
|
||||
{
|
||||
entries = stack_entries;
|
||||
scaled_glyphs = stack_scaled_glyphs;
|
||||
vertices = stack_vertices;
|
||||
}
|
||||
|
||||
|
@ -1929,48 +1937,38 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
if (!buffer)
|
||||
goto FAIL2;
|
||||
|
||||
cache = _cairo_glitz_get_glyph_cache (dst);
|
||||
if (!cache)
|
||||
{
|
||||
num_glyphs = 0;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
status = _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key);
|
||||
if (status)
|
||||
goto UNLOCK;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
key.index = glyphs[i].index;
|
||||
|
||||
status = _cairo_cache_lookup (&cache->base,
|
||||
&key,
|
||||
(void **) &entries[i],
|
||||
NULL);
|
||||
if (status)
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyphs[i]);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
num_glyphs = i;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
_cairo_glitz_glyph_cache_entry_reference (entries[i]);
|
||||
|
||||
if (entries[i]->area)
|
||||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
if (glyph_private && glyph_private->area)
|
||||
{
|
||||
remaining_glyps--;
|
||||
|
||||
if (entries[i]->area->width)
|
||||
if (glyph_private->area->width)
|
||||
{
|
||||
x1 = floor (glyphs[i].x + 0.5) + entries[i]->size.x;
|
||||
y1 = floor (glyphs[i].y + 0.5) + entries[i]->size.y;
|
||||
x2 = x1 + entries[i]->size.width;
|
||||
y2 = y1 + entries[i]->size.height;
|
||||
x_offset = scaled_glyphs[i]->surface->base.device_x_offset;
|
||||
y_offset = scaled_glyphs[i]->surface->base.device_y_offset;
|
||||
|
||||
x1 = floor (glyphs[i].x + 0.5) + x_offset;
|
||||
y1 = floor (glyphs[i].y + 0.5) + y_offset;
|
||||
x2 = x1 + glyph_private->area->width;
|
||||
y2 = y1 + glyph_private->area->height;
|
||||
|
||||
WRITE_BOX (vertices, x1, y1, x2, y2,
|
||||
&entries[i]->p1, &entries[i]->p2);
|
||||
&glyph_private->p1, &glyph_private->p2);
|
||||
|
||||
glyph_private->locked = TRUE;
|
||||
|
||||
entries[i]->locked = TRUE;
|
||||
cached_glyphs++;
|
||||
}
|
||||
}
|
||||
|
@ -1978,85 +1976,54 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
if (remaining_glyps)
|
||||
{
|
||||
cairo_cache_t *image_cache;
|
||||
cairo_image_glyph_cache_entry_t *image_entry;
|
||||
cairo_surface_t *image;
|
||||
cairo_glitz_surface_t *clone;
|
||||
|
||||
_cairo_lock_global_image_glyph_cache ();
|
||||
|
||||
image_cache = _cairo_get_global_image_glyph_cache ();
|
||||
if (!image_cache)
|
||||
{
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
if (!entries[i]->area)
|
||||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
if (!glyph_private || !glyph_private->area)
|
||||
{
|
||||
key.index = glyphs[i].index;
|
||||
|
||||
status = _cairo_cache_lookup (image_cache,
|
||||
&key,
|
||||
(void **) &image_entry,
|
||||
NULL);
|
||||
status = _cairo_glitz_surface_add_glyph (dst,
|
||||
scaled_font,
|
||||
scaled_glyphs[i]);
|
||||
if (status)
|
||||
{
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
goto UNLOCK;
|
||||
|
||||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
}
|
||||
|
||||
status = _cairo_glitz_cache_glyph (cache,
|
||||
entries[i],
|
||||
image_entry);
|
||||
if (status)
|
||||
{
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
goto UNLOCK;
|
||||
}
|
||||
}
|
||||
x_offset = scaled_glyphs[i]->surface->base.device_x_offset;
|
||||
y_offset = scaled_glyphs[i]->surface->base.device_y_offset;
|
||||
|
||||
x1 = floor (glyphs[i].x + 0.5);
|
||||
y1 = floor (glyphs[i].y + 0.5);
|
||||
x1 = floor (glyphs[i].x + 0.5) + x_offset;
|
||||
y1 = floor (glyphs[i].y + 0.5) + y_offset;
|
||||
|
||||
if (entries[i]->area)
|
||||
if (glyph_private->area)
|
||||
{
|
||||
if (entries[i]->area->width)
|
||||
if (glyph_private->area->width)
|
||||
{
|
||||
x1 += entries[i]->size.x;
|
||||
y1 += entries[i]->size.y;
|
||||
x2 = x1 + entries[i]->size.width;
|
||||
y2 = y1 + entries[i]->size.height;
|
||||
x2 = x1 + glyph_private->area->width;
|
||||
y2 = y1 + glyph_private->area->height;
|
||||
|
||||
WRITE_BOX (vertices, x1, y1, x2, y2,
|
||||
&entries[i]->p1, &entries[i]->p2);
|
||||
&glyph_private->p1, &glyph_private->p2);
|
||||
|
||||
glyph_private->locked = TRUE;
|
||||
|
||||
entries[i]->locked = TRUE;
|
||||
cached_glyphs++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 += image_entry->size.x;
|
||||
y1 += image_entry->size.y;
|
||||
|
||||
if (!image_entry->image)
|
||||
continue;
|
||||
|
||||
image = &image_entry->image->base;
|
||||
image = &scaled_glyphs[i]->surface->base;
|
||||
status =
|
||||
_cairo_glitz_surface_clone_similar (abstract_surface,
|
||||
image,
|
||||
(cairo_surface_t **)
|
||||
&clone);
|
||||
if (status)
|
||||
{
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
glitz_composite (_glitz_operator (op),
|
||||
src->surface,
|
||||
|
@ -2066,8 +2033,8 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
src_y + attributes.base.y_offset + y1,
|
||||
0, 0,
|
||||
x1, y1,
|
||||
image_entry->size.width,
|
||||
image_entry->size.height);
|
||||
scaled_glyphs[i]->surface->width,
|
||||
scaled_glyphs[i]->surface->height);
|
||||
|
||||
cairo_surface_destroy (&clone->base);
|
||||
|
||||
|
@ -2075,17 +2042,16 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
GLITZ_STATUS_NOT_SUPPORTED)
|
||||
{
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
goto UNLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_unlock_global_image_glyph_cache ();
|
||||
}
|
||||
|
||||
if (cached_glyphs)
|
||||
{
|
||||
cairo_glitz_surface_font_private_t *font_private;
|
||||
|
||||
glitz_set_geometry (dst->surface,
|
||||
GLITZ_GEOMETRY_TYPE_VERTEX,
|
||||
(glitz_geometry_format_t *) &format,
|
||||
|
@ -2093,9 +2059,11 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
glitz_set_array (dst->surface, 0, 4, cached_glyphs * 4, 0, 0);
|
||||
|
||||
font_private = scaled_font->surface_private;
|
||||
|
||||
glitz_composite (_glitz_operator (op),
|
||||
src->surface,
|
||||
cache->surface,
|
||||
font_private->surface,
|
||||
dst->surface,
|
||||
src_x + attributes.base.x_offset,
|
||||
src_y + attributes.base.y_offset,
|
||||
|
@ -2112,17 +2080,18 @@ UNLOCK:
|
|||
if (cached_glyphs)
|
||||
{
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
entries[i]->locked = FALSE;
|
||||
{
|
||||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
if (glyph_private)
|
||||
glyph_private->locked = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
_cairo_glitz_glyph_cache_destroy_entry (cache, entries[i]);
|
||||
|
||||
glitz_buffer_destroy (buffer);
|
||||
|
||||
FAIL2:
|
||||
if (num_glyphs > N_STACK_BUF)
|
||||
free (entries);
|
||||
free (scaled_glyphs);
|
||||
|
||||
FAIL1:
|
||||
if (attributes.n_params)
|
||||
|
@ -2159,9 +2128,17 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
|
|||
NULL, /* fill_path */
|
||||
NULL, /* get_font_options */
|
||||
NULL, /* flush */
|
||||
NULL /* mark_dirty_rectangle */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
_cairo_glitz_surface_scaled_font_fini,
|
||||
_cairo_glitz_surface_scaled_glyph_fini
|
||||
};
|
||||
|
||||
static const cairo_surface_backend_t *
|
||||
_cairo_glitz_surface_get_backend (void)
|
||||
{
|
||||
return &cairo_glitz_surface_backend;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_glitz_surface_create (glitz_surface_t *surface)
|
||||
{
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_glitz_surface_create (glitz_surface_t *surface);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
|
|
@ -63,14 +63,14 @@ struct _cairo_gstate {
|
|||
|
||||
cairo_clip_t clip;
|
||||
|
||||
cairo_surface_t *target;
|
||||
|
||||
cairo_matrix_t ctm;
|
||||
cairo_matrix_t ctm_inverse;
|
||||
cairo_matrix_t source_ctm_inverse; /* At the time ->source was set */
|
||||
|
||||
cairo_pen_t pen_regular;
|
||||
|
||||
cairo_surface_t *target;
|
||||
|
||||
cairo_pattern_t *source;
|
||||
|
||||
struct _cairo_gstate *next;
|
||||
|
|
|
@ -116,13 +116,13 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
|
|||
|
||||
_cairo_clip_init (&gstate->clip, target);
|
||||
|
||||
gstate->target = cairo_surface_reference (target);
|
||||
|
||||
_cairo_gstate_identity_matrix (gstate);
|
||||
cairo_matrix_init_identity (&gstate->source_ctm_inverse);
|
||||
gstate->source_ctm_inverse = gstate->ctm_inverse;
|
||||
|
||||
_cairo_pen_init_empty (&gstate->pen_regular);
|
||||
|
||||
gstate->target = cairo_surface_reference (target);
|
||||
|
||||
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
|
||||
if (gstate->source->status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -179,7 +179,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
|
|||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
_cairo_gstate_fini (cairo_gstate_t *gstate)
|
||||
{
|
||||
if (gstate->font_face)
|
||||
|
@ -231,6 +231,13 @@ _cairo_gstate_clone (cairo_gstate_t *gstate)
|
|||
return clone;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target)
|
||||
{
|
||||
cairo_surface_destroy (gstate->target);
|
||||
gstate->target = cairo_surface_reference (target);
|
||||
}
|
||||
|
||||
/* Push rendering off to an off-screen group. */
|
||||
/* XXX: Rethinking this API
|
||||
cairo_status_t
|
||||
|
@ -258,8 +265,8 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
|
|||
_cairo_surface_set_drawableWH (gstate->target, pix, width, height);
|
||||
|
||||
status = _cairo_surface_fill_rectangle (gstate->target,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&CAIRO_COLOR_TRANSPARENT,
|
||||
CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
0, 0,
|
||||
_cairo_surface_get_width (gstate->target),
|
||||
_cairo_surface_get_height (gstate->target));
|
||||
|
@ -430,21 +437,48 @@ _cairo_gstate_get_line_join (cairo_gstate_t *gstate)
|
|||
cairo_status_t
|
||||
_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset)
|
||||
{
|
||||
if (gstate->dash) {
|
||||
int i;
|
||||
double dash_total;
|
||||
|
||||
if (gstate->dash)
|
||||
free (gstate->dash);
|
||||
gstate->dash = NULL;
|
||||
}
|
||||
|
||||
gstate->num_dashes = num_dashes;
|
||||
if (gstate->num_dashes) {
|
||||
|
||||
if (gstate->num_dashes == 0) {
|
||||
gstate->dash = NULL;
|
||||
gstate->dash_offset = 0.0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
gstate->dash = malloc (gstate->num_dashes * sizeof (double));
|
||||
if (gstate->dash == NULL) {
|
||||
gstate->num_dashes = 0;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (gstate->dash, dash, gstate->num_dashes * sizeof (double));
|
||||
|
||||
dash_total = 0.0;
|
||||
for (i = 0; i < gstate->num_dashes; i++) {
|
||||
if (gstate->dash[i] < 0)
|
||||
return CAIRO_STATUS_INVALID_DASH;
|
||||
dash_total += gstate->dash[i];
|
||||
}
|
||||
|
||||
if (dash_total == 0.0)
|
||||
return CAIRO_STATUS_INVALID_DASH;
|
||||
|
||||
/* A single dash value indicate symmetric repeating, so the total
|
||||
* is twice as long. */
|
||||
if (gstate->num_dashes == 1)
|
||||
dash_total *= 2;
|
||||
|
||||
/* The dashing code doesn't like a negative offset, so we compute
|
||||
* the equivalent positive offset. */
|
||||
if (offset < 0)
|
||||
offset += ceil (-offset / dash_total + 0.5) * dash_total;
|
||||
|
||||
gstate->dash_offset = offset;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -464,10 +498,37 @@ _cairo_gstate_get_miter_limit (cairo_gstate_t *gstate)
|
|||
return gstate->miter_limit;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_apply_device_transform (cairo_gstate_t *gstate,
|
||||
cairo_matrix_t *matrix)
|
||||
{
|
||||
if (gstate->target->device_x_scale != 1.0 ||
|
||||
gstate->target->device_y_scale != 1.0)
|
||||
{
|
||||
cairo_matrix_scale (matrix,
|
||||
gstate->target->device_x_scale,
|
||||
gstate->target->device_y_scale);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_apply_device_inverse_transform (cairo_gstate_t *gstate,
|
||||
cairo_matrix_t *matrix)
|
||||
{
|
||||
if (gstate->target->device_x_scale != 1.0 ||
|
||||
gstate->target->device_y_scale != 1.0)
|
||||
{
|
||||
cairo_matrix_scale (matrix,
|
||||
1/gstate->target->device_x_scale,
|
||||
1/gstate->target->device_y_scale);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix)
|
||||
{
|
||||
*matrix = gstate->ctm;
|
||||
_cairo_gstate_apply_device_inverse_transform (gstate, matrix);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -553,6 +614,9 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_gstate_apply_device_transform (gstate, &gstate->ctm);
|
||||
_cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -564,6 +628,9 @@ _cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
|
|||
cairo_matrix_init_identity (&gstate->ctm);
|
||||
cairo_matrix_init_identity (&gstate->ctm_inverse);
|
||||
|
||||
_cairo_gstate_apply_device_transform (gstate, &gstate->ctm);
|
||||
_cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -605,19 +672,15 @@ void
|
|||
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
cairo_matrix_transform_point (&gstate->ctm, x, y);
|
||||
if (gstate->target) {
|
||||
*x += gstate->target->device_x_offset;
|
||||
*y += gstate->target->device_y_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
if (gstate->target) {
|
||||
*x -= gstate->target->device_x_offset;
|
||||
*y -= gstate->target->device_y_offset;
|
||||
}
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
|
||||
}
|
||||
|
||||
|
@ -723,6 +786,8 @@ cairo_bool_t
|
|||
_cairo_operator_bounded (cairo_operator_t operator)
|
||||
{
|
||||
switch (operator) {
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
case CAIRO_OPERATOR_OVER:
|
||||
case CAIRO_OPERATOR_ATOP:
|
||||
case CAIRO_OPERATOR_DEST:
|
||||
|
@ -732,8 +797,6 @@ _cairo_operator_bounded (cairo_operator_t operator)
|
|||
case CAIRO_OPERATOR_ADD:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
return TRUE;
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
case CAIRO_OPERATOR_OUT:
|
||||
case CAIRO_OPERATOR_IN:
|
||||
case CAIRO_OPERATOR_DEST_IN:
|
||||
|
@ -753,6 +816,47 @@ typedef cairo_status_t (*cairo_draw_func_t) (void *closure,
|
|||
int dst_y,
|
||||
const cairo_rectangle_t *extents);
|
||||
|
||||
static cairo_status_t
|
||||
_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
|
||||
cairo_clip_t *clip,
|
||||
cairo_draw_func_t draw_func,
|
||||
void *draw_closure,
|
||||
cairo_surface_t *dst,
|
||||
const cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_surface_t *mask;
|
||||
cairo_status_t status;
|
||||
|
||||
mask = cairo_surface_create_similar (dst,
|
||||
CAIRO_CONTENT_ALPHA,
|
||||
extents->width,
|
||||
extents->height);
|
||||
if (mask->status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = (*draw_func) (draw_closure, CAIRO_OPERATOR_ADD,
|
||||
NULL, mask,
|
||||
extents->x, extents->y,
|
||||
extents);
|
||||
if (status)
|
||||
goto CLEANUP_SURFACE;
|
||||
|
||||
if (clip->surface)
|
||||
status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
|
||||
mask,
|
||||
extents->x, extents->y,
|
||||
extents);
|
||||
if (status)
|
||||
goto CLEANUP_SURFACE;
|
||||
|
||||
_cairo_pattern_init_for_surface (mask_pattern, mask);
|
||||
|
||||
CLEANUP_SURFACE:
|
||||
cairo_surface_destroy (mask);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Handles compositing with a clip surface when the operator allows
|
||||
* us to combine the clip with the mask
|
||||
*/
|
||||
|
@ -765,50 +869,30 @@ _cairo_gstate_clip_and_composite_with_mask (cairo_clip_t *clip,
|
|||
cairo_surface_t *dst,
|
||||
const cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_surface_t *intermediate;
|
||||
cairo_surface_pattern_t intermediate_pattern;
|
||||
cairo_surface_pattern_t mask_pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
intermediate = cairo_surface_create_similar (clip->surface,
|
||||
CAIRO_CONTENT_ALPHA,
|
||||
extents->width,
|
||||
extents->height);
|
||||
if (intermediate->status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = (*draw_func) (draw_closure, CAIRO_OPERATOR_SOURCE,
|
||||
NULL, intermediate,
|
||||
extents->x, extents->y,
|
||||
extents);
|
||||
status = _create_composite_mask_pattern (&mask_pattern,
|
||||
clip,
|
||||
draw_func, draw_closure,
|
||||
dst, extents);
|
||||
if (status)
|
||||
goto CLEANUP_SURFACE;
|
||||
|
||||
status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
|
||||
intermediate,
|
||||
extents->x, extents->y,
|
||||
extents);
|
||||
if (status)
|
||||
goto CLEANUP_SURFACE;
|
||||
|
||||
_cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_composite (operator,
|
||||
src, &intermediate_pattern.base, dst,
|
||||
src, &mask_pattern.base, dst,
|
||||
extents->x, extents->y,
|
||||
0, 0,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
|
||||
_cairo_pattern_fini (&intermediate_pattern.base);
|
||||
|
||||
CLEANUP_SURFACE:
|
||||
cairo_surface_destroy (intermediate);
|
||||
_cairo_pattern_fini (&mask_pattern.base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Handles compositing with a clip surface when the operator allows
|
||||
* us to combine the clip with the mask
|
||||
/* Handles compositing with a clip surface when we have to do the operation
|
||||
* in two pieces and combine them together.
|
||||
*/
|
||||
static cairo_status_t
|
||||
_cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip,
|
||||
|
@ -827,6 +911,7 @@ _cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip,
|
|||
/* We'd be better off here creating a surface identical in format
|
||||
* to dst, but we have no way of getting that information.
|
||||
* A CAIRO_CONTENT_CLONE or something might be useful.
|
||||
* cairo_surface_create_similar() also unnecessarily clears the surface.
|
||||
*/
|
||||
intermediate = cairo_surface_create_similar (dst,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
|
@ -895,6 +980,55 @@ _cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* Handles compositing for CAIRO_OPERATOR_SOURCE, which is special; it's
|
||||
* defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
|
||||
*/
|
||||
static cairo_status_t
|
||||
_cairo_gstate_clip_and_composite_source (cairo_clip_t *clip,
|
||||
cairo_pattern_t *src,
|
||||
cairo_draw_func_t draw_func,
|
||||
void *draw_closure,
|
||||
cairo_surface_t *dst,
|
||||
const cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_surface_pattern_t mask_pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
/* Create a surface that is mask IN clip
|
||||
*/
|
||||
status = _create_composite_mask_pattern (&mask_pattern,
|
||||
clip,
|
||||
draw_func, draw_closure,
|
||||
dst, extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Compute dest' = dest OUT (mask IN clip)
|
||||
*/
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
|
||||
&mask_pattern.base, NULL, dst,
|
||||
0, 0,
|
||||
0, 0,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
|
||||
if (status)
|
||||
goto CLEANUP_MASK_PATTERN;
|
||||
|
||||
/* Now compute (src IN (mask IN clip)) ADD dest'
|
||||
*/
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
|
||||
src, &mask_pattern.base, dst,
|
||||
extents->x, extents->y,
|
||||
0, 0,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
|
||||
CLEANUP_MASK_PATTERN:
|
||||
_cairo_pattern_fini (&mask_pattern.base);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_rectangle_empty (const cairo_rectangle_t *rect)
|
||||
{
|
||||
|
@ -931,30 +1065,49 @@ _cairo_gstate_clip_and_composite (cairo_clip_t *clip,
|
|||
cairo_surface_t *dst,
|
||||
const cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_pattern_union_t solid_pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
if (_cairo_rectangle_empty (extents))
|
||||
/* Nothing to do */
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (clip->surface)
|
||||
if (operator == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
|
||||
src = &solid_pattern.base;
|
||||
operator = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
||||
if (clip->surface || operator == CAIRO_OPERATOR_SOURCE)
|
||||
{
|
||||
if (_cairo_operator_bounded (operator))
|
||||
return _cairo_gstate_clip_and_composite_with_mask (clip, operator,
|
||||
if (operator == CAIRO_OPERATOR_SOURCE)
|
||||
status = _cairo_gstate_clip_and_composite_source (clip,
|
||||
src,
|
||||
draw_func, draw_closure,
|
||||
dst, extents);
|
||||
else if (_cairo_operator_bounded (operator))
|
||||
status = _cairo_gstate_clip_and_composite_with_mask (clip, operator,
|
||||
src,
|
||||
draw_func, draw_closure,
|
||||
dst, extents);
|
||||
else
|
||||
return _cairo_gstate_clip_and_composite_combine (clip, operator,
|
||||
status = _cairo_gstate_clip_and_composite_combine (clip, operator,
|
||||
src,
|
||||
draw_func, draw_closure,
|
||||
dst, extents);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*draw_func) (draw_closure, operator,
|
||||
status = (*draw_func) (draw_closure, operator,
|
||||
src, dst,
|
||||
0, 0,
|
||||
extents);
|
||||
}
|
||||
|
||||
if (src == &solid_pattern.base)
|
||||
_cairo_pattern_fini (&solid_pattern.base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1158,10 +1311,17 @@ _composite_trap_region (cairo_clip_t *clip,
|
|||
cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t solid_pattern;
|
||||
cairo_pattern_union_t mask;
|
||||
int num_rects = pixman_region_num_rects (trap_region);
|
||||
unsigned int clip_serial;
|
||||
|
||||
if (clip->surface && operator == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
|
||||
src = &solid_pattern.base;
|
||||
operator = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
||||
if (num_rects == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1193,6 +1353,9 @@ _composite_trap_region (cairo_clip_t *clip,
|
|||
if (clip->surface)
|
||||
_cairo_pattern_fini (&mask.base);
|
||||
|
||||
if (src == &solid_pattern.base)
|
||||
_cairo_pattern_fini (&solid_pattern.base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1308,21 +1471,28 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
|
||||
if (trap_region)
|
||||
{
|
||||
if (src->type == CAIRO_PATTERN_SOLID && !clip->surface)
|
||||
if ((src->type == CAIRO_PATTERN_SOLID || operator == CAIRO_OPERATOR_CLEAR) &&
|
||||
!clip->surface)
|
||||
{
|
||||
const cairo_color_t *color;
|
||||
|
||||
if (operator == CAIRO_OPERATOR_CLEAR)
|
||||
color = CAIRO_COLOR_TRANSPARENT;
|
||||
else
|
||||
color = &((cairo_solid_pattern_t *)src)->color;
|
||||
|
||||
/* Solid rectangles special case */
|
||||
status = _cairo_surface_fill_region (dst, operator,
|
||||
&((cairo_solid_pattern_t *)src)->color,
|
||||
trap_region);
|
||||
status = _cairo_surface_fill_region (dst, operator, color, trap_region);
|
||||
if (!status && clear_region)
|
||||
status = _cairo_surface_fill_region (dst, operator,
|
||||
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
clear_region);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (_cairo_operator_bounded (operator) || !clip->surface)
|
||||
if ((_cairo_operator_bounded (operator) && operator != CAIRO_OPERATOR_SOURCE) ||
|
||||
!clip->surface)
|
||||
{
|
||||
/* For a simple rectangle, we can just use composite(), for more
|
||||
* rectangles, we have to set a clip region. The cost of rasterizing
|
||||
|
@ -1330,8 +1500,10 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
* worthwhile even if a region is needed.
|
||||
*
|
||||
* If we have a clip surface, we set it as the mask; this only works
|
||||
* for bounded operators; for unbounded operators, clip and mask
|
||||
* cannot be interchanged.
|
||||
* for bounded operators other than SOURCE; for unbounded operators,
|
||||
* clip and mask cannot be interchanged. For SOURCE, the operator
|
||||
* as implemented by the backends is different in it's handling
|
||||
* of the mask then what we want.
|
||||
*
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
|
||||
* more than rectangle and the destination doesn't support clip
|
||||
|
@ -1785,30 +1957,17 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
|||
int *num_glyphs)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
status = _cairo_gstate_ensure_scaled_font (gstate);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font,
|
||||
status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
|
||||
utf8, glyphs, num_glyphs);
|
||||
|
||||
if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
|
||||
return status;
|
||||
|
||||
/* The font responded in glyph space, starting from (0,0). Convert to
|
||||
user space by applying the font transform, then add any current point
|
||||
offset. */
|
||||
|
||||
for (i = 0; i < *num_glyphs; ++i) {
|
||||
cairo_matrix_transform_point (&gstate->font_matrix,
|
||||
&((*glyphs)[i].x),
|
||||
&((*glyphs)[i].y));
|
||||
(*glyphs)[i].x += x;
|
||||
(*glyphs)[i].y += y;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1885,6 +2044,17 @@ _cairo_gstate_show_glyphs_draw_func (void *closure,
|
|||
if (!src)
|
||||
src = &pattern.base;
|
||||
|
||||
status = _cairo_surface_show_glyphs (glyph_info->font, operator, src,
|
||||
dst,
|
||||
extents->x, extents->y,
|
||||
extents->x - dst_x, extents->y - dst_y,
|
||||
extents->width, extents->height,
|
||||
glyph_info->glyphs,
|
||||
glyph_info->num_glyphs);
|
||||
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
status = _cairo_scaled_font_show_glyphs (glyph_info->font,
|
||||
operator,
|
||||
src, dst,
|
||||
|
@ -1909,7 +2079,6 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
int i;
|
||||
cairo_glyph_t *transformed_glyphs = NULL;
|
||||
cairo_pattern_union_t pattern;
|
||||
cairo_box_t bbox;
|
||||
cairo_rectangle_t extents;
|
||||
cairo_show_glyphs_info_t glyph_info;
|
||||
|
||||
|
@ -1937,21 +2106,15 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
}
|
||||
|
||||
if (_cairo_operator_bounded (gstate->operator))
|
||||
{
|
||||
status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font,
|
||||
transformed_glyphs, num_glyphs,
|
||||
&bbox);
|
||||
if (status)
|
||||
goto CLEANUP_GLYPHS;
|
||||
|
||||
_cairo_box_round_to_rectangle (&bbox, &extents);
|
||||
}
|
||||
status = _cairo_scaled_font_glyph_device_extents (gstate->scaled_font,
|
||||
transformed_glyphs,
|
||||
num_glyphs,
|
||||
&extents);
|
||||
else
|
||||
{
|
||||
status = _cairo_surface_get_extents (gstate->target, &extents);
|
||||
|
||||
if (status)
|
||||
goto CLEANUP_GLYPHS;
|
||||
}
|
||||
|
||||
status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
|
||||
if (status)
|
||||
|
@ -2011,7 +2174,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
|||
return status;
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_status_t
|
||||
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
|
@ -2020,7 +2183,7 @@ _cairo_gstate_set_antialias (cairo_gstate_t *gstate,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_private cairo_antialias_t
|
||||
cairo_antialias_t
|
||||
_cairo_gstate_get_antialias (cairo_gstate_t *gstate)
|
||||
{
|
||||
return gstate->antialias;
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct cairo_hull
|
|||
cairo_point_t point;
|
||||
cairo_slope_t slope;
|
||||
int discard;
|
||||
int id;
|
||||
} cairo_hull_t;
|
||||
|
||||
static cairo_hull_t *
|
||||
|
@ -69,11 +70,15 @@ _cairo_hull_create (cairo_pen_vertex_t *vertices, int num_vertices)
|
|||
hull[i].point = vertices[i].point;
|
||||
_cairo_slope_init (&hull[i].slope, &hull[0].point, &hull[i].point);
|
||||
|
||||
/* give each point a unique id for later comparison */
|
||||
hull[i].id = i;
|
||||
|
||||
/* Don't discard by default */
|
||||
hull[i].discard = 0;
|
||||
|
||||
/* Discard all points coincident with the extremal point */
|
||||
if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0)
|
||||
hull[i].discard = 1;
|
||||
else
|
||||
hull[i].discard = 0;
|
||||
}
|
||||
|
||||
return hull;
|
||||
|
@ -97,7 +102,12 @@ _cairo_hull_vertex_compare (const void *av, const void *bv)
|
|||
(cairo_fixed_48_16_t) a->slope.dy * a->slope.dy);
|
||||
b_dist = ((cairo_fixed_48_16_t) b->slope.dx * b->slope.dx +
|
||||
(cairo_fixed_48_16_t) b->slope.dy * b->slope.dy);
|
||||
if (a_dist < b_dist) {
|
||||
/*
|
||||
* Use the point's ids to ensure a total ordering.
|
||||
* a well-defined ordering, and avoid setting discard on
|
||||
* both points.
|
||||
*/
|
||||
if (a_dist < b_dist || (a_dist == b_dist && a->id < b->id)) {
|
||||
a->discard = 1;
|
||||
ret = -1;
|
||||
} else {
|
||||
|
|
|
@ -149,8 +149,13 @@ _create_pixman_format (cairo_format_t format)
|
|||
* must explicitely clear the buffer, using, for example,
|
||||
* cairo_rectangle() and cairo_fill() if you want it cleared.
|
||||
*
|
||||
* Return value: the newly created surface, or %NULL if it couldn't
|
||||
* be created because of lack of memory
|
||||
* Return value: a pointer to the newly created surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy when done
|
||||
* with it.
|
||||
*
|
||||
* This function always returns a valid pointer, but it will return a
|
||||
* pointer to a "nil" surface if an error such as out of memory
|
||||
* occurs. You can use cairo_surface_status() to check for this.
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_image_surface_create (cairo_format_t format,
|
||||
|
@ -203,8 +208,13 @@ cairo_image_surface_create (cairo_format_t format,
|
|||
* must explicitely clear the buffer, using, for example,
|
||||
* cairo_rectangle() and cairo_fill() if you want it cleared.
|
||||
*
|
||||
* Return value: the newly created surface, or %NULL if it couldn't
|
||||
* be created because of lack of memory
|
||||
* Return value: a pointer to the newly created surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy when done
|
||||
* with it.
|
||||
*
|
||||
* This function always returns a valid pointer, but it will return a
|
||||
* pointer to a "nil" surface if an error such as out of memory
|
||||
* occurs. You can use cairo_surface_status() to check for this.
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_image_surface_create_for_data (unsigned char *data,
|
||||
|
@ -616,7 +626,9 @@ _cairo_image_surface_composite (cairo_operator_t operator,
|
|||
width, height);
|
||||
}
|
||||
|
||||
if (!_cairo_operator_bounded (operator))
|
||||
if (!_cairo_operator_bounded (operator) ||
|
||||
operator == CAIRO_OPERATOR_SOURCE ||
|
||||
operator == CAIRO_OPERATOR_CLEAR)
|
||||
status = _cairo_surface_composite_fixup_unbounded (&dst->base,
|
||||
&src_attr, src->width, src->height,
|
||||
mask ? &mask_attr : NULL,
|
||||
|
|
|
@ -82,6 +82,7 @@ slim_hidden_def(cairo_matrix_init_identity);
|
|||
void
|
||||
cairo_matrix_init (cairo_matrix_t *matrix,
|
||||
double xx, double yx,
|
||||
|
||||
double xy, double yy,
|
||||
double x0, double y0)
|
||||
{
|
||||
|
@ -228,12 +229,10 @@ cairo_matrix_init_rotate (cairo_matrix_t *matrix,
|
|||
{
|
||||
double s;
|
||||
double c;
|
||||
#if HAVE_SINCOS
|
||||
sincos (radians, &s, &c);
|
||||
#else
|
||||
|
||||
s = sin (radians);
|
||||
c = cos (radians);
|
||||
#endif
|
||||
|
||||
cairo_matrix_init (matrix,
|
||||
c, s,
|
||||
-s, c,
|
||||
|
@ -484,37 +483,6 @@ _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
|
|||
*det = a*d - b*c;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_matrix_compute_eigen_values (const cairo_matrix_t *matrix,
|
||||
double *lambda1, double *lambda2)
|
||||
{
|
||||
/* The eigenvalues of an NxN matrix M are found by solving the polynomial:
|
||||
|
||||
det (M - lI) = 0
|
||||
|
||||
The zeros in our homogeneous 3x3 matrix make this equation equal
|
||||
to that formed by the sub-matrix:
|
||||
|
||||
M = a b
|
||||
c d
|
||||
|
||||
by which:
|
||||
|
||||
l^2 - (a+d)l + (ad - bc) = 0
|
||||
|
||||
l = (a+d +/- sqrt (a^2 + 2ad + d^2 - 4 (ad-bc))) / 2;
|
||||
*/
|
||||
|
||||
double a, b, c, d, rad;
|
||||
|
||||
a = matrix->xx; b = matrix->yx;
|
||||
c = matrix->xy; d = matrix->yy;
|
||||
|
||||
rad = sqrt (a*a + 2*a*d + d*d - 4*(a*d - b*c));
|
||||
*lambda1 = (a + d + rad) / 2.0;
|
||||
*lambda2 = (a + d - rad) / 2.0;
|
||||
}
|
||||
|
||||
/* Compute the amount that each basis vector is scaled by. */
|
||||
cairo_status_t
|
||||
_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
|
||||
|
@ -587,3 +555,148 @@ _cairo_matrix_is_integer_translation(const cairo_matrix_t *m,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
A circle in user space is transformed into an ellipse in device space.
|
||||
|
||||
The following is a derivation of a formula to calculate the length of the
|
||||
major axis for this ellipse; this is useful for error bounds calculations.
|
||||
|
||||
Thanks to Walter Brisken <wbrisken@aoc.nrao.edu> for this derivation:
|
||||
|
||||
1. First some notation:
|
||||
|
||||
All capital letters represent vectors in two dimensions. A prime '
|
||||
represents a transformed coordinate. Matrices are written in underlined
|
||||
form, ie _R_. Lowercase letters represent scalar real values.
|
||||
|
||||
2. The question has been posed: What is the maximum expansion factor
|
||||
achieved by the linear transformation
|
||||
|
||||
X' = X _R_
|
||||
|
||||
where _R_ is a real-valued 2x2 matrix with entries:
|
||||
|
||||
_R_ = [a b]
|
||||
[c d] .
|
||||
|
||||
In other words, what is the maximum radius, MAX[ |X'| ], reached for any
|
||||
X on the unit circle ( |X| = 1 ) ?
|
||||
|
||||
|
||||
3. Some useful formulae
|
||||
|
||||
(A) through (C) below are standard double-angle formulae. (D) is a lesser
|
||||
known result and is derived below:
|
||||
|
||||
(A) sin²(θ) = (1 - cos(2*θ))/2
|
||||
(B) cos²(θ) = (1 + cos(2*θ))/2
|
||||
(C) sin(θ)*cos(θ) = sin(2*θ)/2
|
||||
(D) MAX[a*cos(θ) + b*sin(θ)] = sqrt(a² + b²)
|
||||
|
||||
Proof of (D):
|
||||
|
||||
find the maximum of the function by setting the derivative to zero:
|
||||
|
||||
-a*sin(θ)+b*cos(θ) = 0
|
||||
|
||||
From this it follows that
|
||||
|
||||
tan(θ) = b/a
|
||||
|
||||
and hence
|
||||
|
||||
sin(θ) = b/sqrt(a² + b²)
|
||||
|
||||
and
|
||||
|
||||
cos(θ) = a/sqrt(a² + b²)
|
||||
|
||||
Thus the maximum value is
|
||||
|
||||
MAX[a*cos(θ) + b*sin(θ)] = (a² + b²)/sqrt(a² + b²)
|
||||
= sqrt(a² + b²)
|
||||
|
||||
|
||||
4. Derivation of maximum expansion
|
||||
|
||||
To find MAX[ |X'| ] we search brute force method using calculus. The unit
|
||||
circle on which X is constrained is to be parameterized by t:
|
||||
|
||||
X(θ) = (cos(θ), sin(θ))
|
||||
|
||||
Thus
|
||||
|
||||
X'(θ) = X(θ) * _R_ = (cos(θ), sin(θ)) * [a b]
|
||||
[c d]
|
||||
= (a*cos(θ) + c*sin(θ), b*cos(θ) + d*sin(θ)).
|
||||
|
||||
Define
|
||||
|
||||
r(θ) = |X'(θ)|
|
||||
|
||||
Thus
|
||||
|
||||
r²(θ) = (a*cos(θ) + c*sin(θ))² + (b*cos(θ) + d*sin(θ))²
|
||||
= (a² + b²)*cos²(θ) + (c² + d²)*sin²(θ)
|
||||
+ 2*(a*c + b*d)*cos(θ)*sin(θ)
|
||||
|
||||
Now apply the double angle formulae (A) to (C) from above:
|
||||
|
||||
r²(θ) = (a² + b² + c² + d²)/2
|
||||
+ (a² + b² - c² - d²)*cos(2*θ)/2
|
||||
+ (a*c + b*d)*sin(2*θ)
|
||||
= f + g*cos(φ) + h*sin(φ)
|
||||
|
||||
Where
|
||||
|
||||
f = (a² + b² + c² + d²)/2
|
||||
g = (a² + b² - c² - d²)/2
|
||||
h = (a*c + d*d)
|
||||
φ = 2*θ
|
||||
|
||||
It is clear that MAX[ |X'| ] = sqrt(MAX[ r² ]). Here we determine MAX[ r² ]
|
||||
using (D) from above:
|
||||
|
||||
MAX[ r² ] = f + sqrt(g² + h²)
|
||||
|
||||
And finally
|
||||
|
||||
MAX[ |X'| ] = sqrt( f + sqrt(g² + h²) )
|
||||
|
||||
Which is the solution to this problem.
|
||||
|
||||
|
||||
Walter Brisken
|
||||
2004/10/08
|
||||
|
||||
(Note that the minor axis length is at the minimum of the above solution,
|
||||
which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).
|
||||
*/
|
||||
|
||||
/* determine the length of the major axis of a circle of the given radius
|
||||
after applying the transformation matrix. */
|
||||
double
|
||||
_cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radius)
|
||||
{
|
||||
double a, b, c, d, f, g, h, i, j;
|
||||
|
||||
_cairo_matrix_get_affine (matrix,
|
||||
&a, &b,
|
||||
&c, &d,
|
||||
NULL, NULL);
|
||||
|
||||
i = a*a + b*b;
|
||||
j = c*c + d*d;
|
||||
|
||||
f = 0.5 * (i + j);
|
||||
g = 0.5 * (i - j);
|
||||
h = a*c + b*d;
|
||||
|
||||
return radius * sqrt (f + sqrt (g*g+h*h));
|
||||
|
||||
/*
|
||||
* we don't need the minor axis length, which is
|
||||
* double min = radius * sqrt (f - sqrt (g*g+h*h));
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -541,6 +541,23 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
|
|||
command->show_glyphs.height,
|
||||
command->show_glyphs.glyphs,
|
||||
command->show_glyphs.num_glyphs);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
break;
|
||||
|
||||
status = (*command->show_glyphs.scaled_font->backend->
|
||||
show_glyphs) (command->show_glyphs.scaled_font,
|
||||
command->show_glyphs.operator,
|
||||
&command->show_glyphs.pattern.base,
|
||||
target,
|
||||
command->show_glyphs.source_x,
|
||||
command->show_glyphs.source_y,
|
||||
command->show_glyphs.dest_x,
|
||||
command->show_glyphs.dest_y,
|
||||
command->show_glyphs.width,
|
||||
command->show_glyphs.height,
|
||||
command->show_glyphs.glyphs,
|
||||
command->show_glyphs.num_glyphs);
|
||||
|
||||
break;
|
||||
|
||||
case CAIRO_COMMAND_FILL_PATH:
|
||||
|
|
|
@ -367,8 +367,8 @@ _cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
|
|||
|
||||
/**
|
||||
* cairo_path_destroy:
|
||||
* @path: a path to destroy which was previously returned by either
|
||||
* cairo_copy_path or cairo_copy_path_flat.
|
||||
* @path: a path previously returned by either cairo_copy_path() or
|
||||
* cairo_copy_path_flat().
|
||||
*
|
||||
* Immediately releases all memory associated with @path. After a call
|
||||
* to cairo_path_destroy() the @path pointer is no longer valid and
|
||||
|
|
|
@ -42,17 +42,17 @@ typedef struct cairo_stroker {
|
|||
cairo_gstate_t *gstate;
|
||||
cairo_traps_t *traps;
|
||||
|
||||
int has_current_point;
|
||||
cairo_bool_t has_current_point;
|
||||
cairo_point_t current_point;
|
||||
cairo_point_t first_point;
|
||||
|
||||
int has_current_face;
|
||||
cairo_bool_t has_current_face;
|
||||
cairo_stroke_face_t current_face;
|
||||
|
||||
int has_first_face;
|
||||
cairo_bool_t has_first_face;
|
||||
cairo_stroke_face_t first_face;
|
||||
|
||||
int dashed;
|
||||
cairo_bool_t dashed;
|
||||
int dash_index;
|
||||
int dash_on;
|
||||
double dash_remain;
|
||||
|
@ -80,6 +80,12 @@ _cairo_stroker_curve_to (void *closure,
|
|||
cairo_point_t *c,
|
||||
cairo_point_t *d);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_curve_to_dashed (void *closure,
|
||||
cairo_point_t *b,
|
||||
cairo_point_t *c,
|
||||
cairo_point_t *d);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_close_path (void *closure);
|
||||
|
||||
|
@ -107,7 +113,7 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker)
|
|||
if (++i == gstate->num_dashes)
|
||||
i = 0;
|
||||
}
|
||||
stroker->dashed = 1;
|
||||
stroker->dashed = TRUE;
|
||||
stroker->dash_index = i;
|
||||
stroker->dash_on = on;
|
||||
stroker->dash_remain = gstate->dash[i] - offset;
|
||||
|
@ -133,14 +139,14 @@ _cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_tra
|
|||
stroker->gstate = gstate;
|
||||
stroker->traps = traps;
|
||||
|
||||
stroker->has_current_point = 0;
|
||||
stroker->has_current_face = 0;
|
||||
stroker->has_first_face = 0;
|
||||
stroker->has_current_point = FALSE;
|
||||
stroker->has_current_face = FALSE;
|
||||
stroker->has_first_face = FALSE;
|
||||
|
||||
if (gstate->dash)
|
||||
_cairo_stroker_start_dash (stroker);
|
||||
else
|
||||
stroker->dashed = 0;
|
||||
stroker->dashed = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -335,7 +341,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
|
||||
_cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_gstate_t *gstate = stroker->gstate;
|
||||
|
@ -405,6 +411,54 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_add_leading_cap (cairo_stroker_t *stroker,
|
||||
cairo_stroke_face_t *face)
|
||||
{
|
||||
cairo_stroke_face_t reversed;
|
||||
cairo_point_t t;
|
||||
|
||||
reversed = *face;
|
||||
|
||||
/* The initial cap needs an outward facing vector. Reverse everything */
|
||||
reversed.usr_vector.x = -reversed.usr_vector.x;
|
||||
reversed.usr_vector.y = -reversed.usr_vector.y;
|
||||
reversed.dev_vector.dx = -reversed.dev_vector.dx;
|
||||
reversed.dev_vector.dy = -reversed.dev_vector.dy;
|
||||
t = reversed.cw;
|
||||
reversed.cw = reversed.ccw;
|
||||
reversed.ccw = t;
|
||||
|
||||
return _cairo_stroker_add_cap (stroker, &reversed);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_add_trailing_cap (cairo_stroker_t *stroker,
|
||||
cairo_stroke_face_t *face)
|
||||
{
|
||||
return _cairo_stroker_add_cap (stroker, face);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_add_caps (cairo_stroker_t *stroker)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (stroker->has_first_face) {
|
||||
status = _cairo_stroker_add_leading_cap (stroker, &stroker->first_face);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (stroker->has_current_face) {
|
||||
status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face)
|
||||
{
|
||||
|
@ -527,8 +581,13 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
|
|||
static cairo_status_t
|
||||
_cairo_stroker_move_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_stroker_t *stroker = closure;
|
||||
|
||||
status = _cairo_stroker_add_caps (stroker);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
stroker->first_point = *point;
|
||||
stroker->current_point = *point;
|
||||
stroker->has_current_point = 1;
|
||||
|
@ -633,7 +692,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
/*
|
||||
* Not first dash in this segment, cap start
|
||||
*/
|
||||
status = _cairo_stroker_cap (stroker, &sub_start);
|
||||
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
|
@ -651,7 +710,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
stroker->first_face = sub_start;
|
||||
stroker->has_first_face = 1;
|
||||
} else {
|
||||
status = _cairo_stroker_cap (stroker, &sub_start);
|
||||
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
@ -661,7 +720,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
/*
|
||||
* Cap if not at end of segment
|
||||
*/
|
||||
status = _cairo_stroker_cap (stroker, &sub_end);
|
||||
status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
|
@ -679,7 +738,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
*/
|
||||
if (first) {
|
||||
if (stroker->has_current_face) {
|
||||
status = _cairo_stroker_cap (stroker, &stroker->current_face);
|
||||
status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
@ -767,6 +826,74 @@ _cairo_stroker_curve_to (void *closure,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* We're using two different algorithms here for dashed and un-dashed
|
||||
* splines. The dashed alogorithm uses the existing line dashing
|
||||
* code. It's linear in path length, but gets subtly wrong results for
|
||||
* self-intersecting paths (an outstanding but for self-intersecting
|
||||
* non-curved paths as well). The non-dashed algorithm tessellates a
|
||||
* single polygon for the whole curve. It handles the
|
||||
* self-intersecting problem, but it's (unsurprisingly) not O(n) and
|
||||
* more significantly, it doesn't yet handle dashes.
|
||||
*
|
||||
* The only reason we're doing split algortihms here is to
|
||||
* minimize the impact of fixing the splines-aren't-dashed bug for
|
||||
* 1.0.2. Long-term the right answer is to rewrite the whole pile
|
||||
* of stroking code so that the entire result is computed as a
|
||||
* single polygon that is tessellated, (that is, stroking can be
|
||||
* built on top of filling). That will solve the self-intersecting
|
||||
* problem. It will also increase the importance of implementing
|
||||
* an efficient and more robust tessellator.
|
||||
*/
|
||||
static cairo_status_t
|
||||
_cairo_stroker_curve_to_dashed (void *closure,
|
||||
cairo_point_t *b,
|
||||
cairo_point_t *c,
|
||||
cairo_point_t *d)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_stroker_t *stroker = closure;
|
||||
cairo_gstate_t *gstate = stroker->gstate;
|
||||
cairo_spline_t spline;
|
||||
cairo_point_t *a = &stroker->current_point;
|
||||
cairo_line_join_t line_join_save;
|
||||
int i;
|
||||
|
||||
status = _cairo_spline_init (&spline, a, b, c, d);
|
||||
if (status == CAIRO_INT_STATUS_DEGENERATE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* If the line width is so small that the pen is reduced to a
|
||||
single point, then we have nothing to do. */
|
||||
if (gstate->pen_regular.num_vertices <= 1)
|
||||
goto CLEANUP_SPLINE;
|
||||
|
||||
/* Temporarily modify the gstate to use round joins to guarantee
|
||||
* smooth stroked curves. */
|
||||
line_join_save = gstate->line_join;
|
||||
gstate->line_join = CAIRO_LINE_JOIN_ROUND;
|
||||
|
||||
status = _cairo_spline_decompose (&spline, gstate->tolerance);
|
||||
if (status)
|
||||
goto CLEANUP_GSTATE;
|
||||
|
||||
for (i = 1; i < spline.num_points; i++) {
|
||||
if (stroker->dashed)
|
||||
status = _cairo_stroker_line_to_dashed (stroker, &spline.points[i]);
|
||||
else
|
||||
status = _cairo_stroker_line_to (stroker, &spline.points[i]);
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
|
||||
CLEANUP_GSTATE:
|
||||
gstate->line_join = line_join_save;
|
||||
|
||||
CLEANUP_SPLINE:
|
||||
_cairo_spline_fini (&spline);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_close_path (void *closure)
|
||||
{
|
||||
|
@ -810,7 +937,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
|||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_stroker_move_to,
|
||||
_cairo_stroker_line_to_dashed,
|
||||
_cairo_stroker_curve_to,
|
||||
_cairo_stroker_curve_to_dashed,
|
||||
_cairo_stroker_close_path,
|
||||
&stroker);
|
||||
else
|
||||
|
@ -824,26 +951,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
|||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
if (stroker.has_first_face) {
|
||||
cairo_point_t t;
|
||||
/* The initial cap needs an outward facing vector. Reverse everything */
|
||||
stroker.first_face.usr_vector.x = -stroker.first_face.usr_vector.x;
|
||||
stroker.first_face.usr_vector.y = -stroker.first_face.usr_vector.y;
|
||||
stroker.first_face.dev_vector.dx = -stroker.first_face.dev_vector.dx;
|
||||
stroker.first_face.dev_vector.dy = -stroker.first_face.dev_vector.dy;
|
||||
t = stroker.first_face.cw;
|
||||
stroker.first_face.cw = stroker.first_face.ccw;
|
||||
stroker.first_face.ccw = t;
|
||||
status = _cairo_stroker_cap (&stroker, &stroker.first_face);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
}
|
||||
|
||||
if (stroker.has_current_face) {
|
||||
status = _cairo_stroker_cap (&stroker, &stroker.current_face);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
}
|
||||
status = _cairo_stroker_add_caps (&stroker);
|
||||
|
||||
BAIL:
|
||||
_cairo_stroker_fini (&stroker);
|
||||
|
|
|
@ -132,6 +132,17 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_path_fixed_t *
|
||||
_cairo_path_fixed_create (void)
|
||||
{
|
||||
cairo_path_fixed_t *path = malloc (sizeof (cairo_path_fixed_t));
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
_cairo_path_fixed_init (path);
|
||||
return path;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_fini (cairo_path_fixed_t *path)
|
||||
{
|
||||
|
@ -155,6 +166,13 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
|
|||
path->has_current_point = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_destroy (cairo_path_fixed_t *path)
|
||||
{
|
||||
_cairo_path_fixed_fini (path);
|
||||
free (path);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t x,
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
typedef void (*cairo_shader_function_t) (unsigned char *color0,
|
||||
unsigned char *color1,
|
||||
cairo_fixed_t factor,
|
||||
uint32_t *pixel);
|
||||
|
||||
typedef struct _cairo_shader_color_stop {
|
||||
cairo_fixed_t offset;
|
||||
cairo_fixed_48_16_t scale;
|
||||
|
@ -43,59 +38,64 @@ typedef struct _cairo_shader_op {
|
|||
cairo_shader_color_stop_t *stops;
|
||||
int n_stops;
|
||||
cairo_extend_t extend;
|
||||
cairo_shader_function_t shader_function;
|
||||
} cairo_shader_op_t;
|
||||
|
||||
#define MULTIPLY_COLORCOMP(c1, c2) \
|
||||
((unsigned char) \
|
||||
((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff))
|
||||
|
||||
const cairo_solid_pattern_t cairo_solid_pattern_nil = {
|
||||
const cairo_solid_pattern_t cairo_pattern_nil = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
{ 0.0, 0.0, 0.0, 1.0, /* solid black */
|
||||
0x0, 0x0, 0x0, 0xffff }
|
||||
};
|
||||
|
||||
static const cairo_surface_pattern_t cairo_surface_pattern_nil = {
|
||||
{ CAIRO_PATTERN_SURFACE, /* type */
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
CAIRO_STATUS_NULL_POINTER,/* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
NULL /* surface */
|
||||
};
|
||||
|
||||
static const cairo_linear_pattern_t cairo_linear_pattern_nil = {
|
||||
{ { CAIRO_PATTERN_LINEAR, /* type */
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
NULL, /* stops */
|
||||
0 }, /* n_stops */
|
||||
{ 0., 0. }, { 1.0, 1.0 } /* point0, point1 */
|
||||
};
|
||||
|
||||
static const cairo_radial_pattern_t cairo_radial_pattern_nil = {
|
||||
{ { CAIRO_PATTERN_RADIAL, /* type */
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
CAIRO_STATUS_READ_ERROR, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
NULL, /* stops */
|
||||
0 }, /* n_stops */
|
||||
{ 0., 0. }, { 0.0, 0.0 }, /* center0, center1 */
|
||||
1.0, 1.0, /* radius0, radius1 */
|
||||
};
|
||||
|
||||
static const cairo_pattern_t *
|
||||
_cairo_pattern_nil_for_status (cairo_status_t status)
|
||||
{
|
||||
switch (status) {
|
||||
case CAIRO_STATUS_NULL_POINTER:
|
||||
return &cairo_pattern_nil_null_pointer.base;
|
||||
case CAIRO_STATUS_FILE_NOT_FOUND:
|
||||
return &cairo_pattern_nil_file_not_found.base;
|
||||
case CAIRO_STATUS_READ_ERROR:
|
||||
return &cairo_pattern_nil_read_error.base;
|
||||
default:
|
||||
case CAIRO_STATUS_NO_MEMORY:
|
||||
return &cairo_pattern_nil.base;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_pattern_set_error:
|
||||
* @pattern: a pattern
|
||||
|
@ -116,6 +116,10 @@ static void
|
|||
_cairo_pattern_set_error (cairo_pattern_t *pattern,
|
||||
cairo_status_t status)
|
||||
{
|
||||
/* Don't overwrite an existing error. This preserves the first
|
||||
* error, which is the most significant. It also avoids attempting
|
||||
* to write to read-only data (eg. from a nil pattern). */
|
||||
if (pattern->status == CAIRO_STATUS_SUCCESS)
|
||||
pattern->status = status;
|
||||
|
||||
_cairo_error (status);
|
||||
|
@ -152,17 +156,11 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
|
|||
*dst = *src;
|
||||
}
|
||||
|
||||
if (other->base.status)
|
||||
_cairo_pattern_set_error (&pattern->base, other->base.status);
|
||||
|
||||
if (other->n_stops)
|
||||
{
|
||||
pattern->stops = malloc (other->n_stops * sizeof (cairo_color_stop_t));
|
||||
if (pattern->stops == NULL) {
|
||||
if (other->base.type == CAIRO_PATTERN_LINEAR)
|
||||
_cairo_gradient_pattern_init_copy (pattern, &cairo_linear_pattern_nil.base);
|
||||
else
|
||||
_cairo_gradient_pattern_init_copy (pattern, &cairo_radial_pattern_nil.base);
|
||||
_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -175,6 +173,11 @@ void
|
|||
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
||||
const cairo_pattern_t *other)
|
||||
{
|
||||
if (other->status) {
|
||||
_cairo_pattern_set_error (pattern, other->status);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (other->type) {
|
||||
case CAIRO_PATTERN_SOLID: {
|
||||
cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
|
||||
|
@ -208,16 +211,18 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
|
|||
case CAIRO_PATTERN_SOLID:
|
||||
break;
|
||||
case CAIRO_PATTERN_SURFACE: {
|
||||
cairo_surface_pattern_t *fini = (cairo_surface_pattern_t *) pattern;
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) pattern;
|
||||
|
||||
cairo_surface_destroy (fini->surface);
|
||||
cairo_surface_destroy (surface_pattern->surface);
|
||||
} break;
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_RADIAL: {
|
||||
cairo_gradient_pattern_t *fini = (cairo_gradient_pattern_t *) pattern;
|
||||
cairo_gradient_pattern_t *gradient =
|
||||
(cairo_gradient_pattern_t *) pattern;
|
||||
|
||||
if (fini->n_stops)
|
||||
free (fini->stops);
|
||||
if (gradient->stops)
|
||||
free (gradient->stops);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -234,6 +239,13 @@ void
|
|||
_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
if (surface->status) {
|
||||
/* Force to solid to simplify the pattern_fini process. */
|
||||
pattern->base.type = CAIRO_PATTERN_SOLID;
|
||||
_cairo_pattern_set_error (&pattern->base, surface->status);
|
||||
return;
|
||||
}
|
||||
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SURFACE);
|
||||
|
||||
pattern->surface = cairo_surface_reference (surface);
|
||||
|
@ -245,7 +257,7 @@ _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
|
|||
{
|
||||
_cairo_pattern_init (&pattern->base, type);
|
||||
|
||||
pattern->stops = 0;
|
||||
pattern->stops = NULL;
|
||||
pattern->n_stops = 0;
|
||||
}
|
||||
|
||||
|
@ -283,7 +295,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
|
|||
|
||||
pattern = malloc (sizeof (cairo_solid_pattern_t));
|
||||
if (pattern == NULL)
|
||||
return (cairo_pattern_t *) &cairo_solid_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
|
||||
_cairo_pattern_init_solid (pattern, color);
|
||||
|
||||
|
@ -324,7 +336,7 @@ cairo_pattern_create_rgb (double red, double green, double blue)
|
|||
|
||||
pattern = _cairo_pattern_create_solid (&color);
|
||||
if (pattern->status)
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
_cairo_error (pattern->status);
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
@ -366,7 +378,7 @@ cairo_pattern_create_rgba (double red, double green, double blue,
|
|||
|
||||
pattern = _cairo_pattern_create_solid (&color);
|
||||
if (pattern->status)
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
_cairo_error (pattern->status);
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
@ -391,10 +403,16 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
|
|||
{
|
||||
cairo_surface_pattern_t *pattern;
|
||||
|
||||
if (surface == NULL)
|
||||
return (cairo_pattern_t*) _cairo_pattern_nil_for_status (CAIRO_STATUS_NULL_POINTER);
|
||||
|
||||
if (surface->status)
|
||||
return (cairo_pattern_t*) _cairo_pattern_nil_for_status (surface->status);
|
||||
|
||||
pattern = malloc (sizeof (cairo_surface_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *)&cairo_surface_pattern_nil.base;
|
||||
return (cairo_pattern_t *)&cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_for_surface (pattern, surface);
|
||||
|
@ -436,7 +454,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
|
|||
pattern = malloc (sizeof (cairo_linear_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *) &cairo_linear_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
|
||||
|
@ -481,7 +499,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
|
|||
pattern = malloc (sizeof (cairo_radial_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *) &cairo_radial_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
|
||||
|
@ -508,6 +526,8 @@ cairo_pattern_reference (cairo_pattern_t *pattern)
|
|||
if (pattern->ref_count == (unsigned int)-1)
|
||||
return pattern;
|
||||
|
||||
assert (pattern->ref_count > 0);
|
||||
|
||||
pattern->ref_count++;
|
||||
|
||||
return pattern;
|
||||
|
@ -546,6 +566,8 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
|
|||
if (pattern->ref_count == (unsigned int)-1)
|
||||
return;
|
||||
|
||||
assert (pattern->ref_count > 0);
|
||||
|
||||
pattern->ref_count--;
|
||||
if (pattern->ref_count)
|
||||
return;
|
||||
|
@ -596,7 +618,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
|
|||
*
|
||||
* Note: If the pattern is not a gradient pattern, (eg. a linear or
|
||||
* radial pattern), then the pattern will be put into an error status
|
||||
* with a status of CAIRO_STATUS_PATTERN_MISMATCH.
|
||||
* with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
|
||||
**/
|
||||
void
|
||||
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
|
||||
|
@ -647,7 +669,7 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
|
|||
*
|
||||
* Note: If the pattern is not a gradient pattern, (eg. a linear or
|
||||
* radial pattern), then the pattern will be put into an error status
|
||||
* with a status of CAIRO_STATUS_PATTERN_MISMATCH.
|
||||
* with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
|
||||
*/
|
||||
void
|
||||
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
|
||||
|
@ -703,8 +725,8 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
|
|||
* it does by default the correct code to use is:
|
||||
*
|
||||
* <informalexample><programlisting>
|
||||
* cairo_matrix_init_scale (&matrix, 0.5, 0.5);
|
||||
* cairo_pattern_set_matrix (pattern, &matrix);
|
||||
* cairo_matrix_init_scale (&matrix, 0.5, 0.5);
|
||||
* cairo_pattern_set_matrix (pattern, &matrix);
|
||||
* </programlisting></informalexample>
|
||||
*
|
||||
* Meanwhile, using values of 2.0 rather than 0.5 in the code above
|
||||
|
@ -717,10 +739,8 @@ void
|
|||
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
|
||||
const cairo_matrix_t *matrix)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->matrix = *matrix;
|
||||
}
|
||||
|
@ -741,10 +761,8 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
|
|||
void
|
||||
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->filter = filter;
|
||||
}
|
||||
|
@ -758,10 +776,8 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern)
|
|||
void
|
||||
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->extend = extend;
|
||||
}
|
||||
|
@ -781,24 +797,6 @@ _cairo_pattern_transform (cairo_pattern_t *pattern,
|
|||
cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
|
||||
}
|
||||
|
||||
#define INTERPOLATE_COLOR_NEAREST(c1, c2, factor) \
|
||||
((factor < 32768)? c1: c2)
|
||||
|
||||
static void
|
||||
_cairo_pattern_shader_nearest (unsigned char *color0,
|
||||
unsigned char *color1,
|
||||
cairo_fixed_t factor,
|
||||
uint32_t *pixel)
|
||||
{
|
||||
*pixel =
|
||||
((INTERPOLATE_COLOR_NEAREST (color0[3], color1[3], factor) << 24) |
|
||||
(INTERPOLATE_COLOR_NEAREST (color0[0], color1[0], factor) << 16) |
|
||||
(INTERPOLATE_COLOR_NEAREST (color0[1], color1[1], factor) << 8) |
|
||||
(INTERPOLATE_COLOR_NEAREST (color0[2], color1[2], factor) << 0));
|
||||
}
|
||||
|
||||
#undef INTERPOLATE_COLOR_NEAREST
|
||||
|
||||
#define INTERPOLATE_COLOR_LINEAR(c1, c2, factor) \
|
||||
(((c2 * factor) + (c1 * (65536 - factor))) / 65536)
|
||||
|
||||
|
@ -814,24 +812,6 @@ _cairo_pattern_shader_linear (unsigned char *color0,
|
|||
(INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
|
||||
}
|
||||
|
||||
#define E_MINUS_ONE 1.7182818284590452354
|
||||
|
||||
static void
|
||||
_cairo_pattern_shader_gaussian (unsigned char *color0,
|
||||
unsigned char *color1,
|
||||
cairo_fixed_t factor,
|
||||
uint32_t *pixel)
|
||||
{
|
||||
double f = ((double) factor) / 65536.0;
|
||||
|
||||
factor = (cairo_fixed_t) (((exp (f * f) - 1.0) / E_MINUS_ONE) * 65536);
|
||||
|
||||
*pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) |
|
||||
(INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) |
|
||||
(INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) |
|
||||
(INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
|
||||
}
|
||||
|
||||
#undef INTERPOLATE_COLOR_LINEAR
|
||||
|
||||
static int
|
||||
|
@ -889,24 +869,6 @@ _cairo_pattern_shader_init (cairo_gradient_pattern_t *pattern,
|
|||
op->n_stops = pattern->n_stops;
|
||||
op->extend = pattern->base.extend;
|
||||
|
||||
/* XXX: this is wrong, the filter should not be used for selecting
|
||||
color stop interpolation function. function should always be 'linear'
|
||||
and filter should be used for computing pixels. */
|
||||
switch (pattern->base.filter) {
|
||||
case CAIRO_FILTER_FAST:
|
||||
case CAIRO_FILTER_NEAREST:
|
||||
op->shader_function = _cairo_pattern_shader_nearest;
|
||||
break;
|
||||
case CAIRO_FILTER_GAUSSIAN:
|
||||
op->shader_function = _cairo_pattern_shader_gaussian;
|
||||
break;
|
||||
case CAIRO_FILTER_GOOD:
|
||||
case CAIRO_FILTER_BEST:
|
||||
case CAIRO_FILTER_BILINEAR:
|
||||
op->shader_function = _cairo_pattern_shader_linear;
|
||||
break;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -982,7 +944,7 @@ _cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op,
|
|||
factor = ((cairo_fixed_48_16_t) factor << 16) /
|
||||
stops[1]->scale;
|
||||
|
||||
op->shader_function (stops[0]->color_char,
|
||||
_cairo_pattern_shader_linear (stops[0]->color_char,
|
||||
stops[1]->color_char,
|
||||
factor, pixel);
|
||||
|
||||
|
@ -1050,7 +1012,7 @@ _cairo_image_data_set_linear (cairo_linear_pattern_t *pattern,
|
|||
|
||||
factor = ((dx * qx + dy * qy) - start) * scale;
|
||||
|
||||
_cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++);
|
||||
_cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1233,7 +1195,7 @@ _cairo_image_data_set_radial (cairo_radial_pattern_t *pattern,
|
|||
}
|
||||
}
|
||||
|
||||
_cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++);
|
||||
_cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1268,8 +1230,15 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
|||
height = 1;
|
||||
repeat = TRUE;
|
||||
}
|
||||
if (is_vertical) {
|
||||
width = 1;
|
||||
/* width-1 repeating patterns are quite slow with scan-line based
|
||||
* compositing code, so we use a wider strip and spend some extra
|
||||
* expense in computing the gradient. It's possible that for narrow
|
||||
* gradients we'd be better off using a 2 or 4 pixel strip; the
|
||||
* wider the gradient, the more it's worth spending extra time
|
||||
* computing a sample.
|
||||
*/
|
||||
if (is_vertical && width > 8) {
|
||||
width = 8;
|
||||
repeat = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -1457,8 +1426,11 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (pattern->status)
|
||||
if (pattern->status) {
|
||||
*surface_out = NULL;
|
||||
attributes->acquired = FALSE;
|
||||
return pattern->status;
|
||||
}
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_SOLID: {
|
||||
|
|
|
@ -336,6 +336,16 @@ cairo_pdf_surface_create (const char *filename,
|
|||
return _cairo_pdf_surface_create_for_stream_internal (stream, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo__surface_set_dpi:
|
||||
* @surface: a postscript cairo_surface_t
|
||||
* @x_dpi: horizontal dpi
|
||||
* @y_dpi: vertical dpi
|
||||
*
|
||||
* Set horizontal and vertical resolution for image fallbacks. When
|
||||
* the pdf backend needs to fall back to image overlays, it will use
|
||||
* this resolution.
|
||||
**/
|
||||
void
|
||||
cairo_pdf_surface_set_dpi (cairo_surface_t *surface,
|
||||
double x_dpi,
|
||||
|
@ -1296,6 +1306,7 @@ _cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
cairo_output_stream_t *output = document->output_stream;
|
||||
cairo_font_subset_t *pdf_font;
|
||||
int i, index;
|
||||
double det;
|
||||
|
||||
/* XXX: Need to fix this to work with a general cairo_scaled_font_t. */
|
||||
if (! _cairo_scaled_font_is_ft (scaled_font))
|
||||
|
@ -1305,6 +1316,13 @@ _cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
if (pdf_font == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
/* Some PDF viewers (at least older versions of xpdf) have trouble with
|
||||
* size 0 fonts. If the font size is less than 1/1000pt, ignore the
|
||||
* font */
|
||||
_cairo_matrix_compute_determinant (&scaled_font->scale, &det);
|
||||
if (fabs (det) < 0.000001)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
emit_pattern (surface, pattern);
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
|
|
|
@ -43,18 +43,18 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_pdf_surface_create (const char *filename,
|
||||
double width_in_points,
|
||||
double height_in_points);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
|
||||
void *closure,
|
||||
double width_in_points,
|
||||
double height_in_points);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pdf_surface_set_dpi (cairo_surface_t *surface,
|
||||
double x_dpi,
|
||||
double y_dpi);
|
||||
|
|
|
@ -173,130 +173,13 @@ device space.
|
|||
We construct the pen by computing points along the circumference
|
||||
using equally spaced angles.
|
||||
|
||||
We show below that this approximation to the ellipse has
|
||||
maximum error at the major axis of the ellipse.
|
||||
So, we need to compute the length of the major axis and then
|
||||
use that to compute the number of sides needed in our pen.
|
||||
|
||||
Thanks to Walter Brisken <wbrisken@aoc.nrao.edu> for this
|
||||
derivation:
|
||||
|
||||
1. First some notation:
|
||||
|
||||
All capital letters represent vectors in two dimensions. A prime '
|
||||
represents a transformed coordinate. Matrices are written in underlined
|
||||
form, ie _R_. Lowercase letters represent scalar real values.
|
||||
|
||||
The letter t is used to represent the greek letter theta.
|
||||
|
||||
2. The question has been posed: What is the maximum expansion factor
|
||||
achieved by the linear transformation
|
||||
|
||||
X' = _R_ X
|
||||
|
||||
where _R_ is a real-valued 2x2 matrix with entries:
|
||||
|
||||
_R_ = [a b]
|
||||
[c d] .
|
||||
|
||||
In other words, what is the maximum radius, MAX[ |X'| ], reached for any
|
||||
X on the unit circle ( |X| = 1 ) ?
|
||||
|
||||
|
||||
3. Some useful formulae
|
||||
|
||||
(A) through (C) below are standard double-angle formulae. (D) is a lesser
|
||||
known result and is derived below:
|
||||
|
||||
(A) sin^2(t) = (1 - cos(2*t))/2
|
||||
(B) cos^2(t) = (1 + cos(2*t))/2
|
||||
(C) sin(t)*cos(t) = sin(2*t)/2
|
||||
(D) MAX[a*cos(t) + b*sin(t)] = sqrt(a^2 + b^2)
|
||||
|
||||
Proof of (D):
|
||||
|
||||
find the maximum of the function by setting the derivative to zero:
|
||||
|
||||
-a*sin(t)+b*cos(t) = 0
|
||||
|
||||
From this it follows that
|
||||
|
||||
tan(t) = b/a
|
||||
|
||||
and hence
|
||||
|
||||
sin(t) = b/sqrt(a^2 + b^2)
|
||||
|
||||
and
|
||||
|
||||
cos(t) = a/sqrt(a^2 + b^2)
|
||||
|
||||
Thus the maximum value is
|
||||
|
||||
MAX[a*cos(t) + b*sin(t)] = (a^2 + b^2)/sqrt(a^2 + b^2)
|
||||
= sqrt(a^2 + b^2)
|
||||
|
||||
|
||||
4. Derivation of maximum expansion
|
||||
|
||||
To find MAX[ |X'| ] we search brute force method using calculus. The unit
|
||||
circle on which X is constrained is to be parameterized by t:
|
||||
|
||||
X(t) = (cos(t), sin(t))
|
||||
|
||||
Thus
|
||||
|
||||
X'(t) = (a*cos(t) + b*sin(t), c*cos(t) + d*sin(t)) .
|
||||
|
||||
Define
|
||||
|
||||
r(t) = |X'(t)|
|
||||
|
||||
Thus
|
||||
|
||||
r^2(t) = (a*cos(t) + b*sin(t))^2 + (c*cos(t) + d*sin(t))^2
|
||||
= (a^2 + c^2)*cos^2(t) + (b^2 + d^2)*sin^2(t)
|
||||
+ 2*(a*b + c*d)*cos(t)*sin(t)
|
||||
|
||||
Now apply the double angle formulae (A) to (C) from above:
|
||||
|
||||
r^2(t) = (a^2 + b^2 + c^2 + d^2)/2
|
||||
+ (a^2 - b^2 + c^2 - d^2)*cos(2*t)/2
|
||||
+ (a*b + c*d)*sin(2*t)
|
||||
= f + g*cos(u) + h*sin(u)
|
||||
|
||||
Where
|
||||
|
||||
f = (a^2 + b^2 + c^2 + d^2)/2
|
||||
g = (a^2 - b^2 + c^2 - d^2)/2
|
||||
h = (a*b + c*d)
|
||||
u = 2*t
|
||||
|
||||
It is clear that MAX[ |X'| ] = sqrt(MAX[ r^2 ]). Here we determine MAX[ r^2 ]
|
||||
using (D) from above:
|
||||
|
||||
MAX[ r^2 ] = f + sqrt(g^2 + h^2)
|
||||
|
||||
And finally
|
||||
|
||||
MAX[ |X'| ] = sqrt( f + sqrt(g^2 + h^2) )
|
||||
|
||||
Which is the solution to this problem.
|
||||
|
||||
|
||||
Walter Brisken
|
||||
2004/10/08
|
||||
|
||||
(Note that the minor axis length is at the minimum of the above solution,
|
||||
which is just sqrt (f - sqrt (g^2 + h^2)) given the symmetry of (D)).
|
||||
|
||||
Now to compute how many sides to use for the pen formed by
|
||||
a regular polygon.
|
||||
We show that this approximation to the ellipse has maximum error at the
|
||||
major axis of the ellipse.
|
||||
|
||||
Set
|
||||
|
||||
M = major axis length (computed by above formula)
|
||||
m = minor axis length (computed by above formula)
|
||||
M = major axis length
|
||||
m = minor axis length
|
||||
|
||||
Align 'M' along the X axis and 'm' along the Y axis and draw
|
||||
an ellipse parameterized by angle 't':
|
||||
|
@ -366,7 +249,6 @@ vertices = ceil(2π/2∆).
|
|||
|
||||
Note that this also equation works for M == m (a circle) as it
|
||||
doesn't matter where on the circle the error is computed.
|
||||
|
||||
*/
|
||||
|
||||
static int
|
||||
|
@ -374,27 +256,13 @@ _cairo_pen_vertices_needed (double tolerance,
|
|||
double radius,
|
||||
cairo_matrix_t *matrix)
|
||||
{
|
||||
double a = matrix->xx, b = matrix->yx;
|
||||
double c = matrix->xy, d = matrix->yy;
|
||||
|
||||
double i = a*a + c*c;
|
||||
double j = b*b + d*d;
|
||||
|
||||
double f = 0.5 * (i + j);
|
||||
double g = 0.5 * (i - j);
|
||||
double h = a*b + c*d;
|
||||
|
||||
/*
|
||||
* compute major and minor axes lengths for
|
||||
* a pen with the specified radius
|
||||
* the pen is a circle that gets transformed to an ellipse by matrix.
|
||||
* compute major axis length for a pen with the specified radius.
|
||||
* we don't need the minor axis length.
|
||||
*/
|
||||
|
||||
double major_axis = radius * sqrt (f + sqrt (g*g+h*h));
|
||||
|
||||
/*
|
||||
* we don't need the minor axis length, which is
|
||||
* double min = radius * sqrt (f - sqrt (g*g+h*h));
|
||||
*/
|
||||
double major_axis = _cairo_matrix_transformed_circle_major_axis(matrix, radius);
|
||||
|
||||
/*
|
||||
* compute number of vertices needed
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright <EFBFBD>Â<EFBFBD>© 2005 Mozilla Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_PLATFORM_H
|
||||
#define CAIRO_PLATFORM_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#define cairo_public extern __declspec(dllexport)
|
||||
#define CCALLBACK
|
||||
#define CCALLBACK_DECL
|
||||
#define CSTATIC_CALLBACK(__x) static __x
|
||||
|
||||
#elif defined(XP_BEOS)
|
||||
|
||||
#define cairo_public extern __declspec(dllexport)
|
||||
#define CCALLBACK
|
||||
#define CCALLBACK_DECL
|
||||
#define CSTATIC_CALLBACK(__x) static __x
|
||||
|
||||
#elif defined(XP_MAC)
|
||||
|
||||
#define cairo_public extern __declspec(export)
|
||||
#define CCALLBACK
|
||||
#define CCALLBACK_DECL
|
||||
#define CSTATIC_CALLBACK(__x) static __x
|
||||
|
||||
#elif defined(XP_OS2_VACPP)
|
||||
|
||||
#define cairo_public extern
|
||||
#define CCALLBACK _Optlink
|
||||
#define CCALLBACK_DECL
|
||||
#define CSTATIC_CALLBACK(__x) static __x CCALLBACK
|
||||
|
||||
#else /* Unix */
|
||||
|
||||
#ifdef HAVE_VISIBILITY_PRAGMA
|
||||
#define CVISIBILITY_DEFAULT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define CVISIBILITY_DEFAULT
|
||||
#endif
|
||||
|
||||
#define cairo_public extern CVISIBILITY_DEFAULT
|
||||
#define CCALLBACK
|
||||
#define CCALLBACK_DECL
|
||||
#define CSTATIC_CALLBACK(__x) static __x
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* CAIRO_PLATFORM_H */
|
|
@ -288,6 +288,13 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface,
|
|||
return write_png (surface, stream_write_func, &png_closure);
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
multiply_alpha (int alpha, int color)
|
||||
{
|
||||
int temp = (alpha * color) + 0x80;
|
||||
return ((temp + (temp >> 8)) >> 8);
|
||||
}
|
||||
|
||||
/* Premultiplies data and converts RGBA bytes => native endian */
|
||||
static void
|
||||
premultiply_data (png_structp png,
|
||||
|
@ -298,16 +305,23 @@ premultiply_data (png_structp png,
|
|||
|
||||
for (i = 0; i < row_info->rowbytes; i += 4) {
|
||||
uint8_t *base = &data[i];
|
||||
uint8_t red = base[0];
|
||||
uint8_t green = base[1];
|
||||
uint8_t blue = base[2];
|
||||
uint8_t alpha = base[3];
|
||||
uint32_t p;
|
||||
|
||||
red = ((unsigned) red * (unsigned) alpha + 127) / 255;
|
||||
green = ((unsigned) green * (unsigned) alpha + 127) / 255;
|
||||
blue = ((unsigned) blue * (unsigned) alpha + 127) / 255;
|
||||
if (alpha == 0) {
|
||||
p = 0;
|
||||
} else {
|
||||
uint8_t red = base[0];
|
||||
uint8_t green = base[1];
|
||||
uint8_t blue = base[2];
|
||||
|
||||
if (alpha != 0xff) {
|
||||
red = multiply_alpha (alpha, red);
|
||||
green = multiply_alpha (alpha, green);
|
||||
blue = multiply_alpha (alpha, blue);
|
||||
}
|
||||
p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
|
||||
}
|
||||
memcpy (base, &p, sizeof (uint32_t));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
surface->height = height;
|
||||
surface->x_dpi = PS_SURFACE_DPI_DEFAULT;
|
||||
surface->y_dpi = PS_SURFACE_DPI_DEFAULT;
|
||||
surface->base.device_x_scale = surface->x_dpi / 72.0;
|
||||
surface->base.device_y_scale = surface->y_dpi / 72.0;
|
||||
|
||||
surface->current_page = _cairo_meta_surface_create (width,
|
||||
height);
|
||||
|
@ -154,6 +156,29 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func,
|
|||
height_in_points);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_ps_surface_set_dpi:
|
||||
* @surface: a postscript cairo_surface_t
|
||||
* @x_dpi: horizontal dpi
|
||||
* @y_dpi: vertical dpi
|
||||
*
|
||||
* Set horizontal and vertical resolution for image fallbacks. When
|
||||
* the postscript backend needs to fall back to image overlays, it
|
||||
* will use this resolution.
|
||||
**/
|
||||
void
|
||||
cairo_ps_surface_set_dpi (cairo_surface_t *surface,
|
||||
double x_dpi,
|
||||
double y_dpi)
|
||||
{
|
||||
cairo_ps_surface_t *ps_surface = (cairo_ps_surface_t *) surface;
|
||||
|
||||
ps_surface->x_dpi = x_dpi;
|
||||
ps_surface->y_dpi = y_dpi;
|
||||
ps_surface->base.device_x_scale = ps_surface->x_dpi / 72.0;
|
||||
ps_surface->base.device_y_scale = ps_surface->y_dpi / 72.0;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
@ -164,7 +189,7 @@ _cairo_ps_surface_finish (void *abstract_surface)
|
|||
int i;
|
||||
time_t now;
|
||||
|
||||
now = time (0);
|
||||
now = time (NULL);
|
||||
|
||||
/* Document header */
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
|
@ -610,6 +635,12 @@ color_is_gray (cairo_color_t *color)
|
|||
fabs (color->red - color->blue) < epsilon);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
color_is_translucent (const cairo_color_t *color)
|
||||
{
|
||||
return color->alpha < 0.999;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
pattern_is_translucent (cairo_pattern_t *abstract_pattern)
|
||||
{
|
||||
|
@ -618,7 +649,7 @@ pattern_is_translucent (cairo_pattern_t *abstract_pattern)
|
|||
pattern = (cairo_pattern_union_t *) abstract_pattern;
|
||||
switch (pattern->base.type) {
|
||||
case CAIRO_PATTERN_SOLID:
|
||||
return pattern->solid.color.alpha < 0.9;
|
||||
return color_is_translucent (&pattern->solid.color);
|
||||
case CAIRO_PATTERN_SURFACE:
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_RADIAL:
|
||||
|
@ -658,6 +689,7 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
unsigned char *rgb, *compressed;
|
||||
unsigned long rgb_size, compressed_size;
|
||||
cairo_surface_t *opaque;
|
||||
cairo_image_surface_t *opaque_image;
|
||||
cairo_pattern_union_t pattern;
|
||||
cairo_matrix_t d2i;
|
||||
int x, y, i;
|
||||
|
@ -668,11 +700,10 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
if (image->base.status)
|
||||
return image->base.status;
|
||||
|
||||
opaque = _cairo_surface_create_similar_solid (&image->base,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
if (image->format != CAIRO_FORMAT_RGB24) {
|
||||
opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
||||
image->width,
|
||||
image->height,
|
||||
CAIRO_COLOR_WHITE);
|
||||
image->height);
|
||||
if (opaque->status) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto bail0;
|
||||
|
@ -691,8 +722,13 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
image->height);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
opaque_image = (cairo_image_surface_t *) opaque;
|
||||
} else {
|
||||
opaque = &image->base;
|
||||
opaque_image = image;
|
||||
}
|
||||
|
||||
rgb_size = 3 * image->width * image->height;
|
||||
rgb_size = 3 * opaque_image->width * opaque_image->height;
|
||||
rgb = malloc (rgb_size);
|
||||
if (rgb == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -700,9 +736,9 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
i = 0;
|
||||
for (y = 0; y < image->height; y++) {
|
||||
pixman_bits_t *pixel = (pixman_bits_t *) (image->data + y * image->stride);
|
||||
for (x = 0; x < image->width; x++, pixel++) {
|
||||
for (y = 0; y < opaque_image->height; y++) {
|
||||
pixman_bits_t *pixel = (pixman_bits_t *) (opaque_image->data + y * opaque_image->stride);
|
||||
for (x = 0; x < opaque_image->width; x++, pixel++) {
|
||||
rgb[i++] = (*pixel & 0x00ff0000) >> 16;
|
||||
rgb[i++] = (*pixel & 0x0000ff00) >> 8;
|
||||
rgb[i++] = (*pixel & 0x000000ff) >> 0;
|
||||
|
@ -718,7 +754,7 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
/* matrix transforms from user space to image space. We need to
|
||||
* transform from device space to image space to compensate for
|
||||
* postscripts coordinate system. */
|
||||
cairo_matrix_init (&d2i, 1, 0, 0, -1, 0, surface->height);
|
||||
cairo_matrix_init (&d2i, 1, 0, 0, 1, 0, 0);
|
||||
cairo_matrix_multiply (&d2i, &d2i, matrix);
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
|
@ -733,8 +769,8 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
" /ImageMatrix [ %f %f %f %f %f %f ]\n"
|
||||
">>\n"
|
||||
"image\n",
|
||||
image->width,
|
||||
image->height,
|
||||
opaque_image->width,
|
||||
opaque_image->height,
|
||||
d2i.xx, d2i.yx,
|
||||
d2i.xy, d2i.yy,
|
||||
d2i.x0, d2i.y0);
|
||||
|
@ -750,6 +786,7 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
bail2:
|
||||
free (rgb);
|
||||
bail1:
|
||||
if (opaque_image != image)
|
||||
cairo_surface_destroy (opaque);
|
||||
bail0:
|
||||
return status;
|
||||
|
@ -842,7 +879,7 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
* need pixmap fallbacks for this, though. */
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _ps_output_composite: with mask\n");
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
@ -850,7 +887,7 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
case CAIRO_PATTERN_SOLID:
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _ps_output_composite: solid\n");
|
||||
break;
|
||||
goto bail;
|
||||
|
||||
case CAIRO_PATTERN_SURFACE:
|
||||
surface_pattern = (cairo_surface_pattern_t *) src_pattern;
|
||||
|
@ -858,7 +895,7 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
if (src_pattern->extend != CAIRO_EXTEND_NONE) {
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _ps_output_composite: repeating image\n");
|
||||
break;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
||||
|
@ -868,7 +905,7 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _ps_output_composite: src_pattern not available as image\n");
|
||||
break;
|
||||
goto bail;
|
||||
} else if (status) {
|
||||
break;
|
||||
}
|
||||
|
@ -881,10 +918,12 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
case CAIRO_PATTERN_RADIAL:
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _ps_output_composite: gradient\n");
|
||||
break;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
return status;
|
||||
bail:
|
||||
return _ps_output_add_fallback_area (surface, dst_x, dst_y, width, height);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -899,6 +938,24 @@ _ps_output_fill_rectangles (void *abstract_surface,
|
|||
cairo_solid_pattern_t solid;
|
||||
int i;
|
||||
|
||||
if (!num_rects)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (color_is_translucent (color)) {
|
||||
int min_x = rects[0].x;
|
||||
int min_y = rects[0].y;
|
||||
int max_x = rects[0].x + rects[0].width;
|
||||
int max_y = rects[0].y + rects[0].height;
|
||||
|
||||
for (i = 1; i < num_rects; i++) {
|
||||
if (rects[i].x < min_x) min_x = rects[i].x;
|
||||
if (rects[i].y < min_y) min_y = rects[i].y;
|
||||
if (rects[i].x + rects[i].width > max_x) max_x = rects[i].x + rects[i].width;
|
||||
if (rects[i].y + rects[i].height > max_y) max_y = rects[i].y + rects[i].height;
|
||||
}
|
||||
return _ps_output_add_fallback_area (surface, min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _ps_output_fill_rectangles\n");
|
||||
|
||||
|
@ -909,9 +966,8 @@ _ps_output_fill_rectangles (void *abstract_surface,
|
|||
_cairo_output_stream_printf (stream, "[");
|
||||
for (i = 0; i < num_rects; i++) {
|
||||
_cairo_output_stream_printf (stream,
|
||||
" %d %f %d %d",
|
||||
rects[i].x,
|
||||
(double)(surface->parent->height - rects[i].y - rects[i].height),
|
||||
" %d %d %d %d",
|
||||
rects[i].x, rects[i].y,
|
||||
rects[i].width, rects[i].height);
|
||||
}
|
||||
|
||||
|
@ -962,8 +1018,8 @@ _ps_output_composite_trapezoids (cairo_operator_t operator,
|
|||
left_x2 = intersect (&traps[i].left, traps[i].bottom);
|
||||
right_x1 = intersect (&traps[i].right, traps[i].top);
|
||||
right_x2 = intersect (&traps[i].right, traps[i].bottom);
|
||||
top = surface->parent->height - _cairo_fixed_to_double (traps[i].top);
|
||||
bottom = surface->parent->height - _cairo_fixed_to_double (traps[i].bottom);
|
||||
top = _cairo_fixed_to_double (traps[i].top);
|
||||
bottom = _cairo_fixed_to_double (traps[i].bottom);
|
||||
|
||||
_cairo_output_stream_printf
|
||||
(stream,
|
||||
|
@ -983,7 +1039,6 @@ _ps_output_composite_trapezoids (cairo_operator_t operator,
|
|||
|
||||
typedef struct
|
||||
{
|
||||
double height;
|
||||
cairo_output_stream_t *output_stream;
|
||||
cairo_bool_t has_current_point;
|
||||
} ps_output_path_info_t;
|
||||
|
@ -996,7 +1051,7 @@ _ps_output_path_move_to (void *closure, cairo_point_t *point)
|
|||
_cairo_output_stream_printf (info->output_stream,
|
||||
"%f %f moveto ",
|
||||
_cairo_fixed_to_double (point->x),
|
||||
info->height - _cairo_fixed_to_double (point->y));
|
||||
_cairo_fixed_to_double (point->y));
|
||||
info->has_current_point = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -1016,7 +1071,7 @@ _ps_output_path_line_to (void *closure, cairo_point_t *point)
|
|||
_cairo_output_stream_printf (info->output_stream,
|
||||
"%f %f %s ",
|
||||
_cairo_fixed_to_double (point->x),
|
||||
info->height - _cairo_fixed_to_double (point->y),
|
||||
_cairo_fixed_to_double (point->y),
|
||||
ps_operator);
|
||||
info->has_current_point = TRUE;
|
||||
|
||||
|
@ -1034,11 +1089,11 @@ _ps_output_path_curve_to (void *closure,
|
|||
_cairo_output_stream_printf (info->output_stream,
|
||||
"%f %f %f %f %f %f curveto ",
|
||||
_cairo_fixed_to_double (b->x),
|
||||
info->height - _cairo_fixed_to_double (b->y),
|
||||
_cairo_fixed_to_double (b->y),
|
||||
_cairo_fixed_to_double (c->x),
|
||||
info->height - _cairo_fixed_to_double (c->y),
|
||||
_cairo_fixed_to_double (c->y),
|
||||
_cairo_fixed_to_double (d->x),
|
||||
info->height - _cairo_fixed_to_double (d->y));
|
||||
_cairo_fixed_to_double (d->y));
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1078,7 +1133,6 @@ _ps_output_intersect_clip_path (void *abstract_surface,
|
|||
|
||||
info.output_stream = stream;
|
||||
info.has_current_point = FALSE;
|
||||
info.height = surface->parent->height;
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
|
@ -1150,7 +1204,7 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
scaled_font->scale.xx,
|
||||
scaled_font->scale.yx,
|
||||
scaled_font->scale.xy,
|
||||
scaled_font->scale.yy);
|
||||
-scaled_font->scale.yy);
|
||||
|
||||
/* FIXME: Need to optimize per glyph code. Should detect when
|
||||
* glyphs share the same baseline and when the spacing corresponds
|
||||
|
@ -1161,7 +1215,7 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
_cairo_output_stream_printf (stream,
|
||||
"%f %f moveto (\\%o) show\n",
|
||||
glyphs[i].x,
|
||||
surface->parent->height - glyphs[i].y,
|
||||
glyphs[i].y,
|
||||
subset_index);
|
||||
|
||||
}
|
||||
|
@ -1183,6 +1237,11 @@ _ps_output_fill_path (cairo_operator_t operator,
|
|||
ps_output_path_info_t info;
|
||||
const char *ps_operator;
|
||||
|
||||
if (pattern_is_translucent (pattern))
|
||||
return _ps_output_add_fallback_area (surface,
|
||||
0, 0,
|
||||
surface->parent->width,
|
||||
surface->parent->height);
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _ps_output_fill_path\n");
|
||||
|
||||
|
@ -1190,7 +1249,6 @@ _ps_output_fill_path (cairo_operator_t operator,
|
|||
|
||||
info.output_stream = stream;
|
||||
info.has_current_point = FALSE;
|
||||
info.height = surface->parent->height;
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
|
@ -1312,8 +1370,11 @@ _cairo_ps_surface_render_page (cairo_ps_surface_t *surface,
|
|||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"%%%%Page: %d\n"
|
||||
"gsave\n",
|
||||
page_number);
|
||||
"gsave %f %f translate %f %f scale \n",
|
||||
page_number,
|
||||
0.0, surface->height,
|
||||
1.0/surface->base.device_x_scale,
|
||||
-1.0/surface->base.device_y_scale);
|
||||
|
||||
ps_output = _ps_output_surface_create (surface);
|
||||
if (ps_output->status)
|
||||
|
|
|
@ -47,18 +47,18 @@ CAIRO_BEGIN_DECLS
|
|||
|
||||
/* PS-surface functions */
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_ps_surface_create (const char *filename,
|
||||
double width_in_points,
|
||||
double height_in_points);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_ps_surface_create_for_stream (cairo_write_func_t write_func,
|
||||
void *closure,
|
||||
double width_in_points,
|
||||
double height_in_points);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_ps_surface_set_dpi (cairo_surface_t *surface,
|
||||
double x_dpi,
|
||||
double y_dpi);
|
||||
|
|
|
@ -125,8 +125,8 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
|
|||
surface->width,
|
||||
surface->height, rowBytes);
|
||||
if (surface->image->base.status) {
|
||||
/* XXX: I assume we're leaking memory here, but I don't know
|
||||
* the right call to use to clean up from CGImageCreate. */
|
||||
if (surface->cgImage)
|
||||
CGImageRelease(surface->cgImage);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_quartz_surface_create (CGContextRef context,
|
||||
int width,
|
||||
int height);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -108,6 +108,10 @@ static void
|
|||
_cairo_surface_set_error (cairo_surface_t *surface,
|
||||
cairo_status_t status)
|
||||
{
|
||||
/* Don't overwrite an existing error. This preserves the first
|
||||
* error, which is the most significant. It also avoids attempting
|
||||
* to write to read-only data (eg. from a nil surface). */
|
||||
if (surface->status == CAIRO_STATUS_SUCCESS)
|
||||
surface->status = status;
|
||||
|
||||
_cairo_error (status);
|
||||
|
@ -143,8 +147,10 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
|
||||
_cairo_user_data_array_init (&surface->user_data);
|
||||
|
||||
surface->device_x_offset = 0;
|
||||
surface->device_y_offset = 0;
|
||||
surface->device_x_offset = 0.0;
|
||||
surface->device_y_offset = 0.0;
|
||||
surface->device_x_scale = 1.0;
|
||||
surface->device_y_scale = 1.0;
|
||||
|
||||
surface->next_clip_serial = 0;
|
||||
surface->current_clip_serial = 0;
|
||||
|
@ -264,6 +270,8 @@ cairo_surface_reference (cairo_surface_t *surface)
|
|||
if (surface->ref_count == (unsigned int)-1)
|
||||
return surface;
|
||||
|
||||
assert (surface->ref_count > 0);
|
||||
|
||||
surface->ref_count++;
|
||||
|
||||
return surface;
|
||||
|
@ -286,6 +294,8 @@ cairo_surface_destroy (cairo_surface_t *surface)
|
|||
if (surface->ref_count == (unsigned int)-1)
|
||||
return;
|
||||
|
||||
assert (surface->ref_count > 0);
|
||||
|
||||
surface->ref_count--;
|
||||
if (surface->ref_count)
|
||||
return;
|
||||
|
@ -434,10 +444,8 @@ cairo_surface_get_font_options (cairo_surface_t *surface,
|
|||
void
|
||||
cairo_surface_flush (cairo_surface_t *surface)
|
||||
{
|
||||
if (surface->status) {
|
||||
_cairo_surface_set_error (surface, surface->status);
|
||||
if (surface->status)
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->finished) {
|
||||
_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||
|
@ -487,10 +495,8 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
if (surface->status) {
|
||||
_cairo_surface_set_error (surface, surface->status);
|
||||
if (surface->status)
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->finished) {
|
||||
_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||
|
@ -530,27 +536,25 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
|
|||
double x_offset,
|
||||
double y_offset)
|
||||
{
|
||||
if (surface->status) {
|
||||
_cairo_surface_set_error (surface, surface->status);
|
||||
if (surface->status)
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->finished) {
|
||||
_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||
return;
|
||||
}
|
||||
|
||||
surface->device_x_offset = x_offset;
|
||||
surface->device_y_offset = y_offset;
|
||||
surface->device_x_offset = x_offset * surface->device_x_scale;
|
||||
surface->device_y_offset = y_offset * surface->device_y_scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_acquire_source_image:
|
||||
* @surface: a #cairo_surface_t
|
||||
* @image_out: location to store a pointer to an image surface that includes at least
|
||||
* the intersection of @interest_rect with the visible area of @surface.
|
||||
* This surface could be @surface itself, a surface held internal to @surface,
|
||||
* or it could be a new surface with a copy of the relevant portion of @surface.
|
||||
* @image_out: location to store a pointer to an image surface that
|
||||
* has identical contents to @surface. This surface could be @surface
|
||||
* itself, a surface held internal to @surface, or it could be a new
|
||||
* surface with a copy of the relevant portion of @surface.
|
||||
* @image_extra: location to store image specific backend data
|
||||
*
|
||||
* Gets an image surface to use when drawing as a fallback when drawing with
|
||||
|
@ -574,7 +578,7 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
|
|||
/**
|
||||
* _cairo_surface_release_source_image:
|
||||
* @surface: a #cairo_surface_t
|
||||
* @image_extra: same as return from the matching _cairo_surface_acquire_dest_image()
|
||||
* @image_extra: same as return from the matching _cairo_surface_acquire_source_image()
|
||||
*
|
||||
* Releases any resources obtained with _cairo_surface_acquire_source_image()
|
||||
**/
|
||||
|
@ -598,6 +602,8 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
|
|||
* the intersection of @interest_rect with the visible area of @surface.
|
||||
* This surface could be @surface itself, a surface held internal to @surface,
|
||||
* or it could be a new surface with a copy of the relevant portion of @surface.
|
||||
* If a new surface is created, it should have the same channels and depth
|
||||
* as @surface so that copying to and from it is exact.
|
||||
* @image_rect: location to store area of the original surface occupied
|
||||
* by the surface stored in @image.
|
||||
* @image_extra: location to store image specific backend data
|
||||
|
@ -605,7 +611,7 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
|
|||
* Retrieves a local image for a surface for implementing a fallback drawing
|
||||
* operation. After calling this function, the implementation of the fallback
|
||||
* drawing operation draws the primitive to the surface stored in @image_out
|
||||
* then calls _cairo_surface_release_dest_fallback(),
|
||||
* then calls _cairo_surface_release_dest_image(),
|
||||
* which, if a temporary surface was created, copies the bits back to the
|
||||
* main surface and frees the temporary surface.
|
||||
*
|
||||
|
@ -614,7 +620,7 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
|
|||
* the backend can't draw with fallbacks. It's possible for the routine
|
||||
* to store NULL in @local_out and return %CAIRO_STATUS_SUCCESS;
|
||||
* that indicates that no part of @interest_rect is visible, so no drawing
|
||||
* is necessary. _cairo_surface_release_dest_fallback() should not be called in that
|
||||
* is necessary. _cairo_surface_release_dest_image() should not be called in that
|
||||
* case.
|
||||
**/
|
||||
cairo_status_t
|
||||
|
@ -631,7 +637,7 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
|
|||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_end_fallback:
|
||||
* _cairo_surface_release_dest_image:
|
||||
* @surface: a #cairo_surface_t
|
||||
* @interest_rect: same as passed to the matching _cairo_surface_acquire_dest_image()
|
||||
* @image: same as returned from the matching _cairo_surface_acquire_dest_image()
|
||||
|
@ -684,11 +690,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
|||
if (surface->finished)
|
||||
return CAIRO_STATUS_SURFACE_FINISHED;
|
||||
|
||||
if (surface->backend->clone_similar) {
|
||||
if (surface->backend->clone_similar == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = surface->backend->clone_similar (surface, src, clone_out);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
|
@ -817,6 +824,13 @@ _cairo_surface_composite (cairo_operator_t operator,
|
|||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (mask) {
|
||||
/* These operators aren't interpreted the same way by the backends;
|
||||
* they are implemented in terms of other operators in cairo-gstate.c
|
||||
*/
|
||||
assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR);
|
||||
}
|
||||
|
||||
if (dst->status)
|
||||
return dst->status;
|
||||
|
||||
|
@ -1013,7 +1027,7 @@ _fallback_fill_rectangles (cairo_surface_t *surface,
|
|||
*
|
||||
* Applies an operator to a set of rectangles using a solid color
|
||||
* as the source. Note that even if the operator is an unbounded operator
|
||||
* such as %CAIRO_OPERATOR_CLEAR, only the given set of rectangles
|
||||
* such as %CAIRO_OPERATOR_IN, only the given set of rectangles
|
||||
* is affected. This differs from _cairo_surface_composite_trapezoids()
|
||||
* where the entire destination rectangle is cleared.
|
||||
*
|
||||
|
@ -1152,6 +1166,11 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
|
|||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
/* These operators aren't interpreted the same way by the backends;
|
||||
* they are implemented in terms of other operators in cairo-gstate.c
|
||||
*/
|
||||
assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR);
|
||||
|
||||
if (dst->status)
|
||||
return dst->status;
|
||||
|
||||
|
|
|
@ -827,16 +827,10 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
|
|||
for (i = 0; i < traps->num_traps; i++)
|
||||
if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
|
||||
&& traps->traps[i].right.p1.x == traps->traps[i].right.p2.x
|
||||
&& traps->traps[i].left.p1.y == traps->traps[i].right.p1.y
|
||||
&& traps->traps[i].left.p2.y == traps->traps[i].right.p2.y
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].top)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].bottom)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].left.p1.y)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].left.p2.x)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].left.p2.y)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].right.p1.x)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].right.p1.y)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].right.p2.x)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].right.p2.y))) {
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
|
||||
*region = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -845,9 +839,9 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
|
|||
|
||||
for (i = 0; i < traps->num_traps; i++) {
|
||||
int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
|
||||
int y = _cairo_fixed_integer_part(traps->traps[i].left.p1.y);
|
||||
int y = _cairo_fixed_integer_part(traps->traps[i].top);
|
||||
int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x;
|
||||
int height = _cairo_fixed_integer_part(traps->traps[i].left.p2.y) - y;
|
||||
int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y;
|
||||
|
||||
/* XXX: Sometimes we get degenerate trapezoids from the tesellator,
|
||||
* if we call pixman_region_union_rect(), it bizarrly fails on such
|
||||
|
|
|
@ -101,6 +101,17 @@ typedef struct {
|
|||
|
||||
} cairo_win32_scaled_font_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph);
|
||||
|
||||
#define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))
|
||||
|
||||
static void
|
||||
|
@ -221,6 +232,7 @@ _win32_scaled_font_create (LOGFONTW *logfont,
|
|||
{
|
||||
cairo_win32_scaled_font_t *f;
|
||||
cairo_matrix_t scale;
|
||||
cairo_status_t status;
|
||||
|
||||
f = malloc (sizeof(cairo_win32_scaled_font_t));
|
||||
if (f == NULL)
|
||||
|
@ -252,6 +264,8 @@ _win32_scaled_font_create (LOGFONTW *logfont,
|
|||
else
|
||||
f->quality = ANTIALIASED_QUALITY;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,6 +280,12 @@ _win32_scaled_font_create (LOGFONTW *logfont,
|
|||
font_matrix, ctm, options,
|
||||
&cairo_win32_scaled_font_backend);
|
||||
|
||||
status = _cairo_win32_scaled_font_set_metrics (f);
|
||||
if (status) {
|
||||
cairo_scaled_font_destroy (&f->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &f->base;
|
||||
}
|
||||
|
||||
|
@ -324,7 +344,7 @@ _win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font)
|
|||
{
|
||||
if (!scaled_font->scaled_hfont) {
|
||||
LOGFONTW logfont = scaled_font->logfont;
|
||||
logfont.lfHeight = scaled_font->logical_size;
|
||||
logfont.lfHeight = -scaled_font->logical_size;
|
||||
logfont.lfWidth = 0;
|
||||
logfont.lfEscapement = 0;
|
||||
logfont.lfOrientation = 0;
|
||||
|
@ -379,7 +399,7 @@ _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font,
|
|||
free (otm);
|
||||
|
||||
logfont = scaled_font->logfont;
|
||||
logfont.lfHeight = scaled_font->em_square;
|
||||
logfont.lfHeight = -scaled_font->em_square;
|
||||
logfont.lfWidth = 0;
|
||||
logfont.lfEscapement = 0;
|
||||
logfont.lfOrientation = 0;
|
||||
|
@ -496,7 +516,7 @@ _cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
|
|||
if (!logfont.lfFaceName)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
scaled_font = _win32_scaled_font_create (&logfont, toy_face,
|
||||
scaled_font = _win32_scaled_font_create (&logfont, &toy_face->base,
|
||||
font_matrix, ctm, options);
|
||||
if (!scaled_font)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -521,14 +541,10 @@ _cairo_win32_scaled_font_fini (void *abstract_font)
|
|||
DeleteObject (scaled_font->unscaled_hfont);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_win32_scaled_font_get_glyph_cache_key (void *abstract_font,
|
||||
cairo_glyph_cache_key_t *key)
|
||||
{
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
|
||||
double x,
|
||||
double y,
|
||||
const char *utf8,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs)
|
||||
|
@ -541,9 +557,17 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
|
|||
WCHAR *glyph_indices = NULL;
|
||||
int *dx = NULL;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
double x_pos;
|
||||
double x_pos, y_pos;
|
||||
double x_incr, y_incr;
|
||||
HDC hdc = NULL;
|
||||
|
||||
/* Compute a vector in user space along the baseline of length one logical space unit */
|
||||
x_incr = 1;
|
||||
y_incr = 0;
|
||||
cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr);
|
||||
x_incr /= scaled_font->logical_scale;
|
||||
y_incr /= scaled_font->logical_scale;
|
||||
|
||||
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
|
||||
if (status)
|
||||
return status;
|
||||
|
@ -618,13 +642,16 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
|
|||
goto FAIL2;
|
||||
}
|
||||
|
||||
x_pos = 0;
|
||||
x_pos = x;
|
||||
y_pos = y;
|
||||
|
||||
for (i = 0; i < gcp_results.nGlyphs; i++) {
|
||||
(*glyphs)[i].index = glyph_indices[i];
|
||||
(*glyphs)[i].x = x_pos ;
|
||||
(*glyphs)[i].y = 0;
|
||||
(*glyphs)[i].y = y_pos;
|
||||
|
||||
x_pos += dx[i] / scaled_font->logical_scale;
|
||||
x_pos += x_incr * dx[i];
|
||||
y_pos += y_incr * dx[i];
|
||||
}
|
||||
|
||||
FAIL2:
|
||||
|
@ -642,11 +669,11 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_font_extents (void *abstract_font,
|
||||
cairo_font_extents_t *extents)
|
||||
_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
cairo_status_t status;
|
||||
cairo_font_extents_t extents;
|
||||
|
||||
TEXTMETRIC metrics;
|
||||
HDC hdc;
|
||||
|
||||
|
@ -664,12 +691,12 @@ _cairo_win32_scaled_font_font_extents (void *abstract_font,
|
|||
GetTextMetrics (hdc, &metrics);
|
||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||
|
||||
extents->ascent = metrics.tmAscent / scaled_font->logical_scale;
|
||||
extents->descent = metrics.tmDescent / scaled_font->logical_scale;
|
||||
extents.ascent = metrics.tmAscent / scaled_font->logical_scale;
|
||||
extents.descent = metrics.tmDescent / scaled_font->logical_scale;
|
||||
|
||||
extents->height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale;
|
||||
extents->max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale;
|
||||
extents->max_y_advance = 0;
|
||||
extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale;
|
||||
extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale;
|
||||
extents.max_y_advance = 0;
|
||||
|
||||
} else {
|
||||
/* For all other transformations, we use the design metrics
|
||||
|
@ -683,39 +710,33 @@ _cairo_win32_scaled_font_font_extents (void *abstract_font,
|
|||
GetTextMetrics (hdc, &metrics);
|
||||
_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
|
||||
|
||||
extents->ascent = (double)metrics.tmAscent / scaled_font->em_square;
|
||||
extents->descent = metrics.tmDescent * scaled_font->em_square;
|
||||
extents->height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square;
|
||||
extents->max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square;
|
||||
extents->max_y_advance = 0;
|
||||
extents.ascent = (double)metrics.tmAscent / scaled_font->em_square;
|
||||
extents.descent = metrics.tmDescent * scaled_font->em_square;
|
||||
extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square;
|
||||
extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square;
|
||||
extents.max_y_advance = 0;
|
||||
|
||||
}
|
||||
|
||||
_cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_glyph_extents (void *abstract_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents)
|
||||
_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
|
||||
GLYPHMETRICS metrics;
|
||||
cairo_status_t status;
|
||||
cairo_text_extents_t extents;
|
||||
HDC hdc;
|
||||
|
||||
hdc = _get_global_font_dc ();
|
||||
if (!hdc)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
/* We handle only the case num_glyphs == 1, glyphs[i].x == glyphs[0].y == 0.
|
||||
* This is all that the calling code triggers, and the backend interface
|
||||
* will eventually be changed to match
|
||||
*/
|
||||
assert (num_glyphs == 1);
|
||||
|
||||
if (scaled_font->preserve_axes) {
|
||||
/* If we aren't rotating / skewing the axes, then we get the metrics
|
||||
* from the GDI in device space and convert to font space.
|
||||
|
@ -723,34 +744,38 @@ _cairo_win32_scaled_font_glyph_extents (void *abstract_font,
|
|||
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
|
||||
if (status)
|
||||
return status;
|
||||
GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX,
|
||||
&metrics, 0, NULL, &matrix);
|
||||
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
|
||||
GGO_METRICS | GGO_GLYPH_INDEX,
|
||||
&metrics, 0, NULL, &matrix) == GDI_ERROR) {
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
|
||||
memset (&metrics, 0, sizeof (GLYPHMETRICS));
|
||||
}
|
||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||
|
||||
if (scaled_font->swap_axes) {
|
||||
extents->x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
|
||||
extents->y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
|
||||
extents->width = metrics.gmBlackBoxY / scaled_font->y_scale;
|
||||
extents->height = metrics.gmBlackBoxX / scaled_font->x_scale;
|
||||
extents->x_advance = metrics.gmCellIncY / scaled_font->x_scale;
|
||||
extents->y_advance = metrics.gmCellIncX / scaled_font->y_scale;
|
||||
extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
|
||||
extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
|
||||
extents.width = metrics.gmBlackBoxY / scaled_font->y_scale;
|
||||
extents.height = metrics.gmBlackBoxX / scaled_font->x_scale;
|
||||
extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale;
|
||||
extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale;
|
||||
} else {
|
||||
extents->x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
|
||||
extents->y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
|
||||
extents->width = metrics.gmBlackBoxX / scaled_font->x_scale;
|
||||
extents->height = metrics.gmBlackBoxY / scaled_font->y_scale;
|
||||
extents->x_advance = metrics.gmCellIncX / scaled_font->x_scale;
|
||||
extents->y_advance = metrics.gmCellIncY / scaled_font->y_scale;
|
||||
extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
|
||||
extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
|
||||
extents.width = metrics.gmBlackBoxX / scaled_font->x_scale;
|
||||
extents.height = metrics.gmBlackBoxY / scaled_font->y_scale;
|
||||
extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale;
|
||||
extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale;
|
||||
}
|
||||
|
||||
if (scaled_font->swap_x) {
|
||||
extents->x_bearing = (- extents->x_bearing - extents->width);
|
||||
extents->x_advance = - extents->x_advance;
|
||||
extents.x_bearing = (- extents.x_bearing - extents.width);
|
||||
extents.x_advance = - extents.x_advance;
|
||||
}
|
||||
|
||||
if (scaled_font->swap_y) {
|
||||
extents->y_bearing = (- extents->y_bearing - extents->height);
|
||||
extents->y_advance = - extents->y_advance;
|
||||
extents.y_bearing = (- extents.y_bearing - extents.height);
|
||||
extents.y_advance = - extents.y_advance;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -758,22 +783,35 @@ _cairo_win32_scaled_font_glyph_extents (void *abstract_font,
|
|||
* of the font.
|
||||
*/
|
||||
status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
|
||||
GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX,
|
||||
&metrics, 0, NULL, &matrix);
|
||||
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
|
||||
GGO_METRICS | GGO_GLYPH_INDEX,
|
||||
&metrics, 0, NULL, &matrix) == GDI_ERROR) {
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
|
||||
memset (&metrics, 0, sizeof (GLYPHMETRICS));
|
||||
}
|
||||
_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
|
||||
|
||||
extents->x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
|
||||
extents->y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
|
||||
extents->width = (double)metrics.gmBlackBoxX / scaled_font->em_square;
|
||||
extents->height = (double)metrics.gmBlackBoxY / scaled_font->em_square;
|
||||
extents->x_advance = (double)metrics.gmCellIncX / scaled_font->em_square;
|
||||
extents->y_advance = (double)metrics.gmCellIncY / scaled_font->em_square;
|
||||
extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
|
||||
extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
|
||||
extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square;
|
||||
extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square;
|
||||
extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square;
|
||||
extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square;
|
||||
}
|
||||
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
&extents);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Not currently used code, but may be useful in the future if we add
|
||||
* back the capability to the scaled font backend interface to get the
|
||||
* actual device space bbox rather than computing it from the
|
||||
* font-space metrics.
|
||||
*/
|
||||
#if 0
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
|
||||
const cairo_glyph_t *glyphs,
|
||||
|
@ -808,10 +846,10 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
|
|||
x1 = x + metrics.gmptGlyphOrigin.x;
|
||||
if (i == 0 || y1 > y - metrics.gmptGlyphOrigin.y)
|
||||
y1 = y - metrics.gmptGlyphOrigin.y;
|
||||
if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + metrics.gmBlackBoxX)
|
||||
x2 = x + metrics.gmptGlyphOrigin.x + metrics.gmBlackBoxX;
|
||||
if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + metrics.gmBlackBoxY)
|
||||
y2 = y - metrics.gmptGlyphOrigin.y + metrics.gmBlackBoxY;
|
||||
if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX)
|
||||
x2 = x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX;
|
||||
if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY)
|
||||
y2 = y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY;
|
||||
}
|
||||
|
||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||
|
@ -824,6 +862,7 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
cairo_win32_scaled_font_t *scaled_font;
|
||||
|
@ -1027,7 +1066,35 @@ _compute_a8_mask (cairo_win32_surface_t *mask_surface)
|
|||
return &image8->base;
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_glyph_init (void *abstract_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_glyph_info_t info)
|
||||
{
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
cairo_status_t status;
|
||||
|
||||
if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
|
||||
status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
|
||||
status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_scaled_font_show_glyphs (void *abstract_font,
|
||||
cairo_operator_t operator,
|
||||
cairo_pattern_t *pattern,
|
||||
|
@ -1148,56 +1215,51 @@ _cairo_fixed_from_FIXED (FIXED f)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_glyph_path (void *abstract_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path)
|
||||
_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } };
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
cairo_status_t status;
|
||||
GLYPHMETRICS metrics;
|
||||
HDC hdc;
|
||||
int i;
|
||||
DWORD bytesGlyph;
|
||||
unsigned char *buffer, *ptr;
|
||||
cairo_path_fixed_t *path;
|
||||
|
||||
hdc = _get_global_font_dc ();
|
||||
if (!hdc)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
path = _cairo_path_fixed_create ();
|
||||
if (!path)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
|
||||
if (status)
|
||||
return status;
|
||||
goto CLEANUP_PATH;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
DWORD bytesGlyph;
|
||||
unsigned char *buffer, *ptr;
|
||||
|
||||
cairo_fixed_t x = _cairo_fixed_from_double (glyphs[i].x);
|
||||
cairo_fixed_t y = _cairo_fixed_from_double (glyphs[i].y);
|
||||
|
||||
bytesGlyph = GetGlyphOutlineW (hdc, glyphs[i].index,
|
||||
bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
|
||||
GGO_NATIVE | GGO_GLYPH_INDEX,
|
||||
&metrics, 0, NULL, &matrix);
|
||||
|
||||
if (bytesGlyph == GDI_ERROR) {
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
|
||||
goto FAIL;
|
||||
goto CLEANUP_FONT;
|
||||
}
|
||||
|
||||
ptr = buffer = malloc (bytesGlyph);
|
||||
|
||||
if (!buffer) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto FAIL;
|
||||
goto CLEANUP_FONT;
|
||||
}
|
||||
|
||||
if (GetGlyphOutlineW (hdc, glyphs[i].index,
|
||||
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
|
||||
GGO_NATIVE | GGO_GLYPH_INDEX,
|
||||
&metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
|
||||
free (buffer);
|
||||
goto FAIL;
|
||||
goto CLEANUP_FONT;
|
||||
}
|
||||
|
||||
while (ptr < buffer + bytesGlyph) {
|
||||
|
@ -1207,8 +1269,8 @@ _cairo_win32_scaled_font_glyph_path (void *abstract_font,
|
|||
ptr += sizeof (TTPOLYGONHEADER);
|
||||
|
||||
_cairo_path_fixed_move_to (path,
|
||||
_cairo_fixed_from_FIXED (header->pfxStart.x) + x,
|
||||
_cairo_fixed_from_FIXED (header->pfxStart.y) + y);
|
||||
_cairo_fixed_from_FIXED (header->pfxStart.x),
|
||||
_cairo_fixed_from_FIXED (header->pfxStart.y));
|
||||
|
||||
while (ptr < endPoly) {
|
||||
TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
|
||||
|
@ -1218,25 +1280,25 @@ _cairo_win32_scaled_font_glyph_path (void *abstract_font,
|
|||
case TT_PRIM_LINE:
|
||||
for (i = 0; i < curve->cpfx; i++) {
|
||||
_cairo_path_fixed_line_to (path,
|
||||
_cairo_fixed_from_FIXED (points[i].x) + x,
|
||||
_cairo_fixed_from_FIXED (points[i].y) + y);
|
||||
_cairo_fixed_from_FIXED (points[i].x),
|
||||
_cairo_fixed_from_FIXED (points[i].y));
|
||||
}
|
||||
break;
|
||||
case TT_PRIM_QSPLINE:
|
||||
for (i = 0; i < curve->cpfx - 1; i++) {
|
||||
cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y;
|
||||
_cairo_path_fixed_get_current_point (path, &p1x, &p1y);
|
||||
cx = _cairo_fixed_from_FIXED (points[i].x) + x;
|
||||
cy = _cairo_fixed_from_FIXED (points[i].y) + y;
|
||||
cx = _cairo_fixed_from_FIXED (points[i].x);
|
||||
cy = _cairo_fixed_from_FIXED (points[i].y);
|
||||
|
||||
if (i + 1 == curve->cpfx - 1) {
|
||||
p2x = _cairo_fixed_from_FIXED (points[i + 1].x) + x;
|
||||
p2y = _cairo_fixed_from_FIXED (points[i + 1].y) + y;
|
||||
p2x = _cairo_fixed_from_FIXED (points[i + 1].x);
|
||||
p2y = _cairo_fixed_from_FIXED (points[i + 1].y);
|
||||
} else {
|
||||
/* records with more than one curve use interpolation for
|
||||
control points, per http://support.microsoft.com/kb/q87115/ */
|
||||
p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x) + x) / 2;
|
||||
p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y) + y) / 2;
|
||||
p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x)) / 2;
|
||||
p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y)) / 2;
|
||||
}
|
||||
|
||||
c1x = 2 * cx / 3 + p1x / 3;
|
||||
|
@ -1250,12 +1312,12 @@ _cairo_win32_scaled_font_glyph_path (void *abstract_font,
|
|||
case TT_PRIM_CSPLINE:
|
||||
for (i = 0; i < curve->cpfx - 2; i += 2) {
|
||||
_cairo_path_fixed_curve_to (path,
|
||||
_cairo_fixed_from_FIXED (points[i].x) + x,
|
||||
_cairo_fixed_from_FIXED (points[i].y) + y,
|
||||
_cairo_fixed_from_FIXED (points[i + 1].x) + x,
|
||||
_cairo_fixed_from_FIXED (points[i + 1].y) + y,
|
||||
_cairo_fixed_from_FIXED (points[i + 2].x) + x,
|
||||
_cairo_fixed_from_FIXED (points[i + 2].y) + y);
|
||||
_cairo_fixed_from_FIXED (points[i].x),
|
||||
_cairo_fixed_from_FIXED (points[i].y),
|
||||
_cairo_fixed_from_FIXED (points[i + 1].x),
|
||||
_cairo_fixed_from_FIXED (points[i + 1].y),
|
||||
_cairo_fixed_from_FIXED (points[i + 2].x),
|
||||
_cairo_fixed_from_FIXED (points[i + 2].y));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1264,25 +1326,26 @@ _cairo_win32_scaled_font_glyph_path (void *abstract_font,
|
|||
_cairo_path_fixed_close_path (path);
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
FAIL:
|
||||
CLEANUP_FONT:
|
||||
|
||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||
|
||||
CLEANUP_PATH:
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
_cairo_path_fixed_destroy (path);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
|
||||
_cairo_win32_scaled_font_create_toy,
|
||||
_cairo_win32_scaled_font_fini,
|
||||
_cairo_win32_scaled_font_font_extents,
|
||||
_cairo_win32_scaled_font_glyph_init,
|
||||
_cairo_win32_scaled_font_text_to_glyphs,
|
||||
_cairo_win32_scaled_font_glyph_extents,
|
||||
_cairo_win32_scaled_font_glyph_bbox,
|
||||
NULL, /* ucs4_to_index */
|
||||
_cairo_win32_scaled_font_show_glyphs,
|
||||
_cairo_win32_scaled_font_glyph_path,
|
||||
_cairo_win32_scaled_font_get_glyph_cache_key
|
||||
};
|
||||
|
||||
/* cairo_win32_font_face_t */
|
||||
|
@ -1311,7 +1374,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
|
|||
cairo_win32_font_face_t *font_face = abstract_face;
|
||||
|
||||
*font = _win32_scaled_font_create (&font_face->logfont,
|
||||
font_face,
|
||||
&font_face->base,
|
||||
font_matrix, ctm, options);
|
||||
if (*font)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -1390,10 +1453,8 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
|
|||
HFONT old_hfont = NULL;
|
||||
int old_mode;
|
||||
|
||||
if (scaled_font->status) {
|
||||
_cairo_scaled_font_set_error (scaled_font, scaled_font->status);
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
}
|
||||
|
||||
hfont = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font);
|
||||
if (!hfont)
|
||||
|
@ -1401,11 +1462,11 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
old_hfont = SelectObject (hdc, hfont);
|
||||
if (!old_hfont)
|
||||
return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font");
|
||||
return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject");
|
||||
|
||||
old_mode = SetGraphicsMode (hdc, GM_ADVANCED);
|
||||
if (!old_mode) {
|
||||
status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font");
|
||||
status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode");
|
||||
SelectObject (hdc, old_hfont);
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -36,12 +36,6 @@
|
|||
#ifndef CAIRO_WIN32_PRIVATE_H
|
||||
#define CAIRO_WIN32_PRIVATE_H
|
||||
|
||||
/* We depend on various features introduced with Win2k and Win98,
|
||||
* like AlphaBlend. If it turns out to be a problem, we could
|
||||
* use GetProcAddress() to look them up.
|
||||
*/
|
||||
#define WINVER 0x0500
|
||||
|
||||
#include <cairo-win32.h>
|
||||
#include <cairoint.h>
|
||||
|
||||
|
|
|
@ -124,8 +124,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
|
|||
}
|
||||
|
||||
bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
|
||||
bitmap_info->bmiHeader.biWidth = width;
|
||||
bitmap_info->bmiHeader.biHeight = - height; /* top-down */
|
||||
bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;
|
||||
bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */
|
||||
bitmap_info->bmiHeader.biSizeImage = 0;
|
||||
bitmap_info->bmiHeader.biXPelsPerMeter = 72. / 0.0254; /* unused here */
|
||||
bitmap_info->bmiHeader.biYPelsPerMeter = 72. / 0.0254; /* unused here */
|
||||
|
@ -524,9 +524,6 @@ _cairo_win32_surface_release_dest_image (void *abstract_surfac
|
|||
cairo_surface_destroy ((cairo_surface_t *)local);
|
||||
}
|
||||
|
||||
// AlphaBlend is not available or useable on older versions of Win32
|
||||
|
||||
/* for compatibility with VC++ 5 */
|
||||
#if !defined(AC_SRC_OVER)
|
||||
#define AC_SRC_OVER 0x00
|
||||
#pragma pack(1)
|
||||
|
@ -544,8 +541,7 @@ typedef struct {
|
|||
#define AC_SRC_ALPHA 0x01
|
||||
#endif
|
||||
|
||||
typedef BOOL (WINAPI *ALPHABLENDPROC)(
|
||||
HDC hdcDest,
|
||||
typedef BOOL (WINAPI *cairo_alpha_blend_func_t) (HDC hdcDest,
|
||||
int nXOriginDest,
|
||||
int nYOriginDest,
|
||||
int nWidthDest,
|
||||
|
@ -557,8 +553,65 @@ typedef BOOL (WINAPI *ALPHABLENDPROC)(
|
|||
int nHeightSrc,
|
||||
BLENDFUNCTION blendFunction);
|
||||
|
||||
static unsigned gAlphaBlendChecked = FALSE;
|
||||
static ALPHABLENDPROC gAlphaBlend;
|
||||
static cairo_int_status_t
|
||||
_composite_alpha_blend (cairo_win32_surface_t *dst,
|
||||
cairo_win32_surface_t *src,
|
||||
int alpha,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
static unsigned alpha_blend_checked = FALSE;
|
||||
static cairo_alpha_blend_func_t alpha_blend = NULL;
|
||||
|
||||
BLENDFUNCTION blend_function;
|
||||
|
||||
/* Check for AlphaBlend dynamically to allow compiling on
|
||||
* MSVC 6 and use on older windows versions
|
||||
*/
|
||||
if (!alpha_blend_checked) {
|
||||
OSVERSIONINFO os;
|
||||
|
||||
os.dwOSVersionInfoSize = sizeof (os);
|
||||
GetVersionEx (&os);
|
||||
|
||||
/* If running on Win98, disable using AlphaBlend()
|
||||
* to avoid Win98 AlphaBlend() bug */
|
||||
if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
|
||||
os.dwMajorVersion != 4 || os.dwMinorVersion != 10)
|
||||
{
|
||||
HMODULE msimg32_dll = LoadLibrary ("msimg32");
|
||||
|
||||
if (msimg32_dll != NULL)
|
||||
alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll,
|
||||
"AlphaBlend");
|
||||
}
|
||||
|
||||
alpha_blend_checked = TRUE;
|
||||
}
|
||||
|
||||
if (alpha_blend == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
blend_function.BlendOp = AC_SRC_OVER;
|
||||
blend_function.BlendFlags = 0;
|
||||
blend_function.SourceConstantAlpha = alpha;
|
||||
blend_function.AlphaFormat = src->format == CAIRO_FORMAT_ARGB32 ? AC_SRC_ALPHA : 0;
|
||||
|
||||
if (!alpha_blend (dst->dc,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
src->dc,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
blend_function))
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_surface_composite (cairo_operator_t operator,
|
||||
|
@ -581,21 +634,6 @@ _cairo_win32_surface_composite (cairo_operator_t operator,
|
|||
int integer_transform;
|
||||
int itx, ity;
|
||||
|
||||
if (!gAlphaBlendChecked) {
|
||||
OSVERSIONINFO os;
|
||||
|
||||
os.dwOSVersionInfoSize = sizeof(os);
|
||||
GetVersionEx(&os);
|
||||
// If running on Win98, disable using AlphaBlend()
|
||||
// to avoid Win98 AlphaBlend() bug
|
||||
if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
|
||||
os.dwMajorVersion != 4 || os.dwMinorVersion != 10) {
|
||||
gAlphaBlend = (ALPHABLENDPROC)GetProcAddress(LoadLibrary("msimg32"),
|
||||
"AlphaBlend");
|
||||
}
|
||||
gAlphaBlendChecked = TRUE;
|
||||
}
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_SURFACE ||
|
||||
pattern->extend != CAIRO_EXTEND_NONE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -642,26 +680,9 @@ _cairo_win32_surface_composite (cairo_operator_t operator,
|
|||
dst->format == CAIRO_FORMAT_RGB24 &&
|
||||
operator == CAIRO_OPERATOR_OVER) {
|
||||
|
||||
BLENDFUNCTION blend_function;
|
||||
|
||||
blend_function.BlendOp = AC_SRC_OVER;
|
||||
blend_function.BlendFlags = 0;
|
||||
blend_function.SourceConstantAlpha = alpha;
|
||||
blend_function.AlphaFormat = src->format == CAIRO_FORMAT_ARGB32 ? AC_SRC_ALPHA : 0;
|
||||
|
||||
if (!gAlphaBlend)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (!gAlphaBlend(dst->dc,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
src->dc,
|
||||
return _composite_alpha_blend (dst, src, alpha,
|
||||
src_x + itx, src_y + ity,
|
||||
width, height,
|
||||
blend_function))
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
dst_x, dst_y, width, height);
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -1030,3 +1051,37 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
|||
_cairo_win32_surface_flush,
|
||||
NULL /* mark_dirty_rectangle */
|
||||
};
|
||||
|
||||
/*
|
||||
* Without pthread, on win32 we need to initialize all the 'mutex'es
|
||||
* before use. It is guaranteed that DllMain will get called single
|
||||
* threaded before any other function.
|
||||
* Initializing more than finally needed should not matter much.
|
||||
*/
|
||||
#ifndef HAVE_PTHREAD_H
|
||||
CRITICAL_SECTION cairo_toy_font_face_hash_table_mutex;
|
||||
CRITICAL_SECTION cairo_scaled_font_map_mutex;
|
||||
CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex;
|
||||
|
||||
BOOL WINAPI
|
||||
DllMain (HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved)
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
/* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */
|
||||
InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex);
|
||||
InitializeCriticalSection (&cairo_scaled_font_map_mutex);
|
||||
InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex);
|
||||
DeleteCriticalSection (&cairo_scaled_font_map_mutex);
|
||||
DeleteCriticalSection (&cairo_ft_unscaled_font_map_mutex);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -44,20 +44,20 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_win32_surface_create (HDC hdc);
|
||||
|
||||
cairo_font_face_t *
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
|
||||
HDC hdc);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
double
|
||||
cairo_public double
|
||||
cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xcb_surface_create_with_xrender_format (XCBConnection *c,
|
||||
XCBDRAWABLE drawable,
|
||||
XCBRenderPICTFORMINFO *format,
|
||||
|
|
|
@ -45,20 +45,20 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xcb_surface_create (XCBConnection *c,
|
||||
XCBDRAWABLE drawable,
|
||||
XCBVISUALTYPE *visual,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xcb_surface_create_for_bitmap (XCBConnection *c,
|
||||
XCBPIXMAP bitmap,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_xcb_surface_set_size (cairo_surface_t *surface,
|
||||
int width,
|
||||
int height);
|
||||
|
|
|
@ -247,6 +247,9 @@ CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
|
|||
|
||||
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
|
||||
|
||||
/* XXX: From this function we should also run through and cleanup
|
||||
* anything else that still has a pointer to this Display*. For
|
||||
* example, we should clean up any Xlib-specific glyph caches. */
|
||||
static int
|
||||
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
|
||||
{
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -45,7 +45,7 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
|
||||
Drawable drawable,
|
||||
Screen *screen,
|
||||
|
|
|
@ -45,26 +45,26 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xlib_surface_create (Display *dpy,
|
||||
Drawable drawable,
|
||||
Visual *visual,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xlib_surface_create_for_bitmap (Display *dpy,
|
||||
Pixmap bitmap,
|
||||
Screen *screen,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_xlib_surface_set_size (cairo_surface_t *surface,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_xlib_surface_set_drawable (cairo_surface_t *surface,
|
||||
Drawable drawable,
|
||||
int width,
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -52,10 +52,10 @@ CAIRO_BEGIN_DECLS
|
|||
CAIRO_VERSION_MINOR, \
|
||||
CAIRO_VERSION_MICRO)
|
||||
|
||||
int
|
||||
cairo_public int
|
||||
cairo_version (void);
|
||||
|
||||
const char*
|
||||
cairo_public const char*
|
||||
cairo_version_string (void);
|
||||
|
||||
/**
|
||||
|
@ -106,8 +106,8 @@ typedef struct _cairo_surface cairo_surface_t;
|
|||
* @y0: Y translation component of the affine transformation
|
||||
*
|
||||
* A #cairo_matrix_t holds an affine transformation, such as a scale,
|
||||
* rotation, or shear, or a combination of those. The transformation is given
|
||||
* by:
|
||||
* rotation, shear, or a combination of those. The transformation of
|
||||
* a point (x, y) is given by:
|
||||
* <programlisting>
|
||||
* x_new = xx * x + xy * y + x0;
|
||||
* y_new = yx * x + yy * y + y0;
|
||||
|
@ -166,6 +166,7 @@ typedef struct _cairo_user_data_key {
|
|||
* @CAIRO_STATUS_INVALID_FORMAT: invalid value for an input cairo_format_t
|
||||
* @CAIRO_STATUS_INVALID_VISUAL: invalid value for an input Visual*
|
||||
* @CAIRO_STATUS_FILE_NOT_FOUND: file not found
|
||||
* @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
|
||||
*
|
||||
* #cairo_status_t is used to indicate errors that can occur when
|
||||
* using Cairo. In some cases it is returned directly by functions.
|
||||
|
@ -191,7 +192,8 @@ typedef enum _cairo_status {
|
|||
CAIRO_STATUS_INVALID_CONTENT,
|
||||
CAIRO_STATUS_INVALID_FORMAT,
|
||||
CAIRO_STATUS_INVALID_VISUAL,
|
||||
CAIRO_STATUS_FILE_NOT_FOUND
|
||||
CAIRO_STATUS_FILE_NOT_FOUND,
|
||||
CAIRO_STATUS_INVALID_DASH
|
||||
} cairo_status_t;
|
||||
|
||||
/**
|
||||
|
@ -235,26 +237,29 @@ typedef cairo_status_t (*cairo_read_func_t) (void *closure,
|
|||
unsigned int length);
|
||||
|
||||
/* Functions for manipulating state objects */
|
||||
cairo_t *
|
||||
cairo_public cairo_t *
|
||||
cairo_create (cairo_surface_t *target);
|
||||
|
||||
cairo_t *
|
||||
cairo_public cairo_t *
|
||||
cairo_reference (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_destroy (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_save (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_restore (cairo_t *cr);
|
||||
|
||||
cairo_public void
|
||||
cairo_set_target (cairo_t *cr, cairo_surface_t *target);
|
||||
|
||||
/* XXX: I want to rethink this API
|
||||
void
|
||||
cairo_public void
|
||||
cairo_push_group (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pop_group (cairo_t *cr);
|
||||
*/
|
||||
|
||||
|
@ -280,27 +285,27 @@ typedef enum _cairo_operator {
|
|||
CAIRO_OPERATOR_SATURATE
|
||||
} cairo_operator_t;
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_operator (cairo_t *cr, cairo_operator_t op);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_source (cairo_t *cr, cairo_pattern_t *source);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_source_rgba (cairo_t *cr,
|
||||
double red, double green, double blue,
|
||||
double alpha);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_source_surface (cairo_t *cr,
|
||||
cairo_surface_t *surface,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_tolerance (cairo_t *cr, double tolerance);
|
||||
|
||||
/**
|
||||
|
@ -323,7 +328,7 @@ typedef enum _cairo_antialias {
|
|||
CAIRO_ANTIALIAS_SUBPIXEL
|
||||
} cairo_antialias_t;
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias);
|
||||
|
||||
/**
|
||||
|
@ -352,10 +357,10 @@ typedef enum _cairo_fill_rule {
|
|||
CAIRO_FILL_RULE_EVEN_ODD
|
||||
} cairo_fill_rule_t;
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_line_width (cairo_t *cr, double width);
|
||||
|
||||
|
||||
|
@ -373,7 +378,7 @@ typedef enum _cairo_line_cap {
|
|||
CAIRO_LINE_CAP_SQUARE
|
||||
} cairo_line_cap_t;
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap);
|
||||
|
||||
typedef enum _cairo_line_join {
|
||||
|
@ -382,170 +387,173 @@ typedef enum _cairo_line_join {
|
|||
CAIRO_LINE_JOIN_BEVEL
|
||||
} cairo_line_join_t;
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join);
|
||||
|
||||
void
|
||||
cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset);
|
||||
cairo_public void
|
||||
cairo_set_dash (cairo_t *cr,
|
||||
double *dashes,
|
||||
int num_dashes,
|
||||
double offset);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_miter_limit (cairo_t *cr, double limit);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_translate (cairo_t *cr, double tx, double ty);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_scale (cairo_t *cr, double sx, double sy);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_rotate (cairo_t *cr, double angle);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_transform (cairo_t *cr,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_matrix (cairo_t *cr,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_identity_matrix (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_user_to_device (cairo_t *cr, double *x, double *y);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_device_to_user (cairo_t *cr, double *x, double *y);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy);
|
||||
|
||||
/* Path creation functions */
|
||||
void
|
||||
cairo_public void
|
||||
cairo_new_path (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_move_to (cairo_t *cr, double x, double y);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_line_to (cairo_t *cr, double x, double y);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_curve_to (cairo_t *cr,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_arc (cairo_t *cr,
|
||||
double xc, double yc,
|
||||
double radius,
|
||||
double angle1, double angle2);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_arc_negative (cairo_t *cr,
|
||||
double xc, double yc,
|
||||
double radius,
|
||||
double angle1, double angle2);
|
||||
|
||||
/* XXX: NYI
|
||||
void
|
||||
cairo_public void
|
||||
cairo_arc_to (cairo_t *cr,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double radius);
|
||||
*/
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_rel_move_to (cairo_t *cr, double dx, double dy);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_rel_line_to (cairo_t *cr, double dx, double dy);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_rel_curve_to (cairo_t *cr,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double dx3, double dy3);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_rectangle (cairo_t *cr,
|
||||
double x, double y,
|
||||
double width, double height);
|
||||
|
||||
/* XXX: NYI
|
||||
void
|
||||
cairo_public void
|
||||
cairo_stroke_to_path (cairo_t *cr);
|
||||
*/
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_close_path (cairo_t *cr);
|
||||
|
||||
/* Painting functions */
|
||||
void
|
||||
cairo_public void
|
||||
cairo_paint (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_paint_with_alpha (cairo_t *cr,
|
||||
double alpha);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_mask (cairo_t *cr,
|
||||
cairo_pattern_t *pattern);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_mask_surface (cairo_t *cr,
|
||||
cairo_surface_t *surface,
|
||||
double surface_x,
|
||||
double surface_y);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_stroke (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_stroke_preserve (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_fill (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_fill_preserve (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_copy_page (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_show_page (cairo_t *cr);
|
||||
|
||||
/* Insideness testing */
|
||||
cairo_bool_t
|
||||
cairo_public cairo_bool_t
|
||||
cairo_in_stroke (cairo_t *cr, double x, double y);
|
||||
|
||||
cairo_bool_t
|
||||
cairo_public cairo_bool_t
|
||||
cairo_in_fill (cairo_t *cr, double x, double y);
|
||||
|
||||
/* Rectangular extents */
|
||||
void
|
||||
cairo_public void
|
||||
cairo_stroke_extents (cairo_t *cr,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_fill_extents (cairo_t *cr,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2);
|
||||
|
||||
/* Clipping */
|
||||
void
|
||||
cairo_public void
|
||||
cairo_reset_clip (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_clip (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_clip_preserve (cairo_t *cr);
|
||||
|
||||
/* Font/Text functions */
|
||||
|
@ -772,130 +780,130 @@ typedef enum _cairo_hint_metrics {
|
|||
|
||||
typedef struct _cairo_font_options cairo_font_options_t;
|
||||
|
||||
cairo_font_options_t *
|
||||
cairo_public cairo_font_options_t *
|
||||
cairo_font_options_create (void);
|
||||
|
||||
cairo_font_options_t *
|
||||
cairo_public cairo_font_options_t *
|
||||
cairo_font_options_copy (const cairo_font_options_t *original);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_options_destroy (cairo_font_options_t *options);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_font_options_status (cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_options_merge (cairo_font_options_t *options,
|
||||
const cairo_font_options_t *other);
|
||||
cairo_bool_t
|
||||
cairo_public cairo_bool_t
|
||||
cairo_font_options_equal (const cairo_font_options_t *options,
|
||||
const cairo_font_options_t *other);
|
||||
|
||||
unsigned long
|
||||
cairo_public unsigned long
|
||||
cairo_font_options_hash (const cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_options_set_antialias (cairo_font_options_t *options,
|
||||
cairo_antialias_t antialias);
|
||||
cairo_antialias_t
|
||||
cairo_public cairo_antialias_t
|
||||
cairo_font_options_get_antialias (const cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
|
||||
cairo_subpixel_order_t subpixel_order);
|
||||
cairo_subpixel_order_t
|
||||
cairo_public cairo_subpixel_order_t
|
||||
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_options_set_hint_style (cairo_font_options_t *options,
|
||||
cairo_hint_style_t hint_style);
|
||||
cairo_hint_style_t
|
||||
cairo_public cairo_hint_style_t
|
||||
cairo_font_options_get_hint_style (const cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
|
||||
cairo_hint_metrics_t hint_metrics);
|
||||
cairo_hint_metrics_t
|
||||
cairo_public cairo_hint_metrics_t
|
||||
cairo_font_options_get_hint_metrics (const cairo_font_options_t *options);
|
||||
|
||||
|
||||
/* This interface is for dealing with text as text, not caring about the
|
||||
font object inside the the cairo_t. */
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_select_font_face (cairo_t *cr,
|
||||
const char *family,
|
||||
cairo_font_slant_t slant,
|
||||
cairo_font_weight_t weight);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_font_size (cairo_t *cr, double size);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_font_matrix (cairo_t *cr,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_get_font_matrix (cairo_t *cr,
|
||||
cairo_matrix_t *matrix);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_font_options (cairo_t *cr,
|
||||
const cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_get_font_options (cairo_t *cr,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_show_text (cairo_t *cr, const char *utf8);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs);
|
||||
|
||||
cairo_font_face_t *
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_get_font_face (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_extents (cairo_t *cr,
|
||||
cairo_font_extents_t *extents);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_text_extents (cairo_t *cr,
|
||||
const char *utf8,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_glyph_extents (cairo_t *cr,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_text_path (cairo_t *cr, const char *utf8);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs);
|
||||
|
||||
/* Generic identifier for a font style */
|
||||
|
||||
cairo_font_face_t *
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_font_face_reference (cairo_font_face_t *font_face);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_font_face_destroy (cairo_font_face_t *font_face);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_font_face_status (cairo_font_face_t *font_face);
|
||||
|
||||
void *
|
||||
cairo_public void *
|
||||
cairo_font_face_get_user_data (cairo_font_face_t *font_face,
|
||||
const cairo_user_data_key_t *key);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_font_face_set_user_data (cairo_font_face_t *font_face,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
|
@ -903,26 +911,26 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
|
|||
|
||||
/* Portable interface to general font features. */
|
||||
|
||||
cairo_scaled_font_t *
|
||||
cairo_public cairo_scaled_font_t *
|
||||
cairo_scaled_font_create (cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options);
|
||||
|
||||
cairo_scaled_font_t *
|
||||
cairo_public cairo_scaled_font_t *
|
||||
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_scaled_font_status (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *extents);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
|
@ -930,53 +938,60 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
/* Query functions */
|
||||
|
||||
cairo_operator_t
|
||||
cairo_public cairo_operator_t
|
||||
cairo_get_operator (cairo_t *cr);
|
||||
|
||||
cairo_pattern_t *
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_get_source (cairo_t *cr);
|
||||
|
||||
double
|
||||
cairo_public double
|
||||
cairo_get_tolerance (cairo_t *cr);
|
||||
|
||||
cairo_antialias_t
|
||||
cairo_public cairo_antialias_t
|
||||
cairo_get_antialias (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_get_current_point (cairo_t *cr, double *x, double *y);
|
||||
|
||||
cairo_fill_rule_t
|
||||
cairo_public cairo_fill_rule_t
|
||||
cairo_get_fill_rule (cairo_t *cr);
|
||||
|
||||
double
|
||||
cairo_public double
|
||||
cairo_get_line_width (cairo_t *cr);
|
||||
|
||||
cairo_line_cap_t
|
||||
cairo_public cairo_line_cap_t
|
||||
cairo_get_line_cap (cairo_t *cr);
|
||||
|
||||
cairo_line_join_t
|
||||
cairo_public cairo_line_join_t
|
||||
cairo_get_line_join (cairo_t *cr);
|
||||
|
||||
double
|
||||
cairo_public double
|
||||
cairo_get_miter_limit (cairo_t *cr);
|
||||
|
||||
/* XXX: How to do cairo_get_dash??? Do we want to switch to a cairo_dash object? */
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_get_target (cairo_t *cr);
|
||||
|
||||
typedef enum _cairo_path_data_type {
|
||||
CAIRO_PATH_MOVE_TO,
|
||||
CAIRO_PATH_LINE_TO,
|
||||
CAIRO_PATH_CURVE_TO,
|
||||
CAIRO_PATH_CLOSE_PATH
|
||||
} cairo_path_data_type_t;
|
||||
|
||||
/**
|
||||
* cairo_path_data_t:
|
||||
*
|
||||
* A data structure for holding path data---appears within
|
||||
* #cairo_path_data_t is used to represent the path data inside a
|
||||
* #cairo_path_t.
|
||||
*
|
||||
* The data structure is designed to try to balance the demands of
|
||||
* efficiency and ease-of-use. A path is represented as an array of
|
||||
* cairo_path_data_t which is a union of headers and points.
|
||||
* #cairo_path_data_t, which is a union of headers and points.
|
||||
*
|
||||
* Each portion of the path is represented by one or more elements in
|
||||
* the array, (one header followed by 0 or more points). The length
|
||||
|
@ -985,10 +1000,12 @@ cairo_get_target (cairo_t *cr);
|
|||
* where the number of points for each element type must be as
|
||||
* follows:
|
||||
*
|
||||
* CAIRO_PATH_MOVE_TO: 1 point
|
||||
* CAIRO_PATH_LINE_TO: 1 point
|
||||
* CAIRO_PATH_CURVE_TO: 3 points
|
||||
* CAIRO_PATH_CLOSE_PATH: 0 points
|
||||
* <programlisting>
|
||||
* %CAIRO_PATH_MOVE_TO: 1 point
|
||||
* %CAIRO_PATH_LINE_TO: 1 point
|
||||
* %CAIRO_PATH_CURVE_TO: 3 points
|
||||
* %CAIRO_PATH_CLOSE_PATH: 0 points
|
||||
* </programlisting>
|
||||
*
|
||||
* The semantics and ordering of the coordinate values are consistent
|
||||
* with cairo_move_to(), cairo_line_to(), cairo_curve_to(), and
|
||||
|
@ -1000,11 +1017,11 @@ cairo_get_target (cairo_t *cr);
|
|||
* int i;
|
||||
* cairo_path_t *path;
|
||||
* cairo_path_data_t *data;
|
||||
*
|
||||
*
|
||||
* path = cairo_copy_path (cr);
|
||||
*
|
||||
*
|
||||
* for (i=0; i < path->num_data; i += path->data[i].header.length) {
|
||||
* data = &path->data[i];
|
||||
* data = &path->data[i];
|
||||
* switch (data->header.type) {
|
||||
* case CAIRO_PATH_MOVE_TO:
|
||||
* do_move_to_things (data[1].point.x, data[1].point.y);
|
||||
|
@ -1022,18 +1039,11 @@ cairo_get_target (cairo_t *cr);
|
|||
* break;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* cairo_path_destroy (path);
|
||||
* </programlisting></informalexample>
|
||||
*/
|
||||
typedef enum _cairo_path_data_type {
|
||||
CAIRO_PATH_MOVE_TO,
|
||||
CAIRO_PATH_LINE_TO,
|
||||
CAIRO_PATH_CURVE_TO,
|
||||
CAIRO_PATH_CLOSE_PATH
|
||||
} cairo_path_data_type_t;
|
||||
|
||||
typedef union {
|
||||
**/
|
||||
typedef union _cairo_path_data_t cairo_path_data_t;
|
||||
union _cairo_path_data_t {
|
||||
struct {
|
||||
cairo_path_data_type_t type;
|
||||
int length;
|
||||
|
@ -1041,7 +1051,7 @@ typedef union {
|
|||
struct {
|
||||
double x, y;
|
||||
} point;
|
||||
} cairo_path_data_t;
|
||||
};
|
||||
|
||||
/**
|
||||
* cairo_path_t:
|
||||
|
@ -1059,7 +1069,7 @@ typedef union {
|
|||
*
|
||||
* The num_data member gives the number of elements in the data
|
||||
* array. This number is larger than the number of independent path
|
||||
* portions (MOVE_TO, LINE_TO, CURVE_TO, CLOSE_PATH), since the data
|
||||
* portions (defined in #cairo_path_data_type_t), since the data
|
||||
* includes both headers and coordinates for each portion.
|
||||
**/
|
||||
typedef struct cairo_path {
|
||||
|
@ -1068,25 +1078,25 @@ typedef struct cairo_path {
|
|||
int num_data;
|
||||
} cairo_path_t;
|
||||
|
||||
cairo_path_t *
|
||||
cairo_public cairo_path_t *
|
||||
cairo_copy_path (cairo_t *cr);
|
||||
|
||||
cairo_path_t *
|
||||
cairo_public cairo_path_t *
|
||||
cairo_copy_path_flat (cairo_t *cr);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_append_path (cairo_t *cr,
|
||||
cairo_path_t *path);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_path_destroy (cairo_path_t *path);
|
||||
|
||||
/* Error status queries */
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_status (cairo_t *cr);
|
||||
|
||||
const char *
|
||||
cairo_public const char *
|
||||
cairo_status_to_string (cairo_status_t status);
|
||||
|
||||
/* Surface manipulation */
|
||||
|
@ -1111,71 +1121,65 @@ typedef enum _cairo_content {
|
|||
CAIRO_CONTENT_COLOR_ALPHA = 0x3000
|
||||
} cairo_content_t;
|
||||
|
||||
#define CAIRO_CONTENT_VALID(content) ((content) && \
|
||||
(((content) & ~(CAIRO_CONTENT_COLOR | \
|
||||
CAIRO_CONTENT_ALPHA | \
|
||||
CAIRO_CONTENT_COLOR_ALPHA))\
|
||||
== 0))
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_surface_create_similar (cairo_surface_t *other,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_surface_reference (cairo_surface_t *surface);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_surface_destroy (cairo_surface_t *surface);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_status (cairo_surface_t *surface);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_surface_finish (cairo_surface_t *surface);
|
||||
|
||||
#if CAIRO_HAS_PNG_FUNCTIONS
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_write_to_png (cairo_surface_t *surface,
|
||||
const char *filename);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_write_to_png_stream (cairo_surface_t *surface,
|
||||
cairo_write_func_t write_func,
|
||||
void *closure);
|
||||
|
||||
#endif
|
||||
|
||||
void *
|
||||
cairo_public void *
|
||||
cairo_surface_get_user_data (cairo_surface_t *surface,
|
||||
const cairo_user_data_key_t *key);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_set_user_data (cairo_surface_t *surface,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_surface_get_font_options (cairo_surface_t *surface,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_surface_flush (cairo_surface_t *surface);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_surface_mark_dirty (cairo_surface_t *surface);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_surface_set_device_offset (cairo_surface_t *surface,
|
||||
double x_offset,
|
||||
double y_offset);
|
||||
|
@ -1211,33 +1215,30 @@ typedef enum _cairo_format {
|
|||
CAIRO_FORMAT_A1
|
||||
} cairo_format_t;
|
||||
|
||||
#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \
|
||||
(format) <= CAIRO_FORMAT_A1)
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_image_surface_create (cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_image_surface_create_for_data (unsigned char *data,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height,
|
||||
int stride);
|
||||
|
||||
int
|
||||
cairo_public int
|
||||
cairo_image_surface_get_width (cairo_surface_t *surface);
|
||||
|
||||
int
|
||||
cairo_public int
|
||||
cairo_image_surface_get_height (cairo_surface_t *surface);
|
||||
|
||||
#if CAIRO_HAS_PNG_FUNCTIONS
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_image_surface_create_from_png (const char *filename);
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
|
||||
void *closure);
|
||||
|
||||
|
@ -1245,49 +1246,49 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
|
|||
|
||||
/* Pattern creation functions */
|
||||
|
||||
cairo_pattern_t *
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_create_rgb (double red, double green, double blue);
|
||||
|
||||
cairo_pattern_t *
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_create_rgba (double red, double green, double blue,
|
||||
double alpha);
|
||||
|
||||
cairo_pattern_t *
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_create_for_surface (cairo_surface_t *surface);
|
||||
|
||||
cairo_pattern_t *
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_create_linear (double x0, double y0,
|
||||
double x1, double y1);
|
||||
|
||||
cairo_pattern_t *
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
|
||||
double cx1, double cy1, double radius1);
|
||||
|
||||
cairo_pattern_t *
|
||||
cairo_public cairo_pattern_t *
|
||||
cairo_pattern_reference (cairo_pattern_t *pattern);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pattern_destroy (cairo_pattern_t *pattern);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_pattern_status (cairo_pattern_t *pattern);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
|
||||
double offset,
|
||||
double red, double green, double blue);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
|
||||
double offset,
|
||||
double red, double green, double blue,
|
||||
double alpha);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pattern_get_matrix (cairo_pattern_t *pattern,
|
||||
cairo_matrix_t *matrix);
|
||||
|
||||
|
@ -1297,10 +1298,10 @@ typedef enum _cairo_extend {
|
|||
CAIRO_EXTEND_REFLECT
|
||||
} cairo_extend_t;
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend);
|
||||
|
||||
cairo_extend_t
|
||||
cairo_public cairo_extend_t
|
||||
cairo_pattern_get_extend (cairo_pattern_t *pattern);
|
||||
|
||||
typedef enum _cairo_filter {
|
||||
|
@ -1312,59 +1313,59 @@ typedef enum _cairo_filter {
|
|||
CAIRO_FILTER_GAUSSIAN
|
||||
} cairo_filter_t;
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter);
|
||||
|
||||
cairo_filter_t
|
||||
cairo_public cairo_filter_t
|
||||
cairo_pattern_get_filter (cairo_pattern_t *pattern);
|
||||
|
||||
/* Matrix functions */
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_init (cairo_matrix_t *matrix,
|
||||
double xx, double yx,
|
||||
double xy, double yy,
|
||||
double x0, double y0);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_init_identity (cairo_matrix_t *matrix);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_init_translate (cairo_matrix_t *matrix,
|
||||
double tx, double ty);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_init_scale (cairo_matrix_t *matrix,
|
||||
double sx, double sy);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_init_rotate (cairo_matrix_t *matrix,
|
||||
double radians);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_rotate (cairo_matrix_t *matrix, double radians);
|
||||
|
||||
cairo_status_t
|
||||
cairo_public cairo_status_t
|
||||
cairo_matrix_invert (cairo_matrix_t *matrix);
|
||||
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_multiply (cairo_matrix_t *result,
|
||||
const cairo_matrix_t *a,
|
||||
const cairo_matrix_t *b);
|
||||
|
||||
/* XXX: Need a new name here perhaps. */
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_transform_distance (const cairo_matrix_t *matrix,
|
||||
double *dx, double *dy);
|
||||
|
||||
/* XXX: Need a new name here perhaps. */
|
||||
void
|
||||
cairo_public void
|
||||
cairo_matrix_transform_point (const cairo_matrix_t *matrix,
|
||||
double *x, double *y);
|
||||
|
||||
|
|
|
@ -62,10 +62,6 @@
|
|||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo-debug.h"
|
||||
#include <pixman.h>
|
||||
|
@ -128,6 +124,12 @@
|
|||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
#if HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
# define CAIRO_MUTEX_DECLARE(name) static pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER
|
||||
|
@ -136,15 +138,31 @@
|
|||
# define CAIRO_MUTEX_UNLOCK(name) pthread_mutex_unlock (&name)
|
||||
#endif
|
||||
|
||||
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
/* the real initialization must take place in DllMain */
|
||||
# define CAIRO_MUTEX_DECLARE(name) extern CRITICAL_SECTION name;
|
||||
# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern LPCRITICAL_SECTION name;
|
||||
# define CAIRO_MUTEX_LOCK(name) EnterCriticalSection (&name)
|
||||
# define CAIRO_MUTEX_UNLOCK(name) LeaveCriticalSection (&name)
|
||||
#endif
|
||||
|
||||
#ifndef CAIRO_MUTEX_DECLARE
|
||||
/*# warning "No mutex declarations, assuming single-threaded code" */
|
||||
#if 0
|
||||
# error "No mutex declarations. Cairo will not work with multiple threads." \
|
||||
"(Remove this #error directive to acknowledge & accept this limitation)."
|
||||
#endif
|
||||
# define CAIRO_MUTEX_DECLARE(name)
|
||||
# define CAIRO_MUTEX_DECLARE_GLOBAL(name)
|
||||
# define CAIRO_MUTEX_LOCK(name)
|
||||
# define CAIRO_MUTEX_UNLOCK(name)
|
||||
#endif
|
||||
|
||||
#undef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#ifndef FALSE
|
||||
|
@ -176,8 +194,10 @@ typedef cairo_fixed_16_16_t cairo_fixed_t;
|
|||
#define CAIRO_MINSHORT SHRT_MIN
|
||||
|
||||
#define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff))
|
||||
#define CAIRO_ALPHA_IS_ZERO(alpha) ((alpha) <= 0.0)
|
||||
|
||||
#include "cairo-hash-private.h"
|
||||
#include "cairo-cache-private.h"
|
||||
|
||||
typedef struct _cairo_point {
|
||||
cairo_fixed_t x;
|
||||
|
@ -221,7 +241,8 @@ typedef struct _cairo_rectangle {
|
|||
typedef enum cairo_int_status {
|
||||
CAIRO_INT_STATUS_DEGENERATE = 1000,
|
||||
CAIRO_INT_STATUS_UNSUPPORTED,
|
||||
CAIRO_INT_STATUS_NOTHING_TO_DO
|
||||
CAIRO_INT_STATUS_NOTHING_TO_DO,
|
||||
CAIRO_INT_STATUS_CACHE_EMPTY
|
||||
} cairo_int_status_t;
|
||||
|
||||
typedef enum cairo_direction {
|
||||
|
@ -282,6 +303,8 @@ typedef struct _cairo_pen {
|
|||
typedef struct _cairo_color cairo_color_t;
|
||||
typedef struct _cairo_image_surface cairo_image_surface_t;
|
||||
|
||||
typedef struct _cairo_surface_backend cairo_surface_backend_t;
|
||||
|
||||
cairo_private void
|
||||
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle);
|
||||
|
||||
|
@ -342,108 +365,9 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
|
|||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
/* cairo_cache.c structures and functions */
|
||||
|
||||
typedef struct _cairo_cache_backend {
|
||||
|
||||
unsigned long (*hash) (void *cache,
|
||||
void *key);
|
||||
|
||||
int (*keys_equal) (void *cache,
|
||||
void *k1,
|
||||
void *k2);
|
||||
|
||||
cairo_status_t (*create_entry) (void *cache,
|
||||
void *key,
|
||||
void **entry_return);
|
||||
|
||||
void (*destroy_entry) (void *cache,
|
||||
void *entry);
|
||||
|
||||
void (*destroy_cache) (void *cache);
|
||||
|
||||
} cairo_cache_backend_t;
|
||||
|
||||
/*
|
||||
* The cairo_cache system makes the following assumptions about
|
||||
* entries in its cache:
|
||||
*
|
||||
* - a pointer to an entry can be cast to a cairo_cache_entry_base_t.
|
||||
* - a pointer to an entry can also be cast to the "key type".
|
||||
*
|
||||
* The practical effect of this is that your entries must be laid
|
||||
* out this way:
|
||||
*
|
||||
* struct my_entry {
|
||||
* cairo_cache_entry_base_t;
|
||||
* my_key_value_1;
|
||||
* my_key_value_2;
|
||||
* ...
|
||||
* my_value;
|
||||
* };
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
unsigned long memory;
|
||||
unsigned long hashcode;
|
||||
} cairo_cache_entry_base_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned long high_water_mark;
|
||||
unsigned long size;
|
||||
unsigned long rehash;
|
||||
} cairo_cache_arrangement_t;
|
||||
|
||||
#undef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
|
||||
typedef struct {
|
||||
const cairo_cache_backend_t *backend;
|
||||
const cairo_cache_arrangement_t *arrangement;
|
||||
cairo_cache_entry_base_t **entries;
|
||||
|
||||
unsigned long max_memory;
|
||||
unsigned long used_memory;
|
||||
unsigned long live_entries;
|
||||
|
||||
#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
|
||||
unsigned long hits;
|
||||
unsigned long misses;
|
||||
unsigned long probes;
|
||||
#endif
|
||||
} cairo_cache_t;
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_cache_init (cairo_cache_t *cache,
|
||||
const cairo_cache_backend_t *backend,
|
||||
unsigned long max_memory);
|
||||
|
||||
cairo_private void
|
||||
_cairo_cache_destroy (cairo_cache_t *cache);
|
||||
|
||||
cairo_private void
|
||||
_cairo_cache_shrink_to (cairo_cache_t *cache,
|
||||
unsigned long max_memory);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_cache_lookup (cairo_cache_t *cache,
|
||||
void *key,
|
||||
void **entry_return,
|
||||
int *created_entry);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_cache_remove (cairo_cache_t *cache,
|
||||
void *key);
|
||||
|
||||
cairo_private void *
|
||||
_cairo_cache_random_entry (cairo_cache_t *cache,
|
||||
int (*predicate) (void*));
|
||||
|
||||
cairo_private unsigned long
|
||||
_cairo_hash_string (const char *c);
|
||||
|
||||
#define CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
|
||||
#define CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
|
||||
|
||||
typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t;
|
||||
typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t;
|
||||
typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
|
||||
|
@ -465,16 +389,47 @@ struct _cairo_font_options {
|
|||
cairo_hint_metrics_t hint_metrics;
|
||||
};
|
||||
|
||||
typedef struct _cairo_scaled_glyph {
|
||||
cairo_cache_entry_t cache_entry; /* hash is glyph index */
|
||||
cairo_scaled_font_t *scaled_font; /* font the glyph lives in */
|
||||
cairo_text_extents_t metrics; /* user-space metrics */
|
||||
cairo_box_t bbox; /* device-space bounds */
|
||||
cairo_image_surface_t *surface; /* device-space image */
|
||||
cairo_path_fixed_t *path; /* device-space outline */
|
||||
void *surface_private; /* for the surface backend */
|
||||
} cairo_scaled_glyph_t;
|
||||
|
||||
#define _cairo_scaled_glyph_index(g) ((g)->cache_entry.hash)
|
||||
#define _cairo_scaled_glyph_set_index(g,i) ((g)->cache_entry.hash = (i))
|
||||
|
||||
struct _cairo_scaled_font {
|
||||
/* must be first to be stored in a hash table */
|
||||
cairo_hash_entry_t hash_entry;
|
||||
|
||||
/* useful bits for _cairo_scaled_font_nil */
|
||||
cairo_status_t status;
|
||||
int ref_count;
|
||||
|
||||
/* hash key members */
|
||||
cairo_font_face_t *font_face; /* may be NULL */
|
||||
cairo_matrix_t font_matrix; /* font space => user space */
|
||||
cairo_matrix_t ctm; /* user space => device space */
|
||||
cairo_matrix_t scale; /* font space => device space */
|
||||
cairo_font_options_t options;
|
||||
|
||||
/* "live" scaled_font members */
|
||||
cairo_matrix_t scale; /* font space => device space */
|
||||
cairo_font_extents_t extents; /* user space */
|
||||
cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */
|
||||
|
||||
/*
|
||||
* One surface backend may store data in each glyph.
|
||||
* Whichever surface manages to store its pointer here
|
||||
* first gets to store data in each glyph
|
||||
*/
|
||||
const cairo_surface_backend_t *surface_backend;
|
||||
void *surface_private;
|
||||
|
||||
/* font backend managing this scaled font */
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
};
|
||||
|
||||
|
@ -486,40 +441,6 @@ struct _cairo_font_face {
|
|||
const cairo_font_face_backend_t *backend;
|
||||
};
|
||||
|
||||
/* cairo_font.c is responsible for a global glyph cache:
|
||||
*
|
||||
* - glyph entries: [[[base], cairo_unscaled_font_t, scale, flags, index],
|
||||
* image, size, extents]
|
||||
*
|
||||
* Surfaces may build their own glyph caches if they have surface-specific
|
||||
* glyph resources to maintain; those caches can feed off of the global
|
||||
* caches if need be (eg. cairo_xlib_surface.c does this).
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
cairo_cache_entry_base_t base;
|
||||
cairo_unscaled_font_t *unscaled;
|
||||
cairo_matrix_t scale; /* translation is ignored */
|
||||
int flags;
|
||||
unsigned long index;
|
||||
} cairo_glyph_cache_key_t;
|
||||
|
||||
typedef struct {
|
||||
cairo_glyph_cache_key_t key;
|
||||
cairo_image_surface_t *image;
|
||||
cairo_glyph_size_t size;
|
||||
cairo_text_extents_t extents;
|
||||
} cairo_image_glyph_cache_entry_t;
|
||||
|
||||
cairo_private void
|
||||
_cairo_lock_global_image_glyph_cache (void);
|
||||
|
||||
cairo_private void
|
||||
_cairo_unlock_global_image_glyph_cache (void);
|
||||
|
||||
cairo_private cairo_cache_t *
|
||||
_cairo_get_global_image_glyph_cache (void);
|
||||
|
||||
cairo_private void
|
||||
_cairo_font_reset_static_data (void);
|
||||
|
||||
|
@ -532,22 +453,10 @@ _cairo_xlib_surface_reset_static_data (void);
|
|||
cairo_private void
|
||||
_cairo_xlib_screen_reset_static_data (void);
|
||||
|
||||
/* Some glyph cache functions you can reuse. */
|
||||
|
||||
cairo_private unsigned long
|
||||
_cairo_glyph_cache_hash (void *cache, void *key);
|
||||
|
||||
cairo_private int
|
||||
_cairo_glyph_cache_keys_equal (void *cache,
|
||||
void *k1,
|
||||
void *k2);
|
||||
|
||||
/* the font backend interface */
|
||||
|
||||
struct _cairo_unscaled_font_backend {
|
||||
void (*destroy) (void *unscaled_font);
|
||||
cairo_status_t (*create_glyph) (void *unscaled_font,
|
||||
cairo_image_glyph_cache_entry_t *entry);
|
||||
};
|
||||
|
||||
/* cairo_toy_font_face_t - simple family/slant/weight font faces used for
|
||||
|
@ -562,6 +471,12 @@ typedef struct _cairo_toy_font_face {
|
|||
cairo_font_weight_t weight;
|
||||
} cairo_toy_font_face_t;
|
||||
|
||||
typedef enum _cairo_scaled_glyph_info {
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS = (1 << 0),
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE = (1 << 1),
|
||||
CAIRO_SCALED_GLYPH_INFO_PATH = (1 << 2)
|
||||
} cairo_scaled_glyph_info_t;
|
||||
|
||||
struct _cairo_scaled_font_backend {
|
||||
cairo_status_t
|
||||
(*create_toy) (cairo_toy_font_face_t *toy_face,
|
||||
|
@ -574,28 +489,26 @@ struct _cairo_scaled_font_backend {
|
|||
(*fini) (void *scaled_font);
|
||||
|
||||
cairo_status_t
|
||||
(*font_extents) (void *scaled_font,
|
||||
cairo_font_extents_t *extents);
|
||||
(*scaled_glyph_init) (void *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_glyph_info_t info);
|
||||
|
||||
cairo_status_t
|
||||
/* A backend only needs to implement this or ucs4_to_index(), not
|
||||
* both. This allows the backend to do something more sophisticated
|
||||
* then just converting characters one by one.
|
||||
*/
|
||||
cairo_int_status_t
|
||||
(*text_to_glyphs) (void *scaled_font,
|
||||
double x,
|
||||
double y,
|
||||
const char *utf8,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs);
|
||||
|
||||
cairo_status_t
|
||||
(*glyph_extents) (void *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
cairo_status_t
|
||||
(*glyph_bbox) (void *scaled_font,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_box_t *bbox);
|
||||
|
||||
cairo_status_t
|
||||
unsigned long
|
||||
(*ucs4_to_index) (void *scaled_font,
|
||||
uint32_t ucs4);
|
||||
cairo_int_status_t
|
||||
(*show_glyphs) (void *scaled_font,
|
||||
cairo_operator_t operator,
|
||||
cairo_pattern_t *pattern,
|
||||
|
@ -609,15 +522,6 @@ struct _cairo_scaled_font_backend {
|
|||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
cairo_status_t
|
||||
(*glyph_path) (void *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path);
|
||||
|
||||
void
|
||||
(*get_glyph_cache_key) (void *scaled_font,
|
||||
cairo_glyph_cache_key_t *key);
|
||||
};
|
||||
|
||||
struct _cairo_font_face_backend {
|
||||
|
@ -654,7 +558,7 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_
|
|||
|
||||
#endif
|
||||
|
||||
typedef struct _cairo_surface_backend {
|
||||
struct _cairo_surface_backend {
|
||||
cairo_surface_t *
|
||||
(*create_similar) (void *surface,
|
||||
cairo_content_t content,
|
||||
|
@ -790,8 +694,8 @@ typedef struct _cairo_surface_backend {
|
|||
|
||||
/*
|
||||
* This is an optional entry to let the surface manage its own glyph
|
||||
* resources. If null, the font will be asked to render against this
|
||||
* surface, using image surfaces as glyphs.
|
||||
* resources. If null, render against this surface, using image
|
||||
* surfaces as glyphs.
|
||||
*/
|
||||
cairo_int_status_t
|
||||
(*show_glyphs) (cairo_scaled_font_t *font,
|
||||
|
@ -829,7 +733,13 @@ typedef struct _cairo_surface_backend {
|
|||
int width,
|
||||
int height);
|
||||
|
||||
} cairo_surface_backend_t;
|
||||
void
|
||||
(*scaled_font_fini) (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
void
|
||||
(*scaled_glyph_fini) (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
};
|
||||
|
||||
typedef struct _cairo_format_masks {
|
||||
int bpp;
|
||||
|
@ -849,6 +759,8 @@ struct _cairo_surface {
|
|||
|
||||
double device_x_offset;
|
||||
double device_y_offset;
|
||||
double device_x_scale;
|
||||
double device_y_scale;
|
||||
|
||||
/*
|
||||
* Each time a clip region is modified, it gets the next value in this
|
||||
|
@ -940,7 +852,7 @@ typedef struct _cairo_solid_pattern {
|
|||
cairo_color_t color;
|
||||
} cairo_solid_pattern_t;
|
||||
|
||||
extern const cairo_private cairo_solid_pattern_t cairo_solid_pattern_nil;
|
||||
extern const cairo_private cairo_solid_pattern_t cairo_pattern_nil;
|
||||
|
||||
typedef struct _cairo_surface_pattern {
|
||||
cairo_pattern_t base;
|
||||
|
@ -1085,6 +997,9 @@ _cairo_gstate_destroy (cairo_gstate_t *gstate);
|
|||
cairo_private cairo_gstate_t *
|
||||
_cairo_gstate_clone (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_begin_group (cairo_gstate_t *gstate);
|
||||
|
||||
|
@ -1376,63 +1291,6 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *font);
|
|||
cairo_private void
|
||||
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
const cairo_scaled_font_backend_t *backend);
|
||||
|
||||
void
|
||||
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
const char *utf8,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_box_t *bbox);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t operator,
|
||||
cairo_pattern_t *source,
|
||||
cairo_surface_t *surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_cache_key_t *key);
|
||||
|
||||
/* cairo-font-options.c */
|
||||
|
||||
cairo_private void
|
||||
|
@ -1450,9 +1308,15 @@ cairo_private cairo_status_t
|
|||
_cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
||||
cairo_path_fixed_t *other);
|
||||
|
||||
cairo_path_fixed_t *
|
||||
_cairo_path_fixed_create (void);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_fini (cairo_path_fixed_t *path);
|
||||
|
||||
void
|
||||
_cairo_path_fixed_destroy (cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t x,
|
||||
|
@ -1537,6 +1401,91 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
|||
cairo_gstate_t *gstate,
|
||||
cairo_traps_t *traps);
|
||||
|
||||
/* cairo-scaled-font.c */
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
const cairo_scaled_font_backend_t *backend);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *fs_metrics);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
double x,
|
||||
double y,
|
||||
const char *utf8,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_rectangle_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t operator,
|
||||
cairo_pattern_t *source,
|
||||
cairo_surface_t *surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_text_extents_t *fs_metrics);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_image_surface_t *surface);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_path_fixed_t *path);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long index,
|
||||
cairo_scaled_glyph_info_t info,
|
||||
cairo_scaled_glyph_t **scaled_glyph_ret);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_font_map_destroy (void);
|
||||
|
||||
/* cairo-surface.c */
|
||||
|
||||
extern const cairo_private cairo_surface_t _cairo_surface_nil;
|
||||
|
@ -1741,6 +1690,15 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
|||
|
||||
/* cairo_image_surface.c */
|
||||
|
||||
#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \
|
||||
(format) <= CAIRO_FORMAT_A1)
|
||||
|
||||
#define CAIRO_CONTENT_VALID(content) ((content) && \
|
||||
(((content) & ~(CAIRO_CONTENT_COLOR | \
|
||||
CAIRO_CONTENT_ALPHA | \
|
||||
CAIRO_CONTENT_COLOR_ALPHA))\
|
||||
== 0))
|
||||
|
||||
cairo_private cairo_format_t
|
||||
_cairo_format_from_content (cairo_content_t content);
|
||||
|
||||
|
@ -1851,10 +1809,6 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
|||
cairo_private void
|
||||
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det);
|
||||
|
||||
cairo_private void
|
||||
_cairo_matrix_compute_eigen_values (const cairo_matrix_t *matrix,
|
||||
double *lambda1, double *lambda2);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
|
||||
double *sx, double *sy, int x_major);
|
||||
|
@ -1863,6 +1817,9 @@ cairo_private cairo_bool_t
|
|||
_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
|
||||
int *itx, int *ity);
|
||||
|
||||
cairo_private double
|
||||
_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);
|
||||
|
||||
/* cairo_traps.c */
|
||||
cairo_private void
|
||||
_cairo_traps_init (cairo_traps_t *traps);
|
||||
|
|
|
@ -42,6 +42,8 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
VISIBILITY_FLAGS =
|
||||
|
||||
MODULE = glitz
|
||||
LIBRARY_NAME = mozglitz
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
|
|
@ -83,6 +83,10 @@ _glitz_agl_release_bundle (CFBundleRef bundle)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_agl_notify_dummy (void *abstract_drawable,
|
||||
glitz_surface_t *surface) {}
|
||||
|
||||
static glitz_function_pointer_t
|
||||
_glitz_agl_get_proc_address (const char *name, void *closure)
|
||||
{
|
||||
|
@ -106,7 +110,8 @@ static glitz_context_t *
|
|||
_glitz_agl_create_context (void *abstract_drawable,
|
||||
glitz_drawable_format_t *format)
|
||||
{
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable;
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_agl_thread_info_t *thread_info = drawable->thread_info;
|
||||
glitz_agl_context_t *context;
|
||||
|
||||
|
@ -158,13 +163,20 @@ _glitz_agl_copy_context (void *abstract_src,
|
|||
}
|
||||
|
||||
static void
|
||||
_glitz_agl_make_current (void *abstract_context,
|
||||
void *abstract_drawable)
|
||||
_glitz_agl_make_current (void *abstract_drawable,
|
||||
void *abstract_context)
|
||||
{
|
||||
glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context;
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable;
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
|
||||
abstract_drawable;
|
||||
int update = 0;
|
||||
|
||||
if (drawable->base.width != drawable->width ||
|
||||
drawable->base.height != drawable->height)
|
||||
_glitz_agl_drawable_update_size (drawable,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
|
||||
if (aglGetCurrentContext () != context->context)
|
||||
{
|
||||
update = 1;
|
||||
|
@ -230,7 +242,7 @@ _glitz_agl_context_get_proc_address (void *abstract_context,
|
|||
glitz_function_pointer_t func;
|
||||
CFBundleRef bundle;
|
||||
|
||||
_glitz_agl_make_current (context, drawable);
|
||||
_glitz_agl_make_current (drawable, context, NULL);
|
||||
|
||||
bundle = _glitz_agl_get_bundle ("OpenGL.framework");
|
||||
|
||||
|
@ -281,14 +293,14 @@ glitz_agl_context_get (glitz_agl_thread_info_t *thread_info,
|
|||
if (!thread_info->root_context)
|
||||
thread_info->root_context = context->context;
|
||||
|
||||
memcpy (&context->backend.gl,
|
||||
&_glitz_agl_gl_proc_address,
|
||||
sizeof (glitz_gl_proc_address_list_t));
|
||||
context->backend.gl = &_glitz_agl_gl_proc_address;
|
||||
|
||||
context->backend.create_pbuffer = glitz_agl_create_pbuffer;
|
||||
context->backend.destroy = glitz_agl_destroy;
|
||||
context->backend.push_current = glitz_agl_push_current;
|
||||
context->backend.pop_current = glitz_agl_pop_current;
|
||||
context->backend.attach_notify = _glitz_agl_notify_dummy;
|
||||
context->backend.detach_notify = _glitz_agl_notify_dummy;
|
||||
context->backend.swap_buffers = glitz_agl_swap_buffers;
|
||||
|
||||
context->backend.create_context = _glitz_agl_create_context;
|
||||
|
@ -297,8 +309,22 @@ glitz_agl_context_get (glitz_agl_thread_info_t *thread_info,
|
|||
context->backend.make_current = _glitz_agl_make_current;
|
||||
context->backend.get_proc_address = _glitz_agl_context_get_proc_address;
|
||||
|
||||
context->backend.drawable_formats = thread_info->formats;
|
||||
context->backend.n_drawable_formats = thread_info->n_formats;
|
||||
context->backend.drawable_formats = NULL;
|
||||
context->backend.n_drawable_formats = 0;
|
||||
|
||||
if (screen_info->n_formats)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = sizeof (glitz_int_drawable_format_t) * screen_info->n_formats;
|
||||
context->backend.drawable_formats = malloc (size);
|
||||
if (context->backend.drawable_formats)
|
||||
{
|
||||
memcpy (context->backend.drawable_formats, screen_info->formats,
|
||||
size);
|
||||
context->backend.n_drawable_formats = screen_info->n_formats;
|
||||
}
|
||||
}
|
||||
|
||||
context->backend.texture_formats = NULL;
|
||||
context->backend.formats = NULL;
|
||||
|
@ -316,6 +342,9 @@ void
|
|||
glitz_agl_context_destroy (glitz_agl_thread_info_t *thread_info,
|
||||
glitz_agl_context_t *context)
|
||||
{
|
||||
if (context->backend.drawable_formats)
|
||||
free (context->backend.drawable_formats);
|
||||
|
||||
if (context->backend.formats)
|
||||
free (context->backend.formats);
|
||||
|
||||
|
@ -341,9 +370,6 @@ _glitz_agl_context_initialize (glitz_agl_thread_info_t *thread_info,
|
|||
|
||||
_glitz_agl_release_bundle (bundle);
|
||||
|
||||
context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS,
|
||||
context->max_viewport_dims);
|
||||
|
||||
glitz_initiate_state (&_glitz_agl_gl_proc_address);
|
||||
|
||||
context->initialized = 1;
|
||||
|
@ -384,7 +410,8 @@ _glitz_agl_context_make_current (glitz_agl_drawable_t *drawable,
|
|||
drawable->base.update_all = 1;
|
||||
|
||||
if (!drawable->context->initialized)
|
||||
_glitz_agl_context_initialize (drawable->thread_info, drawable->context);
|
||||
_glitz_agl_context_initialize (drawable->thread_info,
|
||||
drawable->context);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -407,6 +434,12 @@ _glitz_agl_context_update (glitz_agl_drawable_t *drawable,
|
|||
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
|
||||
break;
|
||||
case GLITZ_DRAWABLE_CURRENT:
|
||||
if (drawable->base.width != drawable->width ||
|
||||
drawable->base.height != drawable->height)
|
||||
_glitz_agl_drawable_update_size (drawable,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
|
||||
context = aglGetCurrentContext ();
|
||||
if (context != drawable->context->context) {
|
||||
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
|
||||
|
@ -419,23 +452,27 @@ _glitz_agl_context_update (glitz_agl_drawable_t *drawable,
|
|||
&unused, &unused, &unused);
|
||||
|
||||
if (pbuffer != drawable->pbuffer)
|
||||
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
|
||||
_glitz_agl_context_make_current (drawable,
|
||||
(context)? 1: 0);
|
||||
|
||||
} else if (drawable->drawable) {
|
||||
if (aglGetDrawable (drawable->context->context) != drawable->drawable)
|
||||
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
|
||||
if (aglGetDrawable (drawable->context->context) !=
|
||||
drawable->drawable)
|
||||
_glitz_agl_context_make_current (drawable,
|
||||
(context)? 1: 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_bool_t
|
||||
glitz_agl_push_current (void *abstract_drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint)
|
||||
{
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable;
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_agl_context_info_t *context_info;
|
||||
int index;
|
||||
|
||||
|
@ -447,12 +484,15 @@ glitz_agl_push_current (void *abstract_drawable,
|
|||
context_info->constraint = constraint;
|
||||
|
||||
_glitz_agl_context_update (context_info->drawable, constraint);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
glitz_surface_t *
|
||||
glitz_agl_pop_current (void *abstract_drawable)
|
||||
{
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable;
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_agl_context_info_t *context_info = NULL;
|
||||
int index;
|
||||
|
||||
|
|
|
@ -40,30 +40,29 @@ _glitz_agl_create_drawable (glitz_agl_thread_info_t *thread_info,
|
|||
{
|
||||
glitz_agl_drawable_t *drawable;
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return NULL;
|
||||
|
||||
drawable = (glitz_agl_drawable_t *) malloc (sizeof (glitz_agl_drawable_t));
|
||||
if (drawable == NULL)
|
||||
return NULL;
|
||||
|
||||
drawable->base.ref_count = 1;
|
||||
drawable->thread_info = thread_info;
|
||||
drawable->context = context;
|
||||
drawable->drawable = agl_drawable;
|
||||
drawable->pbuffer = agl_pbuffer;
|
||||
drawable->base.format = format;
|
||||
drawable->base.backend = &context->backend;
|
||||
drawable->width = width;
|
||||
drawable->height = height;
|
||||
|
||||
glitz_drawable_update_size (&drawable->base, width, height);
|
||||
_glitz_drawable_init (&drawable->base,
|
||||
format,
|
||||
&context->backend,
|
||||
width, height);
|
||||
|
||||
if (!context->initialized) {
|
||||
glitz_agl_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
|
||||
glitz_agl_pop_current (drawable);
|
||||
}
|
||||
|
||||
if (width > context->max_viewport_dims[0] ||
|
||||
height > context->max_viewport_dims[1]) {
|
||||
if (width > context->backend.max_viewport_dims[0] ||
|
||||
height > context->backend.max_viewport_dims[1]) {
|
||||
free (drawable);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -73,6 +72,28 @@ _glitz_agl_create_drawable (glitz_agl_thread_info_t *thread_info,
|
|||
return drawable;
|
||||
}
|
||||
|
||||
glitz_bool_t
|
||||
_glitz_agl_drawable_update_size (glitz_agl_drawable_t *drawable,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (drawable->pbuffer)
|
||||
{
|
||||
glitz_agl_pbuffer_destroy (drawable->thread_info, drawable->pbuffer);
|
||||
drawable->pbuffer =
|
||||
glitz_agl_pbuffer_create (drawable->thread_info,
|
||||
drawable->context->fbconfig,
|
||||
(int) width, (int) height);
|
||||
if (!drawable->pbuffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
drawable->width = width;
|
||||
drawable->height = height;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static glitz_drawable_t *
|
||||
_glitz_agl_create_pbuffer_drawable (glitz_agl_thread_info_t *thread_info,
|
||||
glitz_drawable_format_t *format,
|
||||
|
@ -90,7 +111,8 @@ _glitz_agl_create_pbuffer_drawable (glitz_agl_thread_info_t *thread_info,
|
|||
if (!context)
|
||||
return NULL;
|
||||
|
||||
pbuffer = glitz_agl_pbuffer_create (thread_info, (int) width, (int) height);
|
||||
pbuffer = glitz_agl_pbuffer_create (thread_info,
|
||||
(int) width, (int) height);
|
||||
if (!pbuffer)
|
||||
return NULL;
|
||||
|
||||
|
@ -136,6 +158,9 @@ glitz_agl_create_drawable_for_window (glitz_drawable_format_t *format,
|
|||
if (!thread_info)
|
||||
return NULL;
|
||||
|
||||
if (format->id >= screen_info->n_formats)
|
||||
return NULL;
|
||||
|
||||
context = glitz_agl_context_get (thread_info, format);
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
@ -161,6 +186,9 @@ glitz_agl_create_pbuffer_drawable (glitz_drawable_format_t *format,
|
|||
if (!thread_info)
|
||||
return NULL;
|
||||
|
||||
if (format->id >= screen_info->n_formats)
|
||||
return NULL;
|
||||
|
||||
return _glitz_agl_create_pbuffer_drawable (thread_info, format,
|
||||
width, height);
|
||||
}
|
||||
|
@ -169,7 +197,8 @@ slim_hidden_def(glitz_agl_create_pbuffer_drawable);
|
|||
void
|
||||
glitz_agl_destroy (void *abstract_drawable)
|
||||
{
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable;
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
drawable->thread_info->drawables--;
|
||||
if (drawable->thread_info->drawables == 0) {
|
||||
|
@ -177,7 +206,8 @@ glitz_agl_destroy (void *abstract_drawable)
|
|||
* Last drawable? We have to destroy all fragment programs as this may
|
||||
* be our last chance to have a context current.
|
||||
*/
|
||||
glitz_agl_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT);
|
||||
glitz_agl_push_current (abstract_drawable, NULL,
|
||||
GLITZ_CONTEXT_CURRENT);
|
||||
glitz_program_map_fini (&drawable->base.backend->gl,
|
||||
&drawable->thread_info->program_map);
|
||||
glitz_agl_pop_current (abstract_drawable);
|
||||
|
@ -208,12 +238,15 @@ glitz_agl_destroy (void *abstract_drawable)
|
|||
free (drawable);
|
||||
}
|
||||
|
||||
void
|
||||
glitz_bool_t
|
||||
glitz_agl_swap_buffers (void *abstract_drawable)
|
||||
{
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable;
|
||||
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
glitz_agl_push_current (abstract_drawable, NULL, GLITZ_DRAWABLE_CURRENT);
|
||||
aglSwapBuffers (drawable->context->context);
|
||||
glitz_agl_pop_current (abstract_drawable);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ static glitz_extension_map agl_extensions[] = {
|
|||
GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK },
|
||||
{ 0.0, "GL_EXT_texture_rectangle",
|
||||
GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK },
|
||||
{ 0.0, "GL_NV_texture_rectangle", GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK },
|
||||
{ 0.0, "GL_NV_texture_rectangle",
|
||||
GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK },
|
||||
{ 0.0, NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -68,7 +69,8 @@ glitz_agl_query_extensions (glitz_agl_thread_info_t *thread_info)
|
|||
gl_extensions_string,
|
||||
agl_extensions);
|
||||
|
||||
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK) {
|
||||
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK)
|
||||
{
|
||||
const char *vendor;
|
||||
|
||||
vendor = glGetString (GL_VENDOR);
|
||||
|
|
|
@ -260,8 +260,10 @@ glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
|
|||
aglDescribePixelFormat (pixel_format, AGL_STENCIL_SIZE, &value);
|
||||
format.stencil_size = (unsigned short) value;
|
||||
|
||||
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK) {
|
||||
aglDescribePixelFormat (pixel_format, AGL_SAMPLE_BUFFERS_ARB, &value);
|
||||
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK)
|
||||
{
|
||||
aglDescribePixelFormat (pixel_format, AGL_SAMPLE_BUFFERS_ARB,
|
||||
&value);
|
||||
if (value) {
|
||||
aglDescribePixelFormat (pixel_format, AGL_SAMPLES_ARB, &value);
|
||||
format.samples = (unsigned short) (value > 1)? value: 1;
|
||||
|
|
|
@ -89,6 +89,7 @@ glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address = {
|
|||
(glitz_gl_bind_texture_t) glBindTexture,
|
||||
(glitz_gl_tex_image_2d_t) glTexImage2D,
|
||||
(glitz_gl_tex_parameter_i_t) glTexParameteri,
|
||||
(glitz_gl_tex_parameter_fv_t) glTexParameterfv,
|
||||
(glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv,
|
||||
(glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D,
|
||||
(glitz_gl_get_integer_v_t) glGetIntegerv,
|
||||
|
@ -111,7 +112,18 @@ glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address = {
|
|||
(glitz_gl_buffer_sub_data_t) 0,
|
||||
(glitz_gl_get_buffer_sub_data_t) 0,
|
||||
(glitz_gl_map_buffer_t) 0,
|
||||
(glitz_gl_unmap_buffer_t) 0
|
||||
(glitz_gl_unmap_buffer_t) 0,
|
||||
(glitz_gl_gen_framebuffers_t) 0,
|
||||
(glitz_gl_delete_framebuffers_t) 0,
|
||||
(glitz_gl_bind_framebuffer_t) 0,
|
||||
(glitz_gl_framebuffer_renderbuffer_t) 0,
|
||||
(glitz_gl_framebuffer_texture_2d_t) 0,
|
||||
(glitz_gl_check_framebuffer_status_t) 0,
|
||||
(glitz_gl_gen_renderbuffers_t) 0,
|
||||
(glitz_gl_delete_renderbuffers_t) 0,
|
||||
(glitz_gl_bind_renderbuffer_t) 0,
|
||||
(glitz_gl_renderbuffer_storage_t) 0,
|
||||
(glitz_gl_get_renderbuffer_parameter_iv_t) 0
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -55,15 +55,12 @@ typedef struct _glitz_agl_context_t {
|
|||
AGLPixelFormat pixel_format;
|
||||
glitz_bool_t pbuffer;
|
||||
glitz_backend_t backend;
|
||||
glitz_gl_int_t max_viewport_dims[2];
|
||||
glitz_gl_int_t max_texture_2d_size;
|
||||
glitz_gl_int_t max_texture_rect_size;
|
||||
glitz_bool_t initialized;
|
||||
} glitz_agl_context_t;
|
||||
|
||||
typedef struct _glitz_agl_thread_info_t {
|
||||
int drawables;
|
||||
glitz_drawable_format_t *formats;
|
||||
glitz_int_drawable_format_t *formats;
|
||||
AGLPixelFormat *pixel_formats;
|
||||
int n_formats;
|
||||
glitz_agl_context_t **contexts;
|
||||
|
@ -84,6 +81,8 @@ struct _glitz_agl_drawable {
|
|||
AGLDrawable drawable;
|
||||
AGLPbuffer pbuffer;
|
||||
WindowRef window;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
extern glitz_status_t __internal_linkage
|
||||
|
@ -117,7 +116,7 @@ glitz_agl_create_pbuffer (void *abstract_templ,
|
|||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
extern void __internal_linkage
|
||||
extern glitz_bool_t __internal_linkage
|
||||
glitz_agl_push_current (void *abstract_drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint);
|
||||
|
@ -128,7 +127,7 @@ glitz_agl_pop_current (void *abstract_drawable);
|
|||
extern void __internal_linkage
|
||||
glitz_agl_destroy (void *abstract_drawable);
|
||||
|
||||
extern void __internal_linkage
|
||||
extern glitz_bool_t __internal_linkage
|
||||
glitz_agl_swap_buffers (void *abstract_drawable);
|
||||
|
||||
/* Avoid unnecessary PLT entries. */
|
||||
|
|
|
@ -47,12 +47,20 @@ glitz_egl_fini (void);
|
|||
/* glitz_egl_config.c */
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_egl_find_config (EGLDisplay egl_display,
|
||||
glitz_egl_find_window_config (EGLDisplay egl_display,
|
||||
EGLScreenMESA egl_screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_egl_find_pbuffer_config (EGLDisplay egl_display,
|
||||
EGLScreenMESA egl_screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count);
|
||||
|
||||
|
||||
/* glitz_egl_surface.c */
|
||||
|
||||
glitz_drawable_t *
|
||||
|
|
|
@ -36,49 +36,51 @@ static int
|
|||
_glitz_egl_format_compare (const void *elem1,
|
||||
const void *elem2)
|
||||
{
|
||||
glitz_int_drawable_format_t *format[2];
|
||||
int i, score[2];
|
||||
glitz_drawable_format_t *format[2];
|
||||
|
||||
format[0] = (glitz_drawable_format_t *) elem1;
|
||||
format[1] = (glitz_drawable_format_t *) elem2;
|
||||
format[0] = (glitz_int_drawable_format_t *) elem1;
|
||||
format[1] = (glitz_int_drawable_format_t *) elem2;
|
||||
i = score[0] = score[1] = 0;
|
||||
|
||||
for (; i < 2; i++) {
|
||||
if (format[i]->color.red_size) {
|
||||
if (format[i]->color.red_size == 8)
|
||||
for (; i < 2; i++)
|
||||
{
|
||||
if (format[i]->d.color.red_size)
|
||||
{
|
||||
if (format[i]->d.color.red_size >= 8)
|
||||
score[i] += 5;
|
||||
|
||||
score[i] += 10;
|
||||
}
|
||||
|
||||
if (format[i]->color.green_size) {
|
||||
if (format[i]->color.green_size == 8)
|
||||
if (format[i]->d.color.alpha_size)
|
||||
{
|
||||
if (format[i]->d.color.alpha_size >= 8)
|
||||
score[i] += 5;
|
||||
|
||||
score[i] += 10;
|
||||
}
|
||||
|
||||
if (format[i]->color.alpha_size) {
|
||||
if (format[i]->color.alpha_size == 8)
|
||||
score[i] += 5;
|
||||
score[i] += 10;
|
||||
}
|
||||
|
||||
if (format[i]->stencil_size)
|
||||
if (format[i]->d.stencil_size)
|
||||
score[i] += 5;
|
||||
|
||||
if (format[i]->depth_size)
|
||||
if (format[i]->d.depth_size)
|
||||
score[i] += 5;
|
||||
|
||||
if (format[i]->doublebuffer)
|
||||
if (format[i]->d.doublebuffer)
|
||||
score[i] += 10;
|
||||
|
||||
if (format[i]->types.window)
|
||||
if (format[i]->d.samples > 1)
|
||||
score[i] -= (20 - format[i]->d.samples);
|
||||
|
||||
if (format[i]->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK)
|
||||
score[i] += 10;
|
||||
|
||||
if (format[i]->types.pbuffer)
|
||||
if (format[i]->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)
|
||||
score[i] += 10;
|
||||
|
||||
if (format[i]->samples > 1)
|
||||
score[i] -= (20 - format[i]->samples);
|
||||
if (format[i]->caveat)
|
||||
score[i] -= 1000;
|
||||
}
|
||||
|
||||
return score[1] - score[0];
|
||||
|
@ -86,96 +88,102 @@ _glitz_egl_format_compare (const void *elem1,
|
|||
|
||||
static void
|
||||
_glitz_add_format (glitz_egl_screen_info_t *screen_info,
|
||||
glitz_drawable_format_t *format,
|
||||
EGLConfig egl_id)
|
||||
glitz_int_drawable_format_t *format)
|
||||
{
|
||||
if (!glitz_drawable_format_find (screen_info->formats,
|
||||
screen_info->n_formats,
|
||||
GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK,
|
||||
format, 0)) {
|
||||
int n = screen_info->n_formats;
|
||||
|
||||
screen_info->formats =
|
||||
realloc (screen_info->formats,
|
||||
sizeof (glitz_drawable_format_t) * (n + 1));
|
||||
screen_info->egl_config_ids =
|
||||
realloc (screen_info->egl_config_ids, sizeof (EGLConfig) * (n + 1));
|
||||
|
||||
if (screen_info->formats && screen_info->egl_config_ids) {
|
||||
sizeof (glitz_int_drawable_format_t) * (n + 1));
|
||||
if (screen_info->formats)
|
||||
{
|
||||
screen_info->formats[n] = *format;
|
||||
screen_info->formats[n].id = n;
|
||||
screen_info->egl_config_ids[n] = egl_id;
|
||||
screen_info->formats[n].d.id = n;
|
||||
screen_info->n_formats++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static glitz_status_t
|
||||
static void
|
||||
_glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info)
|
||||
{
|
||||
glitz_int_drawable_format_t format;
|
||||
EGLDisplay egl_display;
|
||||
glitz_drawable_format_t format;
|
||||
EGLConfig *egl_configs;
|
||||
int i, num_configs;
|
||||
EGLConfig egl_id;
|
||||
|
||||
egl_display = screen_info->display_info->egl_display;
|
||||
|
||||
eglGetConfigs (egl_display, NULL, 0, &num_configs);
|
||||
egl_configs = malloc(sizeof(*egl_configs) * num_configs);
|
||||
egl_configs = malloc (sizeof (EGLConfig) * num_configs);
|
||||
if (!egl_configs)
|
||||
return;
|
||||
|
||||
format.d.id = 0;
|
||||
format.d.doublebuffer = 1;
|
||||
|
||||
eglGetConfigs (egl_display, egl_configs, num_configs, &num_configs);
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
for (i = 0; i < num_configs; i++)
|
||||
{
|
||||
int value;
|
||||
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i],
|
||||
EGL_SURFACE_TYPE, &value);
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_SURFACE_TYPE,
|
||||
&value);
|
||||
if (!((value & EGL_WINDOW_BIT) || (value & EGL_PBUFFER_BIT)))
|
||||
continue;
|
||||
|
||||
format.types.window = (value & EGL_WINDOW_BIT)? 1: 0;
|
||||
format.types.pbuffer = (value & EGL_PBUFFER_BIT)? 1: 0;
|
||||
format.id = 0;
|
||||
format.types = 0;
|
||||
if (value & EGL_WINDOW_BIT)
|
||||
format.types |= GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
|
||||
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_CONFIG_ID, &value);
|
||||
egl_id = (EGLConfig) value;
|
||||
if (value & EGL_PBUFFER_BIT)
|
||||
format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
|
||||
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_CONFIG_ID,
|
||||
&value);
|
||||
format.u.uval = value;
|
||||
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_RED_SIZE, &value);
|
||||
format.color.red_size = (unsigned short) value;
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_GREEN_SIZE, &value);
|
||||
format.color.green_size = (unsigned short) value;
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_BLUE_SIZE, &value);
|
||||
format.color.blue_size = (unsigned short) value;
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_ALPHA_SIZE, &value);
|
||||
format.color.alpha_size = (unsigned short) value;
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_DEPTH_SIZE, &value);
|
||||
format.depth_size = (unsigned short) value;
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_STENCIL_SIZE, &value);
|
||||
format.stencil_size = (unsigned short) value;
|
||||
format.d.color.red_size = (unsigned short) value;
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_GREEN_SIZE,
|
||||
&value);
|
||||
format.d.color.green_size = (unsigned short) value;
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_BLUE_SIZE,
|
||||
&value);
|
||||
format.d.color.blue_size = (unsigned short) value;
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_ALPHA_SIZE,
|
||||
&value);
|
||||
format.d.color.alpha_size = (unsigned short) value;
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_DEPTH_SIZE,
|
||||
&value);
|
||||
format.d.depth_size = (unsigned short) value;
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_STENCIL_SIZE,
|
||||
&value);
|
||||
format.d.stencil_size = (unsigned short) value;
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_CONFIG_CAVEAT,
|
||||
&value);
|
||||
format.caveat = (unsigned short) value;
|
||||
|
||||
format.doublebuffer = 1;
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_SAMPLE_BUFFERS,
|
||||
&value);
|
||||
if (value)
|
||||
{
|
||||
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_SAMPLES,
|
||||
&value);
|
||||
format.d.samples = (unsigned short) (value > 1)? value: 1;
|
||||
}
|
||||
else
|
||||
format.d.samples = 1;
|
||||
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_SAMPLE_BUFFERS, &value);
|
||||
if (value) {
|
||||
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_SAMPLES, &value);
|
||||
format.samples = (unsigned short) (value > 1)? value: 1;
|
||||
if (format.samples > 1)
|
||||
format.types.pbuffer = 0;
|
||||
} else
|
||||
format.samples = 1;
|
||||
|
||||
_glitz_add_format (screen_info, &format, egl_id);
|
||||
_glitz_add_format (screen_info, &format);
|
||||
}
|
||||
|
||||
free (egl_configs);
|
||||
|
||||
return GLITZ_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info)
|
||||
{
|
||||
EGLConfig *egl_new_ids;
|
||||
int i;
|
||||
|
||||
_glitz_egl_query_configs (screen_info);
|
||||
|
@ -184,38 +192,52 @@ glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info)
|
|||
return;
|
||||
|
||||
qsort (screen_info->formats, screen_info->n_formats,
|
||||
sizeof (glitz_drawable_format_t), _glitz_egl_format_compare);
|
||||
sizeof (glitz_int_drawable_format_t), _glitz_egl_format_compare);
|
||||
|
||||
/*
|
||||
* Update XID list so that it matches the sorted format list.
|
||||
*/
|
||||
egl_new_ids = malloc (sizeof (EGLConfig) * screen_info->n_formats);
|
||||
if (!egl_new_ids) {
|
||||
screen_info->n_formats = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < screen_info->n_formats; i++) {
|
||||
egl_new_ids[i] = screen_info->egl_config_ids[screen_info->formats[i].id];
|
||||
screen_info->formats[i].id = i;
|
||||
}
|
||||
|
||||
free (screen_info->egl_config_ids);
|
||||
screen_info->egl_config_ids = egl_new_ids;
|
||||
for (i = 0; i < screen_info->n_formats; i++)
|
||||
screen_info->formats[i].d.id = i;
|
||||
}
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_egl_find_config (EGLDisplay egl_display,
|
||||
glitz_egl_find_window_config (EGLDisplay egl_display,
|
||||
EGLScreenMESA egl_screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count)
|
||||
{
|
||||
glitz_int_drawable_format_t itempl;
|
||||
glitz_egl_screen_info_t *screen_info =
|
||||
glitz_egl_screen_info_get (egl_display, egl_screen);
|
||||
|
||||
glitz_drawable_format_copy (templ, &itempl.d, mask);
|
||||
|
||||
itempl.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
|
||||
mask |= GLITZ_INT_FORMAT_WINDOW_MASK;
|
||||
|
||||
return glitz_drawable_format_find (screen_info->formats,
|
||||
screen_info->n_formats,
|
||||
mask, templ, count);
|
||||
mask, &itempl, count);
|
||||
}
|
||||
slim_hidden_def(glitz_egl_find_config);
|
||||
slim_hidden_def(glitz_egl_find_window_config);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_egl_find_pbuffer_config (EGLDisplay egl_display,
|
||||
EGLScreenMESA egl_screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count)
|
||||
{
|
||||
glitz_int_drawable_format_t itempl;
|
||||
glitz_egl_screen_info_t *screen_info =
|
||||
glitz_egl_screen_info_get (egl_display, egl_screen);
|
||||
|
||||
glitz_drawable_format_copy (templ, &itempl.d, mask);
|
||||
|
||||
itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
|
||||
mask |= GLITZ_INT_FORMAT_PBUFFER_MASK;
|
||||
|
||||
return glitz_drawable_format_find (screen_info->formats,
|
||||
screen_info->n_formats,
|
||||
mask, &itempl, count);
|
||||
}
|
||||
slim_hidden_def(glitz_egl_find_pbuffer_config);
|
||||
|
|
|
@ -40,7 +40,8 @@ _glitz_egl_context_create (glitz_egl_screen_info_t *screen_info,
|
|||
glitz_egl_context_t *context)
|
||||
{
|
||||
context->id = egl_config;
|
||||
context->egl_context = eglCreateContext (screen_info->display_info->egl_display,
|
||||
context->egl_context =
|
||||
eglCreateContext (screen_info->display_info->egl_display,
|
||||
egl_config, egl_share_list, NULL);
|
||||
}
|
||||
|
||||
|
@ -50,7 +51,7 @@ _glitz_egl_create_context (void *abstract_drawable,
|
|||
{
|
||||
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable;
|
||||
glitz_egl_screen_info_t *screen_info = drawable->screen_info;
|
||||
int format_id = screen_info->egl_config_ids[format->id];
|
||||
int format_id = screen_info->formats[format->id].u.uval;
|
||||
glitz_egl_context_t *context;
|
||||
|
||||
context = malloc (sizeof (glitz_egl_context_t));
|
||||
|
@ -74,7 +75,8 @@ _glitz_egl_context_destroy (void *abstract_context)
|
|||
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *)
|
||||
context->base.drawable;
|
||||
|
||||
if (drawable->screen_info->display_info->thread_info->cctx == &context->base)
|
||||
if (drawable->screen_info->display_info->thread_info->cctx ==
|
||||
&context->base)
|
||||
{
|
||||
eglMakeCurrent (drawable->screen_info->display_info->egl_display,
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
@ -105,21 +107,42 @@ _glitz_egl_copy_context (void *abstract_src,
|
|||
}
|
||||
|
||||
static void
|
||||
_glitz_egl_make_current (void *abstract_context,
|
||||
void *abstract_drawable)
|
||||
_glitz_egl_make_current (void *abstract_drawable,
|
||||
void *abstract_context)
|
||||
{
|
||||
glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context;
|
||||
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable;
|
||||
glitz_egl_display_info_t *display_info = drawable->screen_info->display_info;
|
||||
glitz_egl_display_info_t *display_info =
|
||||
drawable->screen_info->display_info;
|
||||
|
||||
if (drawable->base.width != drawable->width ||
|
||||
drawable->base.height != drawable->height)
|
||||
_glitz_egl_drawable_update_size (drawable,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
|
||||
if ((eglGetCurrentContext () != context->egl_context) ||
|
||||
(eglGetCurrentSurface ( 0 ) != drawable->egl_surface))
|
||||
{
|
||||
if (display_info->thread_info->cctx)
|
||||
{
|
||||
glitz_context_t *ctx = display_info->thread_info->cctx;
|
||||
|
||||
if (ctx->lose_current)
|
||||
ctx->lose_current (ctx->closure);
|
||||
}
|
||||
|
||||
eglMakeCurrent (display_info->egl_display, drawable->egl_surface,
|
||||
drawable->egl_surface, context->egl_context);
|
||||
}
|
||||
|
||||
display_info->thread_info->cctx = &context->base;
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_egl_notify_dummy (void *abstract_drawable,
|
||||
glitz_surface_t *surface) {}
|
||||
|
||||
static glitz_function_pointer_t
|
||||
_glitz_egl_context_get_proc_address (void *abstract_context,
|
||||
const char *name)
|
||||
|
@ -128,7 +151,7 @@ _glitz_egl_context_get_proc_address (void *abstract_context,
|
|||
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *)
|
||||
context->base.drawable;
|
||||
|
||||
_glitz_egl_make_current (context, drawable);
|
||||
_glitz_egl_make_current (drawable, context);
|
||||
|
||||
return glitz_egl_get_proc_address (name, drawable->screen_info);
|
||||
}
|
||||
|
@ -140,10 +163,9 @@ glitz_egl_context_get (glitz_egl_screen_info_t *screen_info,
|
|||
glitz_egl_context_t *context;
|
||||
glitz_egl_context_t **contexts = screen_info->contexts;
|
||||
int index, n_contexts = screen_info->n_contexts;
|
||||
EGLConfig egl_config_id;
|
||||
|
||||
for (; n_contexts; n_contexts--, contexts++)
|
||||
if ((*contexts)->id == screen_info->egl_config_ids[format->id])
|
||||
if ((*contexts)->id == screen_info->formats[format->id].u.uval)
|
||||
return *contexts;
|
||||
|
||||
index = screen_info->n_contexts++;
|
||||
|
@ -160,24 +182,22 @@ glitz_egl_context_get (glitz_egl_screen_info_t *screen_info,
|
|||
|
||||
screen_info->contexts[index] = context;
|
||||
|
||||
egl_config_id = screen_info->egl_config_ids[format->id];
|
||||
|
||||
_glitz_egl_context_create (screen_info,
|
||||
egl_config_id,
|
||||
screen_info->formats[format->id].u.uval,
|
||||
screen_info->egl_root_context,
|
||||
context);
|
||||
|
||||
if (!screen_info->egl_root_context)
|
||||
screen_info->egl_root_context = context->egl_context;
|
||||
|
||||
memcpy (&context->backend.gl,
|
||||
&_glitz_egl_gl_proc_address,
|
||||
sizeof (glitz_gl_proc_address_list_t));
|
||||
context->backend.gl = &_glitz_egl_gl_proc_address;
|
||||
|
||||
context->backend.create_pbuffer = glitz_egl_create_pbuffer;
|
||||
context->backend.destroy = glitz_egl_destroy;
|
||||
context->backend.push_current = glitz_egl_push_current;
|
||||
context->backend.pop_current = glitz_egl_pop_current;
|
||||
context->backend.attach_notify = _glitz_egl_notify_dummy;
|
||||
context->backend.detach_notify = _glitz_egl_notify_dummy;
|
||||
context->backend.swap_buffers = glitz_egl_swap_buffers;
|
||||
|
||||
context->backend.create_context = _glitz_egl_create_context;
|
||||
|
@ -186,8 +206,22 @@ glitz_egl_context_get (glitz_egl_screen_info_t *screen_info,
|
|||
context->backend.make_current = _glitz_egl_make_current;
|
||||
context->backend.get_proc_address = _glitz_egl_context_get_proc_address;
|
||||
|
||||
context->backend.drawable_formats = screen_info->formats;
|
||||
context->backend.drawable_formats = NULL;
|
||||
context->backend.n_drawable_formats = 0;
|
||||
|
||||
if (screen_info->n_formats)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = sizeof (glitz_int_drawable_format_t) * screen_info->n_formats;
|
||||
context->backend.drawable_formats = malloc (size);
|
||||
if (context->backend.drawable_formats)
|
||||
{
|
||||
memcpy (context->backend.drawable_formats, screen_info->formats,
|
||||
size);
|
||||
context->backend.n_drawable_formats = screen_info->n_formats;
|
||||
}
|
||||
}
|
||||
|
||||
context->backend.texture_formats = NULL;
|
||||
context->backend.formats = NULL;
|
||||
|
@ -205,6 +239,9 @@ void
|
|||
glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info,
|
||||
glitz_egl_context_t *context)
|
||||
{
|
||||
if (context->backend.drawable_formats)
|
||||
free (context->backend.drawable_formats);
|
||||
|
||||
if (context->backend.formats)
|
||||
free (context->backend.formats);
|
||||
|
||||
|
@ -226,18 +263,16 @@ _glitz_egl_context_initialize (glitz_egl_screen_info_t *screen_info,
|
|||
glitz_egl_get_proc_address,
|
||||
(void *) screen_info);
|
||||
|
||||
context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS,
|
||||
context->max_viewport_dims);
|
||||
|
||||
glitz_initiate_state (&_glitz_egl_gl_proc_address);
|
||||
|
||||
version = (const char *) context->backend.gl.get_string (GLITZ_GL_VERSION);
|
||||
version = (const char *)
|
||||
context->backend.gl->get_string (GLITZ_GL_VERSION);
|
||||
if (version)
|
||||
{
|
||||
/* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures when
|
||||
using nvidia's binary driver. Seems like a driver issue, but I'm not
|
||||
sure yet. Turning of NPOT GL_TEXTURE_2D textures until this have been
|
||||
solved. */
|
||||
/* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures
|
||||
when using nvidia's binary driver. Seems like a driver issue, but
|
||||
I'm not sure yet. Turning of NPOT GL_TEXTURE_2D textures until
|
||||
this have been solved. */
|
||||
if (strstr (version, "NVIDIA 61.11") ||
|
||||
strstr (version, "NVIDIA 66.29"))
|
||||
{
|
||||
|
@ -253,7 +288,8 @@ static void
|
|||
_glitz_egl_context_make_current (glitz_egl_surface_t *drawable,
|
||||
glitz_bool_t finish)
|
||||
{
|
||||
glitz_egl_display_info_t *display_info = drawable->screen_info->display_info;
|
||||
glitz_egl_display_info_t *display_info =
|
||||
drawable->screen_info->display_info;
|
||||
|
||||
if (finish)
|
||||
glFinish ();
|
||||
|
@ -275,7 +311,8 @@ _glitz_egl_context_make_current (glitz_egl_surface_t *drawable,
|
|||
drawable->base.update_all = 1;
|
||||
|
||||
if (!drawable->context->initialized)
|
||||
_glitz_egl_context_initialize (drawable->screen_info, drawable->context);
|
||||
_glitz_egl_context_initialize (drawable->screen_info,
|
||||
drawable->context);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -307,6 +344,12 @@ _glitz_egl_context_update (glitz_egl_surface_t *drawable,
|
|||
_glitz_egl_context_make_current (drawable, (egl_context)? 1: 0);
|
||||
break;
|
||||
case GLITZ_DRAWABLE_CURRENT:
|
||||
if (drawable->base.width != drawable->width ||
|
||||
drawable->base.height != drawable->height)
|
||||
_glitz_egl_drawable_update_size (drawable,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
|
||||
egl_context = eglGetCurrentContext ();
|
||||
if ((egl_context != drawable->context->egl_context) ||
|
||||
(eglGetCurrentSurface ( 0 ) != drawable->egl_surface))
|
||||
|
@ -315,7 +358,7 @@ _glitz_egl_context_update (glitz_egl_surface_t *drawable,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_bool_t
|
||||
glitz_egl_push_current (void *abstract_drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint)
|
||||
|
@ -332,6 +375,8 @@ glitz_egl_push_current (void *abstract_drawable,
|
|||
context_info->constraint = constraint;
|
||||
|
||||
_glitz_egl_context_update (context_info->drawable, constraint);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
glitz_surface_t *
|
||||
|
|
|
@ -91,6 +91,7 @@ glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address = {
|
|||
(glitz_gl_bind_texture_t) glBindTexture,
|
||||
(glitz_gl_tex_image_2d_t) glTexImage2D,
|
||||
(glitz_gl_tex_parameter_i_t) glTexParameteri,
|
||||
(glitz_gl_tex_parameter_fv_t) glTexParameterfv,
|
||||
(glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv,
|
||||
(glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D,
|
||||
(glitz_gl_get_integer_v_t) glGetIntegerv,
|
||||
|
@ -113,7 +114,18 @@ glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address = {
|
|||
(glitz_gl_buffer_sub_data_t) 0,
|
||||
(glitz_gl_get_buffer_sub_data_t) 0,
|
||||
(glitz_gl_map_buffer_t) 0,
|
||||
(glitz_gl_unmap_buffer_t) 0
|
||||
(glitz_gl_unmap_buffer_t) 0,
|
||||
(glitz_gl_gen_framebuffers_t) 0,
|
||||
(glitz_gl_delete_framebuffers_t) 0,
|
||||
(glitz_gl_bind_framebuffer_t) 0,
|
||||
(glitz_gl_framebuffer_renderbuffer_t) 0,
|
||||
(glitz_gl_framebuffer_texture_2d_t) 0,
|
||||
(glitz_gl_check_framebuffer_status_t) 0,
|
||||
(glitz_gl_gen_renderbuffers_t) 0,
|
||||
(glitz_gl_delete_renderbuffers_t) 0,
|
||||
(glitz_gl_bind_renderbuffer_t) 0,
|
||||
(glitz_gl_renderbuffer_storage_t) 0,
|
||||
(glitz_gl_get_renderbuffer_parameter_iv_t) 0
|
||||
};
|
||||
|
||||
glitz_function_pointer_t
|
||||
|
@ -124,7 +136,8 @@ glitz_egl_get_proc_address (const char *name,
|
|||
glitz_egl_thread_info_t *info = screen_info->display_info->thread_info;
|
||||
glitz_function_pointer_t address = NULL;
|
||||
|
||||
if (screen_info->egl_feature_mask & GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK)
|
||||
if (screen_info->egl_feature_mask &
|
||||
GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK)
|
||||
address = eglGetProcAddress ((char *) name);
|
||||
|
||||
if (!address) {
|
||||
|
@ -305,7 +318,8 @@ _glitz_egl_display_info_get (EGLDisplay egl_display)
|
|||
|
||||
thread_info->displays =
|
||||
realloc (thread_info->displays,
|
||||
sizeof (glitz_egl_display_info_t *) * thread_info->n_displays);
|
||||
sizeof (glitz_egl_display_info_t *) *
|
||||
thread_info->n_displays);
|
||||
|
||||
display_info = malloc (sizeof (glitz_egl_display_info_t));
|
||||
thread_info->displays[index] = display_info;
|
||||
|
@ -341,6 +355,7 @@ glitz_egl_screen_info_get (EGLDisplay display,
|
|||
_glitz_egl_display_info_get (display);
|
||||
glitz_egl_screen_info_t **screens = display_info->screens;
|
||||
int index, n_screens = display_info->n_screens;
|
||||
|
||||
#if 0
|
||||
int error_base, event_base;
|
||||
#endif
|
||||
|
@ -362,7 +377,6 @@ glitz_egl_screen_info_get (EGLDisplay display,
|
|||
screen_info->screen = screen;
|
||||
screen_info->drawables = 0;
|
||||
screen_info->formats = NULL;
|
||||
screen_info->egl_config_ids = NULL;
|
||||
screen_info->n_formats = 0;
|
||||
|
||||
screen_info->contexts = NULL;
|
||||
|
@ -372,6 +386,7 @@ glitz_egl_screen_info_get (EGLDisplay display,
|
|||
|
||||
screen_info->egl_root_context = (EGLContext) 0;
|
||||
screen_info->egl_feature_mask = 0;
|
||||
|
||||
#if 0
|
||||
if (eglQueryExtension (display, &error_base, &event_base)) {
|
||||
int major, minor;
|
||||
|
@ -379,13 +394,15 @@ glitz_egl_screen_info_get (EGLDisplay display,
|
|||
if (eglQueryVersion (display, &major, &minor)) {
|
||||
screen_info->egl_version = major + minor / 10.0f;
|
||||
if (major > 1 || (major > 0 || minor >= 2)) {
|
||||
glitz_egl_query_extensions (screen_info, screen_info->egl_version);
|
||||
glitz_egl_query_extensions (screen_info,
|
||||
screen_info->egl_version);
|
||||
_glitz_egl_proc_address_lookup (screen_info);
|
||||
glitz_egl_query_formats (screen_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
glitz_egl_query_extensions (screen_info, screen_info->egl_version);
|
||||
glitz_egl_query_configs (screen_info);
|
||||
|
||||
|
@ -404,14 +421,14 @@ _glitz_egl_screen_destroy (glitz_egl_screen_info_t *screen_info)
|
|||
int i;
|
||||
|
||||
if (screen_info->egl_root_context)
|
||||
eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
|
||||
for (i = 0; i < screen_info->n_contexts; i++)
|
||||
glitz_egl_context_destroy (screen_info, screen_info->contexts[i]);
|
||||
|
||||
free (screen_info->contexts);
|
||||
free (screen_info->formats);
|
||||
free (screen_info->egl_config_ids);
|
||||
free (screen_info);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info,
|
|||
|
||||
attributes[2] = EGL_HEIGHT;
|
||||
attributes[3] = height;
|
||||
|
||||
#if 0
|
||||
attributes[4] = EGL_LARGEST_PBUFFER;
|
||||
attributes[5] = 0;
|
||||
|
@ -51,6 +52,7 @@ glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info,
|
|||
attributes[7] = 1;
|
||||
attributes[8] = 0;
|
||||
#endif
|
||||
|
||||
return
|
||||
eglCreatePbufferSurface (screen_info->display_info->egl_display,
|
||||
egl_config, attributes);
|
||||
|
|
|
@ -39,29 +39,28 @@ _glitz_egl_create_surface (glitz_egl_screen_info_t *screen_info,
|
|||
{
|
||||
glitz_egl_surface_t *surface;
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return NULL;
|
||||
|
||||
surface = (glitz_egl_surface_t *) malloc (sizeof (glitz_egl_surface_t));
|
||||
if (surface == NULL)
|
||||
return NULL;
|
||||
|
||||
surface->base.ref_count = 1;
|
||||
surface->screen_info = screen_info;
|
||||
surface->context = context;
|
||||
surface->egl_surface = egl_surface;
|
||||
surface->base.format = format;
|
||||
surface->base.backend = &context->backend;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
|
||||
glitz_drawable_update_size (&surface->base, width, height);
|
||||
_glitz_drawable_init (&surface->base,
|
||||
&screen_info->formats[format->id],
|
||||
&context->backend,
|
||||
width, height);
|
||||
|
||||
if (!context->initialized) {
|
||||
glitz_egl_push_current (surface, NULL, GLITZ_CONTEXT_CURRENT);
|
||||
glitz_egl_pop_current (surface);
|
||||
}
|
||||
|
||||
if (width > context->max_viewport_dims[0] ||
|
||||
height > context->max_viewport_dims[1]) {
|
||||
if (width > context->backend.max_viewport_dims[0] ||
|
||||
height > context->backend.max_viewport_dims[1]) {
|
||||
free (surface);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -71,6 +70,29 @@ _glitz_egl_create_surface (glitz_egl_screen_info_t *screen_info,
|
|||
return surface;
|
||||
}
|
||||
|
||||
glitz_bool_t
|
||||
_glitz_egl_drawable_update_size (glitz_egl_surface_t *drawable,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (drawable->egl_surface)
|
||||
{
|
||||
glitz_egl_pbuffer_destroy (drawable->screen_info,
|
||||
drawable->egl_surface);
|
||||
drawable->egl_surface =
|
||||
glitz_egl_pbuffer_create (drawable->screen_info,
|
||||
drawable->context->egl_config,
|
||||
(int) width, (int) height);
|
||||
if (!drawable->egl_surface)
|
||||
return 0;
|
||||
}
|
||||
|
||||
drawable->width = width;
|
||||
drawable->height = height;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static glitz_drawable_t *
|
||||
_glitz_egl_create_pbuffer_surface (glitz_egl_screen_info_t *screen_info,
|
||||
glitz_drawable_format_t *format,
|
||||
|
@ -81,9 +103,6 @@ _glitz_egl_create_pbuffer_surface (glitz_egl_screen_info_t *screen_info,
|
|||
glitz_egl_context_t *context;
|
||||
EGLSurface egl_pbuffer;
|
||||
|
||||
if (!format->types.pbuffer)
|
||||
return NULL;
|
||||
|
||||
context = glitz_egl_context_get (screen_info, format);
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
@ -96,7 +115,8 @@ _glitz_egl_create_pbuffer_surface (glitz_egl_screen_info_t *screen_info,
|
|||
surface = _glitz_egl_create_surface (screen_info, context, format,
|
||||
egl_pbuffer,
|
||||
width, height);
|
||||
if (!surface) {
|
||||
if (!surface)
|
||||
{
|
||||
glitz_egl_pbuffer_destroy (screen_info, egl_pbuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -127,18 +147,25 @@ glitz_egl_create_surface (EGLDisplay egl_display,
|
|||
glitz_egl_surface_t *surface;
|
||||
glitz_egl_screen_info_t *screen_info;
|
||||
glitz_egl_context_t *context;
|
||||
glitz_int_drawable_format_t *iformat;
|
||||
|
||||
screen_info = glitz_egl_screen_info_get (egl_display, egl_screen);
|
||||
if (!screen_info)
|
||||
return NULL;
|
||||
|
||||
if (format->id >= screen_info->n_formats)
|
||||
return NULL;
|
||||
|
||||
iformat = &screen_info->formats[format->id];
|
||||
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK))
|
||||
return NULL;
|
||||
|
||||
context = glitz_egl_context_get (screen_info, format);
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
surface = _glitz_egl_create_surface (screen_info, context, format,
|
||||
egl_surface,
|
||||
width, height);
|
||||
egl_surface, width, height);
|
||||
if (!surface)
|
||||
return NULL;
|
||||
|
||||
|
@ -154,11 +181,19 @@ glitz_egl_create_pbuffer_surface (EGLDisplay display,
|
|||
unsigned int height)
|
||||
{
|
||||
glitz_egl_screen_info_t *screen_info;
|
||||
glitz_int_drawable_format_t *iformat;
|
||||
|
||||
screen_info = glitz_egl_screen_info_get (display, screen);
|
||||
if (!screen_info)
|
||||
return NULL;
|
||||
|
||||
if (format->id >= screen_info->n_formats)
|
||||
return NULL;
|
||||
|
||||
iformat = &screen_info->formats[format->id];
|
||||
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK))
|
||||
return NULL;
|
||||
|
||||
return _glitz_egl_create_pbuffer_surface (screen_info, format,
|
||||
width, height);
|
||||
}
|
||||
|
@ -176,16 +211,19 @@ glitz_egl_destroy (void *abstract_drawable)
|
|||
* Last drawable? We have to destroy all fragment programs as this may
|
||||
* be our last chance to have a context current.
|
||||
*/
|
||||
glitz_egl_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT);
|
||||
glitz_program_map_fini (&surface->base.backend->gl,
|
||||
glitz_egl_push_current (abstract_drawable, NULL,
|
||||
GLITZ_CONTEXT_CURRENT);
|
||||
glitz_program_map_fini (surface->base.backend->gl,
|
||||
&surface->screen_info->program_map);
|
||||
glitz_egl_pop_current (abstract_drawable);
|
||||
}
|
||||
|
||||
if (eglGetCurrentSurface (0) == surface->egl_surface)
|
||||
eglMakeCurrent (surface->screen_info->display_info->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglMakeCurrent (surface->screen_info->display_info->egl_display,
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
eglQuerySurface (surface->screen_info->display_info->egl_display, surface->egl_surface,
|
||||
eglQuerySurface (surface->screen_info->display_info->egl_display,
|
||||
surface->egl_surface,
|
||||
EGL_SURFACE_TYPE, &value);
|
||||
if (value == EGL_PBUFFER_BIT)
|
||||
glitz_egl_pbuffer_destroy (surface->screen_info, surface->egl_surface);
|
||||
|
@ -193,11 +231,13 @@ glitz_egl_destroy (void *abstract_drawable)
|
|||
free (surface);
|
||||
}
|
||||
|
||||
void
|
||||
glitz_bool_t
|
||||
glitz_egl_swap_buffers (void *abstract_drawable)
|
||||
{
|
||||
glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable;
|
||||
|
||||
eglSwapBuffers (surface->screen_info->display_info->egl_display,
|
||||
surface->egl_surface);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
#include "glitz-egl.h"
|
||||
|
||||
#include "glitz_eglext.h"
|
||||
|
||||
#define GLITZ_EGL_FEATURE_MAKE_CURRENT_READ_MASK (1L << 2)
|
||||
#define GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK (1L << 3)
|
||||
#define GLITZ_EGL_FEATURE_MULTISAMPLE_MASK (1L << 4)
|
||||
|
@ -69,9 +67,6 @@ typedef struct _glitz_egl_context_t {
|
|||
glitz_format_id_t id;
|
||||
EGLConfig egl_config;
|
||||
glitz_backend_t backend;
|
||||
glitz_gl_int_t max_viewport_dims[2];
|
||||
glitz_gl_int_t max_texture_2d_size;
|
||||
glitz_gl_int_t max_texture_rect_size;
|
||||
glitz_bool_t initialized;
|
||||
} glitz_egl_context_t;
|
||||
|
||||
|
@ -79,8 +74,7 @@ struct _glitz_egl_screen_info_t {
|
|||
glitz_egl_display_info_t *display_info;
|
||||
int screen;
|
||||
int drawables;
|
||||
glitz_drawable_format_t *formats;
|
||||
EGLConfig *egl_config_ids;
|
||||
glitz_int_drawable_format_t *formats;
|
||||
int n_formats;
|
||||
glitz_egl_context_t **contexts;
|
||||
int n_contexts;
|
||||
|
@ -98,6 +92,8 @@ struct _glitz_egl_surface {
|
|||
glitz_egl_screen_info_t *screen_info;
|
||||
glitz_egl_context_t *context;
|
||||
EGLSurface egl_surface;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
extern void __internal_linkage
|
||||
|
@ -123,6 +119,11 @@ glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info,
|
|||
extern void __internal_linkage
|
||||
glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info);
|
||||
|
||||
extern glitz_bool_t __internal_linkage
|
||||
_glitz_egl_drawable_update_size (glitz_egl_surface_t *drawable,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
extern EGLSurface __internal_linkage
|
||||
glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info,
|
||||
EGLConfig egl_config,
|
||||
|
@ -139,7 +140,7 @@ glitz_egl_create_pbuffer (void *abstract_templ,
|
|||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
extern void __internal_linkage
|
||||
extern glitz_bool_t __internal_linkage
|
||||
glitz_egl_push_current (void *abstract_drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint);
|
||||
|
@ -157,14 +158,15 @@ glitz_egl_make_current_read (void *abstract_surface);
|
|||
extern void __internal_linkage
|
||||
glitz_egl_destroy (void *abstract_drawable);
|
||||
|
||||
extern void __internal_linkage
|
||||
extern glitz_bool_t __internal_linkage
|
||||
glitz_egl_swap_buffers (void *abstract_drawable);
|
||||
|
||||
/* Avoid unnecessary PLT entries. */
|
||||
|
||||
slim_hidden_proto(glitz_egl_init)
|
||||
slim_hidden_proto(glitz_egl_fini)
|
||||
slim_hidden_proto(glitz_egl_find_config)
|
||||
slim_hidden_proto(glitz_egl_find_window_config)
|
||||
slim_hidden_proto(glitz_egl_find_pbuffer_config)
|
||||
slim_hidden_proto(glitz_egl_create_surface)
|
||||
slim_hidden_proto(glitz_egl_create_pbuffer_surface)
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ glitz_composite (glitz_operator_t op,
|
|||
int i, texture_nr = -1;
|
||||
glitz_texture_t *stexture, *mtexture;
|
||||
glitz_texture_unit_t textures[3];
|
||||
glitz_texture_parameters_t param;
|
||||
glitz_box_t bounds;
|
||||
glitz_bool_t no_border_clamp;
|
||||
unsigned long flags;
|
||||
|
@ -91,6 +92,9 @@ glitz_composite (glitz_operator_t op,
|
|||
src = comp_op.src;
|
||||
mask = comp_op.mask;
|
||||
|
||||
param.border_color.red = param.border_color.green =
|
||||
param.border_color.blue = param.border_color.alpha = 0;
|
||||
|
||||
if (src)
|
||||
{
|
||||
stexture = glitz_surface_get_texture (src, 0);
|
||||
|
@ -152,37 +156,39 @@ glitz_composite (glitz_operator_t op,
|
|||
gl->matrix_mode (GLITZ_GL_MODELVIEW);
|
||||
|
||||
if (SURFACE_LINEAR_TRANSFORM_FILTER (mask))
|
||||
glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_LINEAR);
|
||||
param.filter[0] = GLITZ_GL_LINEAR;
|
||||
else
|
||||
glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_NEAREST);
|
||||
param.filter[0] = GLITZ_GL_NEAREST;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((dst->geometry.attributes &
|
||||
GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK) &&
|
||||
SURFACE_LINEAR_TRANSFORM_FILTER (mask))
|
||||
glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_LINEAR);
|
||||
param.filter[0] = GLITZ_GL_LINEAR;
|
||||
else
|
||||
glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_NEAREST);
|
||||
param.filter[0] = GLITZ_GL_NEAREST;
|
||||
}
|
||||
|
||||
if (SURFACE_REPEAT (mask))
|
||||
{
|
||||
if (SURFACE_MIRRORED (mask))
|
||||
glitz_texture_ensure_wrap (gl, mtexture,
|
||||
GLITZ_GL_MIRRORED_REPEAT);
|
||||
param.wrap[0] = GLITZ_GL_MIRRORED_REPEAT;
|
||||
else
|
||||
glitz_texture_ensure_wrap (gl, mtexture, GLITZ_GL_REPEAT);
|
||||
param.wrap[0] = GLITZ_GL_REPEAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (no_border_clamp || SURFACE_PAD (mask))
|
||||
glitz_texture_ensure_wrap (gl, mtexture,
|
||||
GLITZ_GL_CLAMP_TO_EDGE);
|
||||
param.wrap[0] = GLITZ_GL_CLAMP_TO_EDGE;
|
||||
else
|
||||
glitz_texture_ensure_wrap (gl, mtexture,
|
||||
GLITZ_GL_CLAMP_TO_BORDER);
|
||||
param.wrap[0] = GLITZ_GL_CLAMP_TO_BORDER;
|
||||
}
|
||||
|
||||
param.filter[1] = param.filter[0];
|
||||
param.wrap[1] = param.wrap[0];
|
||||
|
||||
glitz_texture_ensure_parameters (gl, mtexture, ¶m);
|
||||
}
|
||||
|
||||
if (stexture)
|
||||
|
@ -228,37 +234,39 @@ glitz_composite (glitz_operator_t op,
|
|||
gl->matrix_mode (GLITZ_GL_MODELVIEW);
|
||||
|
||||
if (SURFACE_LINEAR_TRANSFORM_FILTER (src))
|
||||
glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_LINEAR);
|
||||
param.filter[0] = GLITZ_GL_LINEAR;
|
||||
else
|
||||
glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_NEAREST);
|
||||
param.filter[0] = GLITZ_GL_NEAREST;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((dst->geometry.attributes &
|
||||
GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK) &&
|
||||
SURFACE_LINEAR_TRANSFORM_FILTER (src))
|
||||
glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_LINEAR);
|
||||
param.filter[0] = GLITZ_GL_LINEAR;
|
||||
else
|
||||
glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_NEAREST);
|
||||
param.filter[0] = GLITZ_GL_NEAREST;
|
||||
}
|
||||
|
||||
if (SURFACE_REPEAT (src))
|
||||
{
|
||||
if (SURFACE_MIRRORED (src))
|
||||
glitz_texture_ensure_wrap (gl, stexture,
|
||||
GLITZ_GL_MIRRORED_REPEAT);
|
||||
param.wrap[0] = GLITZ_GL_MIRRORED_REPEAT;
|
||||
else
|
||||
glitz_texture_ensure_wrap (gl, stexture, GLITZ_GL_REPEAT);
|
||||
param.wrap[0] = GLITZ_GL_REPEAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (no_border_clamp || SURFACE_PAD (src))
|
||||
glitz_texture_ensure_wrap (gl, stexture,
|
||||
GLITZ_GL_CLAMP_TO_EDGE);
|
||||
param.wrap[0] = GLITZ_GL_CLAMP_TO_EDGE;
|
||||
else
|
||||
glitz_texture_ensure_wrap (gl, stexture,
|
||||
GLITZ_GL_CLAMP_TO_BORDER);
|
||||
param.wrap[0] = GLITZ_GL_CLAMP_TO_BORDER;
|
||||
}
|
||||
|
||||
param.filter[1] = param.filter[0];
|
||||
param.wrap[1] = param.wrap[0];
|
||||
|
||||
glitz_texture_ensure_parameters (gl, stexture, ¶m);
|
||||
}
|
||||
|
||||
glitz_geometry_enable (gl, dst, &bounds);
|
||||
|
@ -395,12 +403,15 @@ glitz_copy_area (glitz_surface_t *src,
|
|||
return;
|
||||
|
||||
status = GLITZ_STATUS_NOT_SUPPORTED;
|
||||
if ((!src->attached) ||
|
||||
(src->attached == dst->attached) ||
|
||||
(dst->box.x2 * dst->box.y2 >= src->box.x2 * src->box.y2))
|
||||
{
|
||||
if (glitz_surface_push_current (dst, GLITZ_DRAWABLE_CURRENT))
|
||||
{
|
||||
int target_height = SURFACE_DRAWABLE_HEIGHT (dst);
|
||||
int source_height = SURFACE_DRAWABLE_HEIGHT (src);
|
||||
int target_height = dst->attached->height;
|
||||
|
||||
if (src == dst || (dst->attached && src->attached == dst->attached))
|
||||
if (src->attached == dst->attached)
|
||||
{
|
||||
glitz_box_t box, *clip = dst->clip;
|
||||
int n_clip = dst->n_clip;
|
||||
|
@ -446,7 +457,7 @@ glitz_copy_area (glitz_surface_t *src,
|
|||
box.y2 - box.y1);
|
||||
|
||||
gl->copy_pixels (x_src + (box.x1 - x_dst),
|
||||
source_height -
|
||||
target_height -
|
||||
(y_src + (box.y2 - y_dst)),
|
||||
box.x2 - box.x1, box.y2 - box.y1,
|
||||
GLITZ_GL_COLOR);
|
||||
|
@ -466,21 +477,29 @@ glitz_copy_area (glitz_surface_t *src,
|
|||
texture = glitz_surface_get_texture (src, 0);
|
||||
if (texture)
|
||||
{
|
||||
glitz_texture_parameters_t param;
|
||||
unsigned long mask;
|
||||
|
||||
mask = GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK;
|
||||
|
||||
glitz_texture_bind (gl, texture);
|
||||
|
||||
glitz_texture_set_tex_gen (gl, texture, NULL,
|
||||
x_dst - x_src,
|
||||
y_dst - y_src,
|
||||
GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK,
|
||||
mask,
|
||||
NULL);
|
||||
|
||||
gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE,
|
||||
gl->tex_env_f (GLITZ_GL_TEXTURE_ENV,
|
||||
GLITZ_GL_TEXTURE_ENV_MODE,
|
||||
GLITZ_GL_REPLACE);
|
||||
|
||||
gl->color_4us (0x0, 0x0, 0x0, 0xffff);
|
||||
|
||||
glitz_texture_ensure_wrap (gl, texture,
|
||||
GLITZ_GL_CLAMP_TO_EDGE);
|
||||
glitz_texture_ensure_filter (gl, texture, GLITZ_GL_NEAREST);
|
||||
param.filter[0] = param.filter[1] = GLITZ_GL_CLAMP_TO_EDGE;
|
||||
param.wrap[0] = param.wrap[1] = GLITZ_GL_NEAREST;
|
||||
|
||||
glitz_texture_ensure_parameters (gl, texture, ¶m);
|
||||
|
||||
glitz_set_operator (gl, GLITZ_OPERATOR_SRC);
|
||||
|
||||
|
@ -493,10 +512,11 @@ glitz_copy_area (glitz_surface_t *src,
|
|||
int n_clip = dst->n_clip;
|
||||
|
||||
ptr = malloc (n_clip * 8 * sizeof (glitz_float_t));
|
||||
if (!ptr) {
|
||||
if (!ptr)
|
||||
{
|
||||
mask = GLITZ_STATUS_NO_MEMORY_MASK;
|
||||
glitz_surface_pop_current (dst);
|
||||
glitz_surface_status_add (dst,
|
||||
GLITZ_STATUS_NO_MEMORY_MASK);
|
||||
glitz_surface_status_add (dst, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -568,8 +588,9 @@ glitz_copy_area (glitz_surface_t *src,
|
|||
}
|
||||
|
||||
glitz_surface_pop_current (dst);
|
||||
}
|
||||
|
||||
if (status && src->attached)
|
||||
if (status)
|
||||
{
|
||||
if (glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT))
|
||||
{
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
#endif
|
||||
|
||||
#define GLITZ_MAJOR 0
|
||||
#define GLITZ_MINOR 4
|
||||
#define GLITZ_REVISION 4
|
||||
#define GLITZ_MINOR 5
|
||||
#define GLITZ_REVISION 0
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
|
@ -51,6 +51,9 @@ typedef float glitz_float_t;
|
|||
typedef double glitz_double_t;
|
||||
typedef int glitz_fixed16_16_t;
|
||||
|
||||
typedef struct _glitz_drawable glitz_drawable_t;
|
||||
typedef struct _glitz_surface glitz_surface_t;
|
||||
|
||||
typedef struct _glitz_rectangle_t {
|
||||
short x, y;
|
||||
unsigned short width, height;
|
||||
|
@ -137,6 +140,9 @@ typedef enum {
|
|||
#define GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK (1L << 15)
|
||||
#define GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK (1L << 16)
|
||||
|
||||
|
||||
/* glitz_format.c */
|
||||
|
||||
typedef enum {
|
||||
GLITZ_STANDARD_ARGB32,
|
||||
GLITZ_STANDARD_RGB24,
|
||||
|
@ -159,6 +165,54 @@ typedef struct _glitz_color_format_t {
|
|||
unsigned short alpha_size;
|
||||
} glitz_color_format_t;
|
||||
|
||||
#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 5)
|
||||
#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 6)
|
||||
#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 7)
|
||||
#define GLITZ_FORMAT_SAMPLES_MASK (1L << 8)
|
||||
|
||||
typedef struct _glitz_drawable_format_t {
|
||||
glitz_format_id_t id;
|
||||
glitz_color_format_t color;
|
||||
unsigned short depth_size;
|
||||
unsigned short stencil_size;
|
||||
unsigned short samples;
|
||||
glitz_bool_t doublebuffer;
|
||||
} glitz_drawable_format_t;
|
||||
|
||||
#define GLITZ_FORMAT_TYPE_MASK (1L << 5)
|
||||
|
||||
typedef enum {
|
||||
GLITZ_FORMAT_TYPE_COLOR
|
||||
} glitz_format_type_t;
|
||||
|
||||
typedef struct _glitz_format_t {
|
||||
glitz_format_id_t id;
|
||||
glitz_format_type_t type;
|
||||
glitz_color_format_t color;
|
||||
} glitz_format_t;
|
||||
|
||||
glitz_format_t *
|
||||
glitz_find_standard_format (glitz_drawable_t *drawable,
|
||||
glitz_format_name_t format_name);
|
||||
|
||||
glitz_format_t *
|
||||
glitz_find_format (glitz_drawable_t *drawable,
|
||||
unsigned long mask,
|
||||
const glitz_format_t *templ,
|
||||
int count);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_find_drawable_format (glitz_drawable_t *other,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_find_pbuffer_format (glitz_drawable_t *other,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count);
|
||||
|
||||
|
||||
/* glitz_status.c */
|
||||
|
||||
|
@ -176,40 +230,16 @@ glitz_status_string (glitz_status_t status);
|
|||
|
||||
/* glitz_drawable.c */
|
||||
|
||||
typedef struct _glitz_drawable glitz_drawable_t;
|
||||
|
||||
typedef enum {
|
||||
GLITZ_DRAWABLE_BUFFER_FRONT_COLOR,
|
||||
GLITZ_DRAWABLE_BUFFER_BACK_COLOR
|
||||
} glitz_drawable_buffer_t;
|
||||
|
||||
#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 5)
|
||||
#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 6)
|
||||
#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 7)
|
||||
#define GLITZ_FORMAT_SAMPLES_MASK (1L << 8)
|
||||
#define GLITZ_FORMAT_WINDOW_MASK (1L << 9)
|
||||
#define GLITZ_FORMAT_PBUFFER_MASK (1L << 10)
|
||||
|
||||
typedef struct _glitz_drawable_types_t {
|
||||
glitz_bool_t window;
|
||||
glitz_bool_t pbuffer;
|
||||
} glitz_drawable_types_t;
|
||||
|
||||
typedef struct _glitz_drawable_format_t {
|
||||
glitz_format_id_t id;
|
||||
glitz_color_format_t color;
|
||||
unsigned short depth_size;
|
||||
unsigned short stencil_size;
|
||||
unsigned short samples;
|
||||
glitz_bool_t doublebuffer;
|
||||
glitz_drawable_types_t types;
|
||||
} glitz_drawable_format_t;
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_find_similar_drawable_format (glitz_drawable_t *other,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count);
|
||||
glitz_drawable_t *
|
||||
glitz_create_drawable (glitz_drawable_t *other,
|
||||
glitz_drawable_format_t *format,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
glitz_drawable_t *
|
||||
glitz_create_pbuffer_drawable (glitz_drawable_t *other,
|
||||
|
@ -234,6 +264,13 @@ glitz_drawable_get_width (glitz_drawable_t *drawable);
|
|||
unsigned int
|
||||
glitz_drawable_get_height (glitz_drawable_t *drawable);
|
||||
|
||||
void
|
||||
glitz_drawable_swap_buffer_region (glitz_drawable_t *drawable,
|
||||
int x_origin,
|
||||
int y_origin,
|
||||
glitz_box_t *box,
|
||||
int n_box);
|
||||
|
||||
void
|
||||
glitz_drawable_swap_buffers (glitz_drawable_t *drawable);
|
||||
|
||||
|
@ -250,35 +287,8 @@ glitz_drawable_format_t *
|
|||
glitz_drawable_get_format (glitz_drawable_t *drawable);
|
||||
|
||||
|
||||
/* glitz_format.c */
|
||||
|
||||
#define GLITZ_FORMAT_TYPE_MASK (1L << 5)
|
||||
|
||||
typedef enum {
|
||||
GLITZ_FORMAT_TYPE_COLOR
|
||||
} glitz_format_type_t;
|
||||
|
||||
typedef struct _glitz_format_t {
|
||||
glitz_format_id_t id;
|
||||
glitz_format_type_t type;
|
||||
glitz_color_format_t color;
|
||||
} glitz_format_t;
|
||||
|
||||
glitz_format_t *
|
||||
glitz_find_standard_format (glitz_drawable_t *drawable,
|
||||
glitz_format_name_t format_name);
|
||||
|
||||
glitz_format_t *
|
||||
glitz_find_format (glitz_drawable_t *drawable,
|
||||
unsigned long mask,
|
||||
const glitz_format_t *templ,
|
||||
int count);
|
||||
|
||||
|
||||
/* glitz_surface.c */
|
||||
|
||||
typedef struct _glitz_surface glitz_surface_t;
|
||||
|
||||
#define GLITZ_SURFACE_UNNORMALIZED_MASK (1L << 0)
|
||||
|
||||
typedef struct _glitz_surface_attributes_t {
|
||||
|
@ -302,9 +312,7 @@ glitz_surface_reference (glitz_surface_t *surface);
|
|||
void
|
||||
glitz_surface_attach (glitz_surface_t *surface,
|
||||
glitz_drawable_t *drawable,
|
||||
glitz_drawable_buffer_t buffer,
|
||||
int x,
|
||||
int y);
|
||||
glitz_drawable_buffer_t buffer);
|
||||
|
||||
void
|
||||
glitz_surface_detach (glitz_surface_t *surface);
|
||||
|
@ -375,6 +383,65 @@ glitz_bool_t
|
|||
glitz_surface_valid_target (glitz_surface_t *surface);
|
||||
|
||||
|
||||
/* glitz_texture.c */
|
||||
|
||||
typedef struct _glitz_texture_object glitz_texture_object_t;
|
||||
|
||||
glitz_texture_object_t *
|
||||
glitz_texture_object_create (glitz_surface_t *surface);
|
||||
|
||||
void
|
||||
glitz_texture_object_destroy (glitz_texture_object_t *texture);
|
||||
|
||||
void
|
||||
glitz_texture_object_reference (glitz_texture_object_t *texture);
|
||||
|
||||
typedef enum {
|
||||
GLITZ_TEXTURE_FILTER_TYPE_MAG = 0,
|
||||
GLITZ_TEXTURE_FILTER_TYPE_MIN = 1
|
||||
} glitz_texture_filter_type_t;
|
||||
|
||||
typedef enum {
|
||||
GLITZ_TEXTURE_FILTER_NEAREST = 0,
|
||||
GLITZ_TEXTURE_FILTER_LINEAR = 1
|
||||
} glitz_texture_filter_t;
|
||||
|
||||
void
|
||||
glitz_texture_object_set_filter (glitz_texture_object_t *texture,
|
||||
glitz_texture_filter_type_t type,
|
||||
glitz_texture_filter_t filter);
|
||||
|
||||
typedef enum {
|
||||
GLITZ_TEXTURE_WRAP_TYPE_S = 0,
|
||||
GLITZ_TEXTURE_WRAP_TYPE_T = 1
|
||||
} glitz_texture_wrap_type_t;
|
||||
|
||||
typedef enum {
|
||||
GLITZ_TEXTURE_WRAP_CLAMP = 0,
|
||||
GLITZ_TEXTURE_WRAP_CLAMP_TO_EDGE = 1,
|
||||
GLITZ_TEXTURE_WRAP_CLAMP_TO_BORDER = 2,
|
||||
GLITZ_TEXTURE_WRAP_REPEAT = 3,
|
||||
GLITZ_TEXTURE_WRAP_MIRRORED_REPEAT = 4
|
||||
} glitz_texture_wrap_t;
|
||||
|
||||
void
|
||||
glitz_texture_object_set_wrap (glitz_texture_object_t *texture,
|
||||
glitz_texture_wrap_type_t type,
|
||||
glitz_texture_wrap_t wrap);
|
||||
|
||||
void
|
||||
glitz_texture_object_set_border_color (glitz_texture_object_t *texture,
|
||||
glitz_color_t *color);
|
||||
|
||||
typedef enum {
|
||||
GLITZ_TEXTURE_TARGET_2D = 0,
|
||||
GLITZ_TEXTURE_TARGET_RECT = 1
|
||||
} glitz_texture_target_t;
|
||||
|
||||
glitz_texture_target_t
|
||||
glitz_texture_object_get_target (glitz_texture_object_t *texture);
|
||||
|
||||
|
||||
/* glitz_context.c */
|
||||
|
||||
typedef struct _glitz_context glitz_context_t;
|
||||
|
@ -382,6 +449,7 @@ typedef struct _glitz_context glitz_context_t;
|
|||
glitz_context_t *
|
||||
glitz_context_create (glitz_drawable_t *drawable,
|
||||
glitz_drawable_format_t *format);
|
||||
|
||||
void
|
||||
glitz_context_destroy (glitz_context_t *context);
|
||||
|
||||
|
@ -407,11 +475,12 @@ glitz_context_get_proc_address (glitz_context_t *context,
|
|||
const char *name);
|
||||
|
||||
void
|
||||
glitz_context_make_current (glitz_context_t *context);
|
||||
glitz_context_make_current (glitz_context_t *context,
|
||||
glitz_drawable_t *drawable);
|
||||
|
||||
void
|
||||
glitz_context_bind_texture (glitz_context_t *context,
|
||||
glitz_surface_t *surface);
|
||||
glitz_texture_object_t *texture);
|
||||
|
||||
|
||||
/* glitz_rect.c */
|
||||
|
|
|
@ -176,7 +176,8 @@ glitz_pixel_buffer_create (glitz_drawable_t *drawable,
|
|||
break;
|
||||
}
|
||||
|
||||
if (drawable->backend->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK)
|
||||
if (drawable->backend->feature_mask &
|
||||
GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK)
|
||||
status = _glitz_buffer_init (buffer, drawable, data, size, hint);
|
||||
else
|
||||
status = _glitz_buffer_init (buffer, NULL, data, size, hint);
|
||||
|
@ -219,7 +220,7 @@ glitz_buffer_destroy (glitz_buffer_t *buffer)
|
|||
if (buffer->drawable) {
|
||||
buffer->drawable->backend->push_current (buffer->drawable, NULL,
|
||||
GLITZ_ANY_CONTEXT_CURRENT);
|
||||
buffer->drawable->backend->gl.delete_buffers (1, &buffer->name);
|
||||
buffer->drawable->backend->gl->delete_buffers (1, &buffer->name);
|
||||
buffer->drawable->backend->pop_current (buffer->drawable);
|
||||
glitz_drawable_destroy (buffer->drawable);
|
||||
} else if (buffer->owns_data)
|
||||
|
@ -347,7 +348,7 @@ glitz_buffer_bind (glitz_buffer_t *buffer,
|
|||
glitz_gl_enum_t target)
|
||||
{
|
||||
if (buffer->drawable) {
|
||||
buffer->drawable->backend->gl.bind_buffer (target, buffer->name);
|
||||
buffer->drawable->backend->gl->bind_buffer (target, buffer->name);
|
||||
buffer->target = target;
|
||||
|
||||
return NULL;
|
||||
|
@ -360,5 +361,5 @@ void
|
|||
glitz_buffer_unbind (glitz_buffer_t *buffer)
|
||||
{
|
||||
if (buffer->drawable)
|
||||
buffer->drawable->backend->gl.bind_buffer (buffer->target, 0);
|
||||
buffer->drawable->backend->gl->bind_buffer (buffer->target, 0);
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ _glitz_combine_argb_argbc (glitz_composite_op_t *op)
|
|||
op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND2_RGB,
|
||||
GLITZ_GL_SRC_ALPHA);
|
||||
|
||||
/* we don't care about the alpha channel, so lets do something (simple?) */
|
||||
/* we don't care about the alpha channel */
|
||||
op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA,
|
||||
GLITZ_GL_REPLACE);
|
||||
op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA,
|
||||
|
@ -346,7 +346,8 @@ _glitz_combine_solid_solidc (glitz_composite_op_t *op)
|
|||
op->gl->blend_func (GLITZ_GL_CONSTANT_COLOR, GLITZ_GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
if (op->solid->alpha > 0)
|
||||
op->gl->blend_color ((glitz_gl_clampf_t) op->solid->red / op->solid->alpha,
|
||||
op->gl->blend_color ((glitz_gl_clampf_t)
|
||||
op->solid->red / op->solid->alpha,
|
||||
(glitz_gl_clampf_t)
|
||||
op->solid->green / op->solid->alpha,
|
||||
(glitz_gl_clampf_t)
|
||||
|
@ -489,12 +490,12 @@ glitz_composite_op_init (glitz_composite_op_t *op,
|
|||
|
||||
if (dst->attached)
|
||||
{
|
||||
op->gl = &dst->attached->backend->gl;
|
||||
op->gl = dst->attached->backend->gl;
|
||||
feature_mask = dst->attached->backend->feature_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
op->gl = &dst->drawable->backend->gl;
|
||||
op->gl = dst->drawable->backend->gl;
|
||||
feature_mask = dst->drawable->backend->feature_mask;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,21 +107,75 @@ glitz_context_get_proc_address (glitz_context_t *context,
|
|||
slim_hidden_def(glitz_context_get_proc_address);
|
||||
|
||||
void
|
||||
glitz_context_make_current (glitz_context_t *context)
|
||||
glitz_context_make_current (glitz_context_t *context,
|
||||
glitz_drawable_t *drawable)
|
||||
{
|
||||
context->drawable->backend->make_current (context, context->drawable);
|
||||
if (drawable != context->drawable)
|
||||
{
|
||||
glitz_drawable_reference (drawable);
|
||||
glitz_drawable_destroy (context->drawable);
|
||||
context->drawable = drawable;
|
||||
}
|
||||
|
||||
if (drawable->front)
|
||||
{
|
||||
if (REGION_NOTEMPTY (&drawable->front->drawable_damage))
|
||||
{
|
||||
glitz_surface_push_current (drawable->front,
|
||||
GLITZ_DRAWABLE_CURRENT);
|
||||
glitz_surface_pop_current (drawable->front);
|
||||
}
|
||||
|
||||
glitz_surface_damage (drawable->front, NULL,
|
||||
GLITZ_DAMAGE_TEXTURE_MASK |
|
||||
GLITZ_DAMAGE_SOLID_MASK);
|
||||
}
|
||||
|
||||
if (drawable->back)
|
||||
{
|
||||
if (REGION_NOTEMPTY (&drawable->back->drawable_damage))
|
||||
{
|
||||
glitz_surface_push_current (drawable->back,
|
||||
GLITZ_DRAWABLE_CURRENT);
|
||||
glitz_surface_pop_current (drawable->back);
|
||||
}
|
||||
|
||||
glitz_surface_damage (drawable->back, NULL,
|
||||
GLITZ_DAMAGE_TEXTURE_MASK |
|
||||
GLITZ_DAMAGE_SOLID_MASK);
|
||||
}
|
||||
|
||||
drawable->backend->make_current (drawable, context);
|
||||
}
|
||||
slim_hidden_def(glitz_context_make_current);
|
||||
|
||||
void
|
||||
glitz_context_bind_texture (glitz_context_t *context,
|
||||
glitz_surface_t *surface)
|
||||
glitz_texture_object_t *texture)
|
||||
{
|
||||
glitz_gl_proc_address_list_t *gl = &context->drawable->backend->gl;
|
||||
glitz_gl_proc_address_list_t *gl = context->drawable->backend->gl;
|
||||
|
||||
if (!surface->texture.name)
|
||||
gl->gen_textures (1, &surface->texture.name);
|
||||
if (REGION_NOTEMPTY (&texture->surface->texture_damage))
|
||||
{
|
||||
glitz_lose_current_function_t lose_current;
|
||||
|
||||
gl->bind_texture (surface->texture.target, surface->texture.name);
|
||||
lose_current = context->lose_current;
|
||||
context->lose_current = 0;
|
||||
|
||||
glitz_surface_push_current (texture->surface, GLITZ_CONTEXT_CURRENT);
|
||||
_glitz_surface_sync_texture (texture->surface);
|
||||
glitz_surface_pop_current (texture->surface);
|
||||
|
||||
context->lose_current = lose_current;
|
||||
|
||||
glitz_context_make_current (context, context->drawable);
|
||||
}
|
||||
|
||||
gl->bind_texture (texture->surface->texture.target,
|
||||
texture->surface->texture.name);
|
||||
|
||||
glitz_texture_ensure_parameters (gl,
|
||||
&texture->surface->texture,
|
||||
&texture->param);
|
||||
}
|
||||
slim_hidden_def(glitz_context_bind_texture);
|
||||
|
|
|
@ -29,17 +29,68 @@
|
|||
|
||||
#include "glitzint.h"
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_find_similar_drawable_format (glitz_drawable_t *other,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count)
|
||||
void
|
||||
_glitz_drawable_init (glitz_drawable_t *drawable,
|
||||
glitz_int_drawable_format_t *format,
|
||||
glitz_backend_t *backend,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return glitz_drawable_format_find (other->backend->drawable_formats,
|
||||
other->backend->n_drawable_formats,
|
||||
mask, templ, count);
|
||||
drawable->ref_count = 1;
|
||||
|
||||
drawable->format = format;
|
||||
drawable->backend = backend;
|
||||
|
||||
drawable->width = width;
|
||||
drawable->height = height;
|
||||
|
||||
drawable->front = NULL;
|
||||
drawable->back = NULL;
|
||||
|
||||
drawable->viewport.x = -32767;
|
||||
drawable->viewport.y = -32767;
|
||||
drawable->viewport.width = 65535;
|
||||
drawable->viewport.height = 65535;
|
||||
|
||||
drawable->update_all = 1;
|
||||
}
|
||||
slim_hidden_def(glitz_find_similar_drawable_format);
|
||||
|
||||
static glitz_bool_t
|
||||
_glitz_drawable_size_check (glitz_drawable_t *other,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
if (width == 0 || height == 0)
|
||||
return 0;
|
||||
|
||||
if (width > other->backend->max_viewport_dims[0] ||
|
||||
height > other->backend->max_viewport_dims[1])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
glitz_drawable_t *
|
||||
glitz_create_drawable (glitz_drawable_t *other,
|
||||
glitz_drawable_format_t *format,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
glitz_int_drawable_format_t *iformat;
|
||||
|
||||
if (!_glitz_drawable_size_check (other, width, height))
|
||||
return NULL;
|
||||
|
||||
if (format->id >= other->backend->n_drawable_formats)
|
||||
return NULL;
|
||||
|
||||
iformat = &other->backend->drawable_formats[format->id];
|
||||
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_FBO_MASK))
|
||||
return NULL;
|
||||
|
||||
return _glitz_fbo_drawable_create (other, iformat, width, height);
|
||||
}
|
||||
slim_hidden_def(glitz_create_drawable);
|
||||
|
||||
glitz_drawable_t *
|
||||
glitz_create_pbuffer_drawable (glitz_drawable_t *other,
|
||||
|
@ -47,7 +98,16 @@ glitz_create_pbuffer_drawable (glitz_drawable_t *other,
|
|||
unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
if (!format->types.pbuffer)
|
||||
glitz_int_drawable_format_t *iformat;
|
||||
|
||||
if (!_glitz_drawable_size_check (other, width, height))
|
||||
return NULL;
|
||||
|
||||
if (format->id >= other->backend->n_drawable_formats)
|
||||
return NULL;
|
||||
|
||||
iformat = &other->backend->drawable_formats[format->id];
|
||||
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK))
|
||||
return NULL;
|
||||
|
||||
return other->backend->create_pbuffer (other, format, width, height);
|
||||
|
@ -106,11 +166,144 @@ glitz_drawable_get_height (glitz_drawable_t *drawable)
|
|||
}
|
||||
slim_hidden_def(glitz_drawable_get_height);
|
||||
|
||||
void
|
||||
glitz_drawable_swap_buffer_region (glitz_drawable_t *drawable,
|
||||
int x_origin,
|
||||
int y_origin,
|
||||
glitz_box_t *box,
|
||||
int n_box)
|
||||
{
|
||||
if (drawable->format->d.doublebuffer && n_box)
|
||||
{
|
||||
glitz_box_t rect;
|
||||
glitz_surface_t *surface = NULL;
|
||||
int x_pos, y_pos;
|
||||
int x, y, w, h;
|
||||
|
||||
GLITZ_GL_DRAWABLE (drawable);
|
||||
|
||||
if (n_box == 1)
|
||||
{
|
||||
rect.x1 = x_origin + box->x1;
|
||||
rect.y1 = y_origin + box->y1;
|
||||
rect.x2 = x_origin + box->x2;
|
||||
rect.y2 = y_origin + box->y2;
|
||||
|
||||
if (rect.x1 <= 0 &&
|
||||
rect.y1 <= 0 &&
|
||||
rect.x2 >= drawable->width &&
|
||||
rect.x2 >= drawable->height)
|
||||
{
|
||||
if (drawable->backend->swap_buffers (drawable))
|
||||
{
|
||||
if (drawable->front)
|
||||
{
|
||||
REGION_EMPTY (&drawable->front->drawable_damage);
|
||||
glitz_surface_damage (drawable->front, NULL,
|
||||
GLITZ_DAMAGE_TEXTURE_MASK |
|
||||
GLITZ_DAMAGE_SOLID_MASK);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drawable->front)
|
||||
{
|
||||
if (glitz_surface_push_current (drawable->front,
|
||||
GLITZ_DRAWABLE_CURRENT))
|
||||
surface = drawable->front;
|
||||
}
|
||||
|
||||
if (!surface)
|
||||
{
|
||||
if (drawable->backend->push_current (drawable, NULL,
|
||||
GLITZ_DRAWABLE_CURRENT))
|
||||
{
|
||||
drawable->update_all = 1;
|
||||
|
||||
gl->viewport (0, 0, drawable->width, drawable->height);
|
||||
gl->matrix_mode (GLITZ_GL_PROJECTION);
|
||||
gl->load_identity ();
|
||||
gl->ortho (0.0, drawable->width, 0.0,
|
||||
drawable->height, -1.0, 1.0);
|
||||
gl->matrix_mode (GLITZ_GL_MODELVIEW);
|
||||
gl->load_identity ();
|
||||
gl->scale_f (1.0f, -1.0f, 1.0f);
|
||||
gl->translate_f (0.0f, -drawable->height, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawable->backend->pop_current (drawable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gl->disable (GLITZ_GL_DITHER);
|
||||
|
||||
gl->read_buffer (GLITZ_GL_BACK);
|
||||
gl->draw_buffer (GLITZ_GL_FRONT);
|
||||
|
||||
glitz_set_operator (gl, GLITZ_OPERATOR_SRC);
|
||||
|
||||
x_pos = 0;
|
||||
y_pos = 0;
|
||||
|
||||
glitz_set_raster_pos (gl, x_pos, y_pos);
|
||||
|
||||
while (n_box--)
|
||||
{
|
||||
rect.x1 = x_origin + box->x1;
|
||||
rect.y1 = y_origin + box->y1;
|
||||
rect.x2 = x_origin + box->x2;
|
||||
rect.y2 = y_origin + box->y2;
|
||||
|
||||
if (rect.x1 < rect.x2 && rect.y1 < rect.y2)
|
||||
{
|
||||
x = rect.x1;
|
||||
y = drawable->height - rect.y2;
|
||||
w = rect.x2 - rect.x1;
|
||||
h = rect.y2 - rect.y1;
|
||||
|
||||
if (x != x_pos || y != y_pos)
|
||||
{
|
||||
gl->bitmap (0, 0, 0, 0, x - x_pos, y - y_pos, NULL);
|
||||
|
||||
x_pos = x;
|
||||
y_pos = y;
|
||||
}
|
||||
|
||||
gl->scissor (x, y, w, h);
|
||||
gl->copy_pixels (x, y, w, h, GLITZ_GL_COLOR);
|
||||
|
||||
if (surface)
|
||||
glitz_surface_damage (surface, &rect,
|
||||
GLITZ_DAMAGE_TEXTURE_MASK |
|
||||
GLITZ_DAMAGE_SOLID_MASK);
|
||||
|
||||
box++;
|
||||
}
|
||||
}
|
||||
drawable->backend->gl->finish ();
|
||||
|
||||
if (surface)
|
||||
glitz_surface_pop_current (surface);
|
||||
else
|
||||
drawable->backend->pop_current (drawable);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_drawable_swap_buffers (glitz_drawable_t *drawable)
|
||||
{
|
||||
if (drawable->format->doublebuffer)
|
||||
drawable->backend->swap_buffers (drawable);
|
||||
glitz_box_t box;
|
||||
|
||||
box.x1 = 0;
|
||||
box.y1 = 0;
|
||||
box.x2 = drawable->width;
|
||||
box.y2 = drawable->height;
|
||||
|
||||
glitz_drawable_swap_buffer_region (drawable, 0, 0, &box, 1);
|
||||
}
|
||||
slim_hidden_def(glitz_drawable_swap_buffers);
|
||||
|
||||
|
@ -118,7 +311,7 @@ void
|
|||
glitz_drawable_flush (glitz_drawable_t *drawable)
|
||||
{
|
||||
drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT);
|
||||
drawable->backend->gl.flush ();
|
||||
drawable->backend->gl->flush ();
|
||||
drawable->backend->pop_current (drawable);
|
||||
}
|
||||
slim_hidden_def(glitz_drawable_flush);
|
||||
|
@ -127,7 +320,7 @@ void
|
|||
glitz_drawable_finish (glitz_drawable_t *drawable)
|
||||
{
|
||||
drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT);
|
||||
drawable->backend->gl.finish ();
|
||||
drawable->backend->gl->finish ();
|
||||
drawable->backend->pop_current (drawable);
|
||||
}
|
||||
slim_hidden_def(glitz_drawable_finish);
|
||||
|
@ -142,6 +335,6 @@ slim_hidden_def(glitz_drawable_get_features);
|
|||
glitz_drawable_format_t *
|
||||
glitz_drawable_get_format (glitz_drawable_t *drawable)
|
||||
{
|
||||
return drawable->format;
|
||||
return &drawable->format->d;
|
||||
}
|
||||
slim_hidden_def(glitz_drawable_get_format);
|
||||
|
|
|
@ -266,9 +266,12 @@ glitz_filter_set_params (glitz_surface_t *surface,
|
|||
x_default = (surface->box.x2 * i) / (glitz_float_t) size;
|
||||
y_default = (surface->box.y2 * i) / (glitz_float_t) size;
|
||||
|
||||
_glitz_filter_params_set (&vecs[i].v[2], o_default, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[0], x_default, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[1], y_default, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[2], o_default, ¶ms,
|
||||
&n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[0], x_default, ¶ms,
|
||||
&n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[1], y_default, ¶ms,
|
||||
&n_params);
|
||||
|
||||
glitz_clamp_value (&vecs[i].v[2], 0.0f, 1.0f);
|
||||
glitz_clamp_value (&vecs[i].v[0], 0.0f, surface->box.x2 - 1.0f);
|
||||
|
@ -301,7 +304,7 @@ glitz_filter_set_params (glitz_surface_t *surface,
|
|||
if (diff != 0.0f)
|
||||
vecs[i].v[3] = 1.0f / diff;
|
||||
else
|
||||
vecs[i].v[3] = 2147483647.0f; /* should be FLT_MAX, but this will do */
|
||||
vecs[i].v[3] = 2147483647.0f;
|
||||
}
|
||||
break;
|
||||
case GLITZ_FILTER_BILINEAR:
|
||||
|
@ -339,24 +342,31 @@ glitz_filter_set_type (glitz_surface_t *surface,
|
|||
case GLITZ_FILTER_LINEAR_GRADIENT:
|
||||
if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
|
||||
if (SURFACE_MIRRORED (surface))
|
||||
surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_REFLECT;
|
||||
surface->filter_params->fp_type =
|
||||
GLITZ_FP_LINEAR_GRADIENT_REFLECT;
|
||||
else
|
||||
surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_REPEAT;
|
||||
surface->filter_params->fp_type =
|
||||
GLITZ_FP_LINEAR_GRADIENT_REPEAT;
|
||||
} else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
|
||||
surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_NEAREST;
|
||||
surface->filter_params->fp_type =
|
||||
GLITZ_FP_LINEAR_GRADIENT_NEAREST;
|
||||
} else
|
||||
surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT;
|
||||
surface->filter_params->fp_type =
|
||||
GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT;
|
||||
break;
|
||||
case GLITZ_FILTER_RADIAL_GRADIENT:
|
||||
if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
|
||||
if (SURFACE_MIRRORED (surface))
|
||||
surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_REFLECT;
|
||||
surface->filter_params->fp_type =
|
||||
GLITZ_FP_RADIAL_GRADIENT_REFLECT;
|
||||
else
|
||||
surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_REPEAT;
|
||||
surface->filter_params->fp_type =
|
||||
GLITZ_FP_RADIAL_GRADIENT_REPEAT;
|
||||
} else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
|
||||
surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_NEAREST;
|
||||
} else
|
||||
surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT;
|
||||
surface->filter_params->fp_type =
|
||||
GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT;
|
||||
break;
|
||||
case GLITZ_FILTER_BILINEAR:
|
||||
case GLITZ_FILTER_NEAREST:
|
||||
|
@ -406,7 +416,8 @@ glitz_filter_enable (glitz_surface_t *surface,
|
|||
j = 1;
|
||||
|
||||
for (i = 0; i < surface->filter_params->id; i++, vec++)
|
||||
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i + j, vec->v);
|
||||
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM,
|
||||
i + j, vec->v);
|
||||
|
||||
if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT ||
|
||||
fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) {
|
||||
|
@ -415,7 +426,8 @@ glitz_filter_enable (glitz_surface_t *surface,
|
|||
v.v[0] = v.v[1] = -1.0f;
|
||||
v.v[2] = v.v[3] = 1.0f;
|
||||
|
||||
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i + j, v.v);
|
||||
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM,
|
||||
i + j, v.v);
|
||||
}
|
||||
} break;
|
||||
case GLITZ_FILTER_BILINEAR:
|
||||
|
|
|
@ -96,28 +96,32 @@ glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
|
|||
case GLITZ_FORMAT_TYPE_COLOR:
|
||||
if (_texture_formats[i].format.color.red_size) {
|
||||
gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0,
|
||||
GLITZ_GL_TEXTURE_RED_SIZE, &value);
|
||||
GLITZ_GL_TEXTURE_RED_SIZE,
|
||||
&value);
|
||||
if (value != _texture_formats[i].format.color.red_size)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_texture_formats[i].format.color.green_size) {
|
||||
gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0,
|
||||
GLITZ_GL_TEXTURE_GREEN_SIZE, &value);
|
||||
GLITZ_GL_TEXTURE_GREEN_SIZE,
|
||||
&value);
|
||||
if (value != _texture_formats[i].format.color.green_size)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_texture_formats[i].format.color.blue_size) {
|
||||
gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0,
|
||||
GLITZ_GL_TEXTURE_BLUE_SIZE, &value);
|
||||
GLITZ_GL_TEXTURE_BLUE_SIZE,
|
||||
&value);
|
||||
if (value != _texture_formats[i].format.color.blue_size)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_texture_formats[i].format.color.alpha_size) {
|
||||
gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0,
|
||||
GLITZ_GL_TEXTURE_ALPHA_SIZE, &value);
|
||||
GLITZ_GL_TEXTURE_ALPHA_SIZE,
|
||||
&value);
|
||||
if (value != _texture_formats[i].format.color.alpha_size)
|
||||
continue;
|
||||
}
|
||||
|
@ -134,60 +138,151 @@ glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_add_drawable_format (glitz_int_drawable_format_t *format,
|
||||
glitz_int_drawable_format_t **formats,
|
||||
int *n_formats)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = realloc (*formats,
|
||||
sizeof (glitz_int_drawable_format_t) * (*n_formats + 1));
|
||||
if (ptr)
|
||||
{
|
||||
*formats = ptr;
|
||||
(*formats)[*n_formats] = *format;
|
||||
(*n_formats)++;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Available drawable formats needs to be validated is a similar way
|
||||
as surface formats. */
|
||||
void
|
||||
_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
|
||||
unsigned long feature_mask,
|
||||
glitz_int_drawable_format_t **formats,
|
||||
int *n_formats)
|
||||
{
|
||||
if (feature_mask & GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK)
|
||||
{
|
||||
glitz_int_drawable_format_t format;
|
||||
glitz_drawable_format_t d[] = {
|
||||
{ 0, { 8, 8, 8, 0 }, 0, 0, 1, 0 },
|
||||
{ 0, { 8, 8, 8, 8 }, 0, 0, 1, 0 },
|
||||
{ 0, { 8, 8, 8, 0 }, 24, 8, 1, 1 },
|
||||
{ 0, { 8, 8, 8, 8 }, 24, 8, 1, 1 }
|
||||
};
|
||||
int i;
|
||||
|
||||
format.types = GLITZ_DRAWABLE_TYPE_FBO_MASK;
|
||||
format.caveat = 0;
|
||||
format.u.val = 0;
|
||||
|
||||
for (i = 0; i < sizeof (d) / sizeof (d[0]); i++)
|
||||
{
|
||||
format.d = d[i];
|
||||
format.d.id = *n_formats;
|
||||
|
||||
_glitz_add_drawable_format (&format, formats, n_formats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_drawable_format_copy (const glitz_drawable_format_t *src,
|
||||
glitz_drawable_format_t *dst,
|
||||
unsigned long mask)
|
||||
{
|
||||
if (mask & GLITZ_FORMAT_ID_MASK)
|
||||
dst->id = src->id;
|
||||
|
||||
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
|
||||
dst->color.red_size = src->color.red_size;
|
||||
|
||||
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
|
||||
dst->color.green_size = src->color.green_size;
|
||||
|
||||
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
|
||||
dst->color.blue_size = src->color.blue_size;
|
||||
|
||||
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
|
||||
dst->color.alpha_size = src->color.alpha_size;
|
||||
|
||||
if (mask & GLITZ_FORMAT_DEPTH_SIZE_MASK)
|
||||
dst->depth_size = src->depth_size;
|
||||
|
||||
if (mask & GLITZ_FORMAT_STENCIL_SIZE_MASK)
|
||||
dst->stencil_size = src->stencil_size;
|
||||
|
||||
if (mask & GLITZ_FORMAT_DOUBLEBUFFER_MASK)
|
||||
dst->doublebuffer = src->doublebuffer;
|
||||
|
||||
if (mask & GLITZ_FORMAT_SAMPLES_MASK)
|
||||
dst->samples = src->samples;
|
||||
}
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_drawable_format_find (glitz_drawable_format_t *formats,
|
||||
glitz_drawable_format_find (glitz_int_drawable_format_t *formats,
|
||||
int n_formats,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
const glitz_int_drawable_format_t *templ,
|
||||
int count)
|
||||
{
|
||||
for (; n_formats; n_formats--, formats++) {
|
||||
for (; n_formats; n_formats--, formats++)
|
||||
{
|
||||
if (mask & GLITZ_FORMAT_ID_MASK)
|
||||
if (templ->id != formats->id)
|
||||
if (templ->d.id != formats->d.id)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
|
||||
if (templ->color.red_size != formats->color.red_size)
|
||||
if (templ->d.color.red_size != formats->d.color.red_size)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
|
||||
if (templ->color.green_size != formats->color.green_size)
|
||||
if (templ->d.color.green_size != formats->d.color.green_size)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
|
||||
if (templ->color.blue_size != formats->color.blue_size)
|
||||
if (templ->d.color.blue_size != formats->d.color.blue_size)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
|
||||
if (templ->color.alpha_size != formats->color.alpha_size)
|
||||
if (templ->d.color.alpha_size != formats->d.color.alpha_size)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_DEPTH_SIZE_MASK)
|
||||
if (templ->depth_size != formats->depth_size)
|
||||
if (templ->d.depth_size != formats->d.depth_size)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_STENCIL_SIZE_MASK)
|
||||
if (templ->stencil_size != formats->stencil_size)
|
||||
if (templ->d.stencil_size != formats->d.stencil_size)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_DOUBLEBUFFER_MASK)
|
||||
if (templ->doublebuffer != formats->doublebuffer)
|
||||
if (templ->d.doublebuffer != formats->d.doublebuffer)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_SAMPLES_MASK)
|
||||
if (templ->samples != formats->samples)
|
||||
if (templ->d.samples != formats->d.samples)
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_WINDOW_MASK)
|
||||
if (templ->types.window != formats->types.window)
|
||||
if (mask & GLITZ_INT_FORMAT_WINDOW_MASK)
|
||||
if ((templ->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK) !=
|
||||
(formats->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK))
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_FORMAT_PBUFFER_MASK)
|
||||
if (templ->types.pbuffer != formats->types.pbuffer)
|
||||
if (mask & GLITZ_INT_FORMAT_PBUFFER_MASK)
|
||||
if ((templ->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK) !=
|
||||
(formats->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK))
|
||||
continue;
|
||||
|
||||
if (mask & GLITZ_INT_FORMAT_FBO_MASK)
|
||||
if ((templ->types & GLITZ_DRAWABLE_TYPE_FBO_MASK) !=
|
||||
(formats->types & GLITZ_DRAWABLE_TYPE_FBO_MASK))
|
||||
continue;
|
||||
|
||||
if (count-- == 0)
|
||||
return formats;
|
||||
return &formats->d;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -283,3 +378,41 @@ glitz_find_standard_format (glitz_drawable_t *drawable,
|
|||
|
||||
return glitz_find_format (drawable, mask, &templ, 0);
|
||||
}
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_find_drawable_format (glitz_drawable_t *other,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count)
|
||||
{
|
||||
glitz_int_drawable_format_t itempl;
|
||||
|
||||
glitz_drawable_format_copy (templ, &itempl.d, mask);
|
||||
|
||||
itempl.types = GLITZ_DRAWABLE_TYPE_FBO_MASK;
|
||||
mask |= GLITZ_INT_FORMAT_FBO_MASK;
|
||||
|
||||
return glitz_drawable_format_find (other->backend->drawable_formats,
|
||||
other->backend->n_drawable_formats,
|
||||
mask, &itempl, count);
|
||||
}
|
||||
slim_hidden_def(glitz_find_drawable_format);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_find_pbuffer_format (glitz_drawable_t *other,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count)
|
||||
{
|
||||
glitz_int_drawable_format_t itempl;
|
||||
|
||||
glitz_drawable_format_copy (templ, &itempl.d, mask);
|
||||
|
||||
itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
|
||||
mask |= GLITZ_INT_FORMAT_PBUFFER_MASK;
|
||||
|
||||
return glitz_drawable_format_find (other->backend->drawable_formats,
|
||||
other->backend->n_drawable_formats,
|
||||
mask, &itempl, count);
|
||||
}
|
||||
slim_hidden_def(glitz_find_pbuffer_format);
|
||||
|
|
|
@ -29,48 +29,375 @@
|
|||
|
||||
#include "glitzint.h"
|
||||
|
||||
void
|
||||
glitz_framebuffer_init (glitz_framebuffer_t *framebuffer)
|
||||
typedef struct _glitz_fbo_drawable {
|
||||
glitz_drawable_t base;
|
||||
glitz_drawable_t *other;
|
||||
int width;
|
||||
int height;
|
||||
glitz_gl_uint_t fb;
|
||||
glitz_gl_uint_t front;
|
||||
glitz_gl_uint_t back;
|
||||
glitz_gl_uint_t depth;
|
||||
glitz_gl_uint_t stencil;
|
||||
glitz_gl_uint_t front_texture;
|
||||
glitz_gl_uint_t back_texture;
|
||||
glitz_gl_enum_t internal_format;
|
||||
} glitz_fbo_drawable_t;
|
||||
|
||||
static glitz_bool_t
|
||||
_glitz_fbo_bind (glitz_fbo_drawable_t *drawable)
|
||||
{
|
||||
framebuffer->name = 0;
|
||||
glitz_bool_t update = 0;
|
||||
glitz_gl_enum_t status;
|
||||
|
||||
GLITZ_GL_DRAWABLE (drawable->other);
|
||||
|
||||
if (!drawable->fb)
|
||||
{
|
||||
gl->gen_framebuffers (1, &drawable->fb);
|
||||
|
||||
drawable->width = drawable->base.width;
|
||||
drawable->height = drawable->base.height;
|
||||
update = 1;
|
||||
}
|
||||
else if (drawable->width != drawable->base.width ||
|
||||
drawable->height != drawable->base.height)
|
||||
{
|
||||
drawable->width = drawable->base.width;
|
||||
drawable->height = drawable->base.height;
|
||||
update = 1;
|
||||
}
|
||||
|
||||
void
|
||||
glitz_framebuffer_fini (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_framebuffer_t *framebuffer)
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, drawable->fb);
|
||||
|
||||
if (drawable->base.front &&
|
||||
drawable->front_texture != drawable->base.front->texture.name)
|
||||
{
|
||||
if (framebuffer->name)
|
||||
gl->delete_framebuffers (1, &framebuffer->name);
|
||||
}
|
||||
|
||||
void
|
||||
glitz_framebuffer_unbind (glitz_gl_proc_address_list_t *gl)
|
||||
{
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
glitz_bool_t
|
||||
glitz_framebuffer_complete (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_framebuffer_t *framebuffer,
|
||||
glitz_texture_t *texture)
|
||||
{
|
||||
if (!framebuffer->name)
|
||||
{
|
||||
if (!TEXTURE_ALLOCATED (texture))
|
||||
glitz_texture_allocate (gl, texture);
|
||||
|
||||
gl->gen_framebuffers (1, &framebuffer->name);
|
||||
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, framebuffer->name);
|
||||
|
||||
gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_COLOR_ATTACHMENT0,
|
||||
GLITZ_GL_TEXTURE_2D, texture->name,
|
||||
drawable->base.front->texture.target,
|
||||
drawable->base.front->texture.name,
|
||||
0);
|
||||
}
|
||||
else
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, framebuffer->name);
|
||||
|
||||
return (gl->check_framebuffer_status (GLITZ_GL_FRAMEBUFFER) ==
|
||||
GLITZ_GL_FRAMEBUFFER_COMPLETE);
|
||||
drawable->front_texture = drawable->base.front->texture.name;
|
||||
|
||||
if (drawable->front)
|
||||
{
|
||||
gl->delete_renderbuffers (1, &drawable->front);
|
||||
drawable->front = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!drawable->front_texture && !drawable->front)
|
||||
{
|
||||
gl->gen_renderbuffers (1, &drawable->front);
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, drawable->front);
|
||||
gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER,
|
||||
drawable->internal_format,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0);
|
||||
gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_COLOR_ATTACHMENT0,
|
||||
GLITZ_GL_RENDERBUFFER,
|
||||
drawable->front);
|
||||
}
|
||||
|
||||
if (drawable->base.format->d.doublebuffer)
|
||||
{
|
||||
if (drawable->base.back &&
|
||||
drawable->back_texture != drawable->base.back->texture.name)
|
||||
{
|
||||
gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_COLOR_ATTACHMENT1,
|
||||
drawable->base.back->texture.target,
|
||||
drawable->base.back->texture.name,
|
||||
0);
|
||||
|
||||
drawable->back_texture = drawable->base.back->texture.name;
|
||||
|
||||
if (drawable->back)
|
||||
{
|
||||
gl->delete_renderbuffers (1, &drawable->back);
|
||||
drawable->back = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!drawable->back_texture && !drawable->back)
|
||||
{
|
||||
gl->gen_renderbuffers (1, &drawable->back);
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER,
|
||||
drawable->back);
|
||||
gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER,
|
||||
drawable->internal_format,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0);
|
||||
gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_COLOR_ATTACHMENT1,
|
||||
GLITZ_GL_RENDERBUFFER,
|
||||
drawable->back);
|
||||
}
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
if (drawable->base.format->d.depth_size)
|
||||
{
|
||||
if (!drawable->depth)
|
||||
gl->gen_renderbuffers (1, &drawable->depth);
|
||||
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, drawable->depth);
|
||||
gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER,
|
||||
GLITZ_GL_DEPTH_COMPONENT,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0);
|
||||
|
||||
gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_DEPTH_ATTACHMENT,
|
||||
GLITZ_GL_RENDERBUFFER,
|
||||
drawable->depth);
|
||||
}
|
||||
|
||||
if (drawable->base.format->d.stencil_size)
|
||||
{
|
||||
if (!drawable->stencil)
|
||||
gl->gen_renderbuffers (1, &drawable->stencil);
|
||||
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER,
|
||||
drawable->stencil);
|
||||
gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER,
|
||||
GLITZ_GL_STENCIL_INDEX,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0);
|
||||
|
||||
gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_STENCIL_ATTACHMENT,
|
||||
GLITZ_GL_RENDERBUFFER,
|
||||
drawable->stencil);
|
||||
}
|
||||
}
|
||||
|
||||
status = gl->check_framebuffer_status (GLITZ_GL_FRAMEBUFFER);
|
||||
if (status == GLITZ_GL_FRAMEBUFFER_COMPLETE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_fbo_attach_notify (void *abstract_drawable,
|
||||
glitz_surface_t *surface)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_texture_t *texture;
|
||||
|
||||
GLITZ_GL_DRAWABLE (drawable->other);
|
||||
|
||||
texture = &surface->texture;
|
||||
if (!TEXTURE_ALLOCATED (texture))
|
||||
{
|
||||
drawable->other->backend->push_current (drawable->other, NULL,
|
||||
GLITZ_ANY_CONTEXT_CURRENT);
|
||||
glitz_texture_allocate (gl, texture);
|
||||
drawable->other->backend->pop_current (drawable->other);
|
||||
|
||||
if (!TEXTURE_ALLOCATED (texture))
|
||||
return;
|
||||
}
|
||||
|
||||
REGION_EMPTY (&surface->drawable_damage);
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_fbo_detach_notify (void *abstract_drawable,
|
||||
glitz_surface_t *surface)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
if (surface->texture.name == drawable->front_texture ||
|
||||
surface->texture.name == drawable->back_texture)
|
||||
{
|
||||
GLITZ_GL_DRAWABLE (drawable->other);
|
||||
|
||||
drawable->other->backend->push_current (drawable->other, NULL,
|
||||
GLITZ_ANY_CONTEXT_CURRENT);
|
||||
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, drawable->fb);
|
||||
|
||||
if (surface->texture.name == drawable->front_texture)
|
||||
{
|
||||
gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_COLOR_ATTACHMENT0,
|
||||
surface->texture.target,
|
||||
0, 0);
|
||||
drawable->front_texture = 0;
|
||||
}
|
||||
|
||||
if (surface->texture.name == drawable->back_texture)
|
||||
{
|
||||
gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER,
|
||||
GLITZ_GL_COLOR_ATTACHMENT1,
|
||||
surface->texture.target,
|
||||
0, 0);
|
||||
drawable->back_texture = 0;
|
||||
}
|
||||
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0);
|
||||
|
||||
surface->fb = 0;
|
||||
|
||||
drawable->other->backend->pop_current (drawable->other);
|
||||
}
|
||||
}
|
||||
|
||||
static glitz_bool_t
|
||||
_glitz_fbo_push_current (void *abstract_drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
drawable->other->backend->push_current (drawable->other, surface,
|
||||
constraint);
|
||||
|
||||
if (constraint == GLITZ_DRAWABLE_CURRENT)
|
||||
{
|
||||
if (_glitz_fbo_bind (drawable))
|
||||
{
|
||||
drawable->base.update_all = drawable->other->update_all = 1;
|
||||
surface->fb = drawable->fb;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static glitz_surface_t *
|
||||
_glitz_fbo_pop_current (void *abstract_drawable)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
GLITZ_GL_DRAWABLE (drawable->other);
|
||||
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0);
|
||||
|
||||
return drawable->other->backend->pop_current (drawable->other);
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_fbo_make_current (void *abstract_drawable,
|
||||
void *abstract_context)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
drawable->other->backend->make_current (drawable->other, abstract_context);
|
||||
|
||||
_glitz_fbo_bind (drawable);
|
||||
}
|
||||
|
||||
static glitz_bool_t
|
||||
_glitz_fbo_swap_buffers (void *abstract_drawable)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
if (!drawable->fb)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_fbo_destroy (void *abstract_drawable)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
if (drawable->fb)
|
||||
{
|
||||
GLITZ_GL_DRAWABLE (drawable->other);
|
||||
|
||||
drawable->other->backend->push_current (drawable->other, NULL,
|
||||
GLITZ_ANY_CONTEXT_CURRENT);
|
||||
|
||||
gl->delete_framebuffers (1, &drawable->fb);
|
||||
|
||||
if (drawable->front)
|
||||
gl->delete_renderbuffers (1, &drawable->front);
|
||||
|
||||
if (drawable->back)
|
||||
gl->delete_renderbuffers (1, &drawable->back);
|
||||
|
||||
if (drawable->depth)
|
||||
gl->delete_renderbuffers (1, &drawable->depth);
|
||||
|
||||
if (drawable->stencil)
|
||||
gl->delete_renderbuffers (1, &drawable->stencil);
|
||||
|
||||
drawable->other->backend->pop_current (drawable->other);
|
||||
}
|
||||
|
||||
glitz_drawable_destroy (drawable->other);
|
||||
|
||||
free (drawable);
|
||||
}
|
||||
|
||||
glitz_drawable_t *
|
||||
_glitz_fbo_drawable_create (glitz_drawable_t *other,
|
||||
glitz_int_drawable_format_t *format,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
glitz_fbo_drawable_t *drawable;
|
||||
glitz_backend_t *backend;
|
||||
|
||||
drawable = malloc (sizeof (glitz_fbo_drawable_t) +
|
||||
sizeof (glitz_backend_t));
|
||||
if (!drawable)
|
||||
return NULL;
|
||||
|
||||
glitz_drawable_reference (other);
|
||||
drawable->other = other;
|
||||
backend = (glitz_backend_t *) (drawable + 1);
|
||||
*backend = *other->backend;
|
||||
|
||||
backend->destroy = _glitz_fbo_destroy;
|
||||
backend->push_current = _glitz_fbo_push_current;
|
||||
backend->pop_current = _glitz_fbo_pop_current;
|
||||
backend->attach_notify = _glitz_fbo_attach_notify;
|
||||
backend->detach_notify = _glitz_fbo_detach_notify;
|
||||
backend->swap_buffers = _glitz_fbo_swap_buffers;
|
||||
backend->make_current = _glitz_fbo_make_current;
|
||||
|
||||
drawable->fb = 0;
|
||||
|
||||
drawable->width = 0;
|
||||
drawable->height = 0;
|
||||
|
||||
drawable->front = 0;
|
||||
drawable->back = 0;
|
||||
drawable->depth = 0;
|
||||
drawable->stencil = 0;
|
||||
|
||||
drawable->front_texture = 0;
|
||||
drawable->back_texture = 0;
|
||||
|
||||
/* XXX: temporary solution until we have proper format validation */
|
||||
if (format->d.color.alpha_size)
|
||||
drawable->internal_format = GLITZ_GL_RGBA;
|
||||
else
|
||||
drawable->internal_format = GLITZ_GL_RGB;
|
||||
|
||||
_glitz_drawable_init (&drawable->base, format, backend, width, height);
|
||||
|
||||
return &drawable->base;
|
||||
}
|
||||
|
|
|
@ -363,7 +363,6 @@ _glitz_draw_rectangle (glitz_gl_proc_address_list_t *gl,
|
|||
glitz_box_t *clip = dst->clip;
|
||||
int n_clip = dst->n_clip;
|
||||
glitz_box_t box;
|
||||
int target_height = SURFACE_DRAWABLE_HEIGHT (dst);
|
||||
|
||||
while (n_clip--)
|
||||
{
|
||||
|
@ -383,7 +382,7 @@ _glitz_draw_rectangle (glitz_gl_proc_address_list_t *gl,
|
|||
if (box.x1 < box.x2 && box.y1 < box.y2)
|
||||
{
|
||||
gl->scissor (box.x1 + dst->x,
|
||||
target_height - dst->y - box.y2,
|
||||
dst->attached->height - dst->y - box.y2,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
|
||||
gl->draw_arrays (GLITZ_GL_QUADS, 0, 4);
|
||||
|
@ -410,7 +409,6 @@ _glitz_draw_vertex_arrays (glitz_gl_proc_address_list_t *gl,
|
|||
glitz_box_t *clip = dst->clip;
|
||||
int i, n_clip = dst->n_clip;
|
||||
glitz_box_t box;
|
||||
int target_height = SURFACE_DRAWABLE_HEIGHT (dst);
|
||||
|
||||
while (n_clip--)
|
||||
{
|
||||
|
@ -430,7 +428,7 @@ _glitz_draw_vertex_arrays (glitz_gl_proc_address_list_t *gl,
|
|||
if (box.x1 < box.x2 && box.y1 < box.y2)
|
||||
{
|
||||
gl->scissor (box.x1 + dst->x,
|
||||
target_height - dst->y - box.y2,
|
||||
dst->attached->height - dst->y - box.y2,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
|
||||
gl->push_matrix ();
|
||||
|
@ -534,7 +532,6 @@ _glitz_draw_bitmap_arrays (glitz_gl_proc_address_list_t *gl,
|
|||
int byte_offset, pixel_offset = 0;
|
||||
glitz_float_t x_off, y_off;
|
||||
glitz_box_t box;
|
||||
int target_height = SURFACE_DRAWABLE_HEIGHT (dst);
|
||||
|
||||
if (dst->geometry.u.b.top_down)
|
||||
{
|
||||
|
@ -600,7 +597,7 @@ _glitz_draw_bitmap_arrays (glitz_gl_proc_address_list_t *gl,
|
|||
if (box.x1 < box.x2 && box.y1 < box.y2)
|
||||
{
|
||||
gl->scissor (box.x1 + dst->x,
|
||||
target_height - dst->y - box.y2,
|
||||
dst->attached->height - dst->y - box.y2,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
|
||||
x_off = dst->x + dst->geometry.off.v[0];
|
||||
|
@ -611,7 +608,8 @@ _glitz_draw_bitmap_arrays (glitz_gl_proc_address_list_t *gl,
|
|||
x_off += array->off->v[0];
|
||||
y_off += array->off->v[1];
|
||||
|
||||
glitz_set_raster_pos (gl, x_off, target_height - y_off);
|
||||
glitz_set_raster_pos (gl, x_off,
|
||||
dst->attached->height - y_off);
|
||||
|
||||
for (i = 0, n = array->n_arrays; n--; i++)
|
||||
{
|
||||
|
@ -635,7 +633,8 @@ _glitz_draw_bitmap_arrays (glitz_gl_proc_address_list_t *gl,
|
|||
}
|
||||
else
|
||||
{
|
||||
glitz_set_raster_pos (gl, x_off, target_height - y_off);
|
||||
glitz_set_raster_pos (gl, x_off,
|
||||
dst->attached->height - y_off);
|
||||
|
||||
BITMAP_SETUP (dst,
|
||||
dst->geometry.first,
|
||||
|
|
|
@ -114,6 +114,7 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
|
|||
|
||||
#define GLITZ_GL_TEXTURE_WIDTH 0x1000
|
||||
#define GLITZ_GL_TEXTURE_HEIGHT 0x1001
|
||||
#define GLITZ_GL_TEXTURE_BORDER_COLOR 0x1004
|
||||
|
||||
#define GLITZ_GL_TEXTURE_ENV 0x2300
|
||||
#define GLITZ_GL_TEXTURE_ENV_MODE 0x2200
|
||||
|
@ -135,6 +136,7 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
|
|||
#define GLITZ_GL_MODULATE 0x2100
|
||||
#define GLITZ_GL_NEAREST 0x2600
|
||||
#define GLITZ_GL_LINEAR 0x2601
|
||||
#define GLITZ_GL_CLAMP 0x2900
|
||||
#define GLITZ_GL_REPEAT 0x2901
|
||||
#define GLITZ_GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GLITZ_GL_CLAMP_TO_BORDER 0x812D
|
||||
|
@ -188,6 +190,9 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
|
|||
#define GLITZ_GL_TRANSFORM_BIT 0x00001000
|
||||
#define GLITZ_GL_COLOR_BUFFER_BIT 0x00004000
|
||||
|
||||
#define GLITZ_GL_STENCIL_INDEX 0x1901
|
||||
#define GLITZ_GL_DEPTH_COMPONENT 0x1902
|
||||
|
||||
#define GLITZ_GL_ALPHA 0x1906
|
||||
#define GLITZ_GL_RGB 0x1907
|
||||
#define GLITZ_GL_LUMINANCE 0x1909
|
||||
|
@ -310,7 +315,13 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
|
|||
#define GLITZ_GL_READ_WRITE 0x88BA
|
||||
|
||||
#define GLITZ_GL_FRAMEBUFFER 0x8D40
|
||||
#define GLITZ_GL_RENDERBUFFER 0x8D41
|
||||
|
||||
#define GLITZ_GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GLITZ_GL_COLOR_ATTACHMENT1 0x8CE1
|
||||
#define GLITZ_GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define GLITZ_GL_STENCIL_ATTACHMENT 0x8D20
|
||||
|
||||
#define GLITZ_GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GLITZ_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GLITZ_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
|
||||
|
@ -322,6 +333,13 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
|
|||
#define GLITZ_GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
#define GLITZ_GL_FRAMEBUFFER_STATUS_ERROR 0x8CDE
|
||||
|
||||
#define GLITZ_GL_RENDERBUFFER_RED_SIZE 0x8D50
|
||||
#define GLITZ_GL_RENDERBUFFER_GREEN_SIZE 0x8D51
|
||||
#define GLITZ_GL_RENDERBUFFER_BLUE_SIZE 0x8D52
|
||||
#define GLITZ_GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
|
||||
#define GLITZ_GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
|
||||
#define GLITZ_GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
|
||||
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_enable_t)
|
||||
(glitz_gl_enum_t cap);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_disable_t)
|
||||
|
@ -470,6 +488,9 @@ typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_tex_image_2d_t)
|
|||
const glitz_gl_void_t *pixels);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_tex_parameter_i_t)
|
||||
(glitz_gl_enum_t target, glitz_gl_enum_t pname, glitz_gl_int_t param);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_tex_parameter_fv_t)
|
||||
(glitz_gl_enum_t target, glitz_gl_enum_t pname,
|
||||
const glitz_gl_float_t *parama);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_get_tex_level_parameter_iv_t)
|
||||
(glitz_gl_enum_t target, glitz_gl_int_t level,
|
||||
glitz_gl_enum_t pname, glitz_gl_int_t *param);
|
||||
|
@ -524,10 +545,23 @@ typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_delete_framebuffers_t)
|
|||
(glitz_gl_sizei_t, const glitz_gl_uint_t *);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_bind_framebuffer_t)
|
||||
(glitz_gl_enum_t, glitz_gl_uint_t);
|
||||
typedef glitz_gl_enum_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_check_framebuffer_status_t)
|
||||
(glitz_gl_enum_t);
|
||||
typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_framebuffer_renderbuffer_t)
|
||||
(glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_enum_t,
|
||||
glitz_gl_uint_t);
|
||||
typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_framebuffer_texture_2d_t)
|
||||
(glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_enum_t,
|
||||
glitz_gl_uint_t, glitz_gl_int_t);
|
||||
typedef glitz_gl_enum_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_check_framebuffer_status_t)
|
||||
(glitz_gl_enum_t);
|
||||
typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_gen_renderbuffers_t)
|
||||
(glitz_gl_sizei_t, glitz_gl_uint_t *);
|
||||
typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_delete_renderbuffers_t)
|
||||
(glitz_gl_sizei_t, const glitz_gl_uint_t *);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_bind_renderbuffer_t)
|
||||
(glitz_gl_enum_t, glitz_gl_uint_t);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_renderbuffer_storage_t)
|
||||
(glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_sizei_t, glitz_gl_sizei_t);
|
||||
typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_get_renderbuffer_parameter_iv_t)
|
||||
(glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_int_t *);
|
||||
|
||||
#endif /* GLITZ_GL_H_INCLUDED */
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
#include "glitzint.h"
|
||||
|
||||
void
|
||||
glitz_set_operator (glitz_gl_proc_address_list_t *gl, glitz_operator_t op) {
|
||||
glitz_set_operator (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_operator_t op)
|
||||
{
|
||||
switch (op) {
|
||||
case GLITZ_OPERATOR_CLEAR:
|
||||
gl->enable (GLITZ_GL_BLEND);
|
||||
|
|
|
@ -159,13 +159,13 @@ typedef struct _glitz_pixel_transform_op {
|
|||
glitz_pixel_color_t *color;
|
||||
} glitz_pixel_transform_op_t;
|
||||
|
||||
#define FETCH(p, mask) ((mask)? \
|
||||
((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * 0xffffffff) / \
|
||||
((uint64_t) (mask)))): 0x0)
|
||||
#define FETCH(p, mask) \
|
||||
((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
|
||||
0xffffffff) / ((uint64_t) (mask)))): 0x0)
|
||||
|
||||
#define FETCH_A(p, mask) ((mask)? \
|
||||
((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * 0xffffffff) / \
|
||||
((uint64_t) (mask)))): 0xffffffff)
|
||||
#define FETCH_A(p, mask) \
|
||||
((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
|
||||
0xffffffff) /((uint64_t) (mask)))): 0xffffffff)
|
||||
|
||||
typedef void (*glitz_pixel_fetch_function_t) (glitz_pixel_transform_op_t *op);
|
||||
|
||||
|
@ -403,21 +403,26 @@ _glitz_pixel_transform (unsigned long transform,
|
|||
|
||||
for (y = 0; y < height; y++) {
|
||||
if (src->format->scanline_order != dst->format->scanline_order)
|
||||
src_op.line = &src->data[(src->height - (y + y_src) - 1) * src_stride];
|
||||
src_op.line = &src->data[(src->height - (y + y_src) - 1) *
|
||||
src_stride];
|
||||
else
|
||||
src_op.line = &src->data[(y + y_src) * src_stride];
|
||||
|
||||
dst_op.line = &dst->data[(y + y_dst) * dst_stride];
|
||||
|
||||
if (transform & GLITZ_TRANSFORM_PIXELS_MASK) {
|
||||
for (x = 0; x < width; x++) {
|
||||
if (transform & GLITZ_TRANSFORM_PIXELS_MASK)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
src_op.offset = x_src + x;
|
||||
dst_op.offset = x_dst + x;
|
||||
|
||||
fetch (&src_op);
|
||||
store (&dst_op);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This only works for bpp >= 8, but it shouldn't be a problem as
|
||||
it will never be used for bitmaps */
|
||||
if (bytes_per_pixel == 0)
|
||||
|
@ -433,24 +438,24 @@ _glitz_pixel_transform (unsigned long transform,
|
|||
static glitz_bool_t
|
||||
_glitz_format_match (glitz_pixel_masks_t *masks1,
|
||||
glitz_pixel_masks_t *masks2,
|
||||
glitz_color_format_t *internal_color)
|
||||
unsigned long mask)
|
||||
{
|
||||
if (masks1->bpp != masks2->bpp)
|
||||
return 0;
|
||||
|
||||
if (internal_color->red_size)
|
||||
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
|
||||
if (masks1->red_mask != masks2->red_mask)
|
||||
return 0;
|
||||
|
||||
if (internal_color->green_size)
|
||||
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
|
||||
if (masks1->green_mask != masks2->green_mask)
|
||||
return 0;
|
||||
|
||||
if (internal_color->blue_size)
|
||||
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
|
||||
if (masks1->blue_mask != masks2->blue_mask)
|
||||
return 0;
|
||||
|
||||
if (internal_color->alpha_size)
|
||||
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
|
||||
if (masks1->alpha_mask != masks2->alpha_mask)
|
||||
return 0;
|
||||
|
||||
|
@ -459,26 +464,28 @@ _glitz_format_match (glitz_pixel_masks_t *masks1,
|
|||
|
||||
static glitz_gl_pixel_format_t *
|
||||
_glitz_find_gl_pixel_format (glitz_pixel_format_t *format,
|
||||
glitz_color_format_t *internal_color,
|
||||
unsigned long color_mask,
|
||||
unsigned long feature_mask)
|
||||
{
|
||||
int i, n_formats;
|
||||
|
||||
n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t);
|
||||
for (i = 0; i < n_formats; i++) {
|
||||
if (_glitz_format_match (&_gl_pixel_formats[i].pixel.masks, &format->masks,
|
||||
internal_color))
|
||||
for (i = 0; i < n_formats; i++)
|
||||
{
|
||||
if (_glitz_format_match (&_gl_pixel_formats[i].pixel.masks,
|
||||
&format->masks, color_mask))
|
||||
return &_gl_pixel_formats[i];
|
||||
}
|
||||
|
||||
if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK) {
|
||||
if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK)
|
||||
{
|
||||
n_formats = sizeof (_gl_packed_pixel_formats) /
|
||||
sizeof (glitz_gl_pixel_format_t);
|
||||
|
||||
for (i = 0; i < n_formats; i++) {
|
||||
for (i = 0; i < n_formats; i++)
|
||||
{
|
||||
if (_glitz_format_match (&_gl_packed_pixel_formats[i].pixel.masks,
|
||||
&format->masks,
|
||||
internal_color))
|
||||
&format->masks, color_mask))
|
||||
return &_gl_packed_pixel_formats[i];
|
||||
}
|
||||
}
|
||||
|
@ -549,28 +556,35 @@ _glitz_find_best_gl_pixel_format (glitz_pixel_format_t *format,
|
|||
color.alpha_size = _component_size (format->masks.alpha_mask);
|
||||
|
||||
n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t);
|
||||
for (i = 0; best_diff > 0 && i < n_formats; i++) {
|
||||
for (i = 0; best_diff > 0 && i < n_formats; i++)
|
||||
{
|
||||
if (_glitz_format_diff (&_gl_pixel_formats[i].pixel.masks,
|
||||
&color,
|
||||
internal_color,
|
||||
&diff)) {
|
||||
if (diff < best_diff) {
|
||||
&diff))
|
||||
{
|
||||
if (diff < best_diff)
|
||||
{
|
||||
best = &_gl_pixel_formats[i];
|
||||
best_diff = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK) {
|
||||
if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK)
|
||||
{
|
||||
n_formats = sizeof (_gl_packed_pixel_formats) /
|
||||
sizeof (glitz_gl_pixel_format_t);
|
||||
|
||||
for (i = 0; best_diff > 0 && i < n_formats; i++) {
|
||||
for (i = 0; best_diff > 0 && i < n_formats; i++)
|
||||
{
|
||||
if (_glitz_format_diff (&_gl_packed_pixel_formats[i].pixel.masks,
|
||||
&color,
|
||||
internal_color,
|
||||
&diff)) {
|
||||
if (diff < best_diff) {
|
||||
&diff))
|
||||
{
|
||||
if (diff < best_diff)
|
||||
{
|
||||
best = &_gl_packed_pixel_formats[i];
|
||||
best_diff = diff;
|
||||
}
|
||||
|
@ -601,12 +615,14 @@ glitz_set_pixels (glitz_surface_t *dst,
|
|||
glitz_bool_t bound = 0;
|
||||
int bytes_per_line = 0, bytes_per_pixel = 0;
|
||||
glitz_image_t src_image, dst_image;
|
||||
unsigned long color_mask;
|
||||
glitz_box_t box;
|
||||
|
||||
GLITZ_GL_SURFACE (dst);
|
||||
|
||||
if (x_dst < 0 || x_dst > (dst->box.x2 - width) ||
|
||||
y_dst < 0 || y_dst > (dst->box.y2 - height)) {
|
||||
y_dst < 0 || y_dst > (dst->box.y2 - height))
|
||||
{
|
||||
glitz_surface_status_add (dst, GLITZ_STATUS_BAD_COORDINATE_MASK);
|
||||
return;
|
||||
}
|
||||
|
@ -705,14 +721,25 @@ glitz_set_pixels (glitz_surface_t *dst,
|
|||
}
|
||||
break;
|
||||
}
|
||||
clip++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
color_mask = 0;
|
||||
if (dst->format->color.red_size)
|
||||
color_mask |= GLITZ_FORMAT_RED_SIZE_MASK;
|
||||
if (dst->format->color.green_size)
|
||||
color_mask |= GLITZ_FORMAT_GREEN_SIZE_MASK;
|
||||
if (dst->format->color.blue_size)
|
||||
color_mask |= GLITZ_FORMAT_BLUE_SIZE_MASK;
|
||||
if (dst->format->color.alpha_size)
|
||||
color_mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
|
||||
|
||||
/* find direct format */
|
||||
gl_format =
|
||||
_glitz_find_gl_pixel_format (format,
|
||||
&dst->format->color,
|
||||
color_mask,
|
||||
dst->drawable->backend->feature_mask);
|
||||
if (gl_format == NULL)
|
||||
{
|
||||
|
@ -876,29 +903,55 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
glitz_pixel_format_t *format,
|
||||
glitz_buffer_t *buffer)
|
||||
{
|
||||
glitz_box_t *clip = src->clip;
|
||||
int n_clip = src->n_clip;
|
||||
glitz_bool_t from_drawable;
|
||||
glitz_texture_t *texture = NULL;
|
||||
char *pixels, *data = NULL;
|
||||
glitz_gl_pixel_format_t *gl_format = NULL;
|
||||
unsigned long transform = 0;
|
||||
int src_x = 0, src_y = 0, src_w = width, src_h = height;
|
||||
int xoffset, bytes_per_line, bpp;
|
||||
int src_x = 0, src_y = 0;
|
||||
int src_w = width, src_h = height;
|
||||
int bytes_per_line, bytes_per_pixel;
|
||||
glitz_color_format_t *color;
|
||||
unsigned long color_mask;
|
||||
glitz_box_t box;
|
||||
|
||||
GLITZ_GL_SURFACE (src);
|
||||
|
||||
if (x_src < 0 || x_src > (src->box.x2 - width) ||
|
||||
y_src < 0 || y_src > (src->box.y2 - height)) {
|
||||
y_src < 0 || y_src > (src->box.y2 - height))
|
||||
{
|
||||
glitz_surface_status_add (src, GLITZ_STATUS_BAD_COORDINATE_MASK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SURFACE_SOLID (src)) {
|
||||
if (SURFACE_SOLID (src))
|
||||
{
|
||||
glitz_image_t src_image, dst_image;
|
||||
glitz_pixel_format_t dst_format;
|
||||
|
||||
if (SURFACE_SOLID_DAMAGE (src)) {
|
||||
glitz_surface_push_current (src, GLITZ_ANY_CONTEXT_CURRENT);
|
||||
while (n_clip--)
|
||||
{
|
||||
box.x1 = clip->x1 + src->x_clip;
|
||||
box.y1 = clip->y1 + src->y_clip;
|
||||
box.x2 = clip->x2 + src->x_clip;
|
||||
box.y2 = clip->y2 + src->y_clip;
|
||||
if (x_src > box.x1)
|
||||
box.x1 = x_src;
|
||||
if (y_src > box.y1)
|
||||
box.y1 = y_src;
|
||||
if (x_src + width < box.x2)
|
||||
box.x2 = x_src + width;
|
||||
if (y_src + height < box.y2)
|
||||
box.y2 = y_src + height;
|
||||
|
||||
if (box.x1 < box.x2 && box.y1 < box.y2)
|
||||
{
|
||||
if (SURFACE_SOLID_DAMAGE (src))
|
||||
{
|
||||
glitz_surface_push_current (src,
|
||||
GLITZ_ANY_CONTEXT_CURRENT);
|
||||
glitz_surface_sync_solid (src);
|
||||
glitz_surface_pop_current (src);
|
||||
}
|
||||
|
@ -907,12 +960,14 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
|
||||
dst_format = *format;
|
||||
|
||||
dst_image.data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY);
|
||||
dst_image.data =
|
||||
glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY);
|
||||
dst_image.data += format->skip_lines * format->bytes_per_line;
|
||||
dst_image.format = &dst_format;
|
||||
dst_image.width = dst_image.height = 1;
|
||||
|
||||
if (format->masks.alpha_mask) {
|
||||
if (format->masks.alpha_mask)
|
||||
{
|
||||
src_image.data = (void *) &src->solid.alpha;
|
||||
src_image.format = &_solid_format[SOLID_ALPHA];
|
||||
|
||||
|
@ -926,7 +981,8 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
0, 0, format->xoffset, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (format->masks.red_mask) {
|
||||
if (format->masks.red_mask)
|
||||
{
|
||||
src_image.data = (void *) &src->solid.red;
|
||||
src_image.format = &_solid_format[SOLID_RED];
|
||||
|
||||
|
@ -940,7 +996,8 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
0, 0, format->xoffset, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (format->masks.green_mask) {
|
||||
if (format->masks.green_mask)
|
||||
{
|
||||
src_image.data = (void *) &src->solid.green;
|
||||
src_image.format = &_solid_format[SOLID_GREEN];
|
||||
|
||||
|
@ -954,7 +1011,8 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
0, 0, format->xoffset, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (format->masks.blue_mask) {
|
||||
if (format->masks.blue_mask)
|
||||
{
|
||||
src_image.data = (void *) &src->solid.blue;
|
||||
src_image.format = &_solid_format[SOLID_BLUE];
|
||||
|
||||
|
@ -970,81 +1028,121 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
|
||||
glitz_buffer_unmap (buffer);
|
||||
|
||||
break;
|
||||
}
|
||||
clip++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
color = &src->format->color;
|
||||
from_drawable = glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT);
|
||||
if (from_drawable) {
|
||||
if (from_drawable)
|
||||
{
|
||||
if (src->attached)
|
||||
color = &src->attached->format->color;
|
||||
} else {
|
||||
color = &src->attached->format->d.color;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = glitz_surface_get_texture (src, 0);
|
||||
if (!texture) {
|
||||
if (!texture)
|
||||
{
|
||||
glitz_surface_pop_current (src);
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture->width > width || texture->height > height)
|
||||
transform |= GLITZ_TRANSFORM_COPY_BOX_MASK;
|
||||
|
||||
if (src->n_clip > 1 ||
|
||||
clip->x1 + src->x_clip > x_src ||
|
||||
clip->y1 + src->y_clip > y_src ||
|
||||
clip->x2 + src->x_clip < x_src + width ||
|
||||
clip->y2 + src->y_clip < y_src + height)
|
||||
transform |= GLITZ_TRANSFORM_COPY_BOX_MASK;
|
||||
}
|
||||
|
||||
if (transform || height > 1) {
|
||||
if (transform || height > 1)
|
||||
{
|
||||
if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN)
|
||||
transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK;
|
||||
}
|
||||
|
||||
color_mask = 0;
|
||||
if (format->masks.red_mask)
|
||||
color_mask |= GLITZ_FORMAT_RED_SIZE_MASK;
|
||||
if (format->masks.green_mask)
|
||||
color_mask |= GLITZ_FORMAT_GREEN_SIZE_MASK;
|
||||
if (format->masks.blue_mask)
|
||||
color_mask |= GLITZ_FORMAT_BLUE_SIZE_MASK;
|
||||
if (format->masks.alpha_mask)
|
||||
color_mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
|
||||
|
||||
/* find direct format */
|
||||
gl_format =
|
||||
_glitz_find_gl_pixel_format (format, color,
|
||||
_glitz_find_gl_pixel_format (format, color_mask,
|
||||
src->drawable->backend->feature_mask);
|
||||
if (gl_format == NULL) {
|
||||
transform |= GLITZ_TRANSFORM_PIXELS_MASK;
|
||||
if (gl_format == NULL)
|
||||
{
|
||||
unsigned int features;
|
||||
|
||||
gl_format =
|
||||
_glitz_find_best_gl_pixel_format (format, color,
|
||||
src->drawable->backend->feature_mask);
|
||||
transform |= GLITZ_TRANSFORM_PIXELS_MASK;
|
||||
features = src->drawable->backend->feature_mask;
|
||||
|
||||
gl_format = _glitz_find_best_gl_pixel_format (format, color, features);
|
||||
}
|
||||
|
||||
/* should not happen */
|
||||
if (gl_format == NULL) {
|
||||
if (gl_format == NULL)
|
||||
{
|
||||
glitz_surface_pop_current (src);
|
||||
return;
|
||||
}
|
||||
|
||||
if (transform) {
|
||||
if (transform)
|
||||
{
|
||||
int stride;
|
||||
|
||||
if (transform & GLITZ_TRANSFORM_COPY_BOX_MASK) {
|
||||
if (transform & GLITZ_TRANSFORM_COPY_BOX_MASK)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
src_w = texture->width;
|
||||
src_h = texture->height;
|
||||
src_x = x_src + src->texture.box.x1;
|
||||
src_y = y_src + src->texture.box.y1;
|
||||
src_x = src->texture.box.x1;
|
||||
src_y = src->texture.box.y1;
|
||||
}
|
||||
}
|
||||
|
||||
stride = (((src_w * gl_format->pixel.masks.bpp) / 8) + 3) & -4;
|
||||
|
||||
data = malloc (stride * src_h);
|
||||
if (!data) {
|
||||
if (!data)
|
||||
{
|
||||
glitz_surface_status_add (src, GLITZ_STATUS_NO_MEMORY_MASK);
|
||||
return;
|
||||
}
|
||||
|
||||
pixels = data;
|
||||
xoffset = 0;
|
||||
bytes_per_pixel = gl_format->pixel.masks.bpp / 8;
|
||||
bytes_per_line = stride;
|
||||
bpp = gl_format->pixel.masks.bpp;
|
||||
} else {
|
||||
xoffset = format->xoffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes_per_pixel = format->masks.bpp / 8;
|
||||
bytes_per_line = format->bytes_per_line;
|
||||
bpp = format->masks.bpp;
|
||||
if (!bytes_per_line)
|
||||
bytes_per_line = width * bytes_per_pixel;
|
||||
|
||||
pixels = glitz_buffer_bind (buffer, GLITZ_GL_PIXEL_PACK_BUFFER);
|
||||
pixels += format->skip_lines * bytes_per_line;
|
||||
pixels += format->xoffset * bytes_per_pixel;
|
||||
}
|
||||
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_SKIP_ROWS, 0);
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_SKIP_PIXELS, xoffset);
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_SKIP_PIXELS, 0);
|
||||
|
||||
if (bytes_per_line) {
|
||||
if ((bytes_per_line % 4) == 0)
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 4);
|
||||
else if ((bytes_per_line % 2) == 0)
|
||||
|
@ -1052,25 +1150,47 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
else
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_ROW_LENGTH, bytes_per_line / (bpp / 8));
|
||||
} else {
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 1);
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_ROW_LENGTH, 0);
|
||||
}
|
||||
gl->pixel_store_i (GLITZ_GL_PACK_ROW_LENGTH,
|
||||
bytes_per_line / bytes_per_pixel);
|
||||
|
||||
if (from_drawable) {
|
||||
if (from_drawable)
|
||||
{
|
||||
gl->read_buffer (src->buffer);
|
||||
|
||||
gl->disable (GLITZ_GL_SCISSOR_TEST);
|
||||
|
||||
gl->read_pixels (x_src + src->x,
|
||||
SURFACE_DRAWABLE_HEIGHT (src) - (y_src + src->y) - height,
|
||||
width, height,
|
||||
while (n_clip--)
|
||||
{
|
||||
box.x1 = clip->x1 + src->x_clip;
|
||||
box.y1 = clip->y1 + src->y_clip;
|
||||
box.x2 = clip->x2 + src->x_clip;
|
||||
box.y2 = clip->y2 + src->y_clip;
|
||||
if (x_src > box.x1)
|
||||
box.x1 = x_src;
|
||||
if (y_src > box.y1)
|
||||
box.y1 = y_src;
|
||||
if (x_src + width < box.x2)
|
||||
box.x2 = x_src + width;
|
||||
if (y_src + height < box.y2)
|
||||
box.y2 = y_src + height;
|
||||
|
||||
if (box.x1 < box.x2 && box.y1 < box.y2)
|
||||
{
|
||||
gl->read_pixels (box.x1 + src->x,
|
||||
src->attached->height - (box.y2 + src->y),
|
||||
box.x2 - box.x1, box.y2 - box.y1,
|
||||
gl_format->format, gl_format->type,
|
||||
pixels);
|
||||
pixels +
|
||||
(y_src + height - box.y2) * bytes_per_line +
|
||||
(box.x1 - x_src) * bytes_per_pixel);
|
||||
}
|
||||
clip++;
|
||||
}
|
||||
|
||||
gl->enable (GLITZ_GL_SCISSOR_TEST);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
glitz_texture_bind (gl, texture);
|
||||
gl->get_tex_image (texture->target, 0,
|
||||
gl_format->format, gl_format->type,
|
||||
|
@ -1078,7 +1198,8 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
glitz_texture_unbind (gl, texture);
|
||||
}
|
||||
|
||||
if (transform) {
|
||||
if (transform)
|
||||
{
|
||||
glitz_image_t src_image, dst_image;
|
||||
|
||||
src_image.data = data;
|
||||
|
@ -1086,20 +1207,42 @@ glitz_get_pixels (glitz_surface_t *src,
|
|||
src_image.width = src_w;
|
||||
src_image.height = src_h;
|
||||
|
||||
dst_image.data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY);
|
||||
dst_image.data = glitz_buffer_map (buffer,
|
||||
GLITZ_BUFFER_ACCESS_WRITE_ONLY);
|
||||
dst_image.format = format;
|
||||
dst_image.width = width;
|
||||
dst_image.height = height;
|
||||
|
||||
if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP)
|
||||
src_y = src_h - src_y - height;
|
||||
clip = src->clip;
|
||||
n_clip = src->n_clip;
|
||||
|
||||
while (n_clip--)
|
||||
{
|
||||
box.x1 = clip->x1 + src->x_clip;
|
||||
box.y1 = clip->y1 + src->y_clip;
|
||||
box.x2 = clip->x2 + src->x_clip;
|
||||
box.y2 = clip->y2 + src->y_clip;
|
||||
if (x_src > box.x1)
|
||||
box.x1 = x_src;
|
||||
if (y_src > box.y1)
|
||||
box.y1 = y_src;
|
||||
if (x_src + width < box.x2)
|
||||
box.x2 = x_src + width;
|
||||
if (y_src + height < box.y2)
|
||||
box.y2 = y_src + height;
|
||||
|
||||
if (box.x1 < box.x2 && box.y1 < box.y2)
|
||||
{
|
||||
_glitz_pixel_transform (transform,
|
||||
&src_image,
|
||||
&dst_image,
|
||||
src_x, src_y,
|
||||
format->xoffset, format->skip_lines,
|
||||
width, height);
|
||||
box.x1 - x_src, box.y1 - y_src,
|
||||
format->xoffset + box.x1 - x_src,
|
||||
format->skip_lines + box.y1 - y_src,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
}
|
||||
clip++;
|
||||
}
|
||||
|
||||
glitz_buffer_unmap (buffer);
|
||||
} else
|
||||
|
|
|
@ -298,7 +298,8 @@ _glitz_program_under_limits (glitz_gl_proc_address_list_t *gl)
|
|||
{
|
||||
int i, n_limits;
|
||||
|
||||
n_limits = sizeof (_program_limits) / (sizeof (struct _glitz_program_query));
|
||||
n_limits = sizeof (_program_limits) /
|
||||
(sizeof (struct _glitz_program_query));
|
||||
|
||||
for (i = 0; i < n_limits; i++) {
|
||||
glitz_gl_int_t value, max;
|
||||
|
@ -425,7 +426,8 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
|
|||
|
||||
switch (fp_type) {
|
||||
case GLITZ_FP_CONVOLUTION:
|
||||
program = malloc (CONVOLUTION_BASE_SIZE + CONVOLUTION_SAMPLE_SIZE * id);
|
||||
program = malloc (CONVOLUTION_BASE_SIZE +
|
||||
CONVOLUTION_SAMPLE_SIZE * id);
|
||||
if (program == NULL)
|
||||
return 0;
|
||||
|
||||
|
@ -470,10 +472,12 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
|
|||
case GLITZ_FP_LINEAR_GRADIENT_NEAREST:
|
||||
case GLITZ_FP_LINEAR_GRADIENT_REPEAT:
|
||||
case GLITZ_FP_LINEAR_GRADIENT_REFLECT:
|
||||
_string_array_to_char_array (buffer, _linear_gradient_calculations);
|
||||
_string_array_to_char_array (buffer,
|
||||
_linear_gradient_calculations);
|
||||
break;
|
||||
default:
|
||||
_string_array_to_char_array (buffer, _radial_gradient_calculations);
|
||||
_string_array_to_char_array (buffer,
|
||||
_radial_gradient_calculations);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,6 @@ glitz_set_rectangles (glitz_surface_t *dst,
|
|||
{
|
||||
glitz_box_t *clip;
|
||||
int n_clip;
|
||||
int target_height = SURFACE_DRAWABLE_HEIGHT (dst);
|
||||
|
||||
gl->clear_color (color->red / (glitz_gl_clampf_t) 0xffff,
|
||||
color->green / (glitz_gl_clampf_t) 0xffff,
|
||||
|
@ -211,7 +210,7 @@ glitz_set_rectangles (glitz_surface_t *dst,
|
|||
if (box.x1 < box.x2 && box.y1 < box.y2)
|
||||
{
|
||||
gl->scissor (box.x1,
|
||||
target_height - dst->y - box.y2,
|
||||
dst->attached->height - dst->y - box.y2,
|
||||
box.x2 - box.x1,
|
||||
box.y2 - box.y1);
|
||||
|
||||
|
|
|
@ -121,7 +121,8 @@ glitz_region_union (glitz_region_t *region,
|
|||
} else {
|
||||
MERGE_BOXES (dst_box, box, new_box);
|
||||
if (n_box)
|
||||
memmove (box, box + 1, n_box * sizeof (glitz_box_t));
|
||||
memmove (box, box + 1,
|
||||
n_box * sizeof (glitz_box_t));
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
|
|
|
@ -92,12 +92,10 @@ glitz_surface_create (glitz_drawable_t *drawable,
|
|||
drawable->backend->texture_formats[format->id],
|
||||
feature_mask, unnormalized);
|
||||
|
||||
glitz_framebuffer_init (&surface->framebuffer);
|
||||
|
||||
if (width > 64 || height > 64)
|
||||
{
|
||||
glitz_surface_push_current (surface, GLITZ_CONTEXT_CURRENT);
|
||||
glitz_texture_size_check (&drawable->backend->gl, &surface->texture,
|
||||
glitz_texture_size_check (drawable->backend->gl, &surface->texture,
|
||||
drawable->backend->max_texture_2d_size,
|
||||
drawable->backend->max_texture_rect_size);
|
||||
glitz_surface_pop_current (surface);
|
||||
|
@ -122,13 +120,21 @@ glitz_surface_destroy (glitz_surface_t *surface)
|
|||
if (surface->ref_count)
|
||||
return;
|
||||
|
||||
if (surface->attached)
|
||||
{
|
||||
surface->attached->backend->detach_notify (surface->attached, surface);
|
||||
if (surface->attached->front == surface)
|
||||
surface->attached->front = NULL;
|
||||
else if (surface->attached->back == surface)
|
||||
surface->attached->back = NULL;
|
||||
|
||||
glitz_drawable_destroy (surface->attached);
|
||||
surface->attached = NULL;
|
||||
}
|
||||
|
||||
if (surface->texture.name) {
|
||||
glitz_surface_push_current (surface, GLITZ_ANY_CONTEXT_CURRENT);
|
||||
|
||||
glitz_framebuffer_fini (&surface->drawable->backend->gl,
|
||||
&surface->framebuffer);
|
||||
glitz_texture_fini (&surface->drawable->backend->gl, &surface->texture);
|
||||
|
||||
glitz_texture_fini (surface->drawable->backend->gl, &surface->texture);
|
||||
glitz_surface_pop_current (surface);
|
||||
}
|
||||
|
||||
|
@ -147,9 +153,6 @@ glitz_surface_destroy (glitz_surface_t *surface)
|
|||
if (surface->filter_params)
|
||||
free (surface->filter_params);
|
||||
|
||||
if (surface->attached)
|
||||
glitz_drawable_destroy (surface->attached);
|
||||
|
||||
glitz_drawable_destroy (surface->drawable);
|
||||
|
||||
free (surface);
|
||||
|
@ -164,7 +167,7 @@ glitz_surface_reference (glitz_surface_t *surface)
|
|||
surface->ref_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
_glitz_surface_sync_texture (glitz_surface_t *surface)
|
||||
{
|
||||
if (REGION_NOTEMPTY (&surface->texture_damage))
|
||||
|
@ -242,6 +245,7 @@ glitz_surface_sync_drawable (glitz_surface_t *surface)
|
|||
if (REGION_NOTEMPTY (&surface->drawable_damage))
|
||||
{
|
||||
glitz_texture_t *texture;
|
||||
glitz_texture_parameters_t param;
|
||||
glitz_box_t *box, *ext;
|
||||
int n_box;
|
||||
|
||||
|
@ -266,8 +270,10 @@ glitz_surface_sync_drawable (glitz_surface_t *surface)
|
|||
GLITZ_GL_REPLACE);
|
||||
gl->color_4us (0x0, 0x0, 0x0, 0xffff);
|
||||
|
||||
glitz_texture_ensure_wrap (gl, texture, GLITZ_GL_CLAMP_TO_EDGE);
|
||||
glitz_texture_ensure_filter (gl, texture, GLITZ_GL_NEAREST);
|
||||
param.filter[0] = param.filter[1] = GLITZ_GL_CLAMP_TO_EDGE;
|
||||
param.wrap[0] = param.wrap[1] = GLITZ_GL_NEAREST;
|
||||
|
||||
glitz_texture_ensure_parameters (gl, texture, ¶m);
|
||||
|
||||
glitz_set_operator (gl, GLITZ_OPERATOR_SRC);
|
||||
|
||||
|
@ -384,6 +390,8 @@ void
|
|||
glitz_surface_damage (glitz_surface_t *surface,
|
||||
glitz_box_t *box,
|
||||
int what)
|
||||
{
|
||||
if (surface->attached && !DRAWABLE_IS_FBO (surface->attached))
|
||||
{
|
||||
if (box)
|
||||
{
|
||||
|
@ -407,6 +415,7 @@ glitz_surface_damage (glitz_surface_t *surface,
|
|||
REGION_INIT (&surface->texture_damage, &surface->box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (what & GLITZ_DAMAGE_SOLID_MASK)
|
||||
surface->flags |= GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK;
|
||||
|
@ -427,18 +436,9 @@ _glitz_surface_update_state (glitz_surface_t *surface)
|
|||
|
||||
GLITZ_GL_SURFACE (surface);
|
||||
|
||||
if (surface->attached)
|
||||
{
|
||||
drawable = surface->attached;
|
||||
width = drawable->width;
|
||||
height = drawable->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawable = surface->drawable;
|
||||
width = surface->texture.width;
|
||||
height = surface->texture.height;
|
||||
}
|
||||
|
||||
if (drawable->update_all ||
|
||||
drawable->viewport.x != surface->x ||
|
||||
|
@ -481,31 +481,68 @@ _glitz_surface_update_state (glitz_surface_t *surface)
|
|||
void
|
||||
glitz_surface_attach (glitz_surface_t *surface,
|
||||
glitz_drawable_t *drawable,
|
||||
glitz_drawable_buffer_t buffer,
|
||||
int x,
|
||||
int y)
|
||||
glitz_drawable_buffer_t buffer)
|
||||
{
|
||||
if (drawable)
|
||||
{
|
||||
if (buffer == GLITZ_DRAWABLE_BUFFER_FRONT_COLOR)
|
||||
{
|
||||
if (surface == drawable->front)
|
||||
return;
|
||||
|
||||
if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR)
|
||||
drawable = NULL;
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
glitz_drawable_reference (drawable);
|
||||
if (drawable->front)
|
||||
glitz_surface_detach (drawable->front);
|
||||
|
||||
drawable->front = surface;
|
||||
}
|
||||
|
||||
surface->buffer = GLITZ_GL_FRONT;
|
||||
}
|
||||
else if ((buffer == GLITZ_DRAWABLE_BUFFER_BACK_COLOR) &&
|
||||
drawable->format->d.doublebuffer)
|
||||
{
|
||||
if (surface == drawable->back)
|
||||
return;
|
||||
|
||||
if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR)
|
||||
drawable = NULL;
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
glitz_drawable_reference (drawable);
|
||||
if (drawable->back)
|
||||
glitz_surface_detach (drawable->back);
|
||||
|
||||
drawable->back = surface;
|
||||
}
|
||||
|
||||
surface->buffer = GLITZ_GL_BACK;
|
||||
}
|
||||
else
|
||||
drawable = NULL;
|
||||
}
|
||||
|
||||
if (surface->attached)
|
||||
glitz_drawable_destroy (surface->attached);
|
||||
glitz_surface_detach (surface);
|
||||
|
||||
surface->attached = drawable;
|
||||
surface->x = x;
|
||||
surface->y = y;
|
||||
if (drawable)
|
||||
{
|
||||
surface->attached->backend->attach_notify (drawable, surface);
|
||||
|
||||
switch (buffer) {
|
||||
case GLITZ_DRAWABLE_BUFFER_FRONT_COLOR:
|
||||
surface->buffer = GLITZ_GL_FRONT;
|
||||
break;
|
||||
case GLITZ_DRAWABLE_BUFFER_BACK_COLOR:
|
||||
surface->buffer = GLITZ_GL_BACK;
|
||||
break;
|
||||
}
|
||||
if (TEXTURE_ALLOCATED (&surface->texture))
|
||||
glitz_surface_damage (surface, NULL, GLITZ_DAMAGE_DRAWABLE_MASK);
|
||||
|
||||
if ((!SURFACE_SOLID (surface)) || SURFACE_SOLID_DAMAGE (surface))
|
||||
REGION_EMPTY (&surface->texture_damage);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_surface_detach (glitz_surface_t *surface)
|
||||
|
@ -520,11 +557,17 @@ glitz_surface_detach (glitz_surface_t *surface)
|
|||
glitz_surface_pop_current (surface);
|
||||
}
|
||||
|
||||
surface->attached->backend->detach_notify (surface->attached, surface);
|
||||
|
||||
if (surface == surface->attached->front)
|
||||
surface->attached->front = NULL;
|
||||
|
||||
if (surface == surface->attached->back)
|
||||
surface->attached->back = NULL;
|
||||
|
||||
glitz_drawable_destroy (surface->attached);
|
||||
|
||||
surface->attached = NULL;
|
||||
surface->buffer = GLITZ_GL_FRONT;
|
||||
surface->x = 0;
|
||||
surface->y = 0;
|
||||
|
||||
REGION_EMPTY (&surface->drawable_damage);
|
||||
REGION_INIT (&surface->drawable_damage, &surface->box);
|
||||
|
@ -548,70 +591,79 @@ glitz_bool_t
|
|||
glitz_surface_push_current (glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint)
|
||||
{
|
||||
glitz_drawable_t *drawable;
|
||||
|
||||
if (surface->attached)
|
||||
{
|
||||
surface->attached->backend->push_current (surface->attached,
|
||||
surface,
|
||||
constraint);
|
||||
drawable = surface->attached;
|
||||
if (drawable->backend->push_current (drawable, surface,
|
||||
constraint))
|
||||
{
|
||||
if (constraint == GLITZ_DRAWABLE_CURRENT)
|
||||
{
|
||||
if (surface->attached->backend->feature_mask &
|
||||
if (drawable->backend->feature_mask &
|
||||
GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK)
|
||||
glitz_framebuffer_unbind (&surface->attached->backend->gl);
|
||||
{
|
||||
if (!surface->fb)
|
||||
{
|
||||
GLITZ_GL_DRAWABLE (drawable);
|
||||
|
||||
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0);
|
||||
|
||||
_glitz_surface_update_state (surface);
|
||||
glitz_surface_sync_drawable (surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glitz_surface_update_state (surface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
surface->drawable->backend->push_current (surface->drawable,
|
||||
surface,
|
||||
constraint);
|
||||
_glitz_surface_update_state (surface);
|
||||
glitz_surface_sync_drawable (surface);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawable = surface->drawable;
|
||||
|
||||
if (constraint == GLITZ_DRAWABLE_CURRENT)
|
||||
{
|
||||
if (surface->drawable->backend->feature_mask &
|
||||
GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK)
|
||||
drawable->backend->push_current (drawable, surface,
|
||||
GLITZ_ANY_CONTEXT_CURRENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (glitz_framebuffer_complete (&surface->drawable->backend->gl,
|
||||
&surface->framebuffer,
|
||||
&surface->texture))
|
||||
{
|
||||
_glitz_surface_update_state (surface);
|
||||
return 1;
|
||||
return drawable->backend->push_current (drawable, surface,
|
||||
constraint);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
glitz_surface_pop_current (glitz_surface_t *surface)
|
||||
{
|
||||
glitz_drawable_t *drawable;
|
||||
glitz_surface_t *other;
|
||||
|
||||
if (surface->attached) {
|
||||
other = surface->attached->backend->pop_current (surface->attached);
|
||||
} else {
|
||||
if (surface->framebuffer.name)
|
||||
glitz_framebuffer_unbind (&surface->drawable->backend->gl);
|
||||
drawable = (surface->attached) ? surface->attached : surface->drawable;
|
||||
|
||||
other = surface->drawable->backend->pop_current (surface->drawable);
|
||||
}
|
||||
|
||||
if (other) {
|
||||
if ((!other->attached) &&
|
||||
(other->drawable->backend->feature_mask &
|
||||
GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK))
|
||||
other = drawable->backend->pop_current (drawable);
|
||||
if (other)
|
||||
{
|
||||
glitz_framebuffer_complete (&other->drawable->backend->gl,
|
||||
&other->framebuffer,
|
||||
&other->texture);
|
||||
}
|
||||
if (other->fb)
|
||||
drawable->backend->gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER,
|
||||
other->fb);
|
||||
|
||||
_glitz_surface_update_state (other);
|
||||
}
|
||||
}
|
||||
|
@ -638,7 +690,8 @@ glitz_surface_set_transform (glitz_surface_t *surface,
|
|||
if (!surface->transform) {
|
||||
surface->transform = malloc (sizeof (glitz_matrix_t));
|
||||
if (surface->transform == NULL) {
|
||||
glitz_surface_status_add (surface, GLITZ_STATUS_NO_MEMORY_MASK);
|
||||
glitz_surface_status_add (surface,
|
||||
GLITZ_STATUS_NO_MEMORY_MASK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -714,12 +767,14 @@ glitz_surface_set_transform (glitz_surface_t *surface,
|
|||
t[13] -= t[5] * height;
|
||||
t[15] -= t[7] * height;
|
||||
|
||||
/* Translate coordinates into texture. This only makes a difference when
|
||||
GL_ARB_texture_border_clamp is missing as box.x1 and box.y1 are
|
||||
/* Translate coordinates into texture. This only makes a difference
|
||||
when GL_ARB_texture_border_clamp is missing as box.x1 and box.y1 are
|
||||
otherwise always zero. This breaks projective transformations so
|
||||
those wont work without GL_ARB_texture_border_clamp. */
|
||||
t[12] += surface->texture.texcoord_width_unit * surface->texture.box.x1;
|
||||
t[13] += surface->texture.texcoord_height_unit * surface->texture.box.y1;
|
||||
t[12] += surface->texture.texcoord_width_unit *
|
||||
surface->texture.box.x1;
|
||||
t[13] += surface->texture.texcoord_height_unit *
|
||||
surface->texture.box.y1;
|
||||
|
||||
surface->flags |= GLITZ_SURFACE_FLAG_TRANSFORM_MASK;
|
||||
if (m[3] != 0.0f || m[7] != 0.0f || (m[15] != 1.0f && m[15] != -1.0f))
|
||||
|
@ -787,7 +842,8 @@ glitz_surface_set_filter (glitz_surface_t *surface,
|
|||
|
||||
status = glitz_filter_set_params (surface, filter, params, n_params);
|
||||
if (status) {
|
||||
glitz_surface_status_add (surface, glitz_status_to_status_mask (status));
|
||||
glitz_surface_status_add (surface,
|
||||
glitz_status_to_status_mask (status));
|
||||
} else {
|
||||
switch (filter) {
|
||||
case GLITZ_FILTER_NEAREST:
|
||||
|
@ -836,11 +892,18 @@ slim_hidden_def(glitz_surface_set_dither);
|
|||
void
|
||||
glitz_surface_flush (glitz_surface_t *surface)
|
||||
{
|
||||
if (surface->attached && REGION_NOTEMPTY (&surface->drawable_damage)) {
|
||||
if (!surface->attached)
|
||||
return;
|
||||
|
||||
if (!DRAWABLE_IS_FBO (surface->attached))
|
||||
{
|
||||
if (REGION_NOTEMPTY (&surface->drawable_damage))
|
||||
{
|
||||
glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT);
|
||||
glitz_surface_pop_current (surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
slim_hidden_def(glitz_surface_flush);
|
||||
|
||||
unsigned int
|
||||
|
@ -914,14 +977,3 @@ glitz_surface_set_clip_region (glitz_surface_t *surface,
|
|||
}
|
||||
}
|
||||
slim_hidden_def(glitz_surface_set_clip_region);
|
||||
|
||||
glitz_bool_t
|
||||
glitz_surface_valid_target (glitz_surface_t *surface)
|
||||
{
|
||||
glitz_bool_t valid;
|
||||
|
||||
valid = glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT);
|
||||
glitz_surface_pop_current (surface);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,12 @@ glitz_texture_init (glitz_texture_t *texture,
|
|||
unsigned long feature_mask,
|
||||
glitz_bool_t unnormalized)
|
||||
{
|
||||
texture->filter = 0;
|
||||
texture->wrap = 0;
|
||||
texture->param.filter[0] = texture->param.filter[1] = GLITZ_GL_NEAREST;
|
||||
texture->param.wrap[0] = texture->param.wrap[1] = GLITZ_GL_CLAMP;
|
||||
texture->param.border_color.red = texture->param.border_color.green =
|
||||
texture->param.border_color.blue =
|
||||
texture->param.border_color.alpha = 0;
|
||||
|
||||
texture->format = texture_format;
|
||||
texture->name = 0;
|
||||
|
||||
|
@ -103,7 +107,8 @@ void
|
|||
glitz_texture_size_check (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_t *texture,
|
||||
glitz_gl_int_t max_2d,
|
||||
glitz_gl_int_t max_rect) {
|
||||
glitz_gl_int_t max_rect)
|
||||
{
|
||||
glitz_gl_enum_t proxy_target;
|
||||
glitz_gl_int_t value, max;
|
||||
|
||||
|
@ -168,12 +173,10 @@ glitz_texture_allocate (glitz_gl_proc_address_list_t *gl,
|
|||
|
||||
gl->tex_parameter_i (texture->target,
|
||||
GLITZ_GL_TEXTURE_MAG_FILTER,
|
||||
GLITZ_GL_NEAREST);
|
||||
texture->param.filter[0]);
|
||||
gl->tex_parameter_i (texture->target,
|
||||
GLITZ_GL_TEXTURE_MIN_FILTER,
|
||||
GLITZ_GL_NEAREST);
|
||||
|
||||
texture->filter = GLITZ_GL_NEAREST;
|
||||
texture->param.filter[1]);
|
||||
|
||||
glitz_texture_unbind (gl, texture);
|
||||
|
||||
|
@ -189,36 +192,6 @@ glitz_texture_fini (glitz_gl_proc_address_list_t *gl,
|
|||
gl->delete_textures (1, &texture->name);
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_ensure_filter (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_t *texture,
|
||||
glitz_gl_enum_t filter)
|
||||
{
|
||||
if (!texture->name)
|
||||
return;
|
||||
|
||||
if (texture->filter != filter) {
|
||||
gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_MAG_FILTER, filter);
|
||||
gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_MIN_FILTER, filter);
|
||||
texture->filter = filter;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_ensure_wrap (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_t *texture,
|
||||
glitz_gl_enum_t wrap)
|
||||
{
|
||||
if (!texture->name)
|
||||
return;
|
||||
|
||||
if (texture->wrap != wrap) {
|
||||
gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_WRAP_S, wrap);
|
||||
gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_WRAP_T, wrap);
|
||||
texture->wrap = wrap;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_bind (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_t *texture)
|
||||
|
@ -345,3 +318,157 @@ glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
|
|||
} else
|
||||
gl->disable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
glitz_texture_object_t *
|
||||
glitz_texture_object_create (glitz_surface_t *surface)
|
||||
{
|
||||
glitz_texture_object_t *texture;
|
||||
|
||||
GLITZ_GL_SURFACE (surface);
|
||||
|
||||
/* GL_ARB_texture_rectangle is required for sane texture coordinates.
|
||||
GL_ARB_texture_border_clamp is required right now as glitz will
|
||||
emulate it when missing, which means a 1 pixel translucent black
|
||||
border inside textures and that cannot be exposed to clients. */
|
||||
if ((!(surface->drawable->backend->feature_mask &
|
||||
GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)) ||
|
||||
(!(surface->drawable->backend->feature_mask &
|
||||
GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)))
|
||||
return 0;
|
||||
|
||||
texture = malloc (sizeof (glitz_texture_object_t));
|
||||
if (!texture)
|
||||
return 0;
|
||||
|
||||
texture->ref_count = 1;
|
||||
|
||||
glitz_surface_reference (surface);
|
||||
texture->surface = surface;
|
||||
|
||||
if (!(TEXTURE_ALLOCATED (&surface->texture)))
|
||||
glitz_texture_allocate (gl, &surface->texture);
|
||||
|
||||
texture->param = surface->texture.param;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_object_destroy (glitz_texture_object_t *texture)
|
||||
{
|
||||
texture->ref_count--;
|
||||
if (texture->ref_count)
|
||||
return;
|
||||
|
||||
glitz_surface_destroy (texture->surface);
|
||||
free (texture);
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_object_reference (glitz_texture_object_t *texture)
|
||||
{
|
||||
texture->ref_count++;
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_object_set_filter (glitz_texture_object_t *texture,
|
||||
glitz_texture_filter_type_t type,
|
||||
glitz_texture_filter_t filter)
|
||||
{
|
||||
static glitz_gl_enum_t filters[] = {
|
||||
GLITZ_GL_NEAREST,
|
||||
GLITZ_GL_LINEAR
|
||||
};
|
||||
|
||||
texture->param.filter[type] = filters[filter];
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_object_set_wrap (glitz_texture_object_t *texture,
|
||||
glitz_texture_wrap_type_t type,
|
||||
glitz_texture_wrap_t wrap)
|
||||
{
|
||||
static glitz_gl_enum_t wraps[] = {
|
||||
GLITZ_GL_CLAMP,
|
||||
GLITZ_GL_CLAMP_TO_EDGE,
|
||||
GLITZ_GL_CLAMP_TO_BORDER,
|
||||
GLITZ_GL_REPEAT,
|
||||
GLITZ_GL_MIRRORED_REPEAT
|
||||
};
|
||||
|
||||
texture->param.wrap[type] = wraps[wrap];
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_object_set_border_color (glitz_texture_object_t *texture,
|
||||
glitz_color_t *color)
|
||||
{
|
||||
texture->param.border_color = *color;
|
||||
}
|
||||
|
||||
void
|
||||
glitz_texture_ensure_parameters (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_t *texture,
|
||||
glitz_texture_parameters_t *param)
|
||||
{
|
||||
static const glitz_gl_enum_t filters[] = {
|
||||
GLITZ_GL_TEXTURE_MAG_FILTER,
|
||||
GLITZ_GL_TEXTURE_MIN_FILTER
|
||||
};
|
||||
static const glitz_gl_enum_t wraps[] = {
|
||||
GLITZ_GL_TEXTURE_WRAP_S,
|
||||
GLITZ_GL_TEXTURE_WRAP_T
|
||||
};
|
||||
int i;
|
||||
|
||||
if (!texture->name)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (texture->param.filter[i] != param->filter[i])
|
||||
{
|
||||
texture->param.filter[i] = param->filter[i];
|
||||
gl->tex_parameter_i (texture->target, filters[i],
|
||||
param->filter[i]);
|
||||
}
|
||||
|
||||
if (texture->param.wrap[i] != param->wrap[i])
|
||||
{
|
||||
texture->param.wrap[i] = param->wrap[i];
|
||||
gl->tex_parameter_i (texture->target, wraps[i], param->wrap[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (texture->param.wrap[0] == GLITZ_GL_CLAMP_TO_BORDER ||
|
||||
texture->param.wrap[1] == GLITZ_GL_CLAMP_TO_BORDER ||
|
||||
texture->param.wrap[0] == GLITZ_GL_CLAMP ||
|
||||
texture->param.wrap[1] == GLITZ_GL_CLAMP)
|
||||
{
|
||||
if (memcmp (&texture->param.border_color, ¶m->border_color,
|
||||
sizeof (glitz_color_t)))
|
||||
{
|
||||
glitz_vec4_t vec;
|
||||
|
||||
vec.v[0] = (glitz_float_t) param->border_color.red / 0xffff;
|
||||
vec.v[1] = (glitz_float_t) param->border_color.green / 0xffff;
|
||||
vec.v[2] = (glitz_float_t) param->border_color.blue / 0xffff;
|
||||
vec.v[3] = (glitz_float_t) param->border_color.alpha / 0xffff;
|
||||
|
||||
gl->tex_parameter_fv (texture->target,
|
||||
GLITZ_GL_TEXTURE_BORDER_COLOR,
|
||||
vec.v);
|
||||
|
||||
texture->param.border_color = param->border_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glitz_texture_target_t
|
||||
glitz_texture_object_get_target (glitz_texture_object_t *texture)
|
||||
{
|
||||
if (texture->surface->texture.target == GLITZ_GL_TEXTURE_2D)
|
||||
return GLITZ_TEXTURE_TARGET_2D;
|
||||
|
||||
return GLITZ_TEXTURE_TARGET_RECT;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ static glitz_extension_map gl_extensions[] = {
|
|||
{ 0.0, "GL_EXT_blend_color", GLITZ_FEATURE_BLEND_COLOR_MASK },
|
||||
{ 0.0, "GL_ARB_imaging", GLITZ_FEATURE_BLEND_COLOR_MASK },
|
||||
{ 0.0, "GL_APPLE_packed_pixels", GLITZ_FEATURE_PACKED_PIXELS_MASK },
|
||||
{ 0.0, "GL_EXT_framebuffer_object", GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK },
|
||||
{ 0.0, "GL_EXT_framebuffer_object",
|
||||
GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK },
|
||||
{ 0.0, NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -143,136 +144,161 @@ _glitz_gl_proc_address_lookup (glitz_backend_t *backend,
|
|||
{
|
||||
if (backend->feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) {
|
||||
if (backend->gl_version >= 1.4f) {
|
||||
backend->gl.blend_color = (glitz_gl_blend_color_t)
|
||||
backend->gl->blend_color = (glitz_gl_blend_color_t)
|
||||
get_proc_address ("glBlendColor", closure);
|
||||
} else {
|
||||
backend->gl.blend_color = (glitz_gl_blend_color_t)
|
||||
backend->gl->blend_color = (glitz_gl_blend_color_t)
|
||||
get_proc_address ("glBlendColorEXT", closure);
|
||||
}
|
||||
|
||||
if (!backend->gl.blend_color)
|
||||
if (!backend->gl->blend_color)
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_BLEND_COLOR_MASK;
|
||||
}
|
||||
|
||||
if (backend->feature_mask & GLITZ_FEATURE_MULTITEXTURE_MASK) {
|
||||
if (backend->gl_version >= 1.3f) {
|
||||
backend->gl.active_texture = (glitz_gl_active_texture_t)
|
||||
backend->gl->active_texture = (glitz_gl_active_texture_t)
|
||||
get_proc_address ("glActiveTexture", closure);
|
||||
backend->gl.client_active_texture = (glitz_gl_client_active_texture_t)
|
||||
backend->gl->client_active_texture =
|
||||
(glitz_gl_client_active_texture_t)
|
||||
get_proc_address ("glClientActiveTexture", closure);
|
||||
} else {
|
||||
backend->gl.active_texture = (glitz_gl_active_texture_t)
|
||||
backend->gl->active_texture = (glitz_gl_active_texture_t)
|
||||
get_proc_address ("glActiveTextureARB", closure);
|
||||
backend->gl.client_active_texture = (glitz_gl_client_active_texture_t)
|
||||
backend->gl->client_active_texture =
|
||||
(glitz_gl_client_active_texture_t)
|
||||
get_proc_address ("glClientActiveTextureARB", closure);
|
||||
}
|
||||
|
||||
if ((!backend->gl.active_texture) ||
|
||||
(!backend->gl.client_active_texture)) {
|
||||
if ((!backend->gl->active_texture) ||
|
||||
(!backend->gl->client_active_texture)) {
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_MULTITEXTURE_MASK;
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK;
|
||||
backend->feature_mask &=
|
||||
~GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (backend->feature_mask & GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK) {
|
||||
backend->gl.multi_draw_arrays = (glitz_gl_multi_draw_arrays_t)
|
||||
backend->gl->multi_draw_arrays = (glitz_gl_multi_draw_arrays_t)
|
||||
get_proc_address ("glMultiDrawArraysEXT", closure);
|
||||
|
||||
if (!backend->gl.multi_draw_arrays)
|
||||
if (!backend->gl->multi_draw_arrays)
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK;
|
||||
}
|
||||
|
||||
if (backend->feature_mask & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK) {
|
||||
backend->gl.gen_programs = (glitz_gl_gen_programs_t)
|
||||
backend->gl->gen_programs = (glitz_gl_gen_programs_t)
|
||||
get_proc_address ("glGenProgramsARB", closure);
|
||||
backend->gl.delete_programs = (glitz_gl_delete_programs_t)
|
||||
backend->gl->delete_programs = (glitz_gl_delete_programs_t)
|
||||
get_proc_address ("glDeleteProgramsARB", closure);
|
||||
backend->gl.program_string = (glitz_gl_program_string_t)
|
||||
backend->gl->program_string = (glitz_gl_program_string_t)
|
||||
get_proc_address ("glProgramStringARB", closure);
|
||||
backend->gl.bind_program = (glitz_gl_bind_program_t)
|
||||
backend->gl->bind_program = (glitz_gl_bind_program_t)
|
||||
get_proc_address ("glBindProgramARB", closure);
|
||||
backend->gl.program_local_param_4fv = (glitz_gl_program_local_param_4fv_t)
|
||||
backend->gl->program_local_param_4fv =
|
||||
(glitz_gl_program_local_param_4fv_t)
|
||||
get_proc_address ("glProgramLocalParameter4fvARB", closure);
|
||||
backend->gl.get_program_iv = (glitz_gl_get_program_iv_t)
|
||||
backend->gl->get_program_iv = (glitz_gl_get_program_iv_t)
|
||||
get_proc_address ("glGetProgramivARB", closure);
|
||||
|
||||
if ((!backend->gl.gen_programs) ||
|
||||
(!backend->gl.delete_programs) ||
|
||||
(!backend->gl.program_string) ||
|
||||
(!backend->gl.bind_program) ||
|
||||
(!backend->gl.program_local_param_4fv))
|
||||
if ((!backend->gl->gen_programs) ||
|
||||
(!backend->gl->delete_programs) ||
|
||||
(!backend->gl->program_string) ||
|
||||
(!backend->gl->bind_program) ||
|
||||
(!backend->gl->program_local_param_4fv))
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK;
|
||||
}
|
||||
|
||||
if ((backend->feature_mask & GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK) ||
|
||||
(backend->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK)) {
|
||||
if (backend->gl_version >= 1.5f) {
|
||||
backend->gl.gen_buffers = (glitz_gl_gen_buffers_t)
|
||||
backend->gl->gen_buffers = (glitz_gl_gen_buffers_t)
|
||||
get_proc_address ("glGenBuffers", closure);
|
||||
backend->gl.delete_buffers = (glitz_gl_delete_buffers_t)
|
||||
backend->gl->delete_buffers = (glitz_gl_delete_buffers_t)
|
||||
get_proc_address ("glDeleteBuffers", closure);
|
||||
backend->gl.bind_buffer = (glitz_gl_bind_buffer_t)
|
||||
backend->gl->bind_buffer = (glitz_gl_bind_buffer_t)
|
||||
get_proc_address ("glBindBuffer", closure);
|
||||
backend->gl.buffer_data = (glitz_gl_buffer_data_t)
|
||||
backend->gl->buffer_data = (glitz_gl_buffer_data_t)
|
||||
get_proc_address ("glBufferData", closure);
|
||||
backend->gl.buffer_sub_data = (glitz_gl_buffer_sub_data_t)
|
||||
backend->gl->buffer_sub_data = (glitz_gl_buffer_sub_data_t)
|
||||
get_proc_address ("glBufferSubData", closure);
|
||||
backend->gl.get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t)
|
||||
backend->gl->get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t)
|
||||
get_proc_address ("glGetBufferSubData", closure);
|
||||
backend->gl.map_buffer = (glitz_gl_map_buffer_t)
|
||||
backend->gl->map_buffer = (glitz_gl_map_buffer_t)
|
||||
get_proc_address ("glMapBuffer", closure);
|
||||
backend->gl.unmap_buffer = (glitz_gl_unmap_buffer_t)
|
||||
backend->gl->unmap_buffer = (glitz_gl_unmap_buffer_t)
|
||||
get_proc_address ("glUnmapBuffer", closure);
|
||||
} else {
|
||||
backend->gl.gen_buffers = (glitz_gl_gen_buffers_t)
|
||||
backend->gl->gen_buffers = (glitz_gl_gen_buffers_t)
|
||||
get_proc_address ("glGenBuffersARB", closure);
|
||||
backend->gl.delete_buffers = (glitz_gl_delete_buffers_t)
|
||||
backend->gl->delete_buffers = (glitz_gl_delete_buffers_t)
|
||||
get_proc_address ("glDeleteBuffersARB", closure);
|
||||
backend->gl.bind_buffer = (glitz_gl_bind_buffer_t)
|
||||
backend->gl->bind_buffer = (glitz_gl_bind_buffer_t)
|
||||
get_proc_address ("glBindBufferARB", closure);
|
||||
backend->gl.buffer_data = (glitz_gl_buffer_data_t)
|
||||
backend->gl->buffer_data = (glitz_gl_buffer_data_t)
|
||||
get_proc_address ("glBufferDataARB", closure);
|
||||
backend->gl.buffer_sub_data = (glitz_gl_buffer_sub_data_t)
|
||||
backend->gl->buffer_sub_data = (glitz_gl_buffer_sub_data_t)
|
||||
get_proc_address ("glBufferSubDataARB", closure);
|
||||
backend->gl.get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t)
|
||||
backend->gl->get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t)
|
||||
get_proc_address ("glGetBufferSubDataARB", closure);
|
||||
backend->gl.map_buffer = (glitz_gl_map_buffer_t)
|
||||
backend->gl->map_buffer = (glitz_gl_map_buffer_t)
|
||||
get_proc_address ("glMapBufferARB", closure);
|
||||
backend->gl.unmap_buffer = (glitz_gl_unmap_buffer_t)
|
||||
backend->gl->unmap_buffer = (glitz_gl_unmap_buffer_t)
|
||||
get_proc_address ("glUnmapBufferARB", closure);
|
||||
}
|
||||
|
||||
if ((!backend->gl.gen_buffers) ||
|
||||
(!backend->gl.delete_buffers) ||
|
||||
(!backend->gl.bind_buffer) ||
|
||||
(!backend->gl.buffer_data) ||
|
||||
(!backend->gl.buffer_sub_data) ||
|
||||
(!backend->gl.get_buffer_sub_data) ||
|
||||
(!backend->gl.map_buffer) ||
|
||||
(!backend->gl.unmap_buffer)) {
|
||||
if ((!backend->gl->gen_buffers) ||
|
||||
(!backend->gl->delete_buffers) ||
|
||||
(!backend->gl->bind_buffer) ||
|
||||
(!backend->gl->buffer_data) ||
|
||||
(!backend->gl->buffer_sub_data) ||
|
||||
(!backend->gl->get_buffer_sub_data) ||
|
||||
(!backend->gl->map_buffer) ||
|
||||
(!backend->gl->unmap_buffer)) {
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK;
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (backend->feature_mask & GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) {
|
||||
backend->gl.gen_framebuffers = (glitz_gl_gen_framebuffers_t)
|
||||
backend->gl->gen_framebuffers = (glitz_gl_gen_framebuffers_t)
|
||||
get_proc_address ("glGenFramebuffersEXT", closure);
|
||||
backend->gl.delete_framebuffers = (glitz_gl_delete_framebuffers_t)
|
||||
backend->gl->delete_framebuffers = (glitz_gl_delete_framebuffers_t)
|
||||
get_proc_address ("glDeleteFramebuffersEXT", closure);
|
||||
backend->gl.bind_framebuffer = (glitz_gl_bind_framebuffer_t)
|
||||
backend->gl->bind_framebuffer = (glitz_gl_bind_framebuffer_t)
|
||||
get_proc_address ("glBindFramebufferEXT", closure);
|
||||
backend->gl.check_framebuffer_status =
|
||||
backend->gl->framebuffer_renderbuffer =
|
||||
(glitz_gl_framebuffer_renderbuffer_t)
|
||||
get_proc_address ("glFramebufferRenderbufferEXT", closure);
|
||||
backend->gl->framebuffer_texture_2d =
|
||||
(glitz_gl_framebuffer_texture_2d_t)
|
||||
get_proc_address ("glFramebufferTexture2DEXT", closure);
|
||||
backend->gl->check_framebuffer_status =
|
||||
(glitz_gl_check_framebuffer_status_t)
|
||||
get_proc_address ("glCheckFramebufferStatusEXT", closure);
|
||||
backend->gl.framebuffer_texture_2d = (glitz_gl_framebuffer_texture_2d_t)
|
||||
get_proc_address ("glFramebufferTexture2DEXT", closure);
|
||||
backend->gl->gen_renderbuffers = (glitz_gl_gen_renderbuffers_t)
|
||||
get_proc_address ("glGenRenderbuffersEXT", closure);
|
||||
backend->gl->delete_renderbuffers = (glitz_gl_delete_renderbuffers_t)
|
||||
get_proc_address ("glDeleteRenderbuffersEXT", closure);
|
||||
backend->gl->bind_renderbuffer = (glitz_gl_bind_renderbuffer_t)
|
||||
get_proc_address ("glBindRenderbufferEXT", closure);
|
||||
backend->gl->renderbuffer_storage = (glitz_gl_renderbuffer_storage_t)
|
||||
get_proc_address ("glRenderbufferStorageEXT", closure);
|
||||
backend->gl->get_renderbuffer_parameter_iv =
|
||||
(glitz_gl_get_renderbuffer_parameter_iv_t)
|
||||
get_proc_address ("glGetRenderbufferParameterivEXT", closure);
|
||||
|
||||
if ((!backend->gl.gen_framebuffers) ||
|
||||
(!backend->gl.delete_framebuffers) ||
|
||||
(!backend->gl.bind_framebuffer) ||
|
||||
(!backend->gl.check_framebuffer_status) ||
|
||||
(!backend->gl.framebuffer_texture_2d))
|
||||
if ((!backend->gl->gen_framebuffers) ||
|
||||
(!backend->gl->delete_framebuffers) ||
|
||||
(!backend->gl->bind_framebuffer) ||
|
||||
(!backend->gl->framebuffer_renderbuffer) ||
|
||||
(!backend->gl->framebuffer_texture_2d) ||
|
||||
(!backend->gl->check_framebuffer_status) ||
|
||||
(!backend->gl->gen_renderbuffers) ||
|
||||
(!backend->gl->delete_renderbuffers) ||
|
||||
(!backend->gl->bind_renderbuffer) ||
|
||||
(!backend->gl->renderbuffer_storage) ||
|
||||
(!backend->gl->get_renderbuffer_parameter_iv))
|
||||
backend->feature_mask &= ~GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK;
|
||||
}
|
||||
}
|
||||
|
@ -282,21 +308,28 @@ glitz_backend_init (glitz_backend_t *backend,
|
|||
glitz_get_proc_address_proc_t get_proc_address,
|
||||
void *closure)
|
||||
{
|
||||
if (!_glitz_query_gl_extensions (&backend->gl,
|
||||
if (!_glitz_query_gl_extensions (backend->gl,
|
||||
&backend->gl_version,
|
||||
&backend->feature_mask)) {
|
||||
_glitz_gl_proc_address_lookup (backend, get_proc_address, closure);
|
||||
glitz_create_surface_formats (&backend->gl,
|
||||
glitz_create_surface_formats (backend->gl,
|
||||
&backend->formats,
|
||||
&backend->texture_formats,
|
||||
&backend->n_formats);
|
||||
_glitz_add_drawable_formats (backend->gl,
|
||||
backend->feature_mask,
|
||||
&backend->drawable_formats,
|
||||
&backend->n_drawable_formats);
|
||||
}
|
||||
|
||||
backend->gl.get_integer_v (GLITZ_GL_MAX_TEXTURE_SIZE,
|
||||
backend->gl->get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS,
|
||||
backend->max_viewport_dims);
|
||||
|
||||
backend->gl->get_integer_v (GLITZ_GL_MAX_TEXTURE_SIZE,
|
||||
&backend->max_texture_2d_size);
|
||||
|
||||
if (backend->feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK)
|
||||
backend->gl.get_integer_v (GLITZ_GL_MAX_RECTANGLE_TEXTURE_SIZE,
|
||||
backend->gl->get_integer_v (GLITZ_GL_MAX_RECTANGLE_TEXTURE_SIZE,
|
||||
&backend->max_texture_rect_size);
|
||||
else
|
||||
backend->max_texture_rect_size = 0;
|
||||
|
@ -359,7 +392,8 @@ glitz_initiate_state (glitz_gl_proc_address_list_t *gl)
|
|||
gl->disable (GLITZ_GL_LINE_SMOOTH);
|
||||
gl->disable (GLITZ_GL_POINT_SMOOTH);
|
||||
gl->shade_model (GLITZ_GL_FLAT);
|
||||
gl->color_mask (GLITZ_GL_TRUE, GLITZ_GL_TRUE, GLITZ_GL_TRUE, GLITZ_GL_TRUE);
|
||||
gl->color_mask (GLITZ_GL_TRUE, GLITZ_GL_TRUE,
|
||||
GLITZ_GL_TRUE, GLITZ_GL_TRUE);
|
||||
gl->enable (GLITZ_GL_SCISSOR_TEST);
|
||||
gl->disable (GLITZ_GL_STENCIL_TEST);
|
||||
gl->enable_client_state (GLITZ_GL_VERTEX_ARRAY);
|
||||
|
|
|
@ -145,6 +145,7 @@ typedef struct _glitz_gl_proc_address_list_t {
|
|||
glitz_gl_bind_texture_t bind_texture;
|
||||
glitz_gl_tex_image_2d_t tex_image_2d;
|
||||
glitz_gl_tex_parameter_i_t tex_parameter_i;
|
||||
glitz_gl_tex_parameter_fv_t tex_parameter_fv;
|
||||
glitz_gl_get_tex_level_parameter_iv_t get_tex_level_parameter_iv;
|
||||
glitz_gl_copy_tex_sub_image_2d_t copy_tex_sub_image_2d;
|
||||
glitz_gl_get_integer_v_t get_integer_v;
|
||||
|
@ -171,8 +172,14 @@ typedef struct _glitz_gl_proc_address_list_t {
|
|||
glitz_gl_gen_framebuffers_t gen_framebuffers;
|
||||
glitz_gl_delete_framebuffers_t delete_framebuffers;
|
||||
glitz_gl_bind_framebuffer_t bind_framebuffer;
|
||||
glitz_gl_check_framebuffer_status_t check_framebuffer_status;
|
||||
glitz_gl_framebuffer_renderbuffer_t framebuffer_renderbuffer;
|
||||
glitz_gl_framebuffer_texture_2d_t framebuffer_texture_2d;
|
||||
glitz_gl_check_framebuffer_status_t check_framebuffer_status;
|
||||
glitz_gl_gen_renderbuffers_t gen_renderbuffers;
|
||||
glitz_gl_delete_renderbuffers_t delete_renderbuffers;
|
||||
glitz_gl_bind_renderbuffer_t bind_renderbuffer;
|
||||
glitz_gl_renderbuffer_storage_t renderbuffer_storage;
|
||||
glitz_gl_get_renderbuffer_parameter_iv_t get_renderbuffer_parameter_iv;
|
||||
} glitz_gl_proc_address_list_t;
|
||||
|
||||
typedef int glitz_surface_type_t;
|
||||
|
@ -309,6 +316,26 @@ extern glitz_status_t __internal_linkage
|
|||
glitz_region_union (glitz_region_t *region,
|
||||
glitz_box_t *box);
|
||||
|
||||
#define GLITZ_DRAWABLE_TYPE_WINDOW_MASK (1L << 0)
|
||||
#define GLITZ_DRAWABLE_TYPE_PBUFFER_MASK (1L << 1)
|
||||
#define GLITZ_DRAWABLE_TYPE_FBO_MASK (1L << 2)
|
||||
|
||||
#define GLITZ_INT_FORMAT_WINDOW_MASK (1L << 17)
|
||||
#define GLITZ_INT_FORMAT_PBUFFER_MASK (1L << 18)
|
||||
#define GLITZ_INT_FORMAT_FBO_MASK (1L << 19)
|
||||
|
||||
typedef struct _glitz_int_drawable_format_t {
|
||||
glitz_drawable_format_t d;
|
||||
unsigned int types;
|
||||
int caveat;
|
||||
union {
|
||||
void *ptr;
|
||||
long val;
|
||||
unsigned long uval;
|
||||
void *(*fptr) (void);
|
||||
} u;
|
||||
} glitz_int_drawable_format_t;
|
||||
|
||||
typedef struct glitz_backend {
|
||||
glitz_drawable_t *
|
||||
(*create_pbuffer) (void *drawable,
|
||||
|
@ -319,7 +346,7 @@ typedef struct glitz_backend {
|
|||
void
|
||||
(*destroy) (void *drawable);
|
||||
|
||||
void
|
||||
glitz_bool_t
|
||||
(*push_current) (void *drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint);
|
||||
|
@ -328,8 +355,17 @@ typedef struct glitz_backend {
|
|||
(*pop_current) (void *drawable);
|
||||
|
||||
void
|
||||
(*attach_notify) (void *drawable,
|
||||
glitz_surface_t *surface);
|
||||
|
||||
void
|
||||
(*detach_notify) (void *drawable,
|
||||
glitz_surface_t *surface);
|
||||
|
||||
glitz_bool_t
|
||||
(*swap_buffers) (void *drawable);
|
||||
|
||||
|
||||
glitz_context_t *
|
||||
(*create_context) (void *drawable,
|
||||
glitz_drawable_format_t *format);
|
||||
|
@ -343,16 +379,16 @@ typedef struct glitz_backend {
|
|||
unsigned long mask);
|
||||
|
||||
void
|
||||
(*make_current) (void *context,
|
||||
void *drawable);
|
||||
(*make_current) (void *drawable,
|
||||
void *context);
|
||||
|
||||
glitz_function_pointer_t
|
||||
(*get_proc_address) (void *context,
|
||||
const char *name);
|
||||
|
||||
glitz_gl_proc_address_list_t gl;
|
||||
glitz_gl_proc_address_list_t *gl;
|
||||
|
||||
glitz_drawable_format_t *drawable_formats;
|
||||
glitz_int_drawable_format_t *drawable_formats;
|
||||
int n_drawable_formats;
|
||||
|
||||
glitz_gl_int_t *texture_formats;
|
||||
|
@ -360,6 +396,7 @@ typedef struct glitz_backend {
|
|||
int n_formats;
|
||||
|
||||
glitz_gl_float_t gl_version;
|
||||
glitz_gl_int_t max_viewport_dims[2];
|
||||
glitz_gl_int_t max_texture_2d_size;
|
||||
glitz_gl_int_t max_texture_rect_size;
|
||||
unsigned long feature_mask;
|
||||
|
@ -369,16 +406,20 @@ typedef struct glitz_backend {
|
|||
|
||||
struct _glitz_drawable {
|
||||
glitz_backend_t *backend;
|
||||
|
||||
int ref_count;
|
||||
glitz_drawable_format_t *format;
|
||||
glitz_int_drawable_format_t *format;
|
||||
int width, height;
|
||||
glitz_rectangle_t viewport;
|
||||
glitz_bool_t update_all;
|
||||
glitz_surface_t *front;
|
||||
glitz_surface_t *back;
|
||||
};
|
||||
|
||||
#define GLITZ_GL_DRAWABLE(drawable) \
|
||||
glitz_gl_proc_address_list_t *gl = &(drawable)->backend->gl;
|
||||
glitz_gl_proc_address_list_t *gl = (drawable)->backend->gl;
|
||||
|
||||
#define DRAWABLE_IS_FBO(drawable) \
|
||||
((drawable)->format->types == GLITZ_DRAWABLE_TYPE_FBO_MASK)
|
||||
|
||||
typedef struct _glitz_vec2_t {
|
||||
glitz_float_t v[2];
|
||||
|
@ -405,14 +446,19 @@ typedef struct _glitz_vec4_t {
|
|||
#define TEXTURE_INVALID_SIZE(texture) \
|
||||
((texture)->flags & GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK)
|
||||
|
||||
typedef struct _glitz_texture_parameters {
|
||||
glitz_gl_enum_t filter[2];
|
||||
glitz_gl_enum_t wrap[2];
|
||||
glitz_color_t border_color;
|
||||
} glitz_texture_parameters_t;
|
||||
|
||||
typedef struct _glitz_texture {
|
||||
glitz_gl_uint_t name;
|
||||
glitz_gl_enum_t target;
|
||||
glitz_gl_int_t format;
|
||||
unsigned long flags;
|
||||
|
||||
glitz_gl_enum_t filter;
|
||||
glitz_gl_enum_t wrap;
|
||||
glitz_texture_parameters_t param;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
@ -423,12 +469,20 @@ typedef struct _glitz_texture {
|
|||
glitz_float_t texcoord_height_unit;
|
||||
} glitz_texture_t;
|
||||
|
||||
struct _glitz_texture_object {
|
||||
glitz_surface_t *surface;
|
||||
int ref_count;
|
||||
glitz_texture_parameters_t param;
|
||||
};
|
||||
|
||||
struct _glitz_buffer {
|
||||
glitz_gl_uint_t name;
|
||||
glitz_gl_enum_t target;
|
||||
void *data;
|
||||
int owns_data;
|
||||
int ref_count;
|
||||
glitz_surface_t *front_surface;
|
||||
glitz_surface_t *back_surface;
|
||||
glitz_drawable_t *drawable;
|
||||
};
|
||||
|
||||
|
@ -538,10 +592,6 @@ typedef struct _glitz_geometry {
|
|||
#define SURFACE_PROJECTIVE_TRANSFORM(surface) \
|
||||
((surface)->flags & GLITZ_SURFACE_FLAG_PROJECTIVE_TRANSFORM_MASK)
|
||||
|
||||
#define SURFACE_DRAWABLE_HEIGHT(surface) \
|
||||
(((surface)->attached) ? \
|
||||
(surface)->attached->height: surface->texture.height)
|
||||
|
||||
typedef struct _glitz_filter_params_t glitz_filter_params_t;
|
||||
|
||||
typedef struct _glitz_matrix {
|
||||
|
@ -549,10 +599,6 @@ typedef struct _glitz_matrix {
|
|||
glitz_float_t m[16];
|
||||
} glitz_matrix_t;
|
||||
|
||||
typedef struct _glitz_framebuffer {
|
||||
glitz_gl_uint_t name;
|
||||
} glitz_framebuffer_t;
|
||||
|
||||
#define GLITZ_DAMAGE_TEXTURE_MASK (1 << 0)
|
||||
#define GLITZ_DAMAGE_DRAWABLE_MASK (1 << 1)
|
||||
#define GLITZ_DAMAGE_SOLID_MASK (1 << 2)
|
||||
|
@ -587,11 +633,12 @@ struct _glitz_surface {
|
|||
int *primcount;
|
||||
glitz_region_t texture_damage;
|
||||
glitz_region_t drawable_damage;
|
||||
glitz_framebuffer_t framebuffer;
|
||||
unsigned int flip_count;
|
||||
glitz_gl_int_t fb;
|
||||
};
|
||||
|
||||
#define GLITZ_GL_SURFACE(surface) \
|
||||
glitz_gl_proc_address_list_t *gl = &(surface)->drawable->backend->gl;
|
||||
glitz_gl_proc_address_list_t *gl = (surface)->drawable->backend->gl;
|
||||
|
||||
struct _glitz_context {
|
||||
int ref_count;
|
||||
|
@ -671,11 +718,22 @@ glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
|
|||
glitz_gl_int_t **texture_formats,
|
||||
int *n_formats);
|
||||
|
||||
extern void __internal_linkage
|
||||
_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
|
||||
unsigned long feature_mask,
|
||||
glitz_int_drawable_format_t **formats,
|
||||
int *n_formats);
|
||||
|
||||
void
|
||||
glitz_drawable_format_copy (const glitz_drawable_format_t *src,
|
||||
glitz_drawable_format_t *dst,
|
||||
unsigned long mask);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_drawable_format_find (glitz_drawable_format_t *formats,
|
||||
glitz_drawable_format_find (glitz_int_drawable_format_t *formats,
|
||||
int n_formats,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
const glitz_int_drawable_format_t *templ,
|
||||
int count);
|
||||
|
||||
void
|
||||
|
@ -701,14 +759,9 @@ glitz_texture_allocate (glitz_gl_proc_address_list_t *gl,
|
|||
glitz_texture_t *texture);
|
||||
|
||||
extern void __internal_linkage
|
||||
glitz_texture_ensure_filter (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_ensure_parameters (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_t *texture,
|
||||
glitz_gl_enum_t filter);
|
||||
|
||||
extern void __internal_linkage
|
||||
glitz_texture_ensure_wrap (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_texture_t *texture,
|
||||
glitz_gl_enum_t wrap);
|
||||
glitz_texture_parameters_t *param);
|
||||
|
||||
void
|
||||
glitz_texture_bind (glitz_gl_proc_address_list_t *gl,
|
||||
|
@ -738,6 +791,9 @@ glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
|
|||
unsigned long flags,
|
||||
glitz_int_coordinate_t *coord);
|
||||
|
||||
extern void __internal_linkage
|
||||
_glitz_surface_sync_texture (glitz_surface_t *surface);
|
||||
|
||||
extern glitz_texture_t __internal_linkage *
|
||||
glitz_surface_get_texture (glitz_surface_t *surface,
|
||||
glitz_bool_t allocate);
|
||||
|
@ -844,20 +900,18 @@ glitz_geometry_draw_arrays (glitz_gl_proc_address_list_t *gl,
|
|||
glitz_box_t *bounds,
|
||||
int damage);
|
||||
|
||||
extern void __internal_linkage
|
||||
glitz_framebuffer_init (glitz_framebuffer_t *framebuffer);
|
||||
void
|
||||
_glitz_drawable_init (glitz_drawable_t *drawable,
|
||||
glitz_int_drawable_format_t *format,
|
||||
glitz_backend_t *backend,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
extern void __internal_linkage
|
||||
glitz_framebuffer_fini (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_framebuffer_t *framebuffer);
|
||||
|
||||
extern void __internal_linkage
|
||||
glitz_framebuffer_unbind (glitz_gl_proc_address_list_t *gl);
|
||||
|
||||
extern glitz_bool_t __internal_linkage
|
||||
glitz_framebuffer_complete (glitz_gl_proc_address_list_t *gl,
|
||||
glitz_framebuffer_t *framebuffer,
|
||||
glitz_texture_t *texture);
|
||||
extern glitz_drawable_t __internal_linkage *
|
||||
_glitz_fbo_drawable_create (glitz_drawable_t *other,
|
||||
glitz_int_drawable_format_t *format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
_glitz_context_init (glitz_context_t *context,
|
||||
|
@ -955,12 +1009,13 @@ typedef glitz_fixed_16_16 glitz_fixed;
|
|||
|
||||
/* Avoid unnecessary PLT entries. */
|
||||
|
||||
slim_hidden_proto(glitz_find_similar_drawable_format)
|
||||
slim_hidden_proto(glitz_find_drawable_format)
|
||||
slim_hidden_proto(glitz_find_pbuffer_format)
|
||||
slim_hidden_proto(glitz_create_drawable)
|
||||
slim_hidden_proto(glitz_create_pbuffer_drawable)
|
||||
slim_hidden_proto(glitz_drawable_get_width)
|
||||
slim_hidden_proto(glitz_drawable_get_height)
|
||||
slim_hidden_proto(glitz_drawable_swap_buffers)
|
||||
slim_hidden_proto(glitz_drawable_swap_buffers)
|
||||
slim_hidden_proto(glitz_drawable_flush)
|
||||
slim_hidden_proto(glitz_drawable_finish)
|
||||
slim_hidden_proto(glitz_drawable_get_features)
|
||||
|
|
|
@ -42,6 +42,8 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
VISIBILITY_FLAGS =
|
||||
|
||||
MODULE = glitzglx
|
||||
LIBRARY_NAME = mozglitzglx
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
|
|
@ -47,7 +47,14 @@ glitz_glx_fini (void);
|
|||
/* glitz_glx_format.c */
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_glx_find_drawable_format (Display *display,
|
||||
glitz_glx_find_window_format (Display *display,
|
||||
int screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_glx_find_pbuffer_format (Display *display,
|
||||
int screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
|
|
|
@ -74,19 +74,22 @@ _glitz_glx_context_create_using_fbconfig (glitz_glx_screen_info_t *screen_info,
|
|||
for (i = 0; i < n_fbconfigs; i++) {
|
||||
int value;
|
||||
|
||||
glx->get_fbconfig_attrib (screen_info->display_info->display, fbconfigs[i],
|
||||
glx->get_fbconfig_attrib (screen_info->display_info->display,
|
||||
fbconfigs[i],
|
||||
GLX_FBCONFIG_ID, &value);
|
||||
if (value == (int) fbconfigid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < n_fbconfigs)
|
||||
vinfo = glx->get_visual_from_fbconfig (screen_info->display_info->display,
|
||||
vinfo =
|
||||
glx->get_visual_from_fbconfig (screen_info->display_info->display,
|
||||
fbconfigs[i]);
|
||||
|
||||
context->id = fbconfigid;
|
||||
if (vinfo) {
|
||||
context->context = glXCreateContext (screen_info->display_info->display,
|
||||
context->context =
|
||||
glXCreateContext (screen_info->display_info->display,
|
||||
vinfo, share_list, GLITZ_GL_TRUE);
|
||||
XFree (vinfo);
|
||||
} else if (glx->create_new_context)
|
||||
|
@ -108,9 +111,11 @@ static glitz_context_t *
|
|||
_glitz_glx_create_context (void *abstract_drawable,
|
||||
glitz_drawable_format_t *format)
|
||||
{
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable;
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_glx_screen_info_t *screen_info = drawable->screen_info;
|
||||
int format_id = screen_info->format_ids[format->id];
|
||||
unsigned long format_id =
|
||||
screen_info->formats[format->id].u.uval;
|
||||
glitz_glx_context_t *context;
|
||||
|
||||
context = malloc (sizeof (glitz_glx_context_t));
|
||||
|
@ -140,7 +145,8 @@ _glitz_glx_context_destroy (void *abstract_context)
|
|||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
context->base.drawable;
|
||||
|
||||
if (drawable->screen_info->display_info->thread_info->cctx == &context->base)
|
||||
if (drawable->screen_info->display_info->thread_info->cctx ==
|
||||
&context->base)
|
||||
{
|
||||
glXMakeCurrent (drawable->screen_info->display_info->display,
|
||||
None, NULL);
|
||||
|
@ -171,12 +177,20 @@ _glitz_glx_copy_context (void *abstract_src,
|
|||
}
|
||||
|
||||
static void
|
||||
_glitz_glx_make_current (void *abstract_context,
|
||||
void *abstract_drawable)
|
||||
_glitz_glx_make_current (void *abstract_drawable,
|
||||
void *abstract_context)
|
||||
{
|
||||
glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context;
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable;
|
||||
glitz_glx_display_info_t *display_info = drawable->screen_info->display_info;
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_glx_display_info_t *display_info =
|
||||
drawable->screen_info->display_info;
|
||||
|
||||
if (drawable->base.width != drawable->width ||
|
||||
drawable->base.height != drawable->height)
|
||||
_glitz_glx_drawable_update_size (drawable,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
|
||||
if ((glXGetCurrentContext () != context->context) ||
|
||||
(glXGetCurrentDrawable () != drawable->drawable))
|
||||
|
@ -188,6 +202,7 @@ _glitz_glx_make_current (void *abstract_context,
|
|||
if (ctx->lose_current)
|
||||
ctx->lose_current (ctx->closure);
|
||||
}
|
||||
|
||||
glXMakeCurrent (display_info->display, drawable->drawable,
|
||||
context->context);
|
||||
}
|
||||
|
@ -195,6 +210,10 @@ _glitz_glx_make_current (void *abstract_context,
|
|||
display_info->thread_info->cctx = &context->base;
|
||||
}
|
||||
|
||||
static void
|
||||
_glitz_glx_notify_dummy (void *abstract_drawable,
|
||||
glitz_surface_t *surface) {}
|
||||
|
||||
static glitz_function_pointer_t
|
||||
_glitz_glx_context_get_proc_address (void *abstract_context,
|
||||
const char *name)
|
||||
|
@ -203,7 +222,7 @@ _glitz_glx_context_get_proc_address (void *abstract_context,
|
|||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
context->base.drawable;
|
||||
|
||||
_glitz_glx_make_current (context, drawable);
|
||||
/* _glitz_glx_make_current (drawable, context, NULL); */
|
||||
|
||||
return glitz_glx_get_proc_address (name, drawable->screen_info);
|
||||
}
|
||||
|
@ -215,10 +234,10 @@ glitz_glx_context_get (glitz_glx_screen_info_t *screen_info,
|
|||
glitz_glx_context_t *context;
|
||||
glitz_glx_context_t **contexts = screen_info->contexts;
|
||||
int index, n_contexts = screen_info->n_contexts;
|
||||
XID format_id;
|
||||
unsigned long format_id;
|
||||
|
||||
for (; n_contexts; n_contexts--, contexts++)
|
||||
if ((*contexts)->id == screen_info->format_ids[format->id])
|
||||
if ((*contexts)->id == screen_info->formats[format->id].u.uval)
|
||||
return *contexts;
|
||||
|
||||
index = screen_info->n_contexts++;
|
||||
|
@ -235,7 +254,7 @@ glitz_glx_context_get (glitz_glx_screen_info_t *screen_info,
|
|||
|
||||
screen_info->contexts[index] = context;
|
||||
|
||||
format_id = screen_info->format_ids[format->id];
|
||||
format_id = screen_info->formats[format->id].u.uval;
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
|
||||
_glitz_glx_context_create_using_fbconfig (screen_info,
|
||||
|
@ -251,14 +270,14 @@ glitz_glx_context_get (glitz_glx_screen_info_t *screen_info,
|
|||
if (!screen_info->root_context)
|
||||
screen_info->root_context = context->context;
|
||||
|
||||
memcpy (&context->backend.gl,
|
||||
&_glitz_glx_gl_proc_address,
|
||||
sizeof (glitz_gl_proc_address_list_t));
|
||||
context->backend.gl = &_glitz_glx_gl_proc_address;
|
||||
|
||||
context->backend.create_pbuffer = glitz_glx_create_pbuffer;
|
||||
context->backend.destroy = glitz_glx_destroy;
|
||||
context->backend.push_current = glitz_glx_push_current;
|
||||
context->backend.pop_current = glitz_glx_pop_current;
|
||||
context->backend.attach_notify = _glitz_glx_notify_dummy;
|
||||
context->backend.detach_notify = _glitz_glx_notify_dummy;
|
||||
context->backend.swap_buffers = glitz_glx_swap_buffers;
|
||||
|
||||
context->backend.create_context = _glitz_glx_create_context;
|
||||
|
@ -267,8 +286,22 @@ glitz_glx_context_get (glitz_glx_screen_info_t *screen_info,
|
|||
context->backend.make_current = _glitz_glx_make_current;
|
||||
context->backend.get_proc_address = _glitz_glx_context_get_proc_address;
|
||||
|
||||
context->backend.drawable_formats = screen_info->formats;
|
||||
context->backend.drawable_formats = NULL;
|
||||
context->backend.n_drawable_formats = 0;
|
||||
|
||||
if (screen_info->n_formats)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = sizeof (glitz_int_drawable_format_t) * screen_info->n_formats;
|
||||
context->backend.drawable_formats = malloc (size);
|
||||
if (context->backend.drawable_formats)
|
||||
{
|
||||
memcpy (context->backend.drawable_formats, screen_info->formats,
|
||||
size);
|
||||
context->backend.n_drawable_formats = screen_info->n_formats;
|
||||
}
|
||||
}
|
||||
|
||||
context->backend.texture_formats = NULL;
|
||||
context->backend.formats = NULL;
|
||||
|
@ -286,6 +319,9 @@ void
|
|||
glitz_glx_context_destroy (glitz_glx_screen_info_t *screen_info,
|
||||
glitz_glx_context_t *context)
|
||||
{
|
||||
if (context->backend.drawable_formats)
|
||||
free (context->backend.drawable_formats);
|
||||
|
||||
if (context->backend.formats)
|
||||
free (context->backend.formats);
|
||||
|
||||
|
@ -307,18 +343,16 @@ _glitz_glx_context_initialize (glitz_glx_screen_info_t *screen_info,
|
|||
glitz_glx_get_proc_address,
|
||||
(void *) screen_info);
|
||||
|
||||
context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS,
|
||||
context->max_viewport_dims);
|
||||
|
||||
glitz_initiate_state (&_glitz_glx_gl_proc_address);
|
||||
|
||||
version = (const char *) context->backend.gl.get_string (GLITZ_GL_VERSION);
|
||||
version = (const char *)
|
||||
context->backend.gl->get_string (GLITZ_GL_VERSION);
|
||||
if (version)
|
||||
{
|
||||
/* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures when
|
||||
using nvidia's binary driver. Seems like a driver issue, but I'm not
|
||||
sure yet. Turning of NPOT GL_TEXTURE_2D textures until this have been
|
||||
solved. */
|
||||
/* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures
|
||||
when using nvidia's binary driver. Seems like a driver issue, but
|
||||
I'm not sure yet. Turning of NPOT GL_TEXTURE_2D textures until this
|
||||
have been solved. */
|
||||
if (strstr (version, "NVIDIA 61.11") ||
|
||||
strstr (version, "NVIDIA 66.29"))
|
||||
{
|
||||
|
@ -334,7 +368,8 @@ static void
|
|||
_glitz_glx_context_make_current (glitz_glx_drawable_t *drawable,
|
||||
glitz_bool_t finish)
|
||||
{
|
||||
glitz_glx_display_info_t *display_info = drawable->screen_info->display_info;
|
||||
glitz_glx_display_info_t *display_info =
|
||||
drawable->screen_info->display_info;
|
||||
|
||||
if (finish)
|
||||
glFinish ();
|
||||
|
@ -356,7 +391,8 @@ _glitz_glx_context_make_current (glitz_glx_drawable_t *drawable,
|
|||
drawable->base.update_all = 1;
|
||||
|
||||
if (!drawable->context->initialized)
|
||||
_glitz_glx_context_initialize (drawable->screen_info, drawable->context);
|
||||
_glitz_glx_context_initialize (drawable->screen_info,
|
||||
drawable->context);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -387,6 +423,12 @@ _glitz_glx_context_update (glitz_glx_drawable_t *drawable,
|
|||
if (!dinfo->thread_info->cctx)
|
||||
context = glXGetCurrentContext ();
|
||||
|
||||
if (drawable->base.width != drawable->width ||
|
||||
drawable->base.height != drawable->height)
|
||||
_glitz_glx_drawable_update_size (drawable,
|
||||
drawable->base.width,
|
||||
drawable->base.height);
|
||||
|
||||
if ((context != drawable->context->context) ||
|
||||
(glXGetCurrentDrawable () != drawable->drawable))
|
||||
_glitz_glx_context_make_current (drawable, (context)? 1: 0);
|
||||
|
@ -394,12 +436,13 @@ _glitz_glx_context_update (glitz_glx_drawable_t *drawable,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
glitz_bool_t
|
||||
glitz_glx_push_current (void *abstract_drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint)
|
||||
{
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable;
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_glx_context_info_t *context_info;
|
||||
int index;
|
||||
|
||||
|
@ -411,12 +454,15 @@ glitz_glx_push_current (void *abstract_drawable,
|
|||
context_info->constraint = constraint;
|
||||
|
||||
_glitz_glx_context_update (context_info->drawable, constraint);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
glitz_surface_t *
|
||||
glitz_glx_pop_current (void *abstract_drawable)
|
||||
{
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable;
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
abstract_drawable;
|
||||
glitz_glx_context_info_t *context_info = NULL;
|
||||
int index;
|
||||
|
||||
|
|
|
@ -40,30 +40,29 @@ _glitz_glx_create_drawable (glitz_glx_screen_info_t *screen_info,
|
|||
{
|
||||
glitz_glx_drawable_t *drawable;
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return NULL;
|
||||
|
||||
drawable = (glitz_glx_drawable_t *) malloc (sizeof (glitz_glx_drawable_t));
|
||||
if (drawable == NULL)
|
||||
return NULL;
|
||||
|
||||
drawable->base.ref_count = 1;
|
||||
drawable->screen_info = screen_info;
|
||||
drawable->context = context;
|
||||
drawable->drawable = glx_drawable;
|
||||
drawable->pbuffer = glx_pbuffer;
|
||||
drawable->base.format = format;
|
||||
drawable->base.backend = &context->backend;
|
||||
drawable->width = width;
|
||||
drawable->height = height;
|
||||
|
||||
glitz_drawable_update_size (&drawable->base, width, height);
|
||||
_glitz_drawable_init (&drawable->base,
|
||||
&screen_info->formats[format->id],
|
||||
&context->backend,
|
||||
width, height);
|
||||
|
||||
if (!context->initialized) {
|
||||
glitz_glx_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
|
||||
glitz_glx_pop_current (drawable);
|
||||
}
|
||||
|
||||
if (width > context->max_viewport_dims[0] ||
|
||||
height > context->max_viewport_dims[1]) {
|
||||
if (width > context->backend.max_viewport_dims[0] ||
|
||||
height > context->backend.max_viewport_dims[1]) {
|
||||
free (drawable);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -73,6 +72,28 @@ _glitz_glx_create_drawable (glitz_glx_screen_info_t *screen_info,
|
|||
return drawable;
|
||||
}
|
||||
|
||||
glitz_bool_t
|
||||
_glitz_glx_drawable_update_size (glitz_glx_drawable_t *drawable,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (drawable->pbuffer)
|
||||
{
|
||||
glitz_glx_pbuffer_destroy (drawable->screen_info, drawable->pbuffer);
|
||||
drawable->drawable = drawable->pbuffer =
|
||||
glitz_glx_pbuffer_create (drawable->screen_info,
|
||||
drawable->context->fbconfig,
|
||||
(int) width, (int) height);
|
||||
if (!drawable->pbuffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
drawable->width = width;
|
||||
drawable->height = height;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static glitz_drawable_t *
|
||||
_glitz_glx_create_pbuffer_drawable (glitz_glx_screen_info_t *screen_info,
|
||||
glitz_drawable_format_t *format,
|
||||
|
@ -83,9 +104,6 @@ _glitz_glx_create_pbuffer_drawable (glitz_glx_screen_info_t *screen_info,
|
|||
glitz_glx_context_t *context;
|
||||
GLXPbuffer pbuffer;
|
||||
|
||||
if (!format->types.pbuffer)
|
||||
return NULL;
|
||||
|
||||
context = glitz_glx_context_get (screen_info, format);
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
@ -129,11 +147,19 @@ glitz_glx_create_drawable_for_window (Display *display,
|
|||
glitz_glx_drawable_t *drawable;
|
||||
glitz_glx_screen_info_t *screen_info;
|
||||
glitz_glx_context_t *context;
|
||||
glitz_int_drawable_format_t *iformat;
|
||||
|
||||
screen_info = glitz_glx_screen_info_get (display, screen);
|
||||
if (!screen_info)
|
||||
return NULL;
|
||||
|
||||
if (format->id >= screen_info->n_formats)
|
||||
return NULL;
|
||||
|
||||
iformat = &screen_info->formats[format->id];
|
||||
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK))
|
||||
return NULL;
|
||||
|
||||
context = glitz_glx_context_get (screen_info, format);
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
@ -156,11 +182,19 @@ glitz_glx_create_pbuffer_drawable (Display *display,
|
|||
unsigned int height)
|
||||
{
|
||||
glitz_glx_screen_info_t *screen_info;
|
||||
glitz_int_drawable_format_t *iformat;
|
||||
|
||||
screen_info = glitz_glx_screen_info_get (display, screen);
|
||||
if (!screen_info)
|
||||
return NULL;
|
||||
|
||||
if (format->id >= screen_info->n_formats)
|
||||
return NULL;
|
||||
|
||||
iformat = &screen_info->formats[format->id];
|
||||
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK))
|
||||
return NULL;
|
||||
|
||||
return _glitz_glx_create_pbuffer_drawable (screen_info, format,
|
||||
width, height);
|
||||
}
|
||||
|
@ -169,7 +203,8 @@ slim_hidden_def(glitz_glx_create_pbuffer_drawable);
|
|||
void
|
||||
glitz_glx_destroy (void *abstract_drawable)
|
||||
{
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable;
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
drawable->screen_info->drawables--;
|
||||
if (drawable->screen_info->drawables == 0) {
|
||||
|
@ -177,14 +212,16 @@ glitz_glx_destroy (void *abstract_drawable)
|
|||
* Last drawable? We have to destroy all fragment programs as this may
|
||||
* be our last chance to have a context current.
|
||||
*/
|
||||
glitz_glx_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT);
|
||||
glitz_program_map_fini (&drawable->base.backend->gl,
|
||||
glitz_glx_push_current (abstract_drawable, NULL,
|
||||
GLITZ_CONTEXT_CURRENT);
|
||||
glitz_program_map_fini (drawable->base.backend->gl,
|
||||
&drawable->screen_info->program_map);
|
||||
glitz_glx_pop_current (abstract_drawable);
|
||||
}
|
||||
|
||||
if (glXGetCurrentDrawable () == drawable->drawable)
|
||||
glXMakeCurrent (drawable->screen_info->display_info->display, None, NULL);
|
||||
glXMakeCurrent (drawable->screen_info->display_info->display,
|
||||
None, NULL);
|
||||
|
||||
if (drawable->pbuffer)
|
||||
glitz_glx_pbuffer_destroy (drawable->screen_info, drawable->pbuffer);
|
||||
|
@ -192,11 +229,14 @@ glitz_glx_destroy (void *abstract_drawable)
|
|||
free (drawable);
|
||||
}
|
||||
|
||||
void
|
||||
glitz_bool_t
|
||||
glitz_glx_swap_buffers (void *abstract_drawable)
|
||||
{
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable;
|
||||
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
|
||||
abstract_drawable;
|
||||
|
||||
glXSwapBuffers (drawable->screen_info->display_info->display,
|
||||
drawable->drawable);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "glitz_glxint.h"
|
||||
|
||||
static glitz_extension_map glx_extensions[] = {
|
||||
{ 0.0, "GLX_EXT_visual_rating", GLITZ_GLX_FEATURE_VISUAL_RATING_MASK },
|
||||
{ 0.0, "GLX_SGIX_fbconfig", GLITZ_GLX_FEATURE_FBCONFIG_MASK },
|
||||
{ 0.0, "GLX_SGIX_pbuffer", GLITZ_GLX_FEATURE_PBUFFER_MASK },
|
||||
{ 0.0, "GLX_SGI_make_current_read",
|
||||
|
|
|
@ -36,49 +36,51 @@ static int
|
|||
_glitz_glx_format_compare (const void *elem1,
|
||||
const void *elem2)
|
||||
{
|
||||
glitz_int_drawable_format_t *format[2];
|
||||
int i, score[2];
|
||||
glitz_drawable_format_t *format[2];
|
||||
|
||||
format[0] = (glitz_drawable_format_t *) elem1;
|
||||
format[1] = (glitz_drawable_format_t *) elem2;
|
||||
format[0] = (glitz_int_drawable_format_t *) elem1;
|
||||
format[1] = (glitz_int_drawable_format_t *) elem2;
|
||||
i = score[0] = score[1] = 0;
|
||||
|
||||
for (; i < 2; i++) {
|
||||
if (format[i]->color.red_size) {
|
||||
if (format[i]->color.red_size == 8)
|
||||
for (; i < 2; i++)
|
||||
{
|
||||
if (format[i]->d.color.red_size)
|
||||
{
|
||||
if (format[i]->d.color.red_size >= 8)
|
||||
score[i] += 5;
|
||||
|
||||
score[i] += 10;
|
||||
}
|
||||
|
||||
if (format[i]->color.green_size) {
|
||||
if (format[i]->color.green_size == 8)
|
||||
if (format[i]->d.color.alpha_size)
|
||||
{
|
||||
if (format[i]->d.color.alpha_size >= 8)
|
||||
score[i] += 5;
|
||||
|
||||
score[i] += 10;
|
||||
}
|
||||
|
||||
if (format[i]->color.alpha_size) {
|
||||
if (format[i]->color.alpha_size == 8)
|
||||
score[i] += 5;
|
||||
score[i] += 10;
|
||||
}
|
||||
|
||||
if (format[i]->stencil_size)
|
||||
if (format[i]->d.stencil_size)
|
||||
score[i] += 5;
|
||||
|
||||
if (format[i]->depth_size)
|
||||
if (format[i]->d.depth_size)
|
||||
score[i] += 5;
|
||||
|
||||
if (format[i]->doublebuffer)
|
||||
if (format[i]->d.doublebuffer)
|
||||
score[i] += 10;
|
||||
|
||||
if (format[i]->types.window)
|
||||
if (format[i]->d.samples > 1)
|
||||
score[i] -= (20 - format[i]->d.samples);
|
||||
|
||||
if (format[i]->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK)
|
||||
score[i] += 10;
|
||||
|
||||
if (format[i]->types.pbuffer)
|
||||
if (format[i]->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)
|
||||
score[i] += 10;
|
||||
|
||||
if (format[i]->samples > 1)
|
||||
score[i] -= (20 - format[i]->samples);
|
||||
if (format[i]->caveat)
|
||||
score[i] -= 1000;
|
||||
}
|
||||
|
||||
return score[1] - score[0];
|
||||
|
@ -86,21 +88,17 @@ _glitz_glx_format_compare (const void *elem1,
|
|||
|
||||
static void
|
||||
_glitz_add_format (glitz_glx_screen_info_t *screen_info,
|
||||
glitz_drawable_format_t *format,
|
||||
XID id)
|
||||
glitz_int_drawable_format_t *format)
|
||||
{
|
||||
int n = screen_info->n_formats;
|
||||
|
||||
screen_info->formats =
|
||||
realloc (screen_info->formats,
|
||||
sizeof (glitz_drawable_format_t) * (n + 1));
|
||||
screen_info->format_ids =
|
||||
realloc (screen_info->format_ids, sizeof (XID) * (n + 1));
|
||||
|
||||
if (screen_info->formats && screen_info->format_ids) {
|
||||
sizeof (glitz_int_drawable_format_t) * (n + 1));
|
||||
if (screen_info->formats)
|
||||
{
|
||||
screen_info->formats[n] = *format;
|
||||
screen_info->formats[n].id = n;
|
||||
screen_info->format_ids[n] = id;
|
||||
screen_info->formats[n].d.id = n;
|
||||
screen_info->n_formats++;
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +107,7 @@ static void
|
|||
_glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
|
||||
{
|
||||
Display *display;
|
||||
glitz_drawable_format_t format;
|
||||
glitz_int_drawable_format_t format;
|
||||
XVisualInfo visual_templ;
|
||||
XVisualInfo *visuals;
|
||||
int i, num_visuals;
|
||||
|
@ -121,11 +119,11 @@ _glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
|
|||
&visual_templ, &num_visuals);
|
||||
|
||||
/* No pbuffers without fbconfigs */
|
||||
format.types.window = 1;
|
||||
format.types.pbuffer = 0;
|
||||
format.id = 0;
|
||||
format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
|
||||
format.d.id = 0;
|
||||
|
||||
for (i = 0; i < num_visuals; i++) {
|
||||
for (i = 0; i < num_visuals; i++)
|
||||
{
|
||||
int value;
|
||||
|
||||
if ((glXGetConfig (display, &visuals[i], GLX_USE_GL, &value) != 0) ||
|
||||
|
@ -142,31 +140,55 @@ _glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
|
|||
continue;
|
||||
|
||||
glXGetConfig (display, &visuals[i], GLX_RED_SIZE, &value);
|
||||
format.color.red_size = (unsigned short) value;
|
||||
format.d.color.red_size = (unsigned short) value;
|
||||
glXGetConfig (display, &visuals[i], GLX_GREEN_SIZE, &value);
|
||||
format.color.green_size = (unsigned short) value;
|
||||
format.d.color.green_size = (unsigned short) value;
|
||||
glXGetConfig (display, &visuals[i], GLX_BLUE_SIZE, &value);
|
||||
format.color.blue_size = (unsigned short) value;
|
||||
format.d.color.blue_size = (unsigned short) value;
|
||||
glXGetConfig (display, &visuals[i], GLX_ALPHA_SIZE, &value);
|
||||
format.color.alpha_size = (unsigned short) value;
|
||||
format.d.color.alpha_size = (unsigned short) value;
|
||||
glXGetConfig (display, &visuals[i], GLX_DEPTH_SIZE, &value);
|
||||
format.depth_size = (unsigned short) value;
|
||||
format.d.depth_size = (unsigned short) value;
|
||||
glXGetConfig (display, &visuals[i], GLX_STENCIL_SIZE, &value);
|
||||
format.stencil_size = (unsigned short) value;
|
||||
format.d.stencil_size = (unsigned short) value;
|
||||
glXGetConfig (display, &visuals[i], GLX_DOUBLEBUFFER, &value);
|
||||
format.doublebuffer = (value) ? 1: 0;
|
||||
format.d.doublebuffer = (value) ? 1: 0;
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) {
|
||||
glXGetConfig (display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &value);
|
||||
if (value) {
|
||||
if (screen_info->glx_feature_mask &
|
||||
GLITZ_GLX_FEATURE_VISUAL_RATING_MASK)
|
||||
{
|
||||
glXGetConfig (display, &visuals[i], GLX_VISUAL_CAVEAT_EXT, &value);
|
||||
switch (value) {
|
||||
case GLX_SLOW_VISUAL_EXT:
|
||||
case GLX_NON_CONFORMANT_VISUAL_EXT:
|
||||
format.caveat = 1;
|
||||
break;
|
||||
default:
|
||||
format.caveat = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
format.caveat = 0;
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK)
|
||||
{
|
||||
glXGetConfig (display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB,
|
||||
&value);
|
||||
if (value)
|
||||
{
|
||||
glXGetConfig (display, &visuals[i], GLX_SAMPLES_ARB, &value);
|
||||
format.samples = (unsigned short) (value > 1)? value: 1;
|
||||
} else
|
||||
format.samples = 1;
|
||||
} else
|
||||
format.samples = 1;
|
||||
format.d.samples = (unsigned short) (value > 1)? value: 1;
|
||||
}
|
||||
else
|
||||
format.d.samples = 1;
|
||||
}
|
||||
else
|
||||
format.d.samples = 1;
|
||||
|
||||
_glitz_add_format (screen_info, &format, visuals[i].visualid);
|
||||
format.u.uval = visuals[i].visualid;
|
||||
|
||||
_glitz_add_format (screen_info, &format);
|
||||
}
|
||||
|
||||
if (visuals)
|
||||
|
@ -178,15 +200,16 @@ _glitz_glx_query_formats_using_fbconfigs (glitz_glx_screen_info_t *screen_info)
|
|||
{
|
||||
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
|
||||
Display *display;
|
||||
glitz_drawable_format_t format;
|
||||
glitz_int_drawable_format_t format;
|
||||
GLXFBConfig *fbconfigs;
|
||||
int i, num_configs;
|
||||
XID id;
|
||||
|
||||
display = screen_info->display_info->display;
|
||||
|
||||
fbconfigs = glx->get_fbconfigs (display, screen_info->screen, &num_configs);
|
||||
if (!fbconfigs) {
|
||||
fbconfigs = glx->get_fbconfigs (display, screen_info->screen,
|
||||
&num_configs);
|
||||
if (!fbconfigs)
|
||||
{
|
||||
/* fbconfigs are not supported, falling back to visuals */
|
||||
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_FBCONFIG_MASK;
|
||||
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK;
|
||||
|
@ -194,7 +217,8 @@ _glitz_glx_query_formats_using_fbconfigs (glitz_glx_screen_info_t *screen_info)
|
|||
return GLITZ_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
for (i = 0; i < num_configs; i++)
|
||||
{
|
||||
int value;
|
||||
|
||||
if ((glx->get_fbconfig_attrib (display, fbconfigs[i],
|
||||
|
@ -212,46 +236,74 @@ _glitz_glx_query_formats_using_fbconfigs (glitz_glx_screen_info_t *screen_info)
|
|||
if (!((value & GLX_WINDOW_BIT) || (value & GLX_PBUFFER_BIT)))
|
||||
continue;
|
||||
|
||||
format.types.window = (value & GLX_WINDOW_BIT)? 1: 0;
|
||||
format.types.pbuffer = (value & GLX_PBUFFER_BIT)? 1: 0;
|
||||
format.id = 0;
|
||||
format.types = 0;
|
||||
if (value & GLX_WINDOW_BIT)
|
||||
format.types |= GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
|
||||
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_FBCONFIG_ID, &value);
|
||||
id = (XID) value;
|
||||
if (value & GLX_PBUFFER_BIT)
|
||||
format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
|
||||
|
||||
format.d.id = 0;
|
||||
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_FBCONFIG_ID,
|
||||
&value);
|
||||
format.u.uval = value;
|
||||
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_RED_SIZE, &value);
|
||||
format.color.red_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_GREEN_SIZE, &value);
|
||||
format.color.green_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_BLUE_SIZE, &value);
|
||||
format.color.blue_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_ALPHA_SIZE, &value);
|
||||
format.color.alpha_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DEPTH_SIZE, &value);
|
||||
format.depth_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STENCIL_SIZE, &value);
|
||||
format.stencil_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DOUBLEBUFFER, &value);
|
||||
format.doublebuffer = (value)? 1: 0;
|
||||
format.d.color.red_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_GREEN_SIZE,
|
||||
&value);
|
||||
format.d.color.green_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_BLUE_SIZE,
|
||||
&value);
|
||||
format.d.color.blue_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_ALPHA_SIZE,
|
||||
&value);
|
||||
format.d.color.alpha_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DEPTH_SIZE,
|
||||
&value);
|
||||
format.d.depth_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STENCIL_SIZE,
|
||||
&value);
|
||||
format.d.stencil_size = (unsigned short) value;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DOUBLEBUFFER,
|
||||
&value);
|
||||
format.d.doublebuffer = (value)? 1: 0;
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_CONFIG_CAVEAT,
|
||||
&value);
|
||||
switch (value) {
|
||||
case GLX_SLOW_VISUAL_EXT:
|
||||
case GLX_NON_CONFORMANT_VISUAL_EXT:
|
||||
format.caveat = 1;
|
||||
break;
|
||||
default:
|
||||
format.caveat = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) {
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK)
|
||||
{
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i],
|
||||
GLX_SAMPLE_BUFFERS_ARB, &value);
|
||||
if (value) {
|
||||
if (value)
|
||||
{
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i],
|
||||
GLX_SAMPLES_ARB, &value);
|
||||
format.samples = (unsigned short) (value > 1)? value: 1;
|
||||
if (format.samples > 1) {
|
||||
format.d.samples = (unsigned short) (value > 1)? value: 1;
|
||||
if (format.d.samples > 1)
|
||||
{
|
||||
if (!(screen_info->glx_feature_mask &
|
||||
GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK))
|
||||
format.types.pbuffer = 0;
|
||||
format.types &= ~GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
|
||||
}
|
||||
} else
|
||||
format.samples = 1;
|
||||
} else
|
||||
format.samples = 1;
|
||||
}
|
||||
else
|
||||
format.d.samples = 1;
|
||||
}
|
||||
else
|
||||
format.d.samples = 1;
|
||||
|
||||
_glitz_add_format (screen_info, &format, id);
|
||||
_glitz_add_format (screen_info, &format);
|
||||
}
|
||||
|
||||
if (fbconfigs)
|
||||
|
@ -264,7 +316,6 @@ void
|
|||
glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
|
||||
{
|
||||
glitz_status_t status = GLITZ_STATUS_NOT_SUPPORTED;
|
||||
XID *new_ids;
|
||||
int i;
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
|
||||
|
@ -277,41 +328,55 @@ glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
|
|||
return;
|
||||
|
||||
qsort (screen_info->formats, screen_info->n_formats,
|
||||
sizeof (glitz_drawable_format_t), _glitz_glx_format_compare);
|
||||
sizeof (glitz_int_drawable_format_t), _glitz_glx_format_compare);
|
||||
|
||||
/*
|
||||
* Update XID list so that it matches the sorted format list.
|
||||
*/
|
||||
new_ids = malloc (sizeof (XID) * screen_info->n_formats);
|
||||
if (!new_ids) {
|
||||
screen_info->n_formats = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < screen_info->n_formats; i++) {
|
||||
new_ids[i] = screen_info->format_ids[screen_info->formats[i].id];
|
||||
screen_info->formats[i].id = i;
|
||||
}
|
||||
|
||||
free (screen_info->format_ids);
|
||||
screen_info->format_ids = new_ids;
|
||||
for (i = 0; i < screen_info->n_formats; i++)
|
||||
screen_info->formats[i].d.id = i;
|
||||
}
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_glx_find_drawable_format (Display *display,
|
||||
glitz_glx_find_window_format (Display *display,
|
||||
int screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count)
|
||||
{
|
||||
glitz_int_drawable_format_t itempl;
|
||||
glitz_glx_screen_info_t *screen_info =
|
||||
glitz_glx_screen_info_get (display, screen);
|
||||
|
||||
glitz_drawable_format_copy (templ, &itempl.d, mask);
|
||||
|
||||
itempl.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
|
||||
mask |= GLITZ_INT_FORMAT_WINDOW_MASK;
|
||||
|
||||
return glitz_drawable_format_find (screen_info->formats,
|
||||
screen_info->n_formats,
|
||||
mask, templ, count);
|
||||
mask, &itempl, count);
|
||||
}
|
||||
slim_hidden_def(glitz_glx_find_drawable_format);
|
||||
slim_hidden_def(glitz_glx_find_window_format);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_glx_find_pbuffer_format (Display *display,
|
||||
int screen,
|
||||
unsigned long mask,
|
||||
const glitz_drawable_format_t *templ,
|
||||
int count)
|
||||
{
|
||||
glitz_int_drawable_format_t itempl;
|
||||
glitz_glx_screen_info_t *screen_info =
|
||||
glitz_glx_screen_info_get (display, screen);
|
||||
|
||||
glitz_drawable_format_copy (templ, &itempl.d, mask);
|
||||
|
||||
itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
|
||||
mask |= GLITZ_INT_FORMAT_PBUFFER_MASK;
|
||||
|
||||
return glitz_drawable_format_find (screen_info->formats,
|
||||
screen_info->n_formats,
|
||||
mask, &itempl, count);
|
||||
}
|
||||
slim_hidden_def(glitz_glx_find_pbuffer_format);
|
||||
|
||||
glitz_drawable_format_t *
|
||||
glitz_glx_find_drawable_format_for_visual (Display *display,
|
||||
|
@ -347,9 +412,9 @@ glitz_glx_find_drawable_format_for_visual (Display *display,
|
|||
GLX_FBCONFIG_ID, &value);
|
||||
for (fid = 0; fid < screen_info->n_formats; fid++)
|
||||
{
|
||||
if (screen_info->format_ids[fid] == value)
|
||||
if (screen_info->formats[fid].u.uval == value)
|
||||
{
|
||||
format = screen_info->formats + fid;
|
||||
format = &screen_info->formats[fid].d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -366,9 +431,9 @@ glitz_glx_find_drawable_format_for_visual (Display *display,
|
|||
{
|
||||
for (i = 0; i < screen_info->n_formats; i++)
|
||||
{
|
||||
if (visual_id == screen_info->format_ids[i])
|
||||
if (visual_id == screen_info->formats[i].u.uval)
|
||||
{
|
||||
format = screen_info->formats + i;
|
||||
format = &screen_info->formats[i].d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -388,13 +453,15 @@ glitz_glx_get_visual_info_from_format (Display *display,
|
|||
glitz_glx_screen_info_get (display, screen);
|
||||
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) {
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
|
||||
{
|
||||
GLXFBConfig *fbconfigs;
|
||||
int i, n_fbconfigs;
|
||||
int fbconfigid = screen_info->format_ids[format->id];
|
||||
int fbconfigid = screen_info->formats[format->id].u.uval;
|
||||
|
||||
fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs);
|
||||
for (i = 0; i < n_fbconfigs; i++) {
|
||||
for (i = 0; i < n_fbconfigs; i++)
|
||||
{
|
||||
int value;
|
||||
|
||||
glx->get_fbconfig_attrib (display, fbconfigs[i],
|
||||
|
@ -409,11 +476,13 @@ glitz_glx_get_visual_info_from_format (Display *display,
|
|||
if (fbconfigs)
|
||||
XFree (fbconfigs);
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
XVisualInfo templ;
|
||||
int n_items;
|
||||
|
||||
templ.visualid = screen_info->format_ids[format->id];
|
||||
templ.visualid = screen_info->formats[format->id].u.uval;
|
||||
|
||||
vinfo = XGetVisualInfo (display, VisualIDMask, &templ, &n_items);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ glitz_gl_proc_address_list_t _glitz_glx_gl_proc_address = {
|
|||
(glitz_gl_bind_texture_t) glBindTexture,
|
||||
(glitz_gl_tex_image_2d_t) glTexImage2D,
|
||||
(glitz_gl_tex_parameter_i_t) glTexParameteri,
|
||||
(glitz_gl_tex_parameter_fv_t) glTexParameterfv,
|
||||
(glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv,
|
||||
(glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D,
|
||||
(glitz_gl_get_integer_v_t) glGetIntegerv,
|
||||
|
@ -112,7 +113,18 @@ glitz_gl_proc_address_list_t _glitz_glx_gl_proc_address = {
|
|||
(glitz_gl_buffer_sub_data_t) 0,
|
||||
(glitz_gl_get_buffer_sub_data_t) 0,
|
||||
(glitz_gl_map_buffer_t) 0,
|
||||
(glitz_gl_unmap_buffer_t) 0
|
||||
(glitz_gl_unmap_buffer_t) 0,
|
||||
(glitz_gl_gen_framebuffers_t) 0,
|
||||
(glitz_gl_delete_framebuffers_t) 0,
|
||||
(glitz_gl_bind_framebuffer_t) 0,
|
||||
(glitz_gl_framebuffer_renderbuffer_t) 0,
|
||||
(glitz_gl_framebuffer_texture_2d_t) 0,
|
||||
(glitz_gl_check_framebuffer_status_t) 0,
|
||||
(glitz_gl_gen_renderbuffers_t) 0,
|
||||
(glitz_gl_delete_renderbuffers_t) 0,
|
||||
(glitz_gl_bind_renderbuffer_t) 0,
|
||||
(glitz_gl_renderbuffer_storage_t) 0,
|
||||
(glitz_gl_get_renderbuffer_parameter_iv_t) 0
|
||||
};
|
||||
|
||||
glitz_function_pointer_t
|
||||
|
@ -123,8 +135,10 @@ glitz_glx_get_proc_address (const char *name,
|
|||
glitz_glx_thread_info_t *info = screen_info->display_info->thread_info;
|
||||
glitz_function_pointer_t address = NULL;
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK)
|
||||
address = screen_info->glx.get_proc_address ((glitz_gl_ubyte_t *) name);
|
||||
if (screen_info->glx_feature_mask &
|
||||
GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK)
|
||||
address =
|
||||
screen_info->glx.get_proc_address ((glitz_gl_ubyte_t *) name);
|
||||
|
||||
if (!address) {
|
||||
if (!info->dlhand)
|
||||
|
@ -147,26 +161,32 @@ _glitz_glx_proc_address_lookup (glitz_glx_screen_info_t *screen_info)
|
|||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) {
|
||||
if (screen_info->glx_version >= 1.3f) {
|
||||
screen_info->glx.get_fbconfigs = (glitz_glx_get_fbconfigs_t)
|
||||
glitz_glx_get_proc_address ("glXGetFBConfigs", (void *) screen_info);
|
||||
screen_info->glx.get_fbconfig_attrib = (glitz_glx_get_fbconfig_attrib_t)
|
||||
glitz_glx_get_proc_address ("glXGetFBConfigs",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.get_fbconfig_attrib =
|
||||
(glitz_glx_get_fbconfig_attrib_t)
|
||||
glitz_glx_get_proc_address ("glXGetFBConfigAttrib",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.get_visual_from_fbconfig =
|
||||
(glitz_glx_get_visual_from_fbconfig_t)
|
||||
glitz_glx_get_proc_address ("glXGetVisualFromFBConfig",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.create_new_context = (glitz_glx_create_new_context_t)
|
||||
screen_info->glx.create_new_context =
|
||||
(glitz_glx_create_new_context_t)
|
||||
glitz_glx_get_proc_address ("glXCreateNewContext",
|
||||
(void *) screen_info);
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK) {
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK)
|
||||
{
|
||||
screen_info->glx.create_pbuffer = (glitz_glx_create_pbuffer_t)
|
||||
glitz_glx_get_proc_address ("glXCreatePbuffer",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.destroy_pbuffer = (glitz_glx_destroy_pbuffer_t)
|
||||
screen_info->glx.destroy_pbuffer =
|
||||
(glitz_glx_destroy_pbuffer_t)
|
||||
glitz_glx_get_proc_address ("glXDestroyPbuffer",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.query_drawable = (glitz_glx_query_drawable_t)
|
||||
screen_info->glx.query_drawable =
|
||||
(glitz_glx_query_drawable_t)
|
||||
glitz_glx_get_proc_address ("glXQueryDrawable",
|
||||
(void *) screen_info);
|
||||
}
|
||||
|
@ -174,22 +194,26 @@ _glitz_glx_proc_address_lookup (glitz_glx_screen_info_t *screen_info)
|
|||
screen_info->glx.get_fbconfigs = (glitz_glx_get_fbconfigs_t)
|
||||
glitz_glx_get_proc_address ("glXGetFBConfigsSGIX",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.get_fbconfig_attrib = (glitz_glx_get_fbconfig_attrib_t)
|
||||
screen_info->glx.get_fbconfig_attrib =
|
||||
(glitz_glx_get_fbconfig_attrib_t)
|
||||
glitz_glx_get_proc_address ("glXGetFBConfigAttribSGIX",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.get_visual_from_fbconfig =
|
||||
(glitz_glx_get_visual_from_fbconfig_t)
|
||||
glitz_glx_get_proc_address ("glXGetVisualFromFBConfigSGIX",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.create_new_context = (glitz_glx_create_new_context_t)
|
||||
screen_info->glx.create_new_context =
|
||||
(glitz_glx_create_new_context_t)
|
||||
glitz_glx_get_proc_address ("glXCreateContextWithConfigSGIX",
|
||||
(void *) screen_info);
|
||||
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK) {
|
||||
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK)
|
||||
{
|
||||
screen_info->glx.create_pbuffer = (glitz_glx_create_pbuffer_t)
|
||||
glitz_glx_get_proc_address ("glXCreateGLXPbufferSGIX",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.destroy_pbuffer = (glitz_glx_destroy_pbuffer_t)
|
||||
screen_info->glx.destroy_pbuffer =
|
||||
(glitz_glx_destroy_pbuffer_t)
|
||||
glitz_glx_get_proc_address ("glXDestroyGLXPbufferSGIX",
|
||||
(void *) screen_info);
|
||||
screen_info->glx.query_drawable = (glitz_glx_query_drawable_t)
|
||||
|
@ -236,7 +260,8 @@ _glitz_glx_proc_address_lookup (glitz_glx_screen_info_t *screen_info)
|
|||
GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK) {
|
||||
if (screen_info->glx_version >= 1.4f) {
|
||||
screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t)
|
||||
glitz_glx_get_proc_address ("glXGetProcAddress", (void *) screen_info);
|
||||
glitz_glx_get_proc_address ("glXGetProcAddress",
|
||||
(void *) screen_info);
|
||||
} else {
|
||||
screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t)
|
||||
glitz_glx_get_proc_address ("glXGetProcAddressARB",
|
||||
|
@ -415,7 +440,8 @@ _glitz_glx_display_info_get (Display *display)
|
|||
|
||||
thread_info->displays =
|
||||
realloc (thread_info->displays,
|
||||
sizeof (glitz_glx_display_info_t *) * thread_info->n_displays);
|
||||
sizeof (glitz_glx_display_info_t *) *
|
||||
thread_info->n_displays);
|
||||
|
||||
display_info = malloc (sizeof (glitz_glx_display_info_t));
|
||||
thread_info->displays[index] = display_info;
|
||||
|
@ -469,13 +495,13 @@ glitz_glx_screen_info_get (Display *display,
|
|||
screen_info->screen = screen;
|
||||
screen_info->drawables = 0;
|
||||
screen_info->formats = NULL;
|
||||
screen_info->format_ids = NULL;
|
||||
screen_info->n_formats = 0;
|
||||
|
||||
screen_info->contexts = NULL;
|
||||
screen_info->n_contexts = 0;
|
||||
|
||||
memset (&screen_info->glx, 0, sizeof (glitz_glx_static_proc_address_list_t));
|
||||
memset (&screen_info->glx, 0,
|
||||
sizeof (glitz_glx_static_proc_address_list_t));
|
||||
|
||||
glitz_program_map_init (&screen_info->program_map);
|
||||
|
||||
|
@ -488,7 +514,8 @@ glitz_glx_screen_info_get (Display *display,
|
|||
if (glXQueryVersion (display, &major, &minor)) {
|
||||
screen_info->glx_version = major + minor / 10.0f;
|
||||
if (major > 1 || (major > 0 || minor >= 2)) {
|
||||
glitz_glx_query_extensions (screen_info, screen_info->glx_version);
|
||||
glitz_glx_query_extensions (screen_info,
|
||||
screen_info->glx_version);
|
||||
_glitz_glx_proc_address_lookup (screen_info);
|
||||
glitz_glx_query_formats (screen_info);
|
||||
}
|
||||
|
@ -521,9 +548,6 @@ _glitz_glx_screen_destroy (glitz_glx_screen_info_t *screen_info)
|
|||
if (screen_info->formats)
|
||||
free (screen_info->formats);
|
||||
|
||||
if (screen_info->format_ids)
|
||||
free (screen_info->format_ids);
|
||||
|
||||
free (screen_info);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ glitz_glx_pbuffer_create (glitz_glx_screen_info_t *screen_info,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
Display *dpy = screen_info->display_info->display;
|
||||
|
||||
if (fbconfig) {
|
||||
int attributes[9];
|
||||
|
||||
|
@ -51,9 +53,7 @@ glitz_glx_pbuffer_create (glitz_glx_screen_info_t *screen_info,
|
|||
attributes[7] = 1;
|
||||
attributes[8] = 0;
|
||||
|
||||
return
|
||||
screen_info->glx.create_pbuffer (screen_info->display_info->display,
|
||||
fbconfig, attributes);
|
||||
return screen_info->glx.create_pbuffer (dpy, fbconfig, attributes);
|
||||
} else
|
||||
return (GLXPbuffer) 0;
|
||||
}
|
||||
|
|
|
@ -36,12 +36,13 @@
|
|||
|
||||
#include "glitz_glxext.h"
|
||||
|
||||
#define GLITZ_GLX_FEATURE_FBCONFIG_MASK (1L << 0)
|
||||
#define GLITZ_GLX_FEATURE_PBUFFER_MASK (1L << 1)
|
||||
#define GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK (1L << 2)
|
||||
#define GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK (1L << 3)
|
||||
#define GLITZ_GLX_FEATURE_MULTISAMPLE_MASK (1L << 4)
|
||||
#define GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK (1L << 5)
|
||||
#define GLITZ_GLX_FEATURE_VISUAL_RATING_MASK (1L << 0)
|
||||
#define GLITZ_GLX_FEATURE_FBCONFIG_MASK (1L << 1)
|
||||
#define GLITZ_GLX_FEATURE_PBUFFER_MASK (1L << 2)
|
||||
#define GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK (1L << 3)
|
||||
#define GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK (1L << 4)
|
||||
#define GLITZ_GLX_FEATURE_MULTISAMPLE_MASK (1L << 5)
|
||||
#define GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK (1L << 6)
|
||||
|
||||
typedef struct _glitz_glx_drawable glitz_glx_drawable_t;
|
||||
typedef struct _glitz_glx_screen_info_t glitz_glx_screen_info_t;
|
||||
|
@ -86,9 +87,6 @@ typedef struct _glitz_glx_context_t {
|
|||
glitz_format_id_t id;
|
||||
GLXFBConfig fbconfig;
|
||||
glitz_backend_t backend;
|
||||
glitz_gl_int_t max_viewport_dims[2];
|
||||
glitz_gl_int_t max_texture_2d_size;
|
||||
glitz_gl_int_t max_texture_rect_size;
|
||||
glitz_bool_t initialized;
|
||||
} glitz_glx_context_t;
|
||||
|
||||
|
@ -96,8 +94,7 @@ struct _glitz_glx_screen_info_t {
|
|||
glitz_glx_display_info_t *display_info;
|
||||
int screen;
|
||||
int drawables;
|
||||
glitz_drawable_format_t *formats;
|
||||
XID *format_ids;
|
||||
glitz_int_drawable_format_t *formats;
|
||||
int n_formats;
|
||||
glitz_glx_context_t **contexts;
|
||||
int n_contexts;
|
||||
|
@ -117,6 +114,8 @@ struct _glitz_glx_drawable {
|
|||
glitz_glx_context_t *context;
|
||||
GLXDrawable drawable;
|
||||
GLXDrawable pbuffer;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
extern void __internal_linkage
|
||||
|
@ -142,6 +141,11 @@ glitz_glx_context_destroy (glitz_glx_screen_info_t *screen_info,
|
|||
extern void __internal_linkage
|
||||
glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info);
|
||||
|
||||
extern glitz_bool_t __internal_linkage
|
||||
_glitz_glx_drawable_update_size (glitz_glx_drawable_t *drawable,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
extern GLXPbuffer __internal_linkage
|
||||
glitz_glx_pbuffer_create (glitz_glx_screen_info_t *screen_info,
|
||||
GLXFBConfig fbconfig,
|
||||
|
@ -158,7 +162,7 @@ glitz_glx_create_pbuffer (void *abstract_templ,
|
|||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
extern void __internal_linkage
|
||||
extern glitz_bool_t __internal_linkage
|
||||
glitz_glx_push_current (void *abstract_drawable,
|
||||
glitz_surface_t *surface,
|
||||
glitz_constraint_t constraint);
|
||||
|
@ -176,14 +180,15 @@ glitz_glx_make_current_read (void *abstract_surface);
|
|||
extern void __internal_linkage
|
||||
glitz_glx_destroy (void *abstract_drawable);
|
||||
|
||||
extern void __internal_linkage
|
||||
extern glitz_bool_t __internal_linkage
|
||||
glitz_glx_swap_buffers (void *abstract_drawable);
|
||||
|
||||
/* Avoid unnecessary PLT entries. */
|
||||
|
||||
slim_hidden_proto(glitz_glx_init)
|
||||
slim_hidden_proto(glitz_glx_fini)
|
||||
slim_hidden_proto(glitz_glx_find_drawable_format)
|
||||
slim_hidden_proto(glitz_glx_find_window_format)
|
||||
slim_hidden_proto(glitz_glx_find_pbuffer_format)
|
||||
slim_hidden_proto(glitz_glx_find_drawable_format_for_visual)
|
||||
slim_hidden_proto(glitz_glx_get_visual_info_from_format)
|
||||
slim_hidden_proto(glitz_glx_create_drawable_for_window)
|
||||
|
|
|
@ -43,6 +43,8 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
VISIBILITY_FLAGS =
|
||||
|
||||
MODULE = libpixman
|
||||
LIBRARY_NAME = mozlibpixman
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
@ -50,8 +52,8 @@ LIBXUL_LIBRARY = 1
|
|||
CSRCS = \
|
||||
fbcompose.c \
|
||||
fbedge.c \
|
||||
fbpict.c \
|
||||
fbtrap.c \
|
||||
ic.c \
|
||||
icblt.c \
|
||||
icbltone.c \
|
||||
iccolor.c \
|
||||
|
@ -73,7 +75,7 @@ ifdef MOZ_X11
|
|||
#DEFINES += -DUSE_MMX
|
||||
endif
|
||||
|
||||
EXPORTS = pixman.h pixman-remap.h mozstdint.h
|
||||
EXPORTS = pixman.h pixman-remap.h
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include "pixman-xserver-compat.h"
|
||||
#include "fbpict.h"
|
||||
|
||||
|
@ -586,7 +585,7 @@ static fetchProc fetchProcForPicture (PicturePtr pict)
|
|||
case PICT_a1: return fbFetch_a1;
|
||||
case PICT_g1: return fbFetch_g1;
|
||||
default:
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1014,7 +1013,7 @@ static fetchPixelProc fetchPixelProcForPicture (PicturePtr pict)
|
|||
case PICT_a1: return fbFetchPixel_a1;
|
||||
case PICT_g1: return fbFetchPixel_g1;
|
||||
default:
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1050,7 +1049,7 @@ fbStore_a8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexe
|
|||
int i;
|
||||
CARD32 *pixel = (CARD32 *)bits + x;
|
||||
for (i = 0; i < width; ++i)
|
||||
*pixel++ = (values[i] & 0xff00ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16);
|
||||
*pixel++ = (values[i] & 0xff00ff00) | ((values[i] >> 16) & 0xff) | ((values[i] & 0xff) << 16);
|
||||
}
|
||||
|
||||
static FASTCALL void
|
||||
|
@ -1059,7 +1058,7 @@ fbStore_x8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexe
|
|||
int i;
|
||||
CARD32 *pixel = (CARD32 *)bits + x;
|
||||
for (i = 0; i < width; ++i)
|
||||
*pixel++ = (values[i] & 0x0000ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16);
|
||||
*pixel++ = (values[i] & 0x0000ff00) | ((values[i] >> 16) & 0xff) | ((values[i] & 0xff) << 16);
|
||||
}
|
||||
|
||||
static FASTCALL void
|
||||
|
@ -1450,7 +1449,7 @@ static storeProc storeProcForPicture (PicturePtr pict)
|
|||
case PICT_a1: return fbStore_a1;
|
||||
case PICT_g1: return fbStore_g1;
|
||||
default:
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1954,7 +1953,7 @@ fbCombineConjointXorU (CARD32 *dest, const CARD32 *src, int width)
|
|||
static CombineFuncU fbCombineFuncU[] = {
|
||||
fbCombineClear,
|
||||
fbCombineSrcU,
|
||||
0, /* CombineDst */
|
||||
NULL, /* CombineDst */
|
||||
fbCombineOverU,
|
||||
fbCombineOverReverseU,
|
||||
fbCombineInU,
|
||||
|
@ -1966,11 +1965,11 @@ static CombineFuncU fbCombineFuncU[] = {
|
|||
fbCombineXorU,
|
||||
fbCombineAddU,
|
||||
fbCombineSaturateU,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
fbCombineClear,
|
||||
fbCombineSrcU,
|
||||
0, /* CombineDst */
|
||||
NULL, /* CombineDst */
|
||||
fbCombineDisjointOverU,
|
||||
fbCombineSaturateU, /* DisjointOverReverse */
|
||||
fbCombineDisjointInU,
|
||||
|
@ -1980,13 +1979,13 @@ static CombineFuncU fbCombineFuncU[] = {
|
|||
fbCombineDisjointAtopU,
|
||||
fbCombineDisjointAtopReverseU,
|
||||
fbCombineDisjointXorU,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
fbCombineClear,
|
||||
fbCombineSrcU,
|
||||
0, /* CombineDst */
|
||||
NULL, /* CombineDst */
|
||||
fbCombineConjointOverU,
|
||||
fbCombineConjointOverReverseU,
|
||||
fbCombineConjointInU,
|
||||
|
@ -2575,7 +2574,7 @@ fbCombineConjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
|||
static CombineFuncC fbCombineFuncC[] = {
|
||||
fbCombineClearC,
|
||||
fbCombineSrcC,
|
||||
0, /* Dest */
|
||||
NULL, /* Dest */
|
||||
fbCombineOverC,
|
||||
fbCombineOverReverseC,
|
||||
fbCombineInC,
|
||||
|
@ -2587,11 +2586,11 @@ static CombineFuncC fbCombineFuncC[] = {
|
|||
fbCombineXorC,
|
||||
fbCombineAddC,
|
||||
fbCombineSaturateC,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
fbCombineClearC, /* 0x10 */
|
||||
fbCombineSrcC,
|
||||
0, /* Dest */
|
||||
NULL, /* Dest */
|
||||
fbCombineDisjointOverC,
|
||||
fbCombineSaturateC, /* DisjointOverReverse */
|
||||
fbCombineDisjointInC,
|
||||
|
@ -2601,13 +2600,13 @@ static CombineFuncC fbCombineFuncC[] = {
|
|||
fbCombineDisjointAtopC,
|
||||
fbCombineDisjointAtopReverseC,
|
||||
fbCombineDisjointXorC, /* 0x1b */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
fbCombineClearC,
|
||||
fbCombineSrcC,
|
||||
0, /* Dest */
|
||||
NULL, /* Dest */
|
||||
fbCombineConjointOverC,
|
||||
fbCombineConjointOverReverseC,
|
||||
fbCombineConjointInC,
|
||||
|
@ -2639,7 +2638,7 @@ static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffe
|
|||
#ifdef PIXMAN_INDEXED_FORMATS
|
||||
miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
|
||||
#else
|
||||
miIndexedPtr indexed = 0;
|
||||
miIndexedPtr indexed = NULL;
|
||||
#endif
|
||||
|
||||
fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
|
||||
|
@ -2662,7 +2661,7 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
|
|||
#ifdef PIXMAN_INDEXED_FORMATS
|
||||
miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
|
||||
#else
|
||||
miIndexedPtr indexed = 0;
|
||||
miIndexedPtr indexed = NULL;
|
||||
#endif
|
||||
|
||||
fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
|
||||
|
@ -2904,8 +2903,9 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
#ifdef PIXMAN_INDEXED_FORMATS
|
||||
miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
|
||||
#else
|
||||
miIndexedPtr indexed = 0;
|
||||
miIndexedPtr indexed = NULL;
|
||||
#endif
|
||||
Bool projective = FALSE;
|
||||
|
||||
fetch = fetchPixelProcForPicture(pict);
|
||||
|
||||
|
@ -2929,6 +2929,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
projective = (unit.vector[2] != 0);
|
||||
|
||||
if (pict->filter == PIXMAN_FILTER_NEAREST || pict->filter == PIXMAN_FILTER_FAST)
|
||||
{
|
||||
|
@ -2939,8 +2940,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
if (projective) {
|
||||
y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
|
||||
x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
|
||||
} else {
|
||||
y = MOD(v.vector[1]>>16, pict->pDrawable->height);
|
||||
x = MOD(v.vector[0]>>16, pict->pDrawable->width);
|
||||
}
|
||||
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
|
||||
}
|
||||
v.vector[0] += unit.vector[0];
|
||||
|
@ -2952,8 +2958,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
if (projective) {
|
||||
y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
|
||||
x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
|
||||
} else {
|
||||
y = MOD(v.vector[1]>>16, pict->pDrawable->height);
|
||||
x = MOD(v.vector[0]>>16, pict->pDrawable->width);
|
||||
}
|
||||
if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box))
|
||||
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
|
||||
else
|
||||
|
@ -2971,8 +2982,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
if (projective) {
|
||||
y = DIV(v.vector[1],v.vector[2]);
|
||||
x = DIV(v.vector[0],v.vector[2]);
|
||||
} else {
|
||||
y = v.vector[1]>>16;
|
||||
x = v.vector[0]>>16;
|
||||
}
|
||||
buffer[i] = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ?
|
||||
0 : fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
|
||||
}
|
||||
|
@ -2985,8 +3001,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
if (projective) {
|
||||
y = DIV(v.vector[1],v.vector[2]);
|
||||
x = DIV(v.vector[0],v.vector[2]);
|
||||
} else {
|
||||
y = v.vector[1]>>16;
|
||||
x = v.vector[0]>>16;
|
||||
}
|
||||
if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box))
|
||||
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
|
||||
else
|
||||
|
@ -3006,19 +3027,27 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty, k;
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty;
|
||||
FbBits *b;
|
||||
CARD32 tl, tr, bl, br, r;
|
||||
xFixed_48_16 div;
|
||||
CARD32 ft, fb;
|
||||
|
||||
if (projective) {
|
||||
xFixed_48_16 div;
|
||||
div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
|
||||
x1 = div >> 16;
|
||||
distx = ((xFixed)div >> 8) & 0xff;
|
||||
x2 = x1 + 1;
|
||||
div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
|
||||
y1 = div >> 16;
|
||||
y2 = y1 + 1;
|
||||
disty = ((xFixed)div >> 8) & 0xff;
|
||||
} else {
|
||||
x1 = v.vector[0] >> 16;
|
||||
distx = (v.vector[0] >> 8) & 0xff;
|
||||
y1 = v.vector[1] >> 16;
|
||||
disty = (v.vector[1] >> 8) & 0xff;
|
||||
}
|
||||
x2 = x1 + 1;
|
||||
y2 = y1 + 1;
|
||||
|
||||
idistx = 256 - distx;
|
||||
idisty = 256 - disty;
|
||||
|
@ -3036,13 +3065,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
bl = fetch(b, x1 + pict->pDrawable->x, indexed);
|
||||
br = fetch(b, x2 + pict->pDrawable->x, indexed);
|
||||
|
||||
r = 0;
|
||||
for (k = 0; k < 32; k += 8) {
|
||||
CARD32 t, b;
|
||||
t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx;
|
||||
b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx;
|
||||
r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k;
|
||||
}
|
||||
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
|
||||
fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
|
||||
r = (((ft * idisty + fb * disty) >> 16) & 0xff);
|
||||
ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
|
||||
fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
|
||||
r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
|
||||
ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
|
||||
fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
|
||||
r |= (((ft * idisty + fb * disty)) & 0xff0000);
|
||||
ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
|
||||
fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
|
||||
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
|
||||
buffer[i] = r;
|
||||
}
|
||||
v.vector[0] += unit.vector[0];
|
||||
|
@ -3054,19 +3088,27 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty, k;
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty;
|
||||
FbBits *b;
|
||||
CARD32 tl, tr, bl, br, r;
|
||||
xFixed_48_16 div;
|
||||
CARD32 ft, fb;
|
||||
|
||||
if (projective) {
|
||||
xFixed_48_16 div;
|
||||
div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
|
||||
x1 = div >> 16;
|
||||
distx = ((xFixed)div >> 8) & 0xff;
|
||||
x2 = x1 + 1;
|
||||
div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
|
||||
y1 = div >> 16;
|
||||
y2 = y1 + 1;
|
||||
disty = ((xFixed)div >> 8) & 0xff;
|
||||
} else {
|
||||
x1 = v.vector[0] >> 16;
|
||||
distx = (v.vector[0] >> 8) & 0xff;
|
||||
y1 = v.vector[1] >> 16;
|
||||
disty = (v.vector[1] >> 8) & 0xff;
|
||||
}
|
||||
x2 = x1 + 1;
|
||||
y2 = y1 + 1;
|
||||
|
||||
idistx = 256 - distx;
|
||||
idisty = 256 - disty;
|
||||
|
@ -3088,13 +3130,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box)
|
||||
? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
|
||||
|
||||
r = 0;
|
||||
for (k = 0; k < 32; k += 8) {
|
||||
CARD32 t, b;
|
||||
t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx;
|
||||
b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx;
|
||||
r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k;
|
||||
}
|
||||
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
|
||||
fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
|
||||
r = (((ft * idisty + fb * disty) >> 16) & 0xff);
|
||||
ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
|
||||
fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
|
||||
r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
|
||||
ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
|
||||
fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
|
||||
r |= (((ft * idisty + fb * disty)) & 0xff0000);
|
||||
ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
|
||||
fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
|
||||
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
|
||||
buffer[i] = r;
|
||||
}
|
||||
v.vector[0] += unit.vector[0];
|
||||
|
@ -3109,20 +3156,28 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off, k;
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
|
||||
FbBits *b;
|
||||
CARD32 tl, tr, bl, br, r;
|
||||
Bool x1_out, x2_out, y1_out, y2_out;
|
||||
xFixed_48_16 div;
|
||||
CARD32 ft, fb;
|
||||
|
||||
if (projective) {
|
||||
xFixed_48_16 div;
|
||||
div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
|
||||
x1 = div >> 16;
|
||||
distx = ((xFixed)div >> 8) & 0xff;
|
||||
x2 = x1 + 1;
|
||||
div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
|
||||
y1 = div >> 16;
|
||||
y2 = y1 + 1;
|
||||
disty = ((xFixed)div >> 8) & 0xff;
|
||||
} else {
|
||||
x1 = v.vector[0] >> 16;
|
||||
distx = (v.vector[0] >> 8) & 0xff;
|
||||
y1 = v.vector[1] >> 16;
|
||||
disty = (v.vector[1] >> 8) & 0xff;
|
||||
}
|
||||
x2 = x1 + 1;
|
||||
y2 = y1 + 1;
|
||||
|
||||
idistx = 256 - distx;
|
||||
idisty = 256 - disty;
|
||||
|
@ -3141,13 +3196,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed);
|
||||
br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed);
|
||||
|
||||
r = 0;
|
||||
for (k = 0; k < 32; k += 8) {
|
||||
CARD32 t, b;
|
||||
t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx;
|
||||
b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx;
|
||||
r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k;
|
||||
}
|
||||
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
|
||||
fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
|
||||
r = (((ft * idisty + fb * disty) >> 16) & 0xff);
|
||||
ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
|
||||
fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
|
||||
r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
|
||||
ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
|
||||
fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
|
||||
r |= (((ft * idisty + fb * disty)) & 0xff0000);
|
||||
ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
|
||||
fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
|
||||
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
|
||||
buffer[i] = r;
|
||||
}
|
||||
v.vector[0] += unit.vector[0];
|
||||
|
@ -3159,19 +3219,27 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (!v.vector[2]) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off, k;
|
||||
int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
|
||||
FbBits *b;
|
||||
CARD32 tl, tr, bl, br, r;
|
||||
xFixed_48_16 div;
|
||||
CARD32 ft, fb;
|
||||
|
||||
if (projective) {
|
||||
xFixed_48_16 div;
|
||||
div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
|
||||
x1 = div >> 16;
|
||||
distx = ((xFixed)div >> 8) & 0xff;
|
||||
x2 = x1 + 1;
|
||||
div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
|
||||
y1 = div >> 16;
|
||||
y2 = y1 + 1;
|
||||
disty = ((xFixed)div >> 8) & 0xff;
|
||||
} else {
|
||||
x1 = v.vector[0] >> 16;
|
||||
distx = (v.vector[0] >> 8) & 0xff;
|
||||
y1 = v.vector[1] >> 16;
|
||||
disty = (v.vector[1] >> 8) & 0xff;
|
||||
}
|
||||
x2 = x1 + 1;
|
||||
y2 = y1 + 1;
|
||||
|
||||
idistx = 256 - distx;
|
||||
idisty = 256 - disty;
|
||||
|
@ -3189,13 +3257,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box)
|
||||
? fetch(b, x_off + 1, indexed) : 0;
|
||||
|
||||
r = 0;
|
||||
for (k = 0; k < 32; k += 8) {
|
||||
CARD32 t, b;
|
||||
t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx;
|
||||
b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx;
|
||||
r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k;
|
||||
}
|
||||
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
|
||||
fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
|
||||
r = (((ft * idisty + fb * disty) >> 16) & 0xff);
|
||||
ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
|
||||
fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
|
||||
r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
|
||||
ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
|
||||
fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
|
||||
r |= (((ft * idisty + fb * disty)) & 0xff0000);
|
||||
ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
|
||||
fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
|
||||
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
|
||||
buffer[i] = r;
|
||||
}
|
||||
v.vector[0] += unit.vector[0];
|
||||
|
@ -3219,12 +3292,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
int x1, x2, y1, y2, x, y;
|
||||
INT32 srtot, sgtot, sbtot, satot;
|
||||
xFixed *p = params;
|
||||
|
||||
if (projective) {
|
||||
xFixed_48_16 tmp;
|
||||
tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff;
|
||||
x1 = xFixedToInt(tmp);
|
||||
x2 = x1 + cwidth;
|
||||
tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff;
|
||||
y1 = xFixedToInt(tmp);
|
||||
} else {
|
||||
x1 = xFixedToInt(v.vector[0] - xoff);
|
||||
y1 = xFixedToInt(v.vector[1] - yoff);
|
||||
}
|
||||
x2 = x1 + cwidth;
|
||||
y2 = y1 + cheight;
|
||||
|
||||
srtot = sgtot = sbtot = satot = 0;
|
||||
|
@ -3305,7 +3384,7 @@ static void fbStore(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
|
|||
#ifdef PIXMAN_INDEXED_FORMATS
|
||||
miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
|
||||
#else
|
||||
miIndexedPtr indexed = 0;
|
||||
miIndexedPtr indexed = NULL;
|
||||
#endif
|
||||
|
||||
fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
|
||||
|
@ -3328,7 +3407,7 @@ static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD3
|
|||
#ifdef PIXMAN_INDEXED_FORMATS
|
||||
miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
|
||||
#else
|
||||
miIndexedPtr indexed = 0;
|
||||
miIndexedPtr indexed = NULL;
|
||||
#endif
|
||||
miIndexedPtr aindexed;
|
||||
|
||||
|
@ -3342,7 +3421,7 @@ static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD3
|
|||
#ifdef PIXMAN_INDEXED_FORMATS
|
||||
aindexed = (miIndexedPtr) pict->alphaMap->pFormat->index.devPrivate;
|
||||
#else
|
||||
aindexed = 0;
|
||||
aindexed = NULL;
|
||||
#endif
|
||||
|
||||
ax = x;
|
||||
|
@ -3373,10 +3452,10 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
|||
CARD32 *dest_buffer = src_buffer + data->width;
|
||||
int i;
|
||||
scanStoreProc store;
|
||||
scanFetchProc fetchSrc = 0, fetchMask = 0, fetchDest = 0;
|
||||
scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
|
||||
|
||||
if (data->op == PIXMAN_OPERATOR_CLEAR)
|
||||
fetchSrc = 0;
|
||||
fetchSrc = NULL;
|
||||
else if (!data->src->pDrawable) {
|
||||
#ifdef PIXMAN_GRADIENTS
|
||||
if (data->src->pSourcePict)
|
||||
|
@ -3418,7 +3497,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
|||
else
|
||||
fetchMask = fbFetchTransformed;
|
||||
} else {
|
||||
fetchMask = 0;
|
||||
fetchMask = NULL;
|
||||
}
|
||||
|
||||
if (data->dest->alphaMap) {
|
||||
|
@ -3429,7 +3508,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
|||
store = fbStore;
|
||||
}
|
||||
if (data->op == PIXMAN_OPERATOR_CLEAR || data->op == PIXMAN_OPERATOR_SRC)
|
||||
fetchDest = 0;
|
||||
fetchDest = NULL;
|
||||
|
||||
if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format_code)) {
|
||||
CARD32 *mask_buffer = dest_buffer + data->width;
|
||||
|
@ -3465,8 +3544,8 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
|||
fetchMask(data->mask, data->xMask, data->yMask, data->width, dest_buffer);
|
||||
composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width);
|
||||
}
|
||||
fetchSrc = 0;
|
||||
fetchMask = 0;
|
||||
fetchSrc = NULL;
|
||||
fetchMask = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->height; ++i) {
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
#endif
|
||||
|
||||
#include <mmintrin.h>
|
||||
#ifdef USE_SSE
|
||||
#include <xmmintrin.h> /* for _mm_shuffle_pi16 and _MM_SHUFFLE */
|
||||
#endif
|
||||
|
||||
#ifdef RENDER
|
||||
|
||||
|
@ -374,11 +376,17 @@ mmxCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
|
|||
{
|
||||
const CARD32 *end = mask + width;
|
||||
while (mask < end) {
|
||||
__m64 a = load8888(*mask);
|
||||
CARD32 mmask = *mask;
|
||||
CARD32 maska = mmask >> 24;
|
||||
if (maska == 0) {
|
||||
*src = 0;
|
||||
} else if (maska != 0xff) {
|
||||
__m64 a = load8888(mmask);
|
||||
__m64 s = load8888(*src);
|
||||
a = expand_alpha(a);
|
||||
s = pix_multiply(s, a);
|
||||
*src = store8888(s);
|
||||
}
|
||||
++src;
|
||||
++mask;
|
||||
}
|
||||
|
@ -392,10 +400,16 @@ mmxCombineOverU (CARD32 *dest, const CARD32 *src, int width)
|
|||
const CARD32 *end = dest + width;
|
||||
|
||||
while (dest < end) {
|
||||
CARD32 ssrc = *src;
|
||||
CARD32 a = ssrc >> 24;
|
||||
if (a == 0xff) {
|
||||
*dest = ssrc;
|
||||
} else if (a) {
|
||||
__m64 s, sa;
|
||||
s = load8888(*src);
|
||||
s = load8888(ssrc);
|
||||
sa = expand_alpha(s);
|
||||
*dest = store8888(over(s, sa, load8888(*dest)));
|
||||
}
|
||||
++dest;
|
||||
++src;
|
||||
}
|
||||
|
@ -874,7 +888,7 @@ fbCompositeSolid_nx8888mmx (pixman_operator_t op,
|
|||
|
||||
CHECKPOINT();
|
||||
|
||||
fbComposeGetSolid(pSrc, src);
|
||||
fbComposeGetSolid(pSrc, pDst, src);
|
||||
|
||||
if (src >> 24 == 0)
|
||||
return;
|
||||
|
@ -952,7 +966,7 @@ fbCompositeSolid_nx0565mmx (pixman_operator_t op,
|
|||
|
||||
CHECKPOINT();
|
||||
|
||||
fbComposeGetSolid(pSrc, src);
|
||||
fbComposeGetSolid(pSrc, pDst, src);
|
||||
|
||||
if (src >> 24 == 0)
|
||||
return;
|
||||
|
@ -1037,7 +1051,7 @@ fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op,
|
|||
|
||||
CHECKPOINT();
|
||||
|
||||
fbComposeGetSolid(pSrc, src);
|
||||
fbComposeGetSolid(pSrc, pDst, src);
|
||||
|
||||
srca = src >> 24;
|
||||
if (srca == 0)
|
||||
|
@ -1338,6 +1352,56 @@ fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op,
|
|||
_mm_empty();
|
||||
}
|
||||
|
||||
void
|
||||
fbCompositeSrc_8888x8888mmx (pixman_operator_t op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst,
|
||||
INT16 yDst,
|
||||
CARD16 width,
|
||||
CARD16 height)
|
||||
{
|
||||
CARD32 *dstLine, *dst;
|
||||
CARD32 *srcLine, *src, s;
|
||||
FbStride dstStride, srcStride;
|
||||
CARD8 a;
|
||||
CARD16 w;
|
||||
|
||||
fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
|
||||
fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
|
||||
|
||||
while (height--)
|
||||
{
|
||||
dst = dstLine;
|
||||
dstLine += dstStride;
|
||||
src = srcLine;
|
||||
srcLine += srcStride;
|
||||
w = width;
|
||||
|
||||
while (w--)
|
||||
{
|
||||
s = *src++;
|
||||
a = s >> 24;
|
||||
if (a == 0xff)
|
||||
*dst = s;
|
||||
else if (a) {
|
||||
__m64 ms, sa;
|
||||
ms = load8888(s);
|
||||
sa = expand_alpha(ms);
|
||||
*dst = store8888(over(ms, sa, load8888(*dst)));
|
||||
}
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
_mm_empty();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
|
||||
PicturePtr pSrc,
|
||||
|
@ -1362,7 +1426,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
|
|||
|
||||
CHECKPOINT();
|
||||
|
||||
fbComposeGetSolid(pSrc, src);
|
||||
fbComposeGetSolid(pSrc, pDst, src);
|
||||
|
||||
srca = src >> 24;
|
||||
if (srca == 0)
|
||||
|
@ -1477,7 +1541,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
|
||||
CHECKPOINT();
|
||||
|
||||
fbComposeGetSolid(pSrc, src);
|
||||
fbComposeGetSolid(pSrc, pDst, src);
|
||||
|
||||
srca = src >> 24;
|
||||
if (srca == 0)
|
||||
|
@ -1513,6 +1577,10 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
__m64 vdest = in(vsrc, expand_alpha_rev ((__m64)m));
|
||||
*dst = store8888(vdest);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
w--;
|
||||
mask++;
|
||||
|
@ -1543,6 +1611,10 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
|
||||
*(__m64 *)dst = pack8888(dest0, dest1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
dst += 2;
|
||||
|
@ -1561,6 +1633,10 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
vdest = in(vsrc, expand_alpha_rev ((__m64)m));
|
||||
*dst = store8888(vdest);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
w--;
|
||||
mask++;
|
||||
|
@ -1596,7 +1672,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
|
|||
|
||||
CHECKPOINT();
|
||||
|
||||
fbComposeGetSolid(pSrc, src);
|
||||
fbComposeGetSolid(pSrc, pDst, src);
|
||||
|
||||
srca = src >> 24;
|
||||
if (srca == 0)
|
||||
|
@ -1937,7 +2013,7 @@ fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op,
|
|||
|
||||
CHECKPOINT();
|
||||
|
||||
fbComposeGetSolid(pSrc, src);
|
||||
fbComposeGetSolid(pSrc, pDst, src);
|
||||
|
||||
srca = src >> 24;
|
||||
if (srca == 0)
|
||||
|
@ -2397,107 +2473,4 @@ fbCompositeCopyAreammx (pixman_operator_t op,
|
|||
width, height);
|
||||
}
|
||||
|
||||
#if !defined(__amd64__) && !defined(__x86_64__)
|
||||
|
||||
enum CPUFeatures {
|
||||
NoFeatures = 0,
|
||||
MMX = 0x1,
|
||||
MMX_Extensions = 0x2,
|
||||
SSE = 0x6,
|
||||
SSE2 = 0x8,
|
||||
CMOV = 0x10
|
||||
};
|
||||
|
||||
static unsigned int detectCPUFeatures(void) {
|
||||
unsigned int result;
|
||||
char vendor[13];
|
||||
vendor[0] = 0;
|
||||
vendor[12] = 0;
|
||||
/* see p. 118 of amd64 instruction set manual Vol3 */
|
||||
__asm__ ("push %%ebx\n"
|
||||
"pushf\n"
|
||||
"pop %%eax\n"
|
||||
"mov %%eax, %%ebx\n"
|
||||
"xor $0x00200000, %%eax\n"
|
||||
"push %%eax\n"
|
||||
"popf\n"
|
||||
"pushf\n"
|
||||
"pop %%eax\n"
|
||||
"mov $0x0, %%edx\n"
|
||||
"xor %%ebx, %%eax\n"
|
||||
"jz skip\n"
|
||||
|
||||
"mov $0x00000000, %%eax\n"
|
||||
"cpuid\n"
|
||||
"mov %%ebx, %1\n"
|
||||
"mov %%edx, %2\n"
|
||||
"mov %%ecx, %3\n"
|
||||
"mov $0x00000001, %%eax\n"
|
||||
"cpuid\n"
|
||||
"skip:\n"
|
||||
"pop %%ebx\n"
|
||||
"mov %%edx, %0\n"
|
||||
: "=r" (result),
|
||||
"=m" (vendor[0]),
|
||||
"=m" (vendor[4]),
|
||||
"=m" (vendor[8])
|
||||
:
|
||||
: "%eax", "%ecx", "%edx"
|
||||
);
|
||||
|
||||
unsigned int features = 0;
|
||||
if (result) {
|
||||
/* result now contains the standard feature bits */
|
||||
if (result & (1 << 15))
|
||||
features |= CMOV;
|
||||
if (result & (1 << 23))
|
||||
features |= MMX;
|
||||
if (result & (1 << 25))
|
||||
features |= SSE;
|
||||
if (result & (1 << 26))
|
||||
features |= SSE2;
|
||||
if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) {
|
||||
/* check for AMD MMX extensions */
|
||||
|
||||
unsigned int result;
|
||||
__asm__("push %%ebx\n"
|
||||
"mov $0x80000000, %%eax\n"
|
||||
"cpuid\n"
|
||||
"xor %%edx, %%edx\n"
|
||||
"cmp $0x1, %%eax\n"
|
||||
"jge skip2\n"
|
||||
"mov $0x80000001, %%eax\n"
|
||||
"cpuid\n"
|
||||
"skip2:\n"
|
||||
"mov %%edx, %0\n"
|
||||
"pop %%ebx\n"
|
||||
: "=r" (result)
|
||||
:
|
||||
: "%eax", "%ecx", "%edx"
|
||||
);
|
||||
if (result & (1<<22))
|
||||
features |= MMX_Extensions;
|
||||
}
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
Bool
|
||||
fbHaveMMX (void)
|
||||
{
|
||||
static Bool initialized = FALSE;
|
||||
static Bool mmx_present;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
unsigned int features = detectCPUFeatures();
|
||||
mmx_present = (features & (MMX|MMX_Extensions)) == (MMX|MMX_Extensions);
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return mmx_present;
|
||||
}
|
||||
#endif /* __amd64__ */
|
||||
|
||||
|
||||
#endif /* RENDER */
|
||||
|
|
|
@ -198,6 +198,18 @@ void fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op,
|
|||
INT16 yDst,
|
||||
CARD16 width,
|
||||
CARD16 height);
|
||||
void fbCompositeSrc_8888x8888mmx (pixman_operator_t op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst,
|
||||
INT16 yDst,
|
||||
CARD16 width,
|
||||
CARD16 height);
|
||||
Bool fbCopyAreammx (FbPixels *pSrc,
|
||||
FbPixels *pDst,
|
||||
int src_x,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче