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:
vladimir%pobox.com 2005-10-06 04:02:10 +00:00
Родитель 04ff4a140c
Коммит 8994df8c7d
150 изменённых файлов: 17894 добавлений и 15529 удалений

296
configure поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 (&amp;matrix, 0.5, 0.5);
* cairo_pattern_set_matrix (pattern, &amp;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;
*
* &nbsp;
* path = cairo_copy_path (cr);
*
* &nbsp;
* for (i=0; i < path->num_data; i += path->data[i].header.length) {
* data = &path->data[i];
* data = &amp;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, &param);
}
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, &param);
}
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, &param);
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, &params, &n_params);
_glitz_filter_params_set (&vecs[i].v[0], x_default, &params, &n_params);
_glitz_filter_params_set (&vecs[i].v[1], y_default, &params, &n_params);
_glitz_filter_params_set (&vecs[i].v[2], o_default, &params,
&n_params);
_glitz_filter_params_set (&vecs[i].v[0], x_default, &params,
&n_params);
_glitz_filter_params_set (&vecs[i].v[1], y_default, &params,
&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, &param);
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, &param->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,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше