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,235 +329,230 @@ _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_font_text_to_glyphs(void *abstract_font,
const char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs)
_cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_atsui_font_t *font = abstract_font;
size_t i;
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_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,
&glyphCount);
0,
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
(void *)&layoutRecords,
&glyphCount);
*num_glyphs = glyphCount - 1;
*glyphs =
(cairo_glyph_t *) malloc(*num_glyphs * (sizeof(cairo_glyph_t)));
(cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t)));
if (*glyphs == NULL) {
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_NO_MEMORY;
}
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].index = layoutRecords[i].glyphID;
(*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos);
(*glyphs)[i].y = y;
}
free(theText);
free (utf16);
ATSUDirectReleaseLayoutDataArrayPtr(NULL,
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
(void *) &layoutRecords);
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
_cairo_atsui_font_show_glyphs(void *abstract_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *generic_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
static cairo_int_status_t
_cairo_atsui_font_show_glyphs (void *abstract_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *generic_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_atsui_font_t *font = abstract_font;
CGContextRef myBitmapContext;
@ -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;
}
idx += step;
if (idx >= table_size)
idx -= table_size;
while (1) {
entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
if (entry == NULL)
break;
_cairo_cache_remove (cache, entry);
}
return NULL;
_cairo_hash_table_destroy (cache->hash_table);
cache->size = 0;
}
/* public API follows */
cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
const cairo_cache_backend_t *backend,
unsigned long max_memory)
/**
* _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)
{
assert (backend != NULL);
cairo_status_t status;
cairo_cache_t *cache;
if (cache != NULL){
cache->arrangement = &cache_arrangements[0];
cache->max_memory = max_memory;
cache->used_memory = 0;
cache->live_entries = 0;
cache = malloc (sizeof (cairo_cache_t));
if (cache == NULL)
return NULL;
#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;
status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size);
if (status) {
free (cache);
return NULL;
}
_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_lookup (cairo_cache_t *cache,
void *key,
void **entry_return,
int *created_entry)
/**
* _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);
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_cache_entry_base_t **slot = NULL, *new_entry;
cache->freeze_count--;
_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;
}
#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;
if (cache->freeze_count == 0)
_cairo_cache_shrink_to_accomodate (cache, 0);
}
cairo_status_t
_cairo_cache_remove (cairo_cache_t *cache,
void *key)
/**
* _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,
cairo_cache_entry_t *key,
cairo_cache_entry_t **entry_return)
{
cairo_cache_entry_base_t **slot;
return _cairo_hash_table_lookup (cache->hash_table,
(cairo_hash_entry_t *) key,
(cairo_hash_entry_t **) entry_return);
}
_cache_sane_state (cache);
/**
* _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_t *entry;
/* 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);
entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
if (entry == NULL)
return CAIRO_INT_STATUS_CACHE_EMPTY;
_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

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

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

@ -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) {
gstate->dash = malloc (gstate->num_dashes * sizeof (double));
if (gstate->dash == NULL) {
gstate->num_dashes = 0;
return CAIRO_STATUS_NO_MEMORY;
}
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;
}
*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;
}
*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
status = _cairo_gstate_clip_and_composite_combine (clip, operator,
src,
draw_func, draw_closure,
dst, extents);
else
return _cairo_gstate_clip_and_composite_combine (clip, operator,
src,
draw_func, draw_closure,
dst, extents);
}
else
{
return (*draw_func) (draw_closure, operator,
src, dst,
0, 0,
extents);
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;
}
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 */
(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 */
NULL, /* stops */
0 }, /* n_stops */
{ 0., 0. }, { 1.0, 1.0 } /* point0, point1 */
static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
{ CAIRO_PATTERN_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_DEFAULT }, /* extend */
};
static const cairo_radial_pattern_t cairo_radial_pattern_nil = {
{ { CAIRO_PATTERN_RADIAL, /* 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 */
NULL, /* stops */
0 }, /* n_stops */
{ 0., 0. }, { 0.0, 0.0 }, /* center0, center1 */
1.0, 1.0, /* radius0, radius1 */
static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
{ CAIRO_PATTERN_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_STATUS_READ_ERROR, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_DEFAULT }, /* extend */
};
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,7 +116,11 @@ static void
_cairo_pattern_set_error (cairo_pattern_t *pattern,
cairo_status_t status)
{
pattern->status = 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,9 +944,9 @@ _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,
stops[1]->color_char,
factor, pixel);
_cairo_pattern_shader_linear (stops[0]->color_char,
stops[1]->color_char,
factor, pixel);
/* multiply alpha */
if (((unsigned char) (*pixel >> 24)) != 0xff) {
@ -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':
@ -361,12 +244,11 @@ We must make maximum error ≤ tolerance, so compute the ∆ needed:
Remembering that is half of our angle between vertices,
the number of vertices is then
vertices = ceil(2π/2).
= ceil(π/).
vertices = ceil(2π/2).
= ceil(π/).
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;
p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
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,31 +700,35 @@ 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,
image->width,
image->height,
CAIRO_COLOR_WHITE);
if (opaque->status) {
status = CAIRO_STATUS_NO_MEMORY;
goto bail0;
if (image->format != CAIRO_FORMAT_RGB24) {
opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
image->width,
image->height);
if (opaque->status) {
status = CAIRO_STATUS_NO_MEMORY;
goto bail0;
}
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
_cairo_surface_composite (CAIRO_OPERATOR_DEST_OVER,
&pattern.base,
NULL,
opaque,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
_cairo_pattern_fini (&pattern.base);
opaque_image = (cairo_image_surface_t *) opaque;
} else {
opaque = &image->base;
opaque_image = image;
}
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
_cairo_surface_composite (CAIRO_OPERATOR_DEST_OVER,
&pattern.base,
NULL,
opaque,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
_cairo_pattern_fini (&pattern.base);
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,7 +786,8 @@ emit_image (cairo_ps_surface_t *surface,
bail2:
free (rgb);
bail1:
cairo_surface_destroy (opaque);
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,7 +108,11 @@ static void
_cairo_surface_set_error (cairo_surface_t *surface,
cairo_status_t status)
{
surface->status = 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) {
status = surface->backend->clone_similar (surface, src, clone_out);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
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,141 +1215,137 @@ _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;
bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_NATIVE | GGO_GLYPH_INDEX,
&metrics, 0, NULL, &matrix);
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,
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;
}
ptr = buffer = malloc (bytesGlyph);
if (!buffer) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL;
}
if (GetGlyphOutlineW (hdc, glyphs[i].index,
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;
}
while (ptr < buffer + bytesGlyph) {
TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr;
unsigned char *endPoly = ptr + header->cb;
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);
while (ptr < endPoly) {
TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
POINTFX *points = curve->apfx;
int i;
switch (curve->wType) {
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);
}
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;
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;
} 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;
}
c1x = 2 * cx / 3 + p1x / 3;
c1y = 2 * cy / 3 + p1y / 3;
c2x = 2 * cx / 3 + p2x / 3;
c2y = 2 * cy / 3 + p2y / 3;
_cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y);
}
break;
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);
}
break;
}
ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1);
}
_cairo_path_fixed_close_path (path);
}
free(buffer);
if (bytesGlyph == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
goto CLEANUP_FONT;
}
FAIL:
ptr = buffer = malloc (bytesGlyph);
if (!buffer) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_FONT;
}
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 CLEANUP_FONT;
}
while (ptr < buffer + bytesGlyph) {
TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr;
unsigned char *endPoly = ptr + header->cb;
ptr += sizeof (TTPOLYGONHEADER);
_cairo_path_fixed_move_to (path,
_cairo_fixed_from_FIXED (header->pfxStart.x),
_cairo_fixed_from_FIXED (header->pfxStart.y));
while (ptr < endPoly) {
TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
POINTFX *points = curve->apfx;
int i;
switch (curve->wType) {
case TT_PRIM_LINE:
for (i = 0; i < curve->cpfx; i++) {
_cairo_path_fixed_line_to (path,
_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);
cy = _cairo_fixed_from_FIXED (points[i].y);
if (i + 1 == curve->cpfx - 1) {
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)) / 2;
p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y)) / 2;
}
c1x = 2 * cx / 3 + p1x / 3;
c1y = 2 * cy / 3 + p1y / 3;
c2x = 2 * cx / 3 + p2x / 3;
c2y = 2 * cy / 3 + p2y / 3;
_cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y);
}
break;
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),
_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;
}
ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1);
}
_cairo_path_fixed_close_path (path);
}
free(buffer);
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,21 +541,77 @@ typedef struct {
#define AC_SRC_ALPHA 0x01
#endif
typedef BOOL (WINAPI *ALPHABLENDPROC)(
HDC hdcDest,
int nXOriginDest,
int nYOriginDest,
int nWidthDest,
int hHeightDest,
HDC hdcSrc,
int nXOriginSrc,
int nYOriginSrc,
int nWidthSrc,
int nHeightSrc,
BLENDFUNCTION blendFunction);
typedef BOOL (WINAPI *cairo_alpha_blend_func_t) (HDC hdcDest,
int nXOriginDest,
int nYOriginDest,
int nWidthDest,
int hHeightDest,
HDC hdcSrc,
int nXOriginSrc,
int nYOriginSrc,
int nWidthSrc,
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,
src_x + itx, src_y + ity,
width, height,
blend_function))
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
return CAIRO_STATUS_SUCCESS;
return _composite_alpha_blend (dst, src, alpha,
src_x + itx, src_y + ity,
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,

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

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

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

@ -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
(*text_to_glyphs) (void *scaled_font,
const char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs);
/* 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

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

@ -48,22 +48,22 @@ glitz_agl_fini (void);
glitz_drawable_format_t *
glitz_agl_find_drawable_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
const glitz_drawable_format_t *templ,
int count);
/* glitz_agl_drawable.c */
glitz_drawable_t *
glitz_agl_create_drawable_for_window (glitz_drawable_format_t *format,
WindowRef window,
unsigned int width,
unsigned int height);
WindowRef window,
unsigned int width,
unsigned int height);
glitz_drawable_t *
glitz_agl_create_pbuffer_drawable (glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
unsigned int width,
unsigned int height);
#if defined(__cplusplus) || defined(c_plusplus)

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

@ -34,439 +34,479 @@ extern glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address;
static CFBundleRef
_glitz_agl_get_bundle (const char *name)
{
CFBundleRef bundle = 0;
FSRefParam ref_param;
unsigned char framework_name[256];
CFBundleRef bundle = 0;
FSRefParam ref_param;
unsigned char framework_name[256];
framework_name[0] = strlen (name);
strcpy (&framework_name[1], name);
framework_name[0] = strlen (name);
strcpy (&framework_name[1], name);
memset (&ref_param, 0, sizeof (ref_param));
memset (&ref_param, 0, sizeof (ref_param));
if (FindFolder (kSystemDomain,
kFrameworksFolderType,
kDontCreateFolder,
&ref_param.ioVRefNum,
&ref_param.ioDirID) == noErr) {
FSRef ref;
if (FindFolder (kSystemDomain,
kFrameworksFolderType,
kDontCreateFolder,
&ref_param.ioVRefNum,
&ref_param.ioDirID) == noErr) {
FSRef ref;
memset (&ref, 0, sizeof (ref));
memset (&ref, 0, sizeof (ref));
ref_param.ioNamePtr = framework_name;
ref_param.newRef = &ref;
ref_param.ioNamePtr = framework_name;
ref_param.newRef = &ref;
if (PBMakeFSRefSync (&ref_param) == noErr) {
CFURLRef url;
if (PBMakeFSRefSync (&ref_param) == noErr) {
CFURLRef url;
url = CFURLCreateFromFSRef (kCFAllocatorDefault, &ref);
if (url) {
bundle = CFBundleCreate (kCFAllocatorDefault, url);
CFRelease (url);
url = CFURLCreateFromFSRef (kCFAllocatorDefault, &ref);
if (url) {
bundle = CFBundleCreate (kCFAllocatorDefault, url);
CFRelease (url);
if (!CFBundleLoadExecutable (bundle)) {
CFRelease (bundle);
return (CFBundleRef) 0;
}
}
if (!CFBundleLoadExecutable (bundle)) {
CFRelease (bundle);
return (CFBundleRef) 0;
}
}
}
}
}
return bundle;
return bundle;
}
static void
_glitz_agl_release_bundle (CFBundleRef bundle)
{
if (bundle) {
CFBundleUnloadExecutable (bundle);
CFRelease (bundle);
}
if (bundle) {
CFBundleUnloadExecutable (bundle);
CFRelease (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)
{
glitz_function_pointer_t address = NULL;
CFBundleRef bundle = (CFBundleRef) closure;
CFStringRef str;
glitz_function_pointer_t address = NULL;
CFBundleRef bundle = (CFBundleRef) closure;
CFStringRef str;
if (bundle) {
str = CFStringCreateWithCString (kCFAllocatorDefault, name,
kCFStringEncodingMacRoman);
if (bundle) {
str = CFStringCreateWithCString (kCFAllocatorDefault, name,
kCFStringEncodingMacRoman);
address = CFBundleGetFunctionPointerForName (bundle, str);
address = CFBundleGetFunctionPointerForName (bundle, str);
CFRelease (str);
}
CFRelease (str);
}
return address;
return address;
}
static glitz_context_t *
_glitz_agl_create_context (void *abstract_drawable,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
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;
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;
context = malloc (sizeof (glitz_agl_context_t));
if (!context)
return NULL;
context = malloc (sizeof (glitz_agl_context_t));
if (!context)
return NULL;
context->context =
aglCreateContext (thread_info->pixel_formats[format->id],
thread_info->root_context);
context->context =
aglCreateContext (thread_info->pixel_formats[format->id],
thread_info->root_context);
_glitz_context_init (&context->base, &drawable->base);
_glitz_context_init (&context->base, &drawable->base);
context->pbuffer = 0;
context->pbuffer = 0;
return (glitz_context_t *) context;
return (glitz_context_t *) context;
}
static void
_glitz_agl_context_destroy (void *abstract_context)
{
glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context;
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
context->base.drawable;
glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context;
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
context->base.drawable;
if (drawable->thread_info->cctx == &context->base)
{
aglSetCurrentContext (NULL);
if (drawable->thread_info->cctx == &context->base)
{
aglSetCurrentContext (NULL);
drawable->thread_info->cctx = NULL;
}
drawable->thread_info->cctx = NULL;
}
aglDestroyContext (context->context);
aglDestroyContext (context->context);
_glitz_context_fini (&context->base);
_glitz_context_fini (&context->base);
free (context);
free (context);
}
static void
_glitz_agl_copy_context (void *abstract_src,
void *abstract_dst,
unsigned long mask)
void *abstract_dst,
unsigned long mask)
{
glitz_agl_context_t *src = (glitz_agl_context_t *) abstract_src;
glitz_agl_context_t *dst = (glitz_agl_context_t *) abstract_dst;
glitz_agl_context_t *src = (glitz_agl_context_t *) abstract_src;
glitz_agl_context_t *dst = (glitz_agl_context_t *) abstract_dst;
aglCopyContext (src->context, dst->context, mask);
aglCopyContext (src->context, dst->context, mask);
}
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;
int update = 0;
glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context;
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
abstract_drawable;
int update = 0;
if (aglGetCurrentContext () != context->context)
{
update = 1;
}
else
{
if (drawable->pbuffer)
{
AGLPbuffer pbuffer;
GLuint unused;
if (drawable->base.width != drawable->width ||
drawable->base.height != drawable->height)
_glitz_agl_drawable_update_size (drawable,
drawable->base.width,
drawable->base.height);
aglGetPBuffer (context->context, &pbuffer,
&unused, &unused, &unused);
if (aglGetCurrentContext () != context->context)
{
update = 1;
}
else
{
if (drawable->pbuffer)
{
AGLPbuffer pbuffer;
GLuint unused;
if (pbuffer != drawable->pbuffer)
update = 1;
aglGetPBuffer (context->context, &pbuffer,
&unused, &unused, &unused);
}
else if (drawable->drawable)
{
if (aglGetDrawable (context->context) != drawable->drawable)
update = 1;
}
}
if (pbuffer != drawable->pbuffer)
update = 1;
if (update)
{
if (drawable->thread_info->cctx)
{
glitz_context_t *ctx = drawable->thread_info->cctx;
}
else if (drawable->drawable)
{
if (aglGetDrawable (context->context) != drawable->drawable)
update = 1;
}
}
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
}
if (update)
{
if (drawable->thread_info->cctx)
{
glitz_context_t *ctx = drawable->thread_info->cctx;
if (drawable->pbuffer) {
aglSetPBuffer (context->context, drawable->pbuffer, 0, 0,
aglGetVirtualScreen (context->context));
context->pbuffer = 1;
}
else
{
if (context->pbuffer) {
aglSetDrawable (context->context, NULL);
context->pbuffer = 0;
}
aglSetDrawable (context->context, drawable->drawable);
}
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
}
aglSetCurrentContext (context->context);
}
if (drawable->pbuffer) {
aglSetPBuffer (context->context, drawable->pbuffer, 0, 0,
aglGetVirtualScreen (context->context));
context->pbuffer = 1;
}
else
{
if (context->pbuffer) {
aglSetDrawable (context->context, NULL);
context->pbuffer = 0;
}
aglSetDrawable (context->context, drawable->drawable);
}
drawable->thread_info->cctx = &context->base;
aglSetCurrentContext (context->context);
}
drawable->thread_info->cctx = &context->base;
}
static glitz_function_pointer_t
_glitz_agl_context_get_proc_address (void *abstract_context,
const char *name)
const char *name)
{
glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context;
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
context->base.drawable;
glitz_function_pointer_t func;
CFBundleRef bundle;
glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context;
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
context->base.drawable;
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");
bundle = _glitz_agl_get_bundle ("OpenGL.framework");
func = _glitz_agl_get_proc_address (name, (void *) bundle);
func = _glitz_agl_get_proc_address (name, (void *) bundle);
_glitz_agl_release_bundle (bundle);
_glitz_agl_release_bundle (bundle);
return func;
return func;
}
glitz_agl_context_t *
glitz_agl_context_get (glitz_agl_thread_info_t *thread_info,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
glitz_agl_context_t *context;
glitz_agl_context_t **contexts = thread_info->contexts;
int index, n_contexts = thread_info->n_contexts;
glitz_agl_context_t *context;
glitz_agl_context_t **contexts = thread_info->contexts;
int index, n_contexts = thread_info->n_contexts;
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->id == format->id)
return *contexts;
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->id == format->id)
return *contexts;
index = thread_info->n_contexts++;
index = thread_info->n_contexts++;
thread_info->contexts =
realloc (thread_info->contexts,
sizeof (glitz_agl_context_t *) * thread_info->n_contexts);
if (!thread_info->contexts)
return NULL;
thread_info->contexts =
realloc (thread_info->contexts,
sizeof (glitz_agl_context_t *) * thread_info->n_contexts);
if (!thread_info->contexts)
return NULL;
context = malloc (sizeof (glitz_agl_context_t));
if (!context)
return NULL;
context = malloc (sizeof (glitz_agl_context_t));
if (!context)
return NULL;
thread_info->contexts[index] = context;
thread_info->contexts[index] = context;
context->context =
aglCreateContext (thread_info->pixel_formats[format->id],
thread_info->root_context);
if (!context->context) {
free (context);
return NULL;
}
context->context =
aglCreateContext (thread_info->pixel_formats[format->id],
thread_info->root_context);
if (!context->context) {
free (context);
return NULL;
}
context->id = format->id;
context->pbuffer = 0;
context->id = format->id;
context->pbuffer = 0;
if (!thread_info->root_context)
thread_info->root_context = context->context;
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.swap_buffers = glitz_agl_swap_buffers;
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;
context->backend.destroy_context = _glitz_agl_context_destroy;
context->backend.copy_context = _glitz_agl_copy_context;
context->backend.make_current = _glitz_agl_make_current;
context->backend.get_proc_address = _glitz_agl_context_get_proc_address;
context->backend.create_context = _glitz_agl_create_context;
context->backend.destroy_context = _glitz_agl_context_destroy;
context->backend.copy_context = _glitz_agl_copy_context;
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;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
if (screen_info->n_formats)
{
int size;
context->backend.program_map = &thread_info->program_map;
context->backend.feature_mask = 0;
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->initialized = 0;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
return context;
context->backend.program_map = &thread_info->program_map;
context->backend.feature_mask = 0;
context->initialized = 0;
return context;
}
void
glitz_agl_context_destroy (glitz_agl_thread_info_t *thread_info,
glitz_agl_context_t *context)
glitz_agl_context_t *context)
{
if (context->backend.formats)
free (context->backend.formats);
if (context->backend.drawable_formats)
free (context->backend.drawable_formats);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
if (context->backend.formats)
free (context->backend.formats);
aglDestroyContext (context->context);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
free (context);
aglDestroyContext (context->context);
free (context);
}
static void
_glitz_agl_context_initialize (glitz_agl_thread_info_t *thread_info,
glitz_agl_context_t *context)
glitz_agl_context_t *context)
{
CFBundleRef bundle;
CFBundleRef bundle;
bundle = _glitz_agl_get_bundle ("OpenGL.framework");
bundle = _glitz_agl_get_bundle ("OpenGL.framework");
glitz_backend_init (&context->backend,
_glitz_agl_get_proc_address,
(void *) bundle);
glitz_backend_init (&context->backend,
_glitz_agl_get_proc_address,
(void *) bundle);
_glitz_agl_release_bundle (bundle);
_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);
glitz_initiate_state (&_glitz_agl_gl_proc_address);
context->initialized = 1;
context->initialized = 1;
}
static void
_glitz_agl_context_make_current (glitz_agl_drawable_t *drawable,
glitz_bool_t finish)
glitz_bool_t finish)
{
if (finish)
glFinish ();
if (finish)
glFinish ();
if (drawable->thread_info->cctx)
{
glitz_context_t *ctx = drawable->thread_info->cctx;
if (drawable->thread_info->cctx)
{
glitz_context_t *ctx = drawable->thread_info->cctx;
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
drawable->thread_info->cctx = NULL;
}
if (drawable->pbuffer) {
aglSetPBuffer (drawable->context->context, drawable->pbuffer, 0, 0,
aglGetVirtualScreen (drawable->context->context));
drawable->context->pbuffer = 1;
} else {
if (drawable->context->pbuffer) {
aglSetDrawable (drawable->context->context, NULL);
drawable->context->pbuffer = 0;
drawable->thread_info->cctx = NULL;
}
aglSetDrawable (drawable->context->context, drawable->drawable);
}
if (drawable->pbuffer) {
aglSetPBuffer (drawable->context->context, drawable->pbuffer, 0, 0,
aglGetVirtualScreen (drawable->context->context));
drawable->context->pbuffer = 1;
} else {
if (drawable->context->pbuffer) {
aglSetDrawable (drawable->context->context, NULL);
drawable->context->pbuffer = 0;
}
aglSetCurrentContext (drawable->context->context);
aglSetDrawable (drawable->context->context, drawable->drawable);
}
drawable->base.update_all = 1;
aglSetCurrentContext (drawable->context->context);
if (!drawable->context->initialized)
_glitz_agl_context_initialize (drawable->thread_info, drawable->context);
drawable->base.update_all = 1;
if (!drawable->context->initialized)
_glitz_agl_context_initialize (drawable->thread_info,
drawable->context);
}
static void
_glitz_agl_context_update (glitz_agl_drawable_t *drawable,
glitz_constraint_t constraint)
glitz_constraint_t constraint)
{
AGLContext context;
AGLContext context;
switch (constraint) {
case GLITZ_NONE:
break;
case GLITZ_ANY_CONTEXT_CURRENT:
context = aglGetCurrentContext ();
if (context == (AGLContext) 0)
_glitz_agl_context_make_current (drawable, 0);
break;
case GLITZ_CONTEXT_CURRENT:
context = aglGetCurrentContext ();
if (context != drawable->context->context)
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
break;
case GLITZ_DRAWABLE_CURRENT:
context = aglGetCurrentContext ();
if (context != drawable->context->context) {
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
} else {
if (drawable->pbuffer) {
AGLPbuffer pbuffer;
GLuint unused;
switch (constraint) {
case GLITZ_NONE:
break;
case GLITZ_ANY_CONTEXT_CURRENT:
context = aglGetCurrentContext ();
if (context == (AGLContext) 0)
_glitz_agl_context_make_current (drawable, 0);
break;
case GLITZ_CONTEXT_CURRENT:
context = aglGetCurrentContext ();
if (context != drawable->context->context)
_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);
aglGetPBuffer (drawable->context->context, &pbuffer,
&unused, &unused, &unused);
context = aglGetCurrentContext ();
if (context != drawable->context->context) {
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
} else {
if (drawable->pbuffer) {
AGLPbuffer pbuffer;
GLuint unused;
if (pbuffer != drawable->pbuffer)
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
aglGetPBuffer (drawable->context->context, &pbuffer,
&unused, &unused, &unused);
} else if (drawable->drawable) {
if (aglGetDrawable (drawable->context->context) != drawable->drawable)
_glitz_agl_context_make_current (drawable, (context)? 1: 0);
}
if (pbuffer != drawable->pbuffer)
_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);
}
}
break;
}
break;
}
}
void
glitz_bool_t
glitz_agl_push_current (void *abstract_drawable,
glitz_surface_t *surface,
glitz_constraint_t constraint)
glitz_surface_t *surface,
glitz_constraint_t constraint)
{
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable;
glitz_agl_context_info_t *context_info;
int index;
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
abstract_drawable;
glitz_agl_context_info_t *context_info;
int index;
index = drawable->thread_info->context_stack_size++;
index = drawable->thread_info->context_stack_size++;
context_info = &drawable->thread_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
context_info = &drawable->thread_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
_glitz_agl_context_update (context_info->drawable, 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_context_info_t *context_info = NULL;
int index;
glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *)
abstract_drawable;
glitz_agl_context_info_t *context_info = NULL;
int index;
drawable->thread_info->context_stack_size--;
index = drawable->thread_info->context_stack_size - 1;
drawable->thread_info->context_stack_size--;
index = drawable->thread_info->context_stack_size - 1;
context_info = &drawable->thread_info->context_stack[index];
context_info = &drawable->thread_info->context_stack[index];
if (context_info->drawable)
_glitz_agl_context_update (context_info->drawable,
context_info->constraint);
if (context_info->drawable)
_glitz_agl_context_update (context_info->drawable,
context_info->constraint);
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
return NULL;
return NULL;
}

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

@ -31,189 +31,222 @@
static glitz_agl_drawable_t *
_glitz_agl_create_drawable (glitz_agl_thread_info_t *thread_info,
glitz_agl_context_t *context,
glitz_drawable_format_t *format,
AGLDrawable agl_drawable,
AGLPbuffer agl_pbuffer,
unsigned int width,
unsigned int height)
glitz_agl_context_t *context,
glitz_drawable_format_t *format,
AGLDrawable agl_drawable,
AGLPbuffer agl_pbuffer,
unsigned int width,
unsigned int height)
{
glitz_agl_drawable_t *drawable;
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 = (glitz_agl_drawable_t *) malloc (sizeof (glitz_agl_drawable_t));
if (drawable == NULL)
return NULL;
drawable->thread_info = thread_info;
drawable->context = context;
drawable->drawable = agl_drawable;
drawable->pbuffer = agl_pbuffer;
drawable->width = width;
drawable->height = height;
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;
_glitz_drawable_init (&drawable->base,
format,
&context->backend,
width, height);
glitz_drawable_update_size (&drawable->base, width, height);
if (!context->initialized) {
glitz_agl_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_agl_pop_current (drawable);
}
if (!context->initialized) {
glitz_agl_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_agl_pop_current (drawable);
}
if (width > context->backend.max_viewport_dims[0] ||
height > context->backend.max_viewport_dims[1]) {
free (drawable);
return NULL;
}
if (width > context->max_viewport_dims[0] ||
height > context->max_viewport_dims[1]) {
free (drawable);
return NULL;
}
thread_info->drawables++;
thread_info->drawables++;
return drawable;
}
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,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_agl_drawable_t *drawable;
glitz_agl_context_t *context;
AGLPbuffer pbuffer;
glitz_agl_drawable_t *drawable;
glitz_agl_context_t *context;
AGLPbuffer pbuffer;
if (!format->types.pbuffer)
return NULL;
if (!format->types.pbuffer)
return NULL;
context = glitz_agl_context_get (thread_info, format);
if (!context)
return NULL;
context = glitz_agl_context_get (thread_info, format);
if (!context)
return NULL;
pbuffer = glitz_agl_pbuffer_create (thread_info, (int) width, (int) height);
if (!pbuffer)
return NULL;
pbuffer = glitz_agl_pbuffer_create (thread_info,
(int) width, (int) height);
if (!pbuffer)
return NULL;
drawable = _glitz_agl_create_drawable (thread_info, context, format,
(AGLDrawable) 0, pbuffer,
width, height);
if (!drawable) {
glitz_agl_pbuffer_destroy (pbuffer);
return NULL;
}
drawable = _glitz_agl_create_drawable (thread_info, context, format,
(AGLDrawable) 0, pbuffer,
width, height);
if (!drawable) {
glitz_agl_pbuffer_destroy (pbuffer);
return NULL;
}
return &drawable->base;
return &drawable->base;
}
glitz_drawable_t *
glitz_agl_create_pbuffer (void *abstract_templ,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_agl_drawable_t *templ = (glitz_agl_drawable_t *) abstract_templ;
glitz_agl_drawable_t *templ = (glitz_agl_drawable_t *) abstract_templ;
return _glitz_agl_create_pbuffer_drawable (templ->thread_info, format,
width, height);
return _glitz_agl_create_pbuffer_drawable (templ->thread_info, format,
width, height);
}
glitz_drawable_t *
glitz_agl_create_drawable_for_window (glitz_drawable_format_t *format,
WindowRef window,
unsigned int width,
unsigned int height)
WindowRef window,
unsigned int width,
unsigned int height)
{
glitz_agl_drawable_t *drawable;
glitz_agl_thread_info_t *thread_info;
glitz_agl_context_t *context;
AGLDrawable agl_drawable;
glitz_agl_drawable_t *drawable;
glitz_agl_thread_info_t *thread_info;
glitz_agl_context_t *context;
AGLDrawable agl_drawable;
agl_drawable = (AGLDrawable) GetWindowPort (window);
if (!agl_drawable)
return NULL;
agl_drawable = (AGLDrawable) GetWindowPort (window);
if (!agl_drawable)
return NULL;
thread_info = glitz_agl_thread_info_get ();
if (!thread_info)
return NULL;
thread_info = glitz_agl_thread_info_get ();
if (!thread_info)
return NULL;
context = glitz_agl_context_get (thread_info, format);
if (!context)
return NULL;
if (format->id >= screen_info->n_formats)
return NULL;
drawable = _glitz_agl_create_drawable (thread_info, context, format,
agl_drawable, (AGLPbuffer) 0,
width, height);
if (!drawable)
return NULL;
context = glitz_agl_context_get (thread_info, format);
if (!context)
return NULL;
return &drawable->base;
drawable = _glitz_agl_create_drawable (thread_info, context, format,
agl_drawable, (AGLPbuffer) 0,
width, height);
if (!drawable)
return NULL;
return &drawable->base;
}
slim_hidden_def(glitz_agl_create_drawable_for_window);
glitz_drawable_t *
glitz_agl_create_pbuffer_drawable (glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
unsigned int width,
unsigned int height)
{
glitz_agl_thread_info_t *thread_info;
glitz_agl_thread_info_t *thread_info;
thread_info = glitz_agl_thread_info_get ();
if (!thread_info)
return NULL;
thread_info = glitz_agl_thread_info_get ();
if (!thread_info)
return NULL;
return _glitz_agl_create_pbuffer_drawable (thread_info, format,
width, height);
if (format->id >= screen_info->n_formats)
return NULL;
return _glitz_agl_create_pbuffer_drawable (thread_info, format,
width, height);
}
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) {
/*
* 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_program_map_fini (&drawable->base.backend->gl,
&drawable->thread_info->program_map);
glitz_agl_pop_current (abstract_drawable);
}
if (drawable->drawable || drawable->pbuffer) {
AGLContext context = aglGetCurrentContext ();
if (context == drawable->context->context) {
if (drawable->pbuffer) {
AGLPbuffer pbuffer;
GLuint unused;
aglGetPBuffer (context, &pbuffer, &unused, &unused, &unused);
if (pbuffer == drawable->pbuffer)
aglSetCurrentContext (NULL);
} else {
if (aglGetDrawable (context) == drawable->drawable)
aglSetCurrentContext (NULL);
}
drawable->thread_info->drawables--;
if (drawable->thread_info->drawables == 0) {
/*
* 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_program_map_fini (&drawable->base.backend->gl,
&drawable->thread_info->program_map);
glitz_agl_pop_current (abstract_drawable);
}
if (drawable->pbuffer)
glitz_agl_pbuffer_destroy (drawable->pbuffer);
}
if (drawable->drawable || drawable->pbuffer) {
AGLContext context = aglGetCurrentContext ();
free (drawable);
if (context == drawable->context->context) {
if (drawable->pbuffer) {
AGLPbuffer pbuffer;
GLuint unused;
aglGetPBuffer (context, &pbuffer, &unused, &unused, &unused);
if (pbuffer == drawable->pbuffer)
aglSetCurrentContext (NULL);
} else {
if (aglGetDrawable (context) == drawable->drawable)
aglSetCurrentContext (NULL);
}
}
if (drawable->pbuffer)
glitz_agl_pbuffer_destroy (drawable->pbuffer);
}
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);
glitz_agl_push_current (abstract_drawable, NULL, GLITZ_DRAWABLE_CURRENT);
aglSwapBuffers (drawable->context->context);
glitz_agl_pop_current (abstract_drawable);
return 1;
}

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

@ -30,63 +30,65 @@
#include "glitz_aglint.h"
static glitz_extension_map agl_extensions[] = {
{ 0.0, "GL_APPLE_pixel_buffer", GLITZ_AGL_FEATURE_PBUFFER_MASK },
{ 0.0, "GL_ARB_multisample", GLITZ_AGL_FEATURE_MULTISAMPLE_MASK },
{ 0.0, "GL_ARB_texture_rectangle",
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, NULL, 0 }
{ 0.0, "GL_APPLE_pixel_buffer", GLITZ_AGL_FEATURE_PBUFFER_MASK },
{ 0.0, "GL_ARB_multisample", GLITZ_AGL_FEATURE_MULTISAMPLE_MASK },
{ 0.0, "GL_ARB_texture_rectangle",
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, NULL, 0 }
};
glitz_status_t
glitz_agl_query_extensions (glitz_agl_thread_info_t *thread_info)
{
GLint attrib[] = {
AGL_RGBA,
AGL_NO_RECOVERY,
AGL_NONE
};
AGLPixelFormat pf;
AGLContext context;
GLint attrib[] = {
AGL_RGBA,
AGL_NO_RECOVERY,
AGL_NONE
};
AGLPixelFormat pf;
AGLContext context;
thread_info->agl_feature_mask = 0;
thread_info->agl_feature_mask = 0;
pf = aglChoosePixelFormat (NULL, 0, attrib);
context = aglCreateContext (pf, NULL);
pf = aglChoosePixelFormat (NULL, 0, attrib);
context = aglCreateContext (pf, NULL);
if (context) {
const char *gl_extensions_string;
if (context) {
const char *gl_extensions_string;
aglSetCurrentContext (context);
aglSetCurrentContext (context);
gl_extensions_string = (const char *) glGetString (GL_EXTENSIONS);
gl_extensions_string = (const char *) glGetString (GL_EXTENSIONS);
thread_info->agl_feature_mask =
glitz_extensions_query (0.0,
gl_extensions_string,
agl_extensions);
thread_info->agl_feature_mask =
glitz_extensions_query (0.0,
gl_extensions_string,
agl_extensions);
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK) {
const char *vendor;
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK)
{
const char *vendor;
vendor = glGetString (GL_VENDOR);
vendor = glGetString (GL_VENDOR);
if (vendor) {
if (vendor) {
/* NVIDIA's driver seem to support multisample with pbuffers */
if (!strncmp ("NVIDIA", vendor, 6))
thread_info->agl_feature_mask |=
GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK;
}
/* NVIDIA's driver seem to support multisample with pbuffers */
if (!strncmp ("NVIDIA", vendor, 6))
thread_info->agl_feature_mask |=
GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK;
}
}
aglSetCurrentContext (NULL);
aglDestroyContext (context);
}
aglSetCurrentContext (NULL);
aglDestroyContext (context);
}
aglDestroyPixelFormat (pf);
aglDestroyPixelFormat (pf);
return GLITZ_STATUS_SUCCESS;
return GLITZ_STATUS_SUCCESS;
}

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

@ -33,301 +33,303 @@
#include <string.h>
static GLint _attribs[] = {
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_NONE
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_NONE
};
static GLint _db_attribs[] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_NONE
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_NONE
};
static GLint _stencil_attribs[] = {
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_DEPTH_SIZE, 8,
AGL_STENCIL_SIZE, 8,
AGL_NONE
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_DEPTH_SIZE, 8,
AGL_STENCIL_SIZE, 8,
AGL_NONE
};
static GLint _db_stencil_attribs[] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_NONE
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_NONE
};
static GLint _ms2_attribs[] = {
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 2,
AGL_NONE
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 2,
AGL_NONE
};
static GLint _db_ms2_attribs[] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 2,
AGL_NONE
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 2,
AGL_NONE
};
static GLint _ms4_attribs[] = {
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 4,
AGL_NONE
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 4,
AGL_NONE
};
static GLint _db_ms4_attribs[] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 4,
AGL_NONE
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 4,
AGL_NONE
};
static GLint _ms6_attribs[] = {
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 6,
AGL_NONE
AGL_RGBA,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 6,
AGL_NONE
};
static GLint _db_ms6_attribs[] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 6,
AGL_NONE
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ALPHA_SIZE, 16,
AGL_RED_SIZE, 16,
AGL_STENCIL_SIZE, 8,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 6,
AGL_NONE
};
static GLint *_attribs_list[] = {
_attribs,
_db_attribs,
_stencil_attribs,
_db_stencil_attribs,
_ms2_attribs,
_db_ms2_attribs,
_ms4_attribs,
_db_ms4_attribs,
_ms6_attribs,
_db_ms6_attribs
_attribs,
_db_attribs,
_stencil_attribs,
_db_stencil_attribs,
_ms2_attribs,
_db_ms2_attribs,
_ms4_attribs,
_db_ms4_attribs,
_ms6_attribs,
_db_ms6_attribs
};
static int
_glitz_agl_format_compare (const void *elem1,
const void *elem2)
const void *elem2)
{
int i, score[2];
glitz_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;
i = score[0] = score[1] = 0;
format[0] = (glitz_drawable_format_t *) elem1;
format[1] = (glitz_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)
score[i] += 5;
score[i] += 10;
for (; i < 2; i++) {
if (format[i]->color.red_size) {
if (format[i]->color.red_size == 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->color.green_size) {
if (format[i]->color.green_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)
score[i] += 5;
if (format[i]->depth_size)
score[i] += 5;
if (format[i]->doublebuffer)
score[i] += 10;
if (format[i]->types.window)
score[i] += 10;
if (format[i]->types.pbuffer)
score[i] += 10;
if (format[i]->samples > 1)
score[i] -= (20 - format[i]->samples);
}
if (format[i]->color.green_size) {
if (format[i]->color.green_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)
score[i] += 5;
if (format[i]->depth_size)
score[i] += 5;
if (format[i]->doublebuffer)
score[i] += 10;
if (format[i]->types.window)
score[i] += 10;
if (format[i]->types.pbuffer)
score[i] += 10;
if (format[i]->samples > 1)
score[i] -= (20 - format[i]->samples);
}
return score[1] - score[0];
return score[1] - score[0];
}
static void
_glitz_add_format (glitz_agl_thread_info_t *thread_info,
glitz_drawable_format_t *format,
AGLPixelFormat pixel_format)
glitz_drawable_format_t *format,
AGLPixelFormat pixel_format)
{
if (!glitz_drawable_format_find (thread_info->formats,
thread_info->n_formats,
GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK,
format, 0)) {
int n = thread_info->n_formats;
if (!glitz_drawable_format_find (thread_info->formats,
thread_info->n_formats,
GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK,
format, 0)) {
int n = thread_info->n_formats;
thread_info->formats =
realloc (thread_info->formats,
sizeof (glitz_drawable_format_t) * (n + 1));
thread_info->pixel_formats =
realloc (thread_info->pixel_formats,
sizeof (AGLPixelFormat) * (n + 1));
thread_info->formats =
realloc (thread_info->formats,
sizeof (glitz_drawable_format_t) * (n + 1));
thread_info->pixel_formats =
realloc (thread_info->pixel_formats,
sizeof (AGLPixelFormat) * (n + 1));
if (thread_info->formats && thread_info->pixel_formats) {
thread_info->formats[n] = *format;
thread_info->formats[n].id = n;
thread_info->pixel_formats[n] = pixel_format;
thread_info->n_formats++;
if (thread_info->formats && thread_info->pixel_formats) {
thread_info->formats[n] = *format;
thread_info->formats[n].id = n;
thread_info->pixel_formats[n] = pixel_format;
thread_info->n_formats++;
}
}
}
}
void
glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
{
glitz_drawable_format_t format;
AGLPixelFormat pixel_format, *new_pfs;
int n_attribs_list, i;
glitz_drawable_format_t format;
AGLPixelFormat pixel_format, *new_pfs;
int n_attribs_list, i;
format.types.window = 1;
format.id = 0;
format.types.window = 1;
format.id = 0;
n_attribs_list = sizeof (_attribs_list) / sizeof (GLint *);
n_attribs_list = sizeof (_attribs_list) / sizeof (GLint *);
for (i = 0; i < n_attribs_list; i++) {
GLint value;
for (i = 0; i < n_attribs_list; i++) {
GLint value;
pixel_format = aglChoosePixelFormat (NULL, 0, _attribs_list[i]);
pixel_format = aglChoosePixelFormat (NULL, 0, _attribs_list[i]);
/* Stereo is not supported yet */
if (!(aglDescribePixelFormat (pixel_format, AGL_STEREO, &value)) ||
value) {
aglDestroyPixelFormat (pixel_format);
continue;
/* Stereo is not supported yet */
if (!(aglDescribePixelFormat (pixel_format, AGL_STEREO, &value)) ||
value) {
aglDestroyPixelFormat (pixel_format);
continue;
}
aglDescribePixelFormat (pixel_format, AGL_DOUBLEBUFFER, &value);
format.doublebuffer = (value)? 1: 0;
aglDescribePixelFormat (pixel_format, AGL_RED_SIZE, &value);
format.color.red_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_GREEN_SIZE, &value);
format.color.green_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_BLUE_SIZE, &value);
format.color.blue_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_ALPHA_SIZE, &value);
format.color.alpha_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_DEPTH_SIZE, &value);
format.depth_size = (unsigned short) value;
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 (value) {
aglDescribePixelFormat (pixel_format, AGL_SAMPLES_ARB, &value);
format.samples = (unsigned short) (value > 1)? value: 1;
} else
format.samples = 1;
} else
format.samples = 1;
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_PBUFFER_MASK) {
if (format.color.red_size && format.color.green_size &&
format.color.blue_size && format.color.alpha_size &&
format.doublebuffer == 0 && format.stencil_size == 0 &&
format.depth_size == 0) {
if (thread_info->agl_feature_mask &
GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK)
format.types.pbuffer = 1;
else if (format.samples == 1)
format.types.pbuffer = 1;
else
format.types.pbuffer = 0;
} else
format.types.pbuffer = 0;
} else
format.types.pbuffer = 0;
if (format.color.red_size ||
format.color.green_size ||
format.color.blue_size ||
format.color.alpha_size)
_glitz_add_format (thread_info, &format, pixel_format);
}
aglDescribePixelFormat (pixel_format, AGL_DOUBLEBUFFER, &value);
format.doublebuffer = (value)? 1: 0;
if (!thread_info->n_formats)
return;
aglDescribePixelFormat (pixel_format, AGL_RED_SIZE, &value);
format.color.red_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_GREEN_SIZE, &value);
format.color.green_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_BLUE_SIZE, &value);
format.color.blue_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_ALPHA_SIZE, &value);
format.color.alpha_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_DEPTH_SIZE, &value);
format.depth_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_STENCIL_SIZE, &value);
format.stencil_size = (unsigned short) value;
qsort (thread_info->formats, thread_info->n_formats,
sizeof (glitz_drawable_format_t), _glitz_agl_format_compare);
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;
} else
format.samples = 1;
} else
format.samples = 1;
/*
* Update AGLPixelFormat list so that it matches the sorted format list.
*/
new_pfs = malloc (sizeof (AGLPixelFormat) * thread_info->n_formats);
if (!new_pfs) {
thread_info->n_formats = 0;
return;
}
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_PBUFFER_MASK) {
if (format.color.red_size && format.color.green_size &&
format.color.blue_size && format.color.alpha_size &&
format.doublebuffer == 0 && format.stencil_size == 0 &&
format.depth_size == 0) {
for (i = 0; i < thread_info->n_formats; i++) {
new_pfs[i] = thread_info->pixel_formats[thread_info->formats[i].id];
thread_info->formats[i].id = i;
}
if (thread_info->agl_feature_mask &
GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK)
format.types.pbuffer = 1;
else if (format.samples == 1)
format.types.pbuffer = 1;
else
format.types.pbuffer = 0;
} else
format.types.pbuffer = 0;
} else
format.types.pbuffer = 0;
if (format.color.red_size ||
format.color.green_size ||
format.color.blue_size ||
format.color.alpha_size)
_glitz_add_format (thread_info, &format, pixel_format);
}
if (!thread_info->n_formats)
return;
qsort (thread_info->formats, thread_info->n_formats,
sizeof (glitz_drawable_format_t), _glitz_agl_format_compare);
/*
* Update AGLPixelFormat list so that it matches the sorted format list.
*/
new_pfs = malloc (sizeof (AGLPixelFormat) * thread_info->n_formats);
if (!new_pfs) {
thread_info->n_formats = 0;
return;
}
for (i = 0; i < thread_info->n_formats; i++) {
new_pfs[i] = thread_info->pixel_formats[thread_info->formats[i].id];
thread_info->formats[i].id = i;
}
free (thread_info->pixel_formats);
thread_info->pixel_formats = new_pfs;
free (thread_info->pixel_formats);
thread_info->pixel_formats = new_pfs;
}
glitz_drawable_format_t *
glitz_agl_find_drawable_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
const glitz_drawable_format_t *templ,
int count)
{
glitz_agl_thread_info_t *thread_info = glitz_agl_thread_info_get ();
glitz_agl_thread_info_t *thread_info = glitz_agl_thread_info_get ();
return glitz_drawable_format_find (thread_info->formats,
thread_info->n_formats,
mask, templ, count);
return glitz_drawable_format_find (thread_info->formats,
thread_info->n_formats,
mask, templ, count);
}
slim_hidden_def(glitz_agl_find_drawable_format);

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

@ -33,85 +33,97 @@
glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address = {
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(glitz_gl_bind_texture_t) glBindTexture,
(glitz_gl_tex_image_2d_t) glTexImage2D,
(glitz_gl_tex_parameter_i_t) glTexParameteri,
(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,
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(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,
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(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
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(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_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
@ -132,79 +144,79 @@ static pthread_key_t info_tsd;
static void
glitz_agl_thread_info_destroy (glitz_agl_thread_info_t *thread_info)
{
pthread_setspecific (info_tsd, NULL);
pthread_setspecific (info_tsd, NULL);
if (thread_info) {
glitz_agl_thread_info_fini (thread_info);
free (thread_info);
}
if (thread_info) {
glitz_agl_thread_info_fini (thread_info);
free (thread_info);
}
}
static void
_tsd_destroy (void *p)
{
if (p) {
glitz_agl_thread_info_fini ((glitz_agl_thread_info_t *) p);
free (p);
}
if (p) {
glitz_agl_thread_info_fini ((glitz_agl_thread_info_t *) p);
free (p);
}
}
glitz_agl_thread_info_t *
glitz_agl_thread_info_get (void)
{
glitz_agl_thread_info_t *thread_info;
void *p;
glitz_agl_thread_info_t *thread_info;
void *p;
if (!tsd_initialized) {
pthread_key_create (&info_tsd, _tsd_destroy);
tsd_initialized = 1;
}
if (!tsd_initialized) {
pthread_key_create (&info_tsd, _tsd_destroy);
tsd_initialized = 1;
}
p = pthread_getspecific (info_tsd);
p = pthread_getspecific (info_tsd);
if (p == NULL) {
thread_info = malloc (sizeof (glitz_agl_thread_info_t));
glitz_agl_thread_info_init (thread_info);
if (p == NULL) {
thread_info = malloc (sizeof (glitz_agl_thread_info_t));
glitz_agl_thread_info_init (thread_info);
pthread_setspecific (info_tsd, thread_info);
} else
thread_info = (glitz_agl_thread_info_t *) p;
pthread_setspecific (info_tsd, thread_info);
} else
thread_info = (glitz_agl_thread_info_t *) p;
return thread_info;
return thread_info;
}
#else
/* not thread safe */
static glitz_agl_thread_info_t _thread_info = {
0,
NULL,
NULL,
0,
NULL,
0,
{ 0 },
0,
NULL,
0,
NULL,
{ 0 }
0,
NULL,
NULL,
0,
NULL,
0,
{ 0 },
0,
NULL,
0,
NULL,
{ 0 }
};
static void
glitz_agl_thread_info_destroy (glitz_agl_thread_info_t *thread_info)
{
if (thread_info)
glitz_agl_thread_info_fini (thread_info);
if (thread_info)
glitz_agl_thread_info_fini (thread_info);
}
glitz_agl_thread_info_t *
glitz_agl_thread_info_get (void)
{
if (_thread_info.context_stack_size == 0)
glitz_agl_thread_info_init (&_thread_info);
if (_thread_info.context_stack_size == 0)
glitz_agl_thread_info_init (&_thread_info);
return &_thread_info;
return &_thread_info;
}
#endif
@ -212,58 +224,58 @@ glitz_agl_thread_info_get (void)
static void
glitz_agl_thread_info_init (glitz_agl_thread_info_t *thread_info)
{
thread_info->formats = NULL;
thread_info->pixel_formats = (AGLPixelFormat *) 0;
thread_info->n_formats = 0;
thread_info->contexts = NULL;
thread_info->n_contexts = 0;
thread_info->formats = NULL;
thread_info->pixel_formats = (AGLPixelFormat *) 0;
thread_info->n_formats = 0;
thread_info->contexts = NULL;
thread_info->n_contexts = 0;
thread_info->context_stack_size = 1;
thread_info->context_stack->surface = NULL;
thread_info->context_stack->constraint = GLITZ_NONE;
thread_info->context_stack_size = 1;
thread_info->context_stack->surface = NULL;
thread_info->context_stack->constraint = GLITZ_NONE;
thread_info->root_context = NULL;
thread_info->root_context = NULL;
thread_info->agl_feature_mask = 0;
thread_info->agl_feature_mask = 0;
thread_info->cctx = NULL;
thread_info->cctx = NULL;
glitz_program_map_init (&thread_info->program_map);
glitz_program_map_init (&thread_info->program_map);
if (!glitz_agl_query_extensions (thread_info))
glitz_agl_query_formats (thread_info);
if (!glitz_agl_query_extensions (thread_info))
glitz_agl_query_formats (thread_info);
}
static void
glitz_agl_thread_info_fini (glitz_agl_thread_info_t *thread_info)
{
int i;
int i;
for (i = 0; i < thread_info->n_contexts; i++)
glitz_agl_context_destroy (thread_info, thread_info->contexts[i]);
for (i = 0; i < thread_info->n_contexts; i++)
glitz_agl_context_destroy (thread_info, thread_info->contexts[i]);
for (i = 0; i < thread_info->n_formats; i++)
aglDestroyPixelFormat (thread_info->pixel_formats[i]);
for (i = 0; i < thread_info->n_formats; i++)
aglDestroyPixelFormat (thread_info->pixel_formats[i]);
if (thread_info->formats)
free (thread_info->formats);
if (thread_info->formats)
free (thread_info->formats);
if (thread_info->pixel_formats)
free (thread_info->pixel_formats);
if (thread_info->pixel_formats)
free (thread_info->pixel_formats);
}
void
glitz_agl_init (void)
{
glitz_agl_thread_info_get ();
glitz_agl_thread_info_get ();
}
slim_hidden_def(glitz_agl_init);
void
glitz_agl_fini (void)
{
glitz_agl_thread_info_t *info = glitz_agl_thread_info_get ();
glitz_agl_thread_info_t *info = glitz_agl_thread_info_get ();
glitz_agl_thread_info_destroy (info);
glitz_agl_thread_info_destroy (info);
}
slim_hidden_def(glitz_agl_fini);

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

@ -31,28 +31,28 @@
AGLPbuffer
glitz_agl_pbuffer_create (glitz_agl_thread_info_t *thread_info,
int width,
int height)
int width,
int height)
{
AGLPbuffer pbuffer;
glitz_gl_enum_t target;
AGLPbuffer pbuffer;
glitz_gl_enum_t target;
if (!POWER_OF_TWO (width) || !POWER_OF_TWO (height)) {
if (thread_info->agl_feature_mask &
GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK)
target = GLITZ_GL_TEXTURE_RECTANGLE;
else
return (AGLPbuffer) 0;
} else
target = GLITZ_GL_TEXTURE_2D;
if (!POWER_OF_TWO (width) || !POWER_OF_TWO (height)) {
if (thread_info->agl_feature_mask &
GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK)
target = GLITZ_GL_TEXTURE_RECTANGLE;
else
return (AGLPbuffer) 0;
} else
target = GLITZ_GL_TEXTURE_2D;
aglCreatePBuffer (width, height, target, GLITZ_GL_RGBA, 0, &pbuffer);
aglCreatePBuffer (width, height, target, GLITZ_GL_RGBA, 0, &pbuffer);
return pbuffer;
return pbuffer;
}
void
glitz_agl_pbuffer_destroy (AGLPbuffer pbuffer)
{
aglDestroyPBuffer (pbuffer);
aglDestroyPBuffer (pbuffer);
}

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

@ -43,47 +43,46 @@
typedef struct _glitz_agl_drawable glitz_agl_drawable_t;
typedef struct _glitz_agl_context_info_t {
glitz_agl_drawable_t *drawable;
glitz_surface_t *surface;
glitz_constraint_t constraint;
glitz_agl_drawable_t *drawable;
glitz_surface_t *surface;
glitz_constraint_t constraint;
} glitz_agl_context_info_t;
typedef struct _glitz_agl_context_t {
glitz_context_t base;
AGLContext context;
glitz_format_id_t id;
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_context_t base;
AGLContext context;
glitz_format_id_t id;
AGLPixelFormat pixel_format;
glitz_bool_t pbuffer;
glitz_backend_t backend;
glitz_bool_t initialized;
} glitz_agl_context_t;
typedef struct _glitz_agl_thread_info_t {
int drawables;
glitz_drawable_format_t *formats;
AGLPixelFormat *pixel_formats;
int n_formats;
glitz_agl_context_t **contexts;
int n_contexts;
glitz_agl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE];
int context_stack_size;
AGLContext root_context;
unsigned long agl_feature_mask;
glitz_context_t *cctx;
glitz_program_map_t program_map;
int drawables;
glitz_int_drawable_format_t *formats;
AGLPixelFormat *pixel_formats;
int n_formats;
glitz_agl_context_t **contexts;
int n_contexts;
glitz_agl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE];
int context_stack_size;
AGLContext root_context;
unsigned long agl_feature_mask;
glitz_context_t *cctx;
glitz_program_map_t program_map;
} glitz_agl_thread_info_t;
struct _glitz_agl_drawable {
glitz_drawable_t base;
glitz_drawable_t base;
glitz_agl_thread_info_t *thread_info;
glitz_agl_context_t *context;
AGLDrawable drawable;
AGLPbuffer pbuffer;
WindowRef window;
glitz_agl_thread_info_t *thread_info;
glitz_agl_context_t *context;
AGLDrawable drawable;
AGLPbuffer pbuffer;
WindowRef window;
int width;
int height;
};
extern glitz_status_t __internal_linkage
@ -94,33 +93,33 @@ glitz_agl_thread_info_get (void);
extern glitz_agl_context_t __internal_linkage *
glitz_agl_context_get (glitz_agl_thread_info_t *thread_info,
glitz_drawable_format_t *format);
glitz_drawable_format_t *format);
extern void __internal_linkage
glitz_agl_context_destroy (glitz_agl_thread_info_t *thread_info,
glitz_agl_context_t *context);
glitz_agl_context_t *context);
extern void __internal_linkage
glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info);
extern AGLPbuffer __internal_linkage
glitz_agl_pbuffer_create (glitz_agl_thread_info_t *thread_info,
int width,
int height);
int width,
int height);
extern void __internal_linkage
glitz_agl_pbuffer_destroy (AGLPbuffer pbuffer);
extern glitz_drawable_t __internal_linkage *
glitz_agl_create_pbuffer (void *abstract_templ,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
glitz_drawable_format_t *format,
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);
glitz_surface_t *surface,
glitz_constraint_t constraint);
extern glitz_surface_t __internal_linkage *
glitz_agl_pop_current (void *abstract_drawable);
@ -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,28 +47,36 @@ glitz_egl_fini (void);
/* glitz_egl_config.c */
glitz_drawable_format_t *
glitz_egl_find_config (EGLDisplay egl_display,
EGLScreenMESA egl_screen,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
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 *
glitz_egl_create_surface (EGLDisplay egl_display,
EGLScreenMESA egl_screen,
glitz_drawable_format_t *format,
EGLSurface egl_surface,
unsigned int width,
unsigned int height);
EGLScreenMESA egl_screen,
glitz_drawable_format_t *format,
EGLSurface egl_surface,
unsigned int width,
unsigned int height);
glitz_drawable_t *
glitz_egl_create_pbuffer_surface (EGLDisplay egl_display,
EGLScreenMESA egl_screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
EGLScreenMESA egl_screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
#if defined(__cplusplus) || defined(c_plusplus)

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

@ -34,188 +34,210 @@
static int
_glitz_egl_format_compare (const void *elem1,
const void *elem2)
const void *elem2)
{
int i, score[2];
glitz_drawable_format_t *format[2];
glitz_int_drawable_format_t *format[2];
int i, score[2];
format[0] = (glitz_drawable_format_t *) elem1;
format[1] = (glitz_drawable_format_t *) elem2;
i = score[0] = score[1] = 0;
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)
score[i] += 5;
score[i] += 10;
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]->d.color.alpha_size)
{
if (format[i]->d.color.alpha_size >= 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->d.stencil_size)
score[i] += 5;
if (format[i]->d.depth_size)
score[i] += 5;
if (format[i]->d.doublebuffer)
score[i] += 10;
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 & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)
score[i] += 10;
if (format[i]->caveat)
score[i] -= 1000;
}
if (format[i]->color.green_size) {
if (format[i]->color.green_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)
score[i] += 5;
if (format[i]->depth_size)
score[i] += 5;
if (format[i]->doublebuffer)
score[i] += 10;
if (format[i]->types.window)
score[i] += 10;
if (format[i]->types.pbuffer)
score[i] += 10;
if (format[i]->samples > 1)
score[i] -= (20 - format[i]->samples);
}
return score[1] - score[0];
return score[1] - score[0];
}
static void
_glitz_add_format (glitz_egl_screen_info_t *screen_info,
glitz_drawable_format_t *format,
EGLConfig egl_id)
_glitz_add_format (glitz_egl_screen_info_t *screen_info,
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) {
screen_info->formats[n] = *format;
screen_info->formats[n].id = n;
screen_info->egl_config_ids[n] = egl_id;
screen_info->n_formats++;
realloc (screen_info->formats,
sizeof (glitz_int_drawable_format_t) * (n + 1));
if (screen_info->formats)
{
screen_info->formats[n] = *format;
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)
{
EGLDisplay egl_display;
glitz_drawable_format_t format;
EGLConfig *egl_configs;
int i, num_configs;
EGLConfig egl_id;
glitz_int_drawable_format_t format;
EGLDisplay egl_display;
EGLConfig *egl_configs;
int i, num_configs;
egl_display = screen_info->display_info->egl_display;
egl_display = screen_info->display_info->egl_display;
eglGetConfigs(egl_display, NULL, 0, &num_configs);
egl_configs = malloc(sizeof(*egl_configs) * num_configs);
eglGetConfigs(egl_display, egl_configs, num_configs, &num_configs);
eglGetConfigs (egl_display, NULL, 0, &num_configs);
egl_configs = malloc (sizeof (EGLConfig) * num_configs);
if (!egl_configs)
return;
for (i = 0; i < num_configs; i++) {
int value;
format.d.id = 0;
format.d.doublebuffer = 1;
eglGetConfigAttrib(egl_display, egl_configs[i],
EGL_SURFACE_TYPE, &value);
if (!((value & EGL_WINDOW_BIT) || (value & EGL_PBUFFER_BIT)))
continue;
eglGetConfigs (egl_display, egl_configs, num_configs, &num_configs);
format.types.window = (value & EGL_WINDOW_BIT)? 1: 0;
format.types.pbuffer = (value & EGL_PBUFFER_BIT)? 1: 0;
format.id = 0;
for (i = 0; i < num_configs; i++)
{
int value;
eglGetConfigAttrib(egl_display, egl_configs[i], EGL_CONFIG_ID, &value);
egl_id = (EGLConfig) value;
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_SURFACE_TYPE,
&value);
if (!((value & EGL_WINDOW_BIT) || (value & EGL_PBUFFER_BIT)))
continue;
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.types = 0;
if (value & EGL_WINDOW_BIT)
format.types |= GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
format.doublebuffer = 1;
if (value & EGL_PBUFFER_BIT)
format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
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;
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_CONFIG_ID,
&value);
format.u.uval = value;
_glitz_add_format (screen_info, &format, egl_id);
}
eglGetConfigAttrib (egl_display, egl_configs[i], EGL_RED_SIZE, &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;
free(egl_configs);
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;
return GLITZ_STATUS_SUCCESS;
_glitz_add_format (screen_info, &format);
}
free (egl_configs);
}
void
glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info)
{
EGLConfig *egl_new_ids;
int i;
int i;
_glitz_egl_query_configs (screen_info);
_glitz_egl_query_configs (screen_info);
if (!screen_info->n_formats)
return;
if (!screen_info->n_formats)
return;
qsort (screen_info->formats, screen_info->n_formats,
sizeof (glitz_drawable_format_t), _glitz_egl_format_compare);
qsort (screen_info->formats, screen_info->n_formats,
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,
EGLScreenMESA egl_screen,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
glitz_egl_find_window_config (EGLDisplay egl_display,
EGLScreenMESA egl_screen,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
{
glitz_egl_screen_info_t *screen_info =
glitz_egl_screen_info_get (egl_display, egl_screen);
glitz_int_drawable_format_t itempl;
glitz_egl_screen_info_t *screen_info =
glitz_egl_screen_info_get (egl_display, egl_screen);
return glitz_drawable_format_find (screen_info->formats,
screen_info->n_formats,
mask, templ, count);
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, &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);

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

@ -35,323 +35,368 @@ extern glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address;
static void
_glitz_egl_context_create (glitz_egl_screen_info_t *screen_info,
EGLConfig egl_config,
EGLContext egl_share_list,
glitz_egl_context_t *context)
EGLConfig egl_config,
EGLContext egl_share_list,
glitz_egl_context_t *context)
{
context->id = egl_config;
context->egl_context = eglCreateContext (screen_info->display_info->egl_display,
egl_config, egl_share_list, NULL);
context->id = egl_config;
context->egl_context =
eglCreateContext (screen_info->display_info->egl_display,
egl_config, egl_share_list, NULL);
}
static glitz_context_t *
_glitz_egl_create_context (void *abstract_drawable,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
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];
glitz_egl_context_t *context;
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->formats[format->id].u.uval;
glitz_egl_context_t *context;
context = malloc (sizeof (glitz_egl_context_t));
if (!context)
return NULL;
context = malloc (sizeof (glitz_egl_context_t));
if (!context)
return NULL;
_glitz_context_init (&context->base, &drawable->base);
_glitz_context_init (&context->base, &drawable->base);
_glitz_egl_context_create (screen_info,
format_id,
screen_info->egl_root_context,
context);
_glitz_egl_context_create (screen_info,
format_id,
screen_info->egl_root_context,
context);
return (glitz_context_t *) context;
return (glitz_context_t *) context;
}
static void
_glitz_egl_context_destroy (void *abstract_context)
{
glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context;
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *)
context->base.drawable;
glitz_egl_context_t *context = (glitz_egl_context_t *) 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)
{
eglMakeCurrent (drawable->screen_info->display_info->egl_display,
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
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);
drawable->screen_info->display_info->thread_info->cctx = NULL;
}
drawable->screen_info->display_info->thread_info->cctx = NULL;
}
eglDestroyContext (drawable->screen_info->display_info->egl_display,
context->egl_context);
eglDestroyContext (drawable->screen_info->display_info->egl_display,
context->egl_context);
_glitz_context_fini (&context->base);
_glitz_context_fini (&context->base);
free (context);
free (context);
}
static void
_glitz_egl_copy_context (void *abstract_src,
void *abstract_dst,
unsigned long mask)
void *abstract_dst,
unsigned long mask)
{
glitz_egl_context_t *src = (glitz_egl_context_t *) abstract_src;
glitz_egl_context_t *dst = (glitz_egl_context_t *) abstract_dst;
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *)
src->base.drawable;
glitz_egl_context_t *src = (glitz_egl_context_t *) abstract_src;
glitz_egl_context_t *dst = (glitz_egl_context_t *) abstract_dst;
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *)
src->base.drawable;
eglCopyContextMESA (drawable->screen_info->display_info->egl_display,
src->egl_context, dst->egl_context, mask);
eglCopyContextMESA (drawable->screen_info->display_info->egl_display,
src->egl_context, dst->egl_context, mask);
}
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_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;
if ((eglGetCurrentContext () != context->egl_context) ||
(eglGetCurrentSurface ( 0 ) != drawable->egl_surface))
eglMakeCurrent (display_info->egl_display, drawable->egl_surface,
drawable->egl_surface, context->egl_context);
if (drawable->base.width != drawable->width ||
drawable->base.height != drawable->height)
_glitz_egl_drawable_update_size (drawable,
drawable->base.width,
drawable->base.height);
display_info->thread_info->cctx = &context->base;
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)
const char *name)
{
glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context;
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *)
context->base.drawable;
glitz_egl_context_t *context = (glitz_egl_context_t *) 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);
return glitz_egl_get_proc_address (name, drawable->screen_info);
}
glitz_egl_context_t *
glitz_egl_context_get (glitz_egl_screen_info_t *screen_info,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
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;
glitz_egl_context_t *context;
glitz_egl_context_t **contexts = screen_info->contexts;
int index, n_contexts = screen_info->n_contexts;
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->id == screen_info->egl_config_ids[format->id])
return *contexts;
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->id == screen_info->formats[format->id].u.uval)
return *contexts;
index = screen_info->n_contexts++;
index = screen_info->n_contexts++;
screen_info->contexts =
realloc (screen_info->contexts,
sizeof (glitz_egl_context_t *) * screen_info->n_contexts);
if (!screen_info->contexts)
return NULL;
screen_info->contexts =
realloc (screen_info->contexts,
sizeof (glitz_egl_context_t *) * screen_info->n_contexts);
if (!screen_info->contexts)
return NULL;
context = malloc (sizeof (glitz_egl_context_t));
if (!context)
return NULL;
context = malloc (sizeof (glitz_egl_context_t));
if (!context)
return NULL;
screen_info->contexts[index] = context;
screen_info->contexts[index] = context;
egl_config_id = screen_info->egl_config_ids[format->id];
_glitz_egl_context_create (screen_info,
screen_info->formats[format->id].u.uval,
screen_info->egl_root_context,
context);
_glitz_egl_context_create (screen_info,
egl_config_id,
screen_info->egl_root_context,
context);
if (!screen_info->egl_root_context)
screen_info->egl_root_context = context->egl_context;
if (!screen_info->egl_root_context)
screen_info->egl_root_context = context->egl_context;
context->backend.gl = &_glitz_egl_gl_proc_address;
memcpy (&context->backend.gl,
&_glitz_egl_gl_proc_address,
sizeof (glitz_gl_proc_address_list_t));
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_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.swap_buffers = glitz_egl_swap_buffers;
context->backend.create_context = _glitz_egl_create_context;
context->backend.destroy_context = _glitz_egl_context_destroy;
context->backend.copy_context = _glitz_egl_copy_context;
context->backend.make_current = _glitz_egl_make_current;
context->backend.get_proc_address = _glitz_egl_context_get_proc_address;
context->backend.create_context = _glitz_egl_create_context;
context->backend.destroy_context = _glitz_egl_context_destroy;
context->backend.copy_context = _glitz_egl_copy_context;
context->backend.make_current = _glitz_egl_make_current;
context->backend.get_proc_address = _glitz_egl_context_get_proc_address;
context->backend.drawable_formats = NULL;
context->backend.n_drawable_formats = 0;
context->backend.drawable_formats = screen_info->formats;
context->backend.n_drawable_formats = screen_info->n_formats;
if (screen_info->n_formats)
{
int size;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
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.program_map = &screen_info->program_map;
context->backend.feature_mask = 0;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
context->initialized = 0;
context->backend.program_map = &screen_info->program_map;
context->backend.feature_mask = 0;
return context;
context->initialized = 0;
return context;
}
void
glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info,
glitz_egl_context_t *context)
glitz_egl_context_t *context)
{
if (context->backend.formats)
free (context->backend.formats);
if (context->backend.drawable_formats)
free (context->backend.drawable_formats);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
if (context->backend.formats)
free (context->backend.formats);
eglDestroyContext (screen_info->display_info->egl_display,
context->egl_context);
free (context);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
eglDestroyContext (screen_info->display_info->egl_display,
context->egl_context);
free (context);
}
static void
_glitz_egl_context_initialize (glitz_egl_screen_info_t *screen_info,
glitz_egl_context_t *context)
glitz_egl_context_t *context)
{
const char *version;
const char *version;
glitz_backend_init (&context->backend,
glitz_egl_get_proc_address,
(void *) screen_info);
glitz_backend_init (&context->backend,
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);
glitz_initiate_state (&_glitz_egl_gl_proc_address);
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. */
if (strstr (version, "NVIDIA 61.11") ||
strstr (version, "NVIDIA 66.29"))
version = (const char *)
context->backend.gl->get_string (GLITZ_GL_VERSION);
if (version)
{
context->backend.feature_mask &=
~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK;
/* 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"))
{
context->backend.feature_mask &=
~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK;
}
}
}
context->initialized = 1;
context->initialized = 1;
}
static void
_glitz_egl_context_make_current (glitz_egl_surface_t *drawable,
glitz_bool_t finish)
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 ();
if (finish)
glFinish ();
if (display_info->thread_info->cctx)
{
glitz_context_t *ctx = display_info->thread_info->cctx;
if (display_info->thread_info->cctx)
{
glitz_context_t *ctx = display_info->thread_info->cctx;
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
display_info->thread_info->cctx = NULL;
}
display_info->thread_info->cctx = NULL;
}
eglMakeCurrent (display_info->egl_display,
drawable->egl_surface, drawable->egl_surface,
drawable->context->egl_context);
eglMakeCurrent (display_info->egl_display,
drawable->egl_surface, drawable->egl_surface,
drawable->context->egl_context);
drawable->base.update_all = 1;
drawable->base.update_all = 1;
if (!drawable->context->initialized)
_glitz_egl_context_initialize (drawable->screen_info, drawable->context);
if (!drawable->context->initialized)
_glitz_egl_context_initialize (drawable->screen_info,
drawable->context);
}
static void
_glitz_egl_context_update (glitz_egl_surface_t *drawable,
glitz_constraint_t constraint)
glitz_constraint_t constraint)
{
EGLContext egl_context;
EGLContext egl_context;
switch (constraint) {
case GLITZ_NONE:
break;
case GLITZ_ANY_CONTEXT_CURRENT: {
glitz_egl_display_info_t *dinfo = drawable->screen_info->display_info;
switch (constraint) {
case GLITZ_NONE:
break;
case GLITZ_ANY_CONTEXT_CURRENT: {
glitz_egl_display_info_t *dinfo = drawable->screen_info->display_info;
if (dinfo->thread_info->cctx)
{
_glitz_egl_context_make_current (drawable, 0);
}
else
{
egl_context = eglGetCurrentContext ();
if (egl_context == (EGLContext) 0)
_glitz_egl_context_make_current (drawable, 0);
}
if (dinfo->thread_info->cctx)
{
_glitz_egl_context_make_current (drawable, 0);
}
else
{
egl_context = eglGetCurrentContext ();
if (egl_context == (EGLContext) 0)
_glitz_egl_context_make_current (drawable, 0);
}
} break;
case GLITZ_CONTEXT_CURRENT:
egl_context = eglGetCurrentContext ();
if (egl_context != drawable->context->egl_context)
_glitz_egl_context_make_current (drawable, (egl_context)? 1: 0);
break;
case GLITZ_DRAWABLE_CURRENT:
egl_context = eglGetCurrentContext ();
if ((egl_context != drawable->context->egl_context) ||
(eglGetCurrentSurface ( 0 ) != drawable->egl_surface))
_glitz_egl_context_make_current (drawable, (egl_context)? 1: 0);
break;
}
case GLITZ_CONTEXT_CURRENT:
egl_context = eglGetCurrentContext ();
if (egl_context != drawable->context->egl_context)
_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))
_glitz_egl_context_make_current (drawable, (egl_context)? 1: 0);
break;
}
}
void
glitz_bool_t
glitz_egl_push_current (void *abstract_drawable,
glitz_surface_t *surface,
glitz_constraint_t constraint)
glitz_surface_t *surface,
glitz_constraint_t constraint)
{
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable;
glitz_egl_context_info_t *context_info;
int index;
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable;
glitz_egl_context_info_t *context_info;
int index;
index = drawable->screen_info->context_stack_size++;
index = drawable->screen_info->context_stack_size++;
context_info = &drawable->screen_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
context_info = &drawable->screen_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
_glitz_egl_context_update (context_info->drawable, constraint);
_glitz_egl_context_update (context_info->drawable, constraint);
return 1;
}
glitz_surface_t *
glitz_egl_pop_current (void *abstract_drawable)
{
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable;
glitz_egl_context_info_t *context_info = NULL;
int index;
glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable;
glitz_egl_context_info_t *context_info = NULL;
int index;
drawable->screen_info->context_stack_size--;
index = drawable->screen_info->context_stack_size - 1;
drawable->screen_info->context_stack_size--;
index = drawable->screen_info->context_stack_size - 1;
context_info = &drawable->screen_info->context_stack[index];
context_info = &drawable->screen_info->context_stack[index];
if (context_info->drawable)
_glitz_egl_context_update (context_info->drawable,
context_info->constraint);
if (context_info->drawable)
_glitz_egl_context_update (context_info->drawable,
context_info->constraint);
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
return NULL;
return NULL;
}

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

@ -35,111 +35,124 @@
glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address = {
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(glitz_gl_bind_texture_t) glBindTexture,
(glitz_gl_tex_image_2d_t) glTexImage2D,
(glitz_gl_tex_parameter_i_t) glTexParameteri,
(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,
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(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,
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(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
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(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_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
glitz_egl_get_proc_address (const char *name,
void *closure)
void *closure)
{
glitz_egl_screen_info_t *screen_info = (glitz_egl_screen_info_t *) closure;
glitz_egl_thread_info_t *info = screen_info->display_info->thread_info;
glitz_function_pointer_t address = NULL;
glitz_egl_screen_info_t *screen_info = (glitz_egl_screen_info_t *) closure;
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)
address = eglGetProcAddress ((char *) name);
if (screen_info->egl_feature_mask &
GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK)
address = eglGetProcAddress ((char *) name);
if (!address) {
if (!info->dlhand)
info->dlhand = dlopen (info->gl_library, RTLD_LAZY);
if (!address) {
if (!info->dlhand)
info->dlhand = dlopen (info->gl_library, RTLD_LAZY);
if (info->dlhand) {
dlerror ();
address = (glitz_function_pointer_t) dlsym (info->dlhand, name);
if (dlerror () != NULL)
address = NULL;
if (info->dlhand) {
dlerror ();
address = (glitz_function_pointer_t) dlsym (info->dlhand, name);
if (dlerror () != NULL)
address = NULL;
}
}
}
return address;
return address;
}
static void
@ -151,27 +164,27 @@ _glitz_egl_screen_destroy (glitz_egl_screen_info_t *screen_info);
static void
_glitz_egl_thread_info_fini (glitz_egl_thread_info_t *thread_info)
{
int i;
int i;
for (i = 0; i < thread_info->n_displays; i++)
_glitz_egl_display_destroy (thread_info->displays[i]);
for (i = 0; i < thread_info->n_displays; i++)
_glitz_egl_display_destroy (thread_info->displays[i]);
free (thread_info->displays);
free (thread_info->displays);
thread_info->displays = NULL;
thread_info->n_displays = 0;
thread_info->displays = NULL;
thread_info->n_displays = 0;
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
if (thread_info->dlhand) {
dlclose (thread_info->dlhand);
thread_info->dlhand = NULL;
}
if (thread_info->dlhand) {
dlclose (thread_info->dlhand);
thread_info->dlhand = NULL;
}
thread_info->cctx = NULL;
thread_info->cctx = NULL;
}
#ifdef PTHREADS
@ -183,108 +196,108 @@ static pthread_key_t info_tsd;
static void
_glitz_egl_thread_info_init (glitz_egl_thread_info_t *thread_info)
{
thread_info->displays = NULL;
thread_info->n_displays = 0;
thread_info->gl_library = NULL;
thread_info->dlhand = NULL;
thread_info->cctx = NULL;
thread_info->displays = NULL;
thread_info->n_displays = 0;
thread_info->gl_library = NULL;
thread_info->dlhand = NULL;
thread_info->cctx = NULL;
}
static void
_glitz_egl_thread_info_destroy (glitz_egl_thread_info_t *thread_info)
{
pthread_setspecific (info_tsd, NULL);
pthread_setspecific (info_tsd, NULL);
if (thread_info) {
_glitz_egl_thread_info_fini (thread_info);
free (thread_info);
}
if (thread_info) {
_glitz_egl_thread_info_fini (thread_info);
free (thread_info);
}
}
static void
_tsd_destroy (void *p)
{
if (p) {
_glitz_egl_thread_info_fini ((glitz_egl_thread_info_t *) p);
free (p);
}
if (p) {
_glitz_egl_thread_info_fini ((glitz_egl_thread_info_t *) p);
free (p);
}
}
static glitz_egl_thread_info_t *
_glitz_egl_thread_info_get (const char *gl_library)
{
glitz_egl_thread_info_t *thread_info;
void *p;
glitz_egl_thread_info_t *thread_info;
void *p;
if (!tsd_initialized) {
pthread_key_create (&info_tsd, _tsd_destroy);
tsd_initialized = 1;
}
p = pthread_getspecific (info_tsd);
if (p == NULL) {
thread_info = malloc (sizeof (glitz_egl_thread_info_t));
_glitz_egl_thread_info_init (thread_info);
pthread_setspecific (info_tsd, thread_info);
} else
thread_info = (glitz_egl_thread_info_t *) p;
if (gl_library) {
int len = strlen (gl_library);
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
if (!tsd_initialized) {
pthread_key_create (&info_tsd, _tsd_destroy);
tsd_initialized = 1;
}
thread_info->gl_library = malloc (len + 1);
if (thread_info->gl_library) {
memcpy (thread_info->gl_library, gl_library, len);
thread_info->gl_library[len] = '\0';
}
}
p = pthread_getspecific (info_tsd);
return thread_info;
if (p == NULL) {
thread_info = malloc (sizeof (glitz_egl_thread_info_t));
_glitz_egl_thread_info_init (thread_info);
pthread_setspecific (info_tsd, thread_info);
} else
thread_info = (glitz_egl_thread_info_t *) p;
if (gl_library) {
int len = strlen (gl_library);
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
thread_info->gl_library = malloc (len + 1);
if (thread_info->gl_library) {
memcpy (thread_info->gl_library, gl_library, len);
thread_info->gl_library[len] = '\0';
}
}
return thread_info;
}
#else
/* not thread safe */
static glitz_egl_thread_info_t thread_info = {
NULL,
0,
NULL,
NULL
NULL,
0,
NULL,
NULL
};
static void
_glitz_egl_thread_info_destroy (glitz_egl_thread_info_t *thread_info)
{
if (thread_info)
_glitz_egl_thread_info_fini (thread_info);
if (thread_info)
_glitz_egl_thread_info_fini (thread_info);
}
static glitz_egl_thread_info_t *
_glitz_egl_thread_info_get (const char *gl_library)
{
if (gl_library) {
int len = strlen (gl_library);
if (gl_library) {
int len = strlen (gl_library);
if (thread_info.gl_library) {
free (thread_info.gl_library);
thread_info.gl_library = NULL;
if (thread_info.gl_library) {
free (thread_info.gl_library);
thread_info.gl_library = NULL;
}
thread_info.gl_library = malloc (len + 1);
if (thread_info.gl_library) {
memcpy (thread_info.gl_library, gl_library, len);
thread_info.gl_library[len] = '\0';
}
}
thread_info.gl_library = malloc (len + 1);
if (thread_info.gl_library) {
memcpy (thread_info.gl_library, gl_library, len);
thread_info.gl_library[len] = '\0';
}
}
return &thread_info;
return &thread_info;
}
#endif
@ -292,141 +305,145 @@ _glitz_egl_thread_info_get (const char *gl_library)
static glitz_egl_display_info_t *
_glitz_egl_display_info_get (EGLDisplay egl_display)
{
glitz_egl_display_info_t *display_info;
glitz_egl_thread_info_t *thread_info = _glitz_egl_thread_info_get (NULL);
glitz_egl_display_info_t **displays = thread_info->displays;
int index, n_displays = thread_info->n_displays;
glitz_egl_display_info_t *display_info;
glitz_egl_thread_info_t *thread_info = _glitz_egl_thread_info_get (NULL);
glitz_egl_display_info_t **displays = thread_info->displays;
int index, n_displays = thread_info->n_displays;
for (; n_displays; n_displays--, displays++)
if ((*displays)->egl_display == egl_display)
return *displays;
for (; n_displays; n_displays--, displays++)
if ((*displays)->egl_display == egl_display)
return *displays;
index = thread_info->n_displays++;
index = thread_info->n_displays++;
thread_info->displays =
realloc (thread_info->displays,
sizeof (glitz_egl_display_info_t *) * thread_info->n_displays);
thread_info->displays =
realloc (thread_info->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;
display_info = malloc (sizeof (glitz_egl_display_info_t));
thread_info->displays[index] = display_info;
display_info->thread_info = thread_info;
display_info->egl_display = egl_display;
display_info->screens = NULL;
display_info->n_screens = 0;
display_info->thread_info = thread_info;
display_info->egl_display = egl_display;
display_info->screens = NULL;
display_info->n_screens = 0;
return display_info;
return display_info;
}
static void
_glitz_egl_display_destroy (glitz_egl_display_info_t *display_info)
{
int i;
int i;
for (i = 0; i < display_info->n_screens; i++)
_glitz_egl_screen_destroy (display_info->screens[i]);
for (i = 0; i < display_info->n_screens; i++)
_glitz_egl_screen_destroy (display_info->screens[i]);
if (display_info->screens)
free (display_info->screens);
if (display_info->screens)
free (display_info->screens);
free (display_info);
free (display_info);
}
glitz_egl_screen_info_t *
glitz_egl_screen_info_get (EGLDisplay display,
EGLScreenMESA screen)
EGLScreenMESA screen)
{
glitz_egl_screen_info_t *screen_info;
glitz_egl_display_info_t *display_info =
_glitz_egl_display_info_get (display);
glitz_egl_screen_info_t **screens = display_info->screens;
int index, n_screens = display_info->n_screens;
glitz_egl_screen_info_t *screen_info;
glitz_egl_display_info_t *display_info =
_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;
int error_base, event_base;
#endif
for (; n_screens; n_screens--, screens++)
if ((*screens)->screen == screen)
return *screens;
for (; n_screens; n_screens--, screens++)
if ((*screens)->screen == screen)
return *screens;
index = display_info->n_screens++;
index = display_info->n_screens++;
display_info->screens =
realloc (display_info->screens,
sizeof (glitz_egl_screen_info_t *) * display_info->n_screens);
display_info->screens =
realloc (display_info->screens,
sizeof (glitz_egl_screen_info_t *) * display_info->n_screens);
screen_info = malloc (sizeof (glitz_egl_screen_info_t));
display_info->screens[index] = screen_info;
screen_info = malloc (sizeof (glitz_egl_screen_info_t));
display_info->screens[index] = screen_info;
screen_info->display_info = display_info;
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->display_info = display_info;
screen_info->screen = screen;
screen_info->drawables = 0;
screen_info->formats = NULL;
screen_info->n_formats = 0;
screen_info->contexts = NULL;
screen_info->n_contexts = 0;
screen_info->contexts = NULL;
screen_info->n_contexts = 0;
glitz_program_map_init (&screen_info->program_map);
glitz_program_map_init (&screen_info->program_map);
screen_info->egl_root_context = (EGLContext) 0;
screen_info->egl_feature_mask = 0;
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;
if (eglQueryExtension (display, &error_base, &event_base)) {
int major, minor;
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_proc_address_lookup (screen_info);
glitz_egl_query_formats (screen_info);
}
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_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);
screen_info->context_stack_size = 1;
screen_info->context_stack->drawable = NULL;
screen_info->context_stack->surface = NULL;
screen_info->context_stack->constraint = GLITZ_NONE;
glitz_egl_query_extensions (screen_info, screen_info->egl_version);
glitz_egl_query_configs (screen_info);
return screen_info;
screen_info->context_stack_size = 1;
screen_info->context_stack->drawable = NULL;
screen_info->context_stack->surface = NULL;
screen_info->context_stack->constraint = GLITZ_NONE;
return screen_info;
}
static void
_glitz_egl_screen_destroy (glitz_egl_screen_info_t *screen_info)
{
EGLDisplay egl_display = screen_info->display_info->egl_display;
int i;
EGLDisplay egl_display = screen_info->display_info->egl_display;
int i;
if (screen_info->egl_root_context)
eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (screen_info->egl_root_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]);
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);
free (screen_info->contexts);
free (screen_info->formats);
free (screen_info);
}
void
glitz_egl_init (const char *gl_library)
{
_glitz_egl_thread_info_get (gl_library);
_glitz_egl_thread_info_get (gl_library);
}
slim_hidden_def(glitz_egl_init);
void
glitz_egl_fini (void)
{
glitz_egl_thread_info_t *info = _glitz_egl_thread_info_get (NULL);
glitz_egl_thread_info_t *info = _glitz_egl_thread_info_get (NULL);
_glitz_egl_thread_info_destroy (info);
_glitz_egl_thread_info_destroy (info);
}
slim_hidden_def(glitz_egl_fini);

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

@ -31,37 +31,39 @@
EGLSurface
glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info,
EGLConfig egl_config,
int width,
int height)
EGLConfig egl_config,
int width,
int height)
{
if (egl_config) {
int attributes[9];
if (egl_config) {
int attributes[9];
attributes[0] = EGL_WIDTH;
attributes[1] = width;
attributes[0] = EGL_WIDTH;
attributes[1] = width;
attributes[2] = EGL_HEIGHT;
attributes[3] = height;
attributes[2] = EGL_HEIGHT;
attributes[3] = height;
#if 0
attributes[4] = EGL_LARGEST_PBUFFER;
attributes[5] = 0;
attributes[4] = EGL_LARGEST_PBUFFER;
attributes[5] = 0;
attributes[6] = EGL_PRESERVED_CONTENTS;
attributes[7] = 1;
attributes[8] = 0;
attributes[6] = EGL_PRESERVED_CONTENTS;
attributes[7] = 1;
attributes[8] = 0;
#endif
return
eglCreatePbufferSurface(screen_info->display_info->egl_display,
egl_config, attributes);
} else
return (EGLSurface) 0;
return
eglCreatePbufferSurface (screen_info->display_info->egl_display,
egl_config, attributes);
} else
return (EGLSurface) 0;
}
void
glitz_egl_pbuffer_destroy (glitz_egl_screen_info_t *screen_info,
EGLSurface egl_pbuffer)
EGLSurface egl_pbuffer)
{
eglDestroySurface(screen_info->display_info->egl_display,
egl_pbuffer);
eglDestroySurface (screen_info->display_info->egl_display,
egl_pbuffer);
}

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

@ -31,173 +31,213 @@
static glitz_egl_surface_t *
_glitz_egl_create_surface (glitz_egl_screen_info_t *screen_info,
glitz_egl_context_t *context,
glitz_drawable_format_t *format,
EGLSurface egl_surface,
int width,
int height)
glitz_egl_context_t *context,
glitz_drawable_format_t *format,
EGLSurface egl_surface,
int width,
int height)
{
glitz_egl_surface_t *surface;
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 = (glitz_egl_surface_t *) malloc (sizeof (glitz_egl_surface_t));
if (surface == NULL)
return NULL;
surface->screen_info = screen_info;
surface->context = context;
surface->egl_surface = egl_surface;
surface->width = width;
surface->height = height;
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;
_glitz_drawable_init (&surface->base,
&screen_info->formats[format->id],
&context->backend,
width, height);
glitz_drawable_update_size (&surface->base, width, height);
if (!context->initialized) {
glitz_egl_push_current (surface, NULL, GLITZ_CONTEXT_CURRENT);
glitz_egl_pop_current (surface);
}
if (!context->initialized) {
glitz_egl_push_current (surface, NULL, GLITZ_CONTEXT_CURRENT);
glitz_egl_pop_current (surface);
}
if (width > context->backend.max_viewport_dims[0] ||
height > context->backend.max_viewport_dims[1]) {
free (surface);
return NULL;
}
if (width > context->max_viewport_dims[0] ||
height > context->max_viewport_dims[1]) {
free (surface);
return NULL;
}
screen_info->drawables++;
screen_info->drawables++;
return surface;
}
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,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_egl_surface_t *surface;
glitz_egl_context_t *context;
EGLSurface egl_pbuffer;
glitz_egl_surface_t *surface;
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;
context = glitz_egl_context_get (screen_info, format);
if (!context)
return NULL;
egl_pbuffer = glitz_egl_pbuffer_create (screen_info, context->egl_config,
(int) width, (int) height);
if (!egl_pbuffer)
return NULL;
egl_pbuffer = glitz_egl_pbuffer_create (screen_info, context->egl_config,
(int) width, (int) height);
if (!egl_pbuffer)
return NULL;
surface = _glitz_egl_create_surface (screen_info, context, format,
egl_pbuffer,
width, height);
if (!surface)
{
glitz_egl_pbuffer_destroy (screen_info, egl_pbuffer);
return NULL;
}
surface = _glitz_egl_create_surface (screen_info, context, format,
egl_pbuffer,
width, height);
if (!surface) {
glitz_egl_pbuffer_destroy (screen_info, egl_pbuffer);
return NULL;
}
return &surface->base;
return &surface->base;
}
glitz_drawable_t *
glitz_egl_create_pbuffer (void *abstract_templ,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_egl_surface_t *templ = (glitz_egl_surface_t *) abstract_templ;
glitz_egl_surface_t *templ = (glitz_egl_surface_t *) abstract_templ;
return _glitz_egl_create_pbuffer_surface (templ->screen_info, format,
width, height);
return _glitz_egl_create_pbuffer_surface (templ->screen_info, format,
width, height);
}
glitz_drawable_t *
glitz_egl_create_surface (EGLDisplay egl_display,
EGLScreenMESA egl_screen,
glitz_drawable_format_t *format,
EGLSurface egl_surface,
unsigned int width,
unsigned int height)
EGLScreenMESA egl_screen,
glitz_drawable_format_t *format,
EGLSurface egl_surface,
unsigned int width,
unsigned int height)
{
glitz_egl_surface_t *surface;
glitz_egl_screen_info_t *screen_info;
glitz_egl_context_t *context;
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;
screen_info = glitz_egl_screen_info_get (egl_display, egl_screen);
if (!screen_info)
return NULL;
context = glitz_egl_context_get (screen_info, format);
if (!context)
return NULL;
if (format->id >= screen_info->n_formats)
return NULL;
surface = _glitz_egl_create_surface (screen_info, context, format,
egl_surface,
width, height);
if (!surface)
return NULL;
iformat = &screen_info->formats[format->id];
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK))
return NULL;
return &surface->base;
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);
if (!surface)
return NULL;
return &surface->base;
}
slim_hidden_def(glitz_egl_create_surface);
glitz_drawable_t *
glitz_egl_create_pbuffer_surface (EGLDisplay display,
EGLScreenMESA screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
EGLScreenMESA screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_egl_screen_info_t *screen_info;
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;
screen_info = glitz_egl_screen_info_get (display, screen);
if (!screen_info)
return NULL;
return _glitz_egl_create_pbuffer_surface (screen_info, format,
width, height);
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);
}
slim_hidden_def(glitz_egl_create_pbuffer_surface);
void
glitz_egl_destroy (void *abstract_drawable)
{
EGLint value;
glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable;
EGLint value;
glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable;
surface->screen_info->drawables--;
if (surface->screen_info->drawables == 0) {
/*
* 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,
&surface->screen_info->program_map);
glitz_egl_pop_current (abstract_drawable);
}
surface->screen_info->drawables--;
if (surface->screen_info->drawables == 0) {
/*
* 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,
&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);
if (eglGetCurrentSurface (0) == surface->egl_surface)
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,
EGL_SURFACE_TYPE, &value);
if (value == EGL_PBUFFER_BIT)
glitz_egl_pbuffer_destroy (surface->screen_info, 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);
free (surface);
free (surface);
}
void
glitz_bool_t
glitz_egl_swap_buffers (void *abstract_drawable)
{
glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable;
glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable;
eglSwapBuffers (surface->screen_info->display_info->egl_display,
surface->egl_surface);
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)
@ -43,113 +41,116 @@ typedef struct _glitz_egl_screen_info_t glitz_egl_screen_info_t;
typedef struct _glitz_egl_display_info_t glitz_egl_display_info_t;
typedef struct _glitz_egl_thread_info_t {
glitz_egl_display_info_t **displays;
int n_displays;
char *gl_library;
void *dlhand;
glitz_context_t *cctx;
glitz_egl_display_info_t **displays;
int n_displays;
char *gl_library;
void *dlhand;
glitz_context_t *cctx;
} glitz_egl_thread_info_t;
struct _glitz_egl_display_info_t {
glitz_egl_thread_info_t *thread_info;
EGLDisplay egl_display;
glitz_egl_screen_info_t **screens;
int n_screens;
glitz_egl_thread_info_t *thread_info;
EGLDisplay egl_display;
glitz_egl_screen_info_t **screens;
int n_screens;
};
typedef struct _glitz_egl_context_info_t {
glitz_egl_surface_t *drawable;
glitz_surface_t *surface;
glitz_constraint_t constraint;
glitz_egl_surface_t *drawable;
glitz_surface_t *surface;
glitz_constraint_t constraint;
} glitz_egl_context_info_t;
typedef struct _glitz_egl_context_t {
glitz_context_t base;
EGLContext egl_context;
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_context_t base;
EGLContext egl_context;
glitz_format_id_t id;
EGLConfig egl_config;
glitz_backend_t backend;
glitz_bool_t initialized;
} glitz_egl_context_t;
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;
int n_formats;
glitz_egl_context_t **contexts;
int n_contexts;
glitz_egl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE];
int context_stack_size;
EGLContext egl_root_context;
unsigned long egl_feature_mask;
glitz_gl_float_t egl_version;
glitz_program_map_t program_map;
glitz_egl_display_info_t *display_info;
int screen;
int drawables;
glitz_int_drawable_format_t *formats;
int n_formats;
glitz_egl_context_t **contexts;
int n_contexts;
glitz_egl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE];
int context_stack_size;
EGLContext egl_root_context;
unsigned long egl_feature_mask;
glitz_gl_float_t egl_version;
glitz_program_map_t program_map;
};
struct _glitz_egl_surface {
glitz_drawable_t base;
glitz_drawable_t base;
glitz_egl_screen_info_t *screen_info;
glitz_egl_context_t *context;
EGLSurface 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
glitz_egl_query_extensions (glitz_egl_screen_info_t *screen_info,
glitz_gl_float_t egl_version);
glitz_gl_float_t egl_version);
extern glitz_egl_screen_info_t __internal_linkage *
glitz_egl_screen_info_get (EGLDisplay egl_display,
EGLScreenMESA egl_screen);
EGLScreenMESA egl_screen);
extern glitz_function_pointer_t __internal_linkage
glitz_egl_get_proc_address (const char *name,
void *closure);
void *closure);
extern glitz_egl_context_t __internal_linkage *
glitz_egl_context_get (glitz_egl_screen_info_t *screen_info,
glitz_drawable_format_t *format);
glitz_drawable_format_t *format);
extern void __internal_linkage
glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info,
glitz_egl_context_t *context);
glitz_egl_context_t *context);
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,
int width,
int height);
EGLConfig egl_config,
int width,
int height);
extern void __internal_linkage
glitz_egl_pbuffer_destroy (glitz_egl_screen_info_t *screen_info,
EGLSurface egl_pbuffer);
EGLSurface egl_pbuffer);
extern glitz_drawable_t __internal_linkage *
glitz_egl_create_pbuffer (void *abstract_templ,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
glitz_drawable_format_t *format,
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);
glitz_surface_t *surface,
glitz_constraint_t constraint);
extern glitz_surface_t __internal_linkage *
glitz_egl_pop_current (void *abstract_drawable);
void
glitz_egl_make_current (void *abstract_drawable,
glitz_constraint_t constraint);
glitz_constraint_t constraint);
extern glitz_status_t __internal_linkage
glitz_egl_make_current_read (void *abstract_surface);
@ -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. */
/* 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)

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

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

@ -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,46 +230,22 @@ 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,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
void
glitz_drawable_destroy (glitz_drawable_t *drawable);
@ -225,8 +255,8 @@ glitz_drawable_reference (glitz_drawable_t *drawable);
void
glitz_drawable_update_size (glitz_drawable_t *drawable,
unsigned int width,
unsigned int height);
unsigned int width,
unsigned int height);
unsigned int
glitz_drawable_get_width (glitz_drawable_t *drawable);
@ -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 {
@ -287,11 +297,11 @@ typedef struct _glitz_surface_attributes_t {
glitz_surface_t *
glitz_surface_create (glitz_drawable_t *drawable,
glitz_format_t *format,
unsigned int width,
unsigned int height,
unsigned long mask,
glitz_surface_attributes_t *attributes);
glitz_format_t *format,
unsigned int width,
unsigned int height,
unsigned long mask,
glitz_surface_attributes_t *attributes);
void
glitz_surface_destroy (glitz_surface_t *surface);
@ -301,10 +311,8 @@ 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_t *drawable,
glitz_drawable_buffer_t buffer);
void
glitz_surface_detach (glitz_surface_t *surface);
@ -320,7 +328,7 @@ glitz_surface_get_attached_drawable (glitz_surface_t *surface);
void
glitz_surface_set_transform (glitz_surface_t *surface,
glitz_transform_t *transform);
glitz_transform_t *transform);
typedef enum {
GLITZ_FILL_TRANSPARENT,
@ -331,21 +339,21 @@ typedef enum {
void
glitz_surface_set_fill (glitz_surface_t *surface,
glitz_fill_t fill);
glitz_fill_t fill);
void
glitz_surface_set_component_alpha (glitz_surface_t *surface,
glitz_bool_t component_alpha);
glitz_bool_t component_alpha);
void
glitz_surface_set_filter (glitz_surface_t *surface,
glitz_filter_t filter,
glitz_fixed16_16_t *params,
int n_params);
glitz_filter_t filter,
glitz_fixed16_16_t *params,
int n_params);
void
glitz_surface_set_dither (glitz_surface_t *surface,
glitz_bool_t dither);
glitz_bool_t dither);
unsigned int
glitz_surface_get_width (glitz_surface_t *surface);
@ -361,27 +369,87 @@ glitz_surface_get_format (glitz_surface_t *surface);
void
glitz_surface_translate_point (glitz_surface_t *surface,
glitz_point_fixed_t *src,
glitz_point_fixed_t *dst);
glitz_point_fixed_t *src,
glitz_point_fixed_t *dst);
void
glitz_surface_set_clip_region (glitz_surface_t *surface,
int x_origin,
int y_origin,
glitz_box_t *box,
int n_box);
int x_origin,
int y_origin,
glitz_box_t *box,
int n_box);
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;
glitz_context_t *
glitz_context_create (glitz_drawable_t *drawable,
glitz_drawable_format_t *format);
glitz_drawable_format_t *format);
void
glitz_context_destroy (glitz_context_t *context);
@ -390,45 +458,46 @@ glitz_context_reference (glitz_context_t *context);
void
glitz_context_copy (glitz_context_t *src,
glitz_context_t *dst,
unsigned long mask);
glitz_context_t *dst,
unsigned long mask);
typedef void (*glitz_lose_current_function_t) (void *closure);
void
glitz_context_set_user_data (glitz_context_t *context,
void *closure,
glitz_lose_current_function_t lose_current);
void *closure,
glitz_lose_current_function_t lose_current);
typedef void (*glitz_function_pointer_t) (void);
glitz_function_pointer_t
glitz_context_get_proc_address (glitz_context_t *context,
const char *name);
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_context_bind_texture (glitz_context_t *context,
glitz_texture_object_t *texture);
/* glitz_rect.c */
void
glitz_set_rectangle (glitz_surface_t *dst,
const glitz_color_t *color,
int x,
int y,
unsigned int width,
unsigned int height);
const glitz_color_t *color,
int x,
int y,
unsigned int width,
unsigned int height);
void
glitz_set_rectangles (glitz_surface_t *dst,
const glitz_color_t *color,
const glitz_rectangle_t *rects,
int n_rects);
const glitz_color_t *color,
const glitz_rectangle_t *rects,
int n_rects);
/* glitz_buffer.c */
@ -455,15 +524,15 @@ typedef enum {
glitz_buffer_t *
glitz_vertex_buffer_create (glitz_drawable_t *drawable,
void *data,
unsigned int size,
glitz_buffer_hint_t hint);
void *data,
unsigned int size,
glitz_buffer_hint_t hint);
glitz_buffer_t *
glitz_pixel_buffer_create (glitz_drawable_t *drawable,
void *data,
unsigned int size,
glitz_buffer_hint_t hint);
void *data,
unsigned int size,
glitz_buffer_hint_t hint);
glitz_buffer_t *
glitz_buffer_create_for_data (void *data);
@ -476,19 +545,19 @@ glitz_buffer_reference (glitz_buffer_t *buffer);
void
glitz_buffer_set_data (glitz_buffer_t *buffer,
int offset,
unsigned int size,
const void *data);
int offset,
unsigned int size,
const void *data);
void
glitz_buffer_get_data (glitz_buffer_t *buffer,
int offset,
unsigned int size,
void *data);
int offset,
unsigned int size,
void *data);
void *
glitz_buffer_map (glitz_buffer_t *buffer,
glitz_buffer_access_t access);
glitz_buffer_access_t access);
glitz_status_t
glitz_buffer_unmap (glitz_buffer_t *buffer);
@ -519,21 +588,21 @@ typedef struct _glitz_pixel_format {
void
glitz_set_pixels (glitz_surface_t *dst,
int x_dst,
int y_dst,
int width,
int height,
glitz_pixel_format_t *format,
glitz_buffer_t *buffer);
int x_dst,
int y_dst,
int width,
int height,
glitz_pixel_format_t *format,
glitz_buffer_t *buffer);
void
glitz_get_pixels (glitz_surface_t *src,
int x_src,
int y_src,
int width,
int height,
glitz_pixel_format_t *format,
glitz_buffer_t *buffer);
int x_src,
int y_src,
int width,
int height,
glitz_pixel_format_t *format,
glitz_buffer_t *buffer);
/* glitz_geometry.c */
@ -600,17 +669,17 @@ typedef union _glitz_geometry_format {
void
glitz_set_geometry (glitz_surface_t *dst,
glitz_geometry_type_t type,
glitz_geometry_format_t *format,
glitz_buffer_t *buffer);
glitz_geometry_type_t type,
glitz_geometry_format_t *format,
glitz_buffer_t *buffer);
void
glitz_set_array (glitz_surface_t *dst,
int first,
int size,
unsigned int count,
glitz_fixed16_16_t x_off,
glitz_fixed16_16_t y_off);
int first,
int size,
unsigned int count,
glitz_fixed16_16_t x_off,
glitz_fixed16_16_t y_off);
typedef struct _glitz_multi_array glitz_multi_array_t;
@ -625,70 +694,70 @@ glitz_multi_array_reference (glitz_multi_array_t *array);
void
glitz_multi_array_add (glitz_multi_array_t *array,
int first,
int size,
unsigned int count,
glitz_fixed16_16_t x_off,
glitz_fixed16_16_t y_off);
int first,
int size,
unsigned int count,
glitz_fixed16_16_t x_off,
glitz_fixed16_16_t y_off);
void
glitz_multi_array_reset (glitz_multi_array_t *array);
void
glitz_set_multi_array (glitz_surface_t *dst,
glitz_multi_array_t *array,
glitz_fixed16_16_t x_off,
glitz_fixed16_16_t y_off);
glitz_multi_array_t *array,
glitz_fixed16_16_t x_off,
glitz_fixed16_16_t y_off);
/* glitz_trap.c */
int
glitz_add_trapezoids (glitz_buffer_t *buffer,
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trapezoid_t *traps,
int n_traps,
int *n_added);
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trapezoid_t *traps,
int n_traps,
int *n_added);
int
glitz_add_traps (glitz_buffer_t *buffer,
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trap_t *traps,
int n_traps,
int *n_added);
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trap_t *traps,
int n_traps,
int *n_added);
/* glitz.c */
void
glitz_composite (glitz_operator_t op,
glitz_surface_t *src,
glitz_surface_t *mask,
glitz_surface_t *dst,
int x_src,
int y_src,
int x_mask,
int y_mask,
int x_dst,
int y_dst,
int width,
int height);
glitz_surface_t *src,
glitz_surface_t *mask,
glitz_surface_t *dst,
int x_src,
int y_src,
int x_mask,
int y_mask,
int x_dst,
int y_dst,
int width,
int height);
void
glitz_copy_area (glitz_surface_t *src,
glitz_surface_t *dst,
int x_src,
int y_src,
int width,
int height,
int x_dst,
int y_dst);
glitz_surface_t *dst,
int x_src,
int y_src,
int width,
int height,
int x_dst,
int y_dst);
#if defined(__cplusplus) || defined(c_plusplus)
}

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

@ -31,10 +31,10 @@
static glitz_status_t
_glitz_buffer_init (glitz_buffer_t *buffer,
glitz_drawable_t *drawable,
void *data,
unsigned int size,
glitz_buffer_hint_t hint)
glitz_drawable_t *drawable,
void *data,
unsigned int size,
glitz_buffer_hint_t hint)
{
glitz_gl_enum_t usage;
@ -43,75 +43,75 @@ _glitz_buffer_init (glitz_buffer_t *buffer,
if (drawable)
{
GLITZ_GL_DRAWABLE (drawable);
GLITZ_GL_DRAWABLE (drawable);
switch (hint) {
case GLITZ_BUFFER_HINT_STREAM_DRAW:
usage = GLITZ_GL_STREAM_DRAW;
break;
case GLITZ_BUFFER_HINT_STREAM_READ:
usage = GLITZ_GL_STREAM_READ;
break;
case GLITZ_BUFFER_HINT_STREAM_COPY:
usage = GLITZ_GL_STREAM_COPY;
break;
case GLITZ_BUFFER_HINT_STATIC_DRAW:
usage = GLITZ_GL_STATIC_DRAW;
break;
case GLITZ_BUFFER_HINT_STATIC_READ:
usage = GLITZ_GL_STATIC_READ;
break;
case GLITZ_BUFFER_HINT_STATIC_COPY:
usage = GLITZ_GL_STATIC_COPY;
break;
case GLITZ_BUFFER_HINT_DYNAMIC_DRAW:
usage = GLITZ_GL_DYNAMIC_DRAW;
break;
case GLITZ_BUFFER_HINT_DYNAMIC_READ:
usage = GLITZ_GL_DYNAMIC_READ;
break;
default:
usage = GLITZ_GL_DYNAMIC_COPY;
break;
}
switch (hint) {
case GLITZ_BUFFER_HINT_STREAM_DRAW:
usage = GLITZ_GL_STREAM_DRAW;
break;
case GLITZ_BUFFER_HINT_STREAM_READ:
usage = GLITZ_GL_STREAM_READ;
break;
case GLITZ_BUFFER_HINT_STREAM_COPY:
usage = GLITZ_GL_STREAM_COPY;
break;
case GLITZ_BUFFER_HINT_STATIC_DRAW:
usage = GLITZ_GL_STATIC_DRAW;
break;
case GLITZ_BUFFER_HINT_STATIC_READ:
usage = GLITZ_GL_STATIC_READ;
break;
case GLITZ_BUFFER_HINT_STATIC_COPY:
usage = GLITZ_GL_STATIC_COPY;
break;
case GLITZ_BUFFER_HINT_DYNAMIC_DRAW:
usage = GLITZ_GL_DYNAMIC_DRAW;
break;
case GLITZ_BUFFER_HINT_DYNAMIC_READ:
usage = GLITZ_GL_DYNAMIC_READ;
break;
default:
usage = GLITZ_GL_DYNAMIC_COPY;
break;
}
buffer->owns_data = 1;
buffer->drawable = drawable;
glitz_drawable_reference (drawable);
buffer->owns_data = 1;
buffer->drawable = drawable;
glitz_drawable_reference (drawable);
drawable->backend->push_current (drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
drawable->backend->push_current (drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
gl->gen_buffers (1, &buffer->name);
if (buffer->name) {
gl->bind_buffer (buffer->target, buffer->name);
gl->buffer_data (buffer->target, size, data, usage);
gl->bind_buffer (buffer->target, 0);
}
gl->gen_buffers (1, &buffer->name);
if (buffer->name) {
gl->bind_buffer (buffer->target, buffer->name);
gl->buffer_data (buffer->target, size, data, usage);
gl->bind_buffer (buffer->target, 0);
}
drawable->backend->pop_current (drawable);
drawable->backend->pop_current (drawable);
}
else
{
buffer->drawable = NULL;
usage = GLITZ_GL_DYNAMIC_COPY;
buffer->drawable = NULL;
usage = GLITZ_GL_DYNAMIC_COPY;
}
if (size > 0 && buffer->name == 0)
{
buffer->data = malloc (size);
if (buffer->data == NULL)
return GLITZ_STATUS_NO_MEMORY;
buffer->data = malloc (size);
if (buffer->data == NULL)
return GLITZ_STATUS_NO_MEMORY;
if (data)
memcpy (buffer->data, data, size);
if (data)
memcpy (buffer->data, data, size);
buffer->owns_data = 1;
buffer->owns_data = 1;
}
else
{
buffer->owns_data = 0;
buffer->data = data;
buffer->owns_data = 0;
buffer->data = data;
}
return GLITZ_STATUS_SUCCESS;
@ -119,246 +119,247 @@ _glitz_buffer_init (glitz_buffer_t *buffer,
glitz_buffer_t *
glitz_vertex_buffer_create (glitz_drawable_t *drawable,
void *data,
unsigned int size,
glitz_buffer_hint_t hint)
void *data,
unsigned int size,
glitz_buffer_hint_t hint)
{
glitz_buffer_t *buffer;
glitz_status_t status;
glitz_buffer_t *buffer;
glitz_status_t status;
if (size == 0)
return NULL;
if (size == 0)
return NULL;
buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t));
if (buffer == NULL)
return NULL;
buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t));
if (buffer == NULL)
return NULL;
buffer->target = GLITZ_GL_ARRAY_BUFFER;
buffer->target = GLITZ_GL_ARRAY_BUFFER;
if (drawable->backend->feature_mask &
GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK)
status = _glitz_buffer_init (buffer, drawable, data, size, hint);
else
status = _glitz_buffer_init (buffer, NULL, data, size, hint);
if (drawable->backend->feature_mask &
GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK)
status = _glitz_buffer_init (buffer, drawable, data, size, hint);
else
status = _glitz_buffer_init (buffer, NULL, data, size, hint);
if (status != GLITZ_STATUS_SUCCESS) {
free (buffer);
return NULL;
}
if (status != GLITZ_STATUS_SUCCESS) {
free (buffer);
return NULL;
}
return buffer;
return buffer;
}
glitz_buffer_t *
glitz_pixel_buffer_create (glitz_drawable_t *drawable,
void *data,
unsigned int size,
glitz_buffer_hint_t hint)
void *data,
unsigned int size,
glitz_buffer_hint_t hint)
{
glitz_buffer_t *buffer;
glitz_status_t status;
glitz_buffer_t *buffer;
glitz_status_t status;
if (size == 0)
return NULL;
if (size == 0)
return NULL;
buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t));
if (buffer == NULL)
return NULL;
buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t));
if (buffer == NULL)
return NULL;
switch (hint) {
case GLITZ_BUFFER_HINT_STREAM_READ:
case GLITZ_BUFFER_HINT_STATIC_READ:
case GLITZ_BUFFER_HINT_DYNAMIC_READ:
buffer->target = GLITZ_GL_PIXEL_PACK_BUFFER;
break;
default:
buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER;
break;
}
switch (hint) {
case GLITZ_BUFFER_HINT_STREAM_READ:
case GLITZ_BUFFER_HINT_STATIC_READ:
case GLITZ_BUFFER_HINT_DYNAMIC_READ:
buffer->target = GLITZ_GL_PIXEL_PACK_BUFFER;
break;
default:
buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER;
break;
}
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);
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);
if (status != GLITZ_STATUS_SUCCESS) {
free (buffer);
return NULL;
}
if (status != GLITZ_STATUS_SUCCESS) {
free (buffer);
return NULL;
}
return buffer;
return buffer;
}
glitz_buffer_t *
glitz_buffer_create_for_data (void *data)
{
glitz_buffer_t *buffer;
glitz_buffer_t *buffer;
buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t));
if (buffer == NULL)
return NULL;
buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t));
if (buffer == NULL)
return NULL;
if (_glitz_buffer_init (buffer, NULL, data, 0, 0)) {
free (buffer);
return NULL;
}
if (_glitz_buffer_init (buffer, NULL, data, 0, 0)) {
free (buffer);
return NULL;
}
return buffer;
return buffer;
}
void
glitz_buffer_destroy (glitz_buffer_t *buffer)
{
if (!buffer)
return;
if (!buffer)
return;
buffer->ref_count--;
if (buffer->ref_count)
return;
buffer->ref_count--;
if (buffer->ref_count)
return;
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->pop_current (buffer->drawable);
glitz_drawable_destroy (buffer->drawable);
} else if (buffer->owns_data)
free (buffer->data);
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->pop_current (buffer->drawable);
glitz_drawable_destroy (buffer->drawable);
} else if (buffer->owns_data)
free (buffer->data);
free (buffer);
free (buffer);
}
void
glitz_buffer_reference (glitz_buffer_t *buffer)
{
if (!buffer)
return;
if (!buffer)
return;
buffer->ref_count++;
buffer->ref_count++;
}
void
glitz_buffer_set_data (glitz_buffer_t *buffer,
int offset,
unsigned int size,
const void *data)
int offset,
unsigned int size,
const void *data)
{
if (buffer->drawable) {
GLITZ_GL_DRAWABLE (buffer->drawable);
if (buffer->drawable) {
GLITZ_GL_DRAWABLE (buffer->drawable);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
gl->bind_buffer (buffer->target, buffer->name);
gl->buffer_sub_data (buffer->target, offset, size, data);
gl->bind_buffer (buffer->target, 0);
buffer->drawable->backend->pop_current (buffer->drawable);
} else if (buffer->data)
memcpy ((char *) buffer->data + offset, data, size);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
gl->bind_buffer (buffer->target, buffer->name);
gl->buffer_sub_data (buffer->target, offset, size, data);
gl->bind_buffer (buffer->target, 0);
buffer->drawable->backend->pop_current (buffer->drawable);
} else if (buffer->data)
memcpy ((char *) buffer->data + offset, data, size);
}
slim_hidden_def(glitz_buffer_set_data);
void
glitz_buffer_get_data (glitz_buffer_t *buffer,
int offset,
unsigned int size,
void *data)
int offset,
unsigned int size,
void *data)
{
if (buffer->drawable) {
GLITZ_GL_DRAWABLE (buffer->drawable);
if (buffer->drawable) {
GLITZ_GL_DRAWABLE (buffer->drawable);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
gl->bind_buffer (buffer->target, buffer->name);
gl->get_buffer_sub_data (buffer->target, offset, size, data);
gl->bind_buffer (buffer->target, 0);
gl->bind_buffer (buffer->target, buffer->name);
gl->get_buffer_sub_data (buffer->target, offset, size, data);
gl->bind_buffer (buffer->target, 0);
buffer->drawable->backend->pop_current (buffer->drawable);
} else if (buffer->data)
memcpy (data, (char *) buffer->data + offset, size);
buffer->drawable->backend->pop_current (buffer->drawable);
} else if (buffer->data)
memcpy (data, (char *) buffer->data + offset, size);
}
slim_hidden_def(glitz_buffer_get_data);
void *
glitz_buffer_map (glitz_buffer_t *buffer,
glitz_buffer_access_t access)
glitz_buffer_access_t access)
{
void *pointer = NULL;
void *pointer = NULL;
if (buffer->drawable) {
glitz_gl_enum_t buffer_access;
if (buffer->drawable) {
glitz_gl_enum_t buffer_access;
GLITZ_GL_DRAWABLE (buffer->drawable);
GLITZ_GL_DRAWABLE (buffer->drawable);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
switch (access) {
case GLITZ_BUFFER_ACCESS_READ_ONLY:
buffer_access = GLITZ_GL_READ_ONLY;
break;
case GLITZ_BUFFER_ACCESS_WRITE_ONLY:
buffer_access = GLITZ_GL_WRITE_ONLY;
break;
default:
buffer_access = GLITZ_GL_READ_WRITE;
break;
switch (access) {
case GLITZ_BUFFER_ACCESS_READ_ONLY:
buffer_access = GLITZ_GL_READ_ONLY;
break;
case GLITZ_BUFFER_ACCESS_WRITE_ONLY:
buffer_access = GLITZ_GL_WRITE_ONLY;
break;
default:
buffer_access = GLITZ_GL_READ_WRITE;
break;
}
gl->bind_buffer (buffer->target, buffer->name);
pointer = gl->map_buffer (buffer->target, buffer_access);
gl->bind_buffer (buffer->target, 0);
buffer->drawable->backend->pop_current (buffer->drawable);
}
gl->bind_buffer (buffer->target, buffer->name);
pointer = gl->map_buffer (buffer->target, buffer_access);
gl->bind_buffer (buffer->target, 0);
if (pointer == NULL)
pointer = buffer->data;
buffer->drawable->backend->pop_current (buffer->drawable);
}
if (pointer == NULL)
pointer = buffer->data;
return pointer;
return pointer;
}
glitz_status_t
glitz_buffer_unmap (glitz_buffer_t *buffer)
{
glitz_status_t status = GLITZ_STATUS_SUCCESS;
glitz_status_t status = GLITZ_STATUS_SUCCESS;
if (buffer->drawable) {
GLITZ_GL_DRAWABLE (buffer->drawable);
if (buffer->drawable) {
GLITZ_GL_DRAWABLE (buffer->drawable);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
buffer->drawable->backend->push_current (buffer->drawable, NULL,
GLITZ_ANY_CONTEXT_CURRENT);
gl->bind_buffer (buffer->target, buffer->name);
gl->bind_buffer (buffer->target, buffer->name);
if (gl->unmap_buffer (buffer->target) == GLITZ_GL_FALSE)
status = GLITZ_STATUS_CONTENT_DESTROYED;
if (gl->unmap_buffer (buffer->target) == GLITZ_GL_FALSE)
status = GLITZ_STATUS_CONTENT_DESTROYED;
gl->bind_buffer (buffer->target, 0);
gl->bind_buffer (buffer->target, 0);
buffer->drawable->backend->pop_current (buffer->drawable);
}
buffer->drawable->backend->pop_current (buffer->drawable);
}
return status;
return status;
}
void *
glitz_buffer_bind (glitz_buffer_t *buffer,
glitz_gl_enum_t target)
glitz_gl_enum_t target)
{
if (buffer->drawable) {
buffer->drawable->backend->gl.bind_buffer (target, buffer->name);
buffer->target = target;
if (buffer->drawable) {
buffer->drawable->backend->gl->bind_buffer (target, buffer->name);
buffer->target = target;
return NULL;
}
return NULL;
}
return buffer->data;
return buffer->data;
}
void
glitz_buffer_unbind (glitz_buffer_t *buffer)
{
if (buffer->drawable)
buffer->drawable->backend->gl.bind_buffer (buffer->target, 0);
if (buffer->drawable)
buffer->drawable->backend->gl->bind_buffer (buffer->target, 0);
}

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

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

@ -31,7 +31,7 @@
void
_glitz_context_init (glitz_context_t *context,
glitz_drawable_t *drawable)
glitz_drawable_t *drawable)
{
glitz_drawable_reference (drawable);
@ -49,7 +49,7 @@ _glitz_context_fini (glitz_context_t *context)
glitz_context_t *
glitz_context_create (glitz_drawable_t *drawable,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
return drawable->backend->create_context (drawable, format);
}
@ -59,11 +59,11 @@ void
glitz_context_destroy (glitz_context_t *context)
{
if (!context)
return;
return;
context->ref_count--;
if (context->ref_count)
return;
return;
context->drawable->backend->destroy_context (context);
}
@ -73,7 +73,7 @@ void
glitz_context_reference (glitz_context_t *context)
{
if (!context)
return;
return;
context->ref_count++;
}
@ -81,8 +81,8 @@ slim_hidden_def(glitz_context_reference);
void
glitz_context_copy (glitz_context_t *src,
glitz_context_t *dst,
unsigned long mask)
glitz_context_t *dst,
unsigned long mask)
{
src->drawable->backend->copy_context (src, dst, mask);
}
@ -90,8 +90,8 @@ slim_hidden_def(glitz_context_copy);
void
glitz_context_set_user_data (glitz_context_t *context,
void *closure,
glitz_lose_current_function_t lose_current)
void *closure,
glitz_lose_current_function_t lose_current)
{
context->closure = closure;
context->lose_current = lose_current;
@ -100,28 +100,82 @@ slim_hidden_def(glitz_context_set_user_data);
glitz_function_pointer_t
glitz_context_get_proc_address (glitz_context_t *context,
const char *name)
const char *name)
{
return context->drawable->backend->get_proc_address (context, name);
}
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_context_bind_texture (glitz_context_t *context,
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,119 +29,312 @@
#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,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
if (!format->types.pbuffer)
return NULL;
glitz_int_drawable_format_t *iformat;
return other->backend->create_pbuffer (other, format, width, height);
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);
}
slim_hidden_def(glitz_create_pbuffer_drawable);
void
glitz_drawable_destroy (glitz_drawable_t *drawable)
{
if (!drawable)
return;
if (!drawable)
return;
drawable->ref_count--;
if (drawable->ref_count)
return;
drawable->ref_count--;
if (drawable->ref_count)
return;
drawable->backend->destroy (drawable);
drawable->backend->destroy (drawable);
}
void
glitz_drawable_reference (glitz_drawable_t *drawable)
{
if (!drawable)
return;
if (!drawable)
return;
drawable->ref_count++;
drawable->ref_count++;
}
void
glitz_drawable_update_size (glitz_drawable_t *drawable,
unsigned int width,
unsigned int height)
unsigned int width,
unsigned int height)
{
drawable->width = (int) width;
drawable->height = (int) height;
drawable->width = (int) width;
drawable->height = (int) height;
drawable->viewport.x = -32767;
drawable->viewport.y = -32767;
drawable->viewport.width = 65535;
drawable->viewport.height = 65535;
drawable->viewport.x = -32767;
drawable->viewport.y = -32767;
drawable->viewport.width = 65535;
drawable->viewport.height = 65535;
drawable->update_all = 1;
drawable->update_all = 1;
}
unsigned int
glitz_drawable_get_width (glitz_drawable_t *drawable)
{
return (unsigned int) drawable->width;
return (unsigned int) drawable->width;
}
slim_hidden_def(glitz_drawable_get_width);
unsigned int
glitz_drawable_get_height (glitz_drawable_t *drawable)
{
return (unsigned int) drawable->height;
return (unsigned int) drawable->height;
}
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);
void
glitz_drawable_flush (glitz_drawable_t *drawable)
{
drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT);
drawable->backend->gl.flush ();
drawable->backend->pop_current (drawable);
drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT);
drawable->backend->gl->flush ();
drawable->backend->pop_current (drawable);
}
slim_hidden_def(glitz_drawable_flush);
void
glitz_drawable_finish (glitz_drawable_t *drawable)
{
drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT);
drawable->backend->gl.finish ();
drawable->backend->pop_current (drawable);
drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT);
drawable->backend->gl->finish ();
drawable->backend->pop_current (drawable);
}
slim_hidden_def(glitz_drawable_finish);
unsigned long
glitz_drawable_get_features (glitz_drawable_t *drawable)
{
return drawable->backend->feature_mask;
return drawable->backend->feature_mask;
}
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);

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

@ -30,35 +30,35 @@
#include "glitzint.h"
struct _glitz_filter_params_t {
int fp_type;
int id;
glitz_vec4_t *vectors;
int n_vectors;
int fp_type;
int id;
glitz_vec4_t *vectors;
int n_vectors;
};
static glitz_status_t
_glitz_filter_params_ensure (glitz_surface_t *surface,
int vectors)
int vectors)
{
int size;
size = sizeof (glitz_filter_params_t) + vectors * sizeof (glitz_vec4_t);
if (!surface->filter_params ||
surface->filter_params->n_vectors != vectors)
surface->filter_params->n_vectors != vectors)
{
if (surface->filter_params)
free (surface->filter_params);
if (surface->filter_params)
free (surface->filter_params);
surface->filter_params = malloc (size);
if (surface->filter_params == NULL)
return GLITZ_STATUS_NO_MEMORY;
surface->filter_params = malloc (size);
if (surface->filter_params == NULL)
return GLITZ_STATUS_NO_MEMORY;
surface->filter_params->fp_type = 0;
surface->filter_params->id = 0;
surface->filter_params->vectors =
(glitz_vec4_t *) (surface->filter_params + 1);
surface->filter_params->n_vectors = vectors;
surface->filter_params->fp_type = 0;
surface->filter_params->id = 0;
surface->filter_params->vectors =
(glitz_vec4_t *) (surface->filter_params + 1);
surface->filter_params->n_vectors = vectors;
}
return GLITZ_STATUS_SUCCESS;
@ -66,360 +66,372 @@ _glitz_filter_params_ensure (glitz_surface_t *surface,
static void
_glitz_filter_params_set (glitz_float_t *value,
const glitz_float_t default_value,
glitz_fixed16_16_t **params,
int *n_params)
const glitz_float_t default_value,
glitz_fixed16_16_t **params,
int *n_params)
{
if (*n_params > 0) {
*value = FIXED_TO_FLOAT (**params);
(*params)++;
(*n_params)--;
} else
*value = default_value;
if (*n_params > 0) {
*value = FIXED_TO_FLOAT (**params);
(*params)++;
(*n_params)--;
} else
*value = default_value;
}
static int
_glitz_color_stop_compare (const void *elem1, const void *elem2)
{
return
(((glitz_vec4_t *) elem1)->v[2] == ((glitz_vec4_t *) elem2)->v[2]) ?
/* equal offsets, sort on id */
((((glitz_vec4_t *) elem1)->v[3] <
((glitz_vec4_t *) elem2)->v[3]) ? -1 : 1) :
/* sort on offset */
((((glitz_vec4_t *) elem1)->v[2] <
((glitz_vec4_t *) elem2)->v[2]) ? -1 : 1);
return
(((glitz_vec4_t *) elem1)->v[2] == ((glitz_vec4_t *) elem2)->v[2]) ?
/* equal offsets, sort on id */
((((glitz_vec4_t *) elem1)->v[3] <
((glitz_vec4_t *) elem2)->v[3]) ? -1 : 1) :
/* sort on offset */
((((glitz_vec4_t *) elem1)->v[2] <
((glitz_vec4_t *) elem2)->v[2]) ? -1 : 1);
}
glitz_status_t
glitz_filter_set_params (glitz_surface_t *surface,
glitz_filter_t filter,
glitz_fixed16_16_t *params,
int n_params)
glitz_filter_t filter,
glitz_fixed16_16_t *params,
int n_params)
{
glitz_vec4_t *vecs;
int i, size = 0;
glitz_vec4_t *vecs;
int i, size = 0;
switch (filter) {
case GLITZ_FILTER_CONVOLUTION: {
glitz_float_t dm, dn;
int cx, cy, m, n, j;
switch (filter) {
case GLITZ_FILTER_CONVOLUTION: {
glitz_float_t dm, dn;
int cx, cy, m, n, j;
_glitz_filter_params_set (&dm, 3.0f, &params, &n_params);
_glitz_filter_params_set (&dn, 3.0f, &params, &n_params);
m = dm;
n = dn;
_glitz_filter_params_set (&dm, 3.0f, &params, &n_params);
_glitz_filter_params_set (&dn, 3.0f, &params, &n_params);
m = dm;
n = dn;
size = m * n;
if (_glitz_filter_params_ensure (surface, size))
return GLITZ_STATUS_NO_MEMORY;
size = m * n;
if (_glitz_filter_params_ensure (surface, size))
return GLITZ_STATUS_NO_MEMORY;
vecs = surface->filter_params->vectors;
vecs = surface->filter_params->vectors;
surface->filter_params->id = 0;
surface->filter_params->id = 0;
/* center point is rounded down in case dimensions are not even */
cx = m / 2;
cy = n / 2;
/* center point is rounded down in case dimensions are not even */
cx = m / 2;
cy = n / 2;
for (i = 0; i < m; i++) {
glitz_vec4_t *vec;
glitz_float_t weight;
for (i = 0; i < m; i++) {
glitz_vec4_t *vec;
glitz_float_t weight;
for (j = 0; j < n; j++) {
_glitz_filter_params_set (&weight, 0.0f, &params, &n_params);
if (weight != 0.0f) {
vec = &vecs[surface->filter_params->id++];
vec->v[0] = (i - cx) * surface->texture.texcoord_width_unit;
vec->v[1] = (cy - j) * surface->texture.texcoord_height_unit;
vec->v[2] = weight;
vec->v[3] = 0.0f;
}
}
}
} break;
case GLITZ_FILTER_GAUSSIAN: {
glitz_float_t radius, sigma, alpha, scale, xy_scale, sum;
int half_size, x, y;
for (j = 0; j < n; j++) {
_glitz_filter_params_set (&weight, 0.0f, &params, &n_params);
if (weight != 0.0f) {
vec = &vecs[surface->filter_params->id++];
vec->v[0] = (i - cx) * surface->texture.texcoord_width_unit;
vec->v[1] = (cy - j) * surface->texture.texcoord_height_unit;
vec->v[2] = weight;
vec->v[3] = 0.0f;
}
}
}
} break;
case GLITZ_FILTER_GAUSSIAN: {
glitz_float_t radius, sigma, alpha, scale, xy_scale, sum;
int half_size, x, y;
_glitz_filter_params_set (&radius, 1.0f, &params, &n_params);
glitz_clamp_value (&radius, 0.0f, 1024.0f);
_glitz_filter_params_set (&radius, 1.0f, &params, &n_params);
glitz_clamp_value (&radius, 0.0f, 1024.0f);
_glitz_filter_params_set (&sigma, radius / 2.0f, &params, &n_params);
glitz_clamp_value (&sigma, 0.0f, 1024.0f);
_glitz_filter_params_set (&sigma, radius / 2.0f, &params, &n_params);
glitz_clamp_value (&sigma, 0.0f, 1024.0f);
_glitz_filter_params_set (&alpha, radius, &params, &n_params);
glitz_clamp_value (&alpha, 0.0f, 1024.0f);
_glitz_filter_params_set (&alpha, radius, &params, &n_params);
glitz_clamp_value (&alpha, 0.0f, 1024.0f);
scale = 1.0f / (2.0f * GLITZ_PI * sigma * sigma);
half_size = alpha + 0.5f;
scale = 1.0f / (2.0f * GLITZ_PI * sigma * sigma);
half_size = alpha + 0.5f;
if (half_size == 0)
half_size = 1;
if (half_size == 0)
half_size = 1;
size = half_size * 2 + 1;
xy_scale = 2.0f * radius / size;
size = half_size * 2 + 1;
xy_scale = 2.0f * radius / size;
if (_glitz_filter_params_ensure (surface, size * size))
return GLITZ_STATUS_NO_MEMORY;
if (_glitz_filter_params_ensure (surface, size * size))
return GLITZ_STATUS_NO_MEMORY;
vecs = surface->filter_params->vectors;
vecs = surface->filter_params->vectors;
surface->filter_params->id = 0;
surface->filter_params->id = 0;
sum = 0.0f;
for (x = 0; x < size; x++) {
glitz_vec4_t *vec;
glitz_float_t fx, fy, amp;
sum = 0.0f;
for (x = 0; x < size; x++) {
glitz_vec4_t *vec;
glitz_float_t fx, fy, amp;
fx = xy_scale * (x - half_size);
fx = xy_scale * (x - half_size);
for (y = 0; y < size; y++) {
fy = xy_scale * (y - half_size);
for (y = 0; y < size; y++) {
fy = xy_scale * (y - half_size);
amp = scale * exp ((-1.0f * (fx * fx + fy * fy)) /
(2.0f * sigma * sigma));
amp = scale * exp ((-1.0f * (fx * fx + fy * fy)) /
(2.0f * sigma * sigma));
if (amp > 0.0f) {
vec = &vecs[surface->filter_params->id++];
vec->v[0] = fx * surface->texture.texcoord_width_unit;
vec->v[1] = fy * surface->texture.texcoord_height_unit;
vec->v[2] = amp;
vec->v[3] = 0.0f;
sum += amp;
}
}
if (amp > 0.0f) {
vec = &vecs[surface->filter_params->id++];
vec->v[0] = fx * surface->texture.texcoord_width_unit;
vec->v[1] = fy * surface->texture.texcoord_height_unit;
vec->v[2] = amp;
vec->v[3] = 0.0f;
sum += amp;
}
}
}
/* normalize */
if (sum != 0.0f)
sum = 1.0f / sum;
for (i = 0; i < surface->filter_params->id; i++)
vecs[i].v[2] *= sum;
} break;
case GLITZ_FILTER_LINEAR_GRADIENT:
case GLITZ_FILTER_RADIAL_GRADIENT:
if (n_params <= 4) {
if (surface->box.x2 == 1)
size = surface->box.y2;
else if (surface->box.y2 == 1)
size = surface->box.x2;
} else
size = (n_params - 2) / 3;
if (size < 2)
size = 2;
if (_glitz_filter_params_ensure (surface, size + 1))
return GLITZ_STATUS_NO_MEMORY;
vecs = surface->filter_params->vectors;
if (filter == GLITZ_FILTER_LINEAR_GRADIENT) {
glitz_float_t length, angle, dh, dv;
glitz_float_t start_x, start_y, stop_x, stop_y;
_glitz_filter_params_set (&start_x, 0.0f, &params, &n_params);
_glitz_filter_params_set (&start_y, 0.0f, &params, &n_params);
_glitz_filter_params_set (&stop_x, 1.0f, &params, &n_params);
_glitz_filter_params_set (&stop_y, 0.0f, &params, &n_params);
dh = stop_x - start_x;
dv = stop_y - start_y;
length = sqrtf (dh * dh + dv * dv);
angle = -atan2f (dv, dh);
vecs->v[2] = cosf (angle);
vecs->v[3] = -sinf (angle);
vecs->v[0] = vecs->v[2] * start_x;
vecs->v[0] += vecs->v[3] * start_y;
vecs->v[1] = (length)? 1.0f / length: 2147483647.0f;
} else {
glitz_float_t r0, r1;
_glitz_filter_params_set (&vecs->v[0], 0.5f, &params, &n_params);
_glitz_filter_params_set (&vecs->v[1], 0.5f, &params, &n_params);
_glitz_filter_params_set (&r0, 0.0f, &params, &n_params);
_glitz_filter_params_set (&r1, 0.5f, &params, &n_params);
glitz_clamp_value (&r0, 0.0f, r1);
vecs->v[2] = r0;
if (r1 != r0)
vecs->v[3] = 1.0f / (r1 - r0);
else
vecs->v[3] = 2147483647.0f;
}
vecs++;
surface->filter_params->id = size;
for (i = 0; i < size; i++) {
glitz_float_t x_default, y_default, o_default;
o_default = i / (glitz_float_t) (size - 1);
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_clamp_value (&vecs[i].v[2], 0.0f, 1.0f);
glitz_clamp_value (&vecs[i].v[0], 0.0f, surface->box.x2 - 1.0f);
glitz_clamp_value (&vecs[i].v[1], 0.0f, surface->box.y2 - 1.0f);
vecs[i].v[0] += 0.5f;
vecs[i].v[1] += 0.5f;
vecs[i].v[0] += surface->texture.box.x1;
vecs[i].v[1] = surface->texture.box.y2 - vecs[i].v[1];
vecs[i].v[0] *= surface->texture.texcoord_width_unit;
vecs[i].v[1] *= surface->texture.texcoord_height_unit;
vecs[i].v[3] = i;
}
/* sort color stops in ascending order */
qsort (vecs, surface->filter_params->id, sizeof (glitz_vec4_t),
_glitz_color_stop_compare);
for (i = 0; i < size; i++) {
glitz_float_t diff;
if ((i + 1) == size)
diff = 1.0f - vecs[i].v[2];
else
diff = vecs[i + 1].v[2] - vecs[i].v[2];
if (diff != 0.0f)
vecs[i].v[3] = 1.0f / diff;
else
vecs[i].v[3] = 2147483647.0f;
}
break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
if (surface->filter_params)
free (surface->filter_params);
surface->filter_params = NULL;
break;
}
/* normalize */
if (sum != 0.0f)
sum = 1.0f / sum;
glitz_filter_set_type (surface, filter);
for (i = 0; i < surface->filter_params->id; i++)
vecs[i].v[2] *= sum;
} break;
case GLITZ_FILTER_LINEAR_GRADIENT:
case GLITZ_FILTER_RADIAL_GRADIENT:
if (n_params <= 4) {
if (surface->box.x2 == 1)
size = surface->box.y2;
else if (surface->box.y2 == 1)
size = surface->box.x2;
} else
size = (n_params - 2) / 3;
if (size < 2)
size = 2;
if (_glitz_filter_params_ensure (surface, size + 1))
return GLITZ_STATUS_NO_MEMORY;
vecs = surface->filter_params->vectors;
if (filter == GLITZ_FILTER_LINEAR_GRADIENT) {
glitz_float_t length, angle, dh, dv;
glitz_float_t start_x, start_y, stop_x, stop_y;
_glitz_filter_params_set (&start_x, 0.0f, &params, &n_params);
_glitz_filter_params_set (&start_y, 0.0f, &params, &n_params);
_glitz_filter_params_set (&stop_x, 1.0f, &params, &n_params);
_glitz_filter_params_set (&stop_y, 0.0f, &params, &n_params);
dh = stop_x - start_x;
dv = stop_y - start_y;
length = sqrtf (dh * dh + dv * dv);
angle = -atan2f (dv, dh);
vecs->v[2] = cosf (angle);
vecs->v[3] = -sinf (angle);
vecs->v[0] = vecs->v[2] * start_x;
vecs->v[0] += vecs->v[3] * start_y;
vecs->v[1] = (length)? 1.0f / length: 2147483647.0f;
} else {
glitz_float_t r0, r1;
_glitz_filter_params_set (&vecs->v[0], 0.5f, &params, &n_params);
_glitz_filter_params_set (&vecs->v[1], 0.5f, &params, &n_params);
_glitz_filter_params_set (&r0, 0.0f, &params, &n_params);
_glitz_filter_params_set (&r1, 0.5f, &params, &n_params);
glitz_clamp_value (&r0, 0.0f, r1);
vecs->v[2] = r0;
if (r1 != r0)
vecs->v[3] = 1.0f / (r1 - r0);
else
vecs->v[3] = 2147483647.0f;
}
vecs++;
surface->filter_params->id = size;
for (i = 0; i < size; i++) {
glitz_float_t x_default, y_default, o_default;
o_default = i / (glitz_float_t) (size - 1);
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_clamp_value (&vecs[i].v[2], 0.0f, 1.0f);
glitz_clamp_value (&vecs[i].v[0], 0.0f, surface->box.x2 - 1.0f);
glitz_clamp_value (&vecs[i].v[1], 0.0f, surface->box.y2 - 1.0f);
vecs[i].v[0] += 0.5f;
vecs[i].v[1] += 0.5f;
vecs[i].v[0] += surface->texture.box.x1;
vecs[i].v[1] = surface->texture.box.y2 - vecs[i].v[1];
vecs[i].v[0] *= surface->texture.texcoord_width_unit;
vecs[i].v[1] *= surface->texture.texcoord_height_unit;
vecs[i].v[3] = i;
}
/* sort color stops in ascending order */
qsort (vecs, surface->filter_params->id, sizeof (glitz_vec4_t),
_glitz_color_stop_compare);
for (i = 0; i < size; i++) {
glitz_float_t diff;
if ((i + 1) == size)
diff = 1.0f - vecs[i].v[2];
else
diff = vecs[i + 1].v[2] - vecs[i].v[2];
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 */
}
break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
if (surface->filter_params)
free (surface->filter_params);
surface->filter_params = NULL;
break;
}
glitz_filter_set_type (surface, filter);
return GLITZ_STATUS_SUCCESS;
return GLITZ_STATUS_SUCCESS;
}
glitz_gl_uint_t
glitz_filter_get_fragment_program (glitz_surface_t *surface,
glitz_composite_op_t *op)
glitz_composite_op_t *op)
{
return glitz_get_fragment_program (op,
surface->filter_params->fp_type,
surface->filter_params->id);
return glitz_get_fragment_program (op,
surface->filter_params->fp_type,
surface->filter_params->id);
}
void
glitz_filter_set_type (glitz_surface_t *surface,
glitz_filter_t filter)
glitz_filter_t filter)
{
switch (filter) {
case GLITZ_FILTER_CONVOLUTION:
case GLITZ_FILTER_GAUSSIAN:
surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION;
break;
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;
else
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;
} else
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;
else
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;
break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
break;
}
switch (filter) {
case GLITZ_FILTER_CONVOLUTION:
case GLITZ_FILTER_GAUSSIAN:
surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION;
break;
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;
else
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;
} else
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;
else
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;
break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
break;
}
}
void
glitz_filter_enable (glitz_surface_t *surface,
glitz_composite_op_t *op)
glitz_composite_op_t *op)
{
glitz_gl_proc_address_list_t *gl = op->gl;
int i;
glitz_gl_proc_address_list_t *gl = op->gl;
int i;
gl->enable (GLITZ_GL_FRAGMENT_PROGRAM);
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, op->fp);
gl->enable (GLITZ_GL_FRAGMENT_PROGRAM);
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, op->fp);
switch (surface->filter) {
case GLITZ_FILTER_GAUSSIAN:
case GLITZ_FILTER_CONVOLUTION:
for (i = 0; i < surface->filter_params->id; i++)
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i,
surface->filter_params->vectors[i].v);
break;
case GLITZ_FILTER_LINEAR_GRADIENT:
case GLITZ_FILTER_RADIAL_GRADIENT: {
int j, fp_type = surface->filter_params->fp_type;
glitz_vec4_t *vec;
switch (surface->filter) {
case GLITZ_FILTER_GAUSSIAN:
case GLITZ_FILTER_CONVOLUTION:
for (i = 0; i < surface->filter_params->id; i++)
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i,
surface->filter_params->vectors[i].v);
break;
case GLITZ_FILTER_LINEAR_GRADIENT:
case GLITZ_FILTER_RADIAL_GRADIENT: {
int j, fp_type = surface->filter_params->fp_type;
glitz_vec4_t *vec;
vec = surface->filter_params->vectors;
vec = surface->filter_params->vectors;
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 0, vec->v);
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 0, vec->v);
vec++;
vec++;
if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT ||
fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) {
glitz_vec4_t v;
if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT ||
fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) {
glitz_vec4_t v;
v.v[0] = v.v[1] = -1.0f;
v.v[2] = 0.0f;
v.v[3] = (vec->v[3])? 1.0f / vec->v[3]: 1.0f;
v.v[0] = v.v[1] = -1.0f;
v.v[2] = 0.0f;
v.v[3] = (vec->v[3])? 1.0f / vec->v[3]: 1.0f;
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1, v.v);
j = 2;
} else
j = 1;
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1, v.v);
j = 2;
} else
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);
for (i = 0; i < surface->filter_params->id; i++, vec++)
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) {
glitz_vec4_t v;
if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT ||
fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) {
glitz_vec4_t v;
v.v[0] = v.v[1] = -1.0f;
v.v[2] = v.v[3] = 1.0f;
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:
case GLITZ_FILTER_NEAREST:
break;
}
} break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
break;
}
}

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

@ -32,254 +32,387 @@
#include <stdlib.h>
struct _texture_format {
glitz_gl_int_t texture_format;
glitz_format_t format;
glitz_gl_int_t texture_format;
glitz_format_t format;
} _texture_formats[] = {
{ GLITZ_GL_ALPHA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 4 } } },
{ GLITZ_GL_ALPHA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 8 } } },
{ GLITZ_GL_ALPHA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 12 } } },
{ GLITZ_GL_ALPHA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 16 } } },
{ GLITZ_GL_R3_G3_B2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 3, 3, 2, 0 } } },
{ GLITZ_GL_RGB4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 0 } } },
{ GLITZ_GL_RGB5, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 6, 5, 0 } } },
{ GLITZ_GL_RGB8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 0 } } },
{ GLITZ_GL_RGB10, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 0 } } },
{ GLITZ_GL_RGB12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 0 } } },
{ GLITZ_GL_RGB16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 0 } } },
{ GLITZ_GL_RGBA2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 2, 2, 2, 2 } } },
{ GLITZ_GL_RGB5_A1, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 5, 5, 1 } } },
{ GLITZ_GL_RGBA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 4 } } },
{ GLITZ_GL_RGBA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 8 } } },
{ GLITZ_GL_RGB10_A2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 2 } } },
{ GLITZ_GL_RGBA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 12 } } },
{ GLITZ_GL_RGBA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 16 } } }
{ GLITZ_GL_ALPHA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 4 } } },
{ GLITZ_GL_ALPHA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 8 } } },
{ GLITZ_GL_ALPHA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 12 } } },
{ GLITZ_GL_ALPHA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 16 } } },
{ GLITZ_GL_R3_G3_B2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 3, 3, 2, 0 } } },
{ GLITZ_GL_RGB4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 0 } } },
{ GLITZ_GL_RGB5, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 6, 5, 0 } } },
{ GLITZ_GL_RGB8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 0 } } },
{ GLITZ_GL_RGB10, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 0 } } },
{ GLITZ_GL_RGB12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 0 } } },
{ GLITZ_GL_RGB16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 0 } } },
{ GLITZ_GL_RGBA2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 2, 2, 2, 2 } } },
{ GLITZ_GL_RGB5_A1, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 5, 5, 1 } } },
{ GLITZ_GL_RGBA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 4 } } },
{ GLITZ_GL_RGBA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 8 } } },
{ GLITZ_GL_RGB10_A2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 2 } } },
{ GLITZ_GL_RGBA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 12 } } },
{ GLITZ_GL_RGBA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 16 } } }
};
static void
_glitz_add_texture_format (glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
int *n_formats,
glitz_gl_int_t texture_format,
glitz_format_t *format)
glitz_gl_int_t **texture_formats,
int *n_formats,
glitz_gl_int_t texture_format,
glitz_format_t *format)
{
*formats = realloc (*formats, sizeof (glitz_format_t) * (*n_formats + 1));
*texture_formats = realloc (*texture_formats,
sizeof (glitz_gl_enum_t) * (*n_formats + 1));
*formats = realloc (*formats, sizeof (glitz_format_t) * (*n_formats + 1));
*texture_formats = realloc (*texture_formats,
sizeof (glitz_gl_enum_t) * (*n_formats + 1));
if (*formats && *texture_formats) {
(*texture_formats)[*n_formats] = texture_format;
(*formats)[*n_formats] = *format;
(*formats)[*n_formats].id = *n_formats;
(*n_formats)++;
} else
*n_formats = 0;
if (*formats && *texture_formats) {
(*texture_formats)[*n_formats] = texture_format;
(*formats)[*n_formats] = *format;
(*formats)[*n_formats].id = *n_formats;
(*n_formats)++;
} else
*n_formats = 0;
}
void
glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
int *n_formats)
glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
int *n_formats)
{
glitz_gl_int_t value;
int i, n_texture_formats;
glitz_gl_int_t value;
int i, n_texture_formats;
n_texture_formats =
sizeof (_texture_formats) / sizeof (struct _texture_format);
n_texture_formats =
sizeof (_texture_formats) / sizeof (struct _texture_format);
for (i = 0; i < n_texture_formats; i++) {
gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0,
_texture_formats[i].texture_format, 1, 1, 0,
GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
for (i = 0; i < n_texture_formats; i++) {
gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0,
_texture_formats[i].texture_format, 1, 1, 0,
GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
switch (_texture_formats[i].format.type) {
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);
if (value != _texture_formats[i].format.color.red_size)
continue;
}
switch (_texture_formats[i].format.type) {
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);
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);
if (value != _texture_formats[i].format.color.green_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);
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);
if (value != _texture_formats[i].format.color.blue_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);
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);
if (value != _texture_formats[i].format.color.alpha_size)
continue;
}
break;
default:
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);
if (value != _texture_formats[i].format.color.alpha_size)
continue;
}
break;
default:
continue;
}
_glitz_add_texture_format (formats,
texture_formats,
n_formats,
_texture_formats[i].texture_format,
&_texture_formats[i].format);
}
}
_glitz_add_texture_format (formats,
texture_formats,
n_formats,
_texture_formats[i].texture_format,
&_texture_formats[i].format);
}
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,
int n_formats,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
glitz_drawable_format_find (glitz_int_drawable_format_t *formats,
int n_formats,
unsigned long mask,
const glitz_int_drawable_format_t *templ,
int count)
{
for (; n_formats; n_formats--, formats++) {
if (mask & GLITZ_FORMAT_ID_MASK)
if (templ->id != formats->id)
continue;
for (; n_formats; n_formats--, formats++)
{
if (mask & GLITZ_FORMAT_ID_MASK)
if (templ->d.id != formats->d.id)
continue;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
if (templ->color.red_size != formats->color.red_size)
continue;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
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)
continue;
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
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)
continue;
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
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)
continue;
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
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)
continue;
if (mask & GLITZ_FORMAT_DEPTH_SIZE_MASK)
if (templ->d.depth_size != formats->d.depth_size)
continue;
if (mask & GLITZ_FORMAT_STENCIL_SIZE_MASK)
if (templ->stencil_size != formats->stencil_size)
continue;
if (mask & GLITZ_FORMAT_STENCIL_SIZE_MASK)
if (templ->d.stencil_size != formats->d.stencil_size)
continue;
if (mask & GLITZ_FORMAT_DOUBLEBUFFER_MASK)
if (templ->doublebuffer != formats->doublebuffer)
continue;
if (mask & GLITZ_FORMAT_DOUBLEBUFFER_MASK)
if (templ->d.doublebuffer != formats->d.doublebuffer)
continue;
if (mask & GLITZ_FORMAT_SAMPLES_MASK)
if (templ->samples != formats->samples)
continue;
if (mask & GLITZ_FORMAT_SAMPLES_MASK)
if (templ->d.samples != formats->d.samples)
continue;
if (mask & GLITZ_FORMAT_WINDOW_MASK)
if (templ->types.window != formats->types.window)
continue;
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)
continue;
if (mask & GLITZ_INT_FORMAT_PBUFFER_MASK)
if ((templ->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK) !=
(formats->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK))
continue;
if (count-- == 0)
return formats;
}
if (mask & GLITZ_INT_FORMAT_FBO_MASK)
if ((templ->types & GLITZ_DRAWABLE_TYPE_FBO_MASK) !=
(formats->types & GLITZ_DRAWABLE_TYPE_FBO_MASK))
continue;
return NULL;
if (count-- == 0)
return &formats->d;
}
return NULL;
}
static glitz_format_t *
_glitz_format_find (glitz_format_t *formats,
int n_formats,
unsigned long mask,
const glitz_format_t *templ,
int count)
int n_formats,
unsigned long mask,
const glitz_format_t *templ,
int count)
{
for (; n_formats; n_formats--, formats++) {
if (mask & GLITZ_FORMAT_ID_MASK)
if (templ->id != formats->id)
continue;
for (; n_formats; n_formats--, formats++) {
if (mask & GLITZ_FORMAT_ID_MASK)
if (templ->id != formats->id)
continue;
if (mask & GLITZ_FORMAT_TYPE_MASK)
if (templ->type != formats->type)
continue;
if (mask & GLITZ_FORMAT_TYPE_MASK)
if (templ->type != formats->type)
continue;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
if (templ->color.red_size != formats->color.red_size)
continue;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
if (templ->color.red_size != formats->color.red_size)
continue;
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
if (templ->color.green_size != formats->color.green_size)
continue;
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
if (templ->color.green_size != formats->color.green_size)
continue;
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
if (templ->color.blue_size != formats->color.blue_size)
continue;
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
if (templ->color.blue_size != formats->color.blue_size)
continue;
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
if (templ->color.alpha_size != formats->color.alpha_size)
continue;
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
if (templ->color.alpha_size != formats->color.alpha_size)
continue;
if (count-- == 0)
return formats;
}
if (count-- == 0)
return formats;
}
return NULL;
return NULL;
}
glitz_format_t *
glitz_find_format (glitz_drawable_t *drawable,
unsigned long mask,
const glitz_format_t *templ,
int count)
unsigned long mask,
const glitz_format_t *templ,
int count)
{
return _glitz_format_find (drawable->backend->formats,
drawable->backend->n_formats,
mask, templ, count);
return _glitz_format_find (drawable->backend->formats,
drawable->backend->n_formats,
mask, templ, count);
}
glitz_format_t *
glitz_find_standard_format (glitz_drawable_t *drawable,
glitz_format_name_t format_name)
glitz_format_name_t format_name)
{
glitz_format_t templ;
unsigned long mask = GLITZ_FORMAT_RED_SIZE_MASK |
GLITZ_FORMAT_GREEN_SIZE_MASK | GLITZ_FORMAT_BLUE_SIZE_MASK |
GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_TYPE_MASK;
glitz_format_t templ;
unsigned long mask = GLITZ_FORMAT_RED_SIZE_MASK |
GLITZ_FORMAT_GREEN_SIZE_MASK | GLITZ_FORMAT_BLUE_SIZE_MASK |
GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_TYPE_MASK;
templ.type = GLITZ_FORMAT_TYPE_COLOR;
templ.type = GLITZ_FORMAT_TYPE_COLOR;
switch (format_name) {
case GLITZ_STANDARD_ARGB32:
templ.color.red_size = 8;
templ.color.green_size = 8;
templ.color.blue_size = 8;
templ.color.alpha_size = 8;
break;
case GLITZ_STANDARD_RGB24:
templ.color.red_size = 8;
templ.color.green_size = 8;
templ.color.blue_size = 8;
templ.color.alpha_size = 0;
break;
case GLITZ_STANDARD_A8:
templ.color.red_size = 0;
templ.color.green_size = 0;
templ.color.blue_size = 0;
templ.color.alpha_size = 8;
break;
case GLITZ_STANDARD_A1:
templ.color.red_size = 0;
templ.color.green_size = 0;
templ.color.blue_size = 0;
templ.color.alpha_size = 1;
break;
}
switch (format_name) {
case GLITZ_STANDARD_ARGB32:
templ.color.red_size = 8;
templ.color.green_size = 8;
templ.color.blue_size = 8;
templ.color.alpha_size = 8;
break;
case GLITZ_STANDARD_RGB24:
templ.color.red_size = 8;
templ.color.green_size = 8;
templ.color.blue_size = 8;
templ.color.alpha_size = 0;
break;
case GLITZ_STANDARD_A8:
templ.color.red_size = 0;
templ.color.green_size = 0;
templ.color.blue_size = 0;
templ.color.alpha_size = 8;
break;
case GLITZ_STANDARD_A1:
templ.color.red_size = 0;
templ.color.green_size = 0;
templ.color.blue_size = 0;
templ.color.alpha_size = 1;
break;
}
return glitz_find_format (drawable, mask, &templ, 0);
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)
{
framebuffer->name = 0;
}
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;
void
glitz_framebuffer_fini (glitz_gl_proc_address_list_t *gl,
glitz_framebuffer_t *framebuffer)
static glitz_bool_t
_glitz_fbo_bind (glitz_fbo_drawable_t *drawable)
{
if (framebuffer->name)
gl->delete_framebuffers (1, &framebuffer->name);
}
glitz_bool_t update = 0;
glitz_gl_enum_t status;
void
glitz_framebuffer_unbind (glitz_gl_proc_address_list_t *gl)
{
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0);
}
GLITZ_GL_DRAWABLE (drawable->other);
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 (!drawable->fb)
{
if (!TEXTURE_ALLOCATED (texture))
glitz_texture_allocate (gl, texture);
gl->gen_framebuffers (1, &drawable->fb);
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,
0);
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;
}
else
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, framebuffer->name);
return (gl->check_framebuffer_status (GLITZ_GL_FRAMEBUFFER) ==
GLITZ_GL_FRAMEBUFFER_COMPLETE);
gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, drawable->fb);
if (drawable->base.front &&
drawable->front_texture != drawable->base.front->texture.name)
{
gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER,
GLITZ_GL_COLOR_ATTACHMENT0,
drawable->base.front->texture.target,
drawable->base.front->texture.name,
0);
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;
}

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

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

@ -112,8 +112,9 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
#define GLITZ_GL_MAX_TEXTURE_SIZE 0x0D33
#define GLITZ_GL_MAX_VIEWPORT_DIMS 0x0D3A
#define GLITZ_GL_TEXTURE_WIDTH 0x1000
#define GLITZ_GL_TEXTURE_HEIGHT 0x1001
#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
@ -309,8 +314,14 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
#define GLITZ_GL_WRITE_ONLY 0x88B9
#define GLITZ_GL_READ_WRITE 0x88BA
#define GLITZ_GL_FRAMEBUFFER 0x8D40
#define GLITZ_GL_COLOR_ATTACHMENT0 0x8CE0
#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,59 +32,61 @@
#include "glitzint.h"
void
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);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ZERO);
break;
case GLITZ_OPERATOR_SRC:
gl->disable (GLITZ_GL_BLEND);
break;
case GLITZ_OPERATOR_DST:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE);
break;
case GLITZ_OPERATOR_OVER:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_OVER_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ONE);
break;
case GLITZ_OPERATOR_IN:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ZERO);
break;
case GLITZ_OPERATOR_IN_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_SRC_ALPHA);
break;
case GLITZ_OPERATOR_OUT:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ZERO);
break;
case GLITZ_OPERATOR_OUT_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_ATOP:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_ATOP_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_SRC_ALPHA);
break;
case GLITZ_OPERATOR_XOR:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA,
GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_ADD:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE);
break;
}
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);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ZERO);
break;
case GLITZ_OPERATOR_SRC:
gl->disable (GLITZ_GL_BLEND);
break;
case GLITZ_OPERATOR_DST:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE);
break;
case GLITZ_OPERATOR_OVER:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_OVER_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ONE);
break;
case GLITZ_OPERATOR_IN:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ZERO);
break;
case GLITZ_OPERATOR_IN_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_SRC_ALPHA);
break;
case GLITZ_OPERATOR_OUT:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ZERO);
break;
case GLITZ_OPERATOR_OUT_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_ATOP:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_ATOP_REVERSE:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_SRC_ALPHA);
break;
case GLITZ_OPERATOR_XOR:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA,
GLITZ_GL_ONE_MINUS_SRC_ALPHA);
break;
case GLITZ_OPERATOR_ADD:
gl->enable (GLITZ_GL_BLEND);
gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE);
break;
}
}

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

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

@ -36,36 +36,36 @@
#define EXPAND_RECT "RECT"
#define EXPAND_NA "NA"
#define EXPAND_X_IN_SOLID_OP \
{ "", "", "MUL result.color, color, fragment.color.a;" }
#define EXPAND_X_IN_SOLID_OP \
{ "", "", "MUL result.color, color, fragment.color.a;" }
#define EXPAND_SOLID_IN_X_OP \
{ "", "", "MUL result.color, fragment.color, color.a;" }
#define EXPAND_SOLID_IN_X_OP \
{ "", "", "MUL result.color, fragment.color, color.a;" }
#define EXPAND_SRC_DECL "TEMP src;"
#define EXPAND_SRC_2D_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], 2D;", \
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
#define EXPAND_SRC_2D_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], 2D;", \
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
#define EXPAND_SRC_RECT_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], RECT;", \
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
#define EXPAND_SRC_RECT_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], RECT;", \
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
#define EXPAND_MASK_DECL "TEMP mask;"
#define EXPAND_MASK_2D_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
#define EXPAND_MASK_2D_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
#define EXPAND_MASK_RECT_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], RECT;", \
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
#define EXPAND_MASK_RECT_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], RECT;", \
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
#define EXPAND_IN_NA \
{ "NA", "NA", "NA" }
#define EXPAND_IN_NA \
{ "NA", "NA", "NA" }
typedef struct _glitz_program_expand_t glitz_program_expand_t;
@ -76,98 +76,98 @@ typedef struct _glitz_inop {
} glitz_in_op_t;
static const struct _glitz_program_expand_t {
char *texture;
char *declarations;
glitz_in_op_t in;
char *texture;
char *declarations;
glitz_in_op_t in;
} _program_expand_map[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST][2] = {
{
/* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_NONE] */
{
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA },
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }
},
/* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_NONE] */
{
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA },
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }
},
/* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_2D] */
{
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA },
{ EXPAND_2D, EXPAND_NONE, EXPAND_SOLID_IN_X_OP }
},
/* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_2D] */
{
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA },
{ EXPAND_2D, EXPAND_NONE, EXPAND_SOLID_IN_X_OP }
},
/* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_RECT] */
{
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA },
{ EXPAND_RECT, EXPAND_NONE, EXPAND_SOLID_IN_X_OP }
/* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_RECT] */
{
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA },
{ EXPAND_RECT, EXPAND_NONE, EXPAND_SOLID_IN_X_OP }
}
}, {
/* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_NONE] */
{
{ EXPAND_2D, EXPAND_NONE, EXPAND_X_IN_SOLID_OP },
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }
},
/* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_2D] */
{
{ EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP },
{ EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP }
},
/* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_RECT] */
{
{ EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP },
{ EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP }
}
}, {
/* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_NONE] */
{
{ EXPAND_RECT, EXPAND_NONE, EXPAND_X_IN_SOLID_OP },
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }
},
/* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_2D] */
{
{ EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP },
{ EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP }
},
/* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_RECT] */
{
{ EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP },
{ EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_RECT_IN_OP }
}
}
}, {
/* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_NONE] */
{
{ EXPAND_2D, EXPAND_NONE, EXPAND_X_IN_SOLID_OP },
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }
},
/* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_2D] */
{
{ EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP },
{ EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP }
},
/* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_RECT] */
{
{ EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP },
{ EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP }
}
}, {
/* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_NONE] */
{
{ EXPAND_RECT, EXPAND_NONE, EXPAND_X_IN_SOLID_OP },
{ EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }
},
/* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_2D] */
{
{ EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP },
{ EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP }
},
/* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_RECT] */
{
{ EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP },
{ EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_RECT_IN_OP }
}
}
};
/*
* general convolution filter.
*/
static const char *_convolution_header[] = {
"PARAM p[%d] = { program.local[0..%d] };",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, in, coord, position;",
"PARAM p[%d] = { program.local[0..%d] };",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, in, coord, position;",
/* extra declarations */
"%s"
/* extra declarations */
"%s"
/* perspective divide */
"RCP position.w, pos.w;",
"MUL position, pos, position.w;", NULL
/* perspective divide */
"RCP position.w, pos.w;",
"MUL position, pos, position.w;", NULL
};
static const char *_convolution_sample_first[] = {
"MOV coord, 0.0;",
"ADD coord.x, position.x, p[0].x;",
"ADD coord.y, position.y, p[0].y;",
"TEX in, coord, texture[%s], %s;",
"MUL color, in, p[0].z;", NULL
"MOV coord, 0.0;",
"ADD coord.x, position.x, p[0].x;",
"ADD coord.y, position.y, p[0].y;",
"TEX in, coord, texture[%s], %s;",
"MUL color, in, p[0].z;", NULL
};
static const char *_convolution_sample[] = {
"ADD coord.x, position.x, p[%d].x;",
"ADD coord.y, position.y, p[%d].y;",
"TEX in, coord, texture[%s], %s;",
"MAD color, in, p[%d].z, color;", NULL
"ADD coord.x, position.x, p[%d].x;",
"ADD coord.y, position.y, p[%d].y;",
"TEX in, coord, texture[%s], %s;",
"MAD color, in, p[%d].z, color;", NULL
};
@ -175,17 +175,17 @@ static const char *_convolution_sample[] = {
* gradient filters.
*/
static const char *_gradient_header[] = {
"PARAM gradient = program.local[0];",
"PARAM stops[%d] = { program.local[1..%d] };",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, second_color, stop0, stop1, position;",
"PARAM gradient = program.local[0];",
"PARAM stops[%d] = { program.local[1..%d] };",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, second_color, stop0, stop1, position;",
/* extra declarations */
"%s",
/* extra declarations */
"%s",
/* perspective divide */
"RCP position.w, pos.w;",
"MUL position, pos, position.w;", NULL
/* perspective divide */
"RCP position.w, pos.w;",
"MUL position, pos, position.w;", NULL
};
/*
@ -197,10 +197,10 @@ static const char *_gradient_header[] = {
* gradient.w = -sin (angle)
*/
static const char *_linear_gradient_calculations[] = {
"MUL position.x, gradient.z, position.x;",
"MAD position.x, gradient.w, position.y, position.x;",
"SUB position.z, position.x, gradient.x;",
"MUL position.z, position.z, gradient.y;", NULL
"MUL position.x, gradient.z, position.x;",
"MAD position.x, gradient.w, position.y, position.x;",
"SUB position.z, position.x, gradient.x;",
"MUL position.z, position.z, gradient.y;", NULL
};
/*
@ -212,171 +212,172 @@ static const char *_linear_gradient_calculations[] = {
* gradient.w = 1 / (radius1 - radius0)
*/
static const char *_radial_gradient_calculations[] = {
"SUB position, position, gradient;",
"MUL position.x, position.x, position.x;",
"MAD position.x, position.y, position.y, position.x;",
"RSQ position.y, position.x;",
"RCP position.x, position.y;",
"MUL position.x, position.x, position.x;",
"MUL position.x, position.x, position.y;",
"SUB position.x, position.x, gradient.z;",
"MUL position.z, position.x, gradient.w;", NULL
"SUB position, position, gradient;",
"MUL position.x, position.x, position.x;",
"MAD position.x, position.y, position.y, position.x;",
"RSQ position.y, position.x;",
"RCP position.x, position.y;",
"MUL position.x, position.x, position.x;",
"MUL position.x, position.x, position.y;",
"SUB position.x, position.x, gradient.z;",
"MUL position.z, position.x, gradient.w;", NULL
};
static const char *_gradient_fill_repeat[] = {
"FRC position.z, position.z;", NULL
"FRC position.z, position.z;", NULL
};
static const char *_gradient_fill_reflect[] = {
"FLR position.w, position.z;",
"MUL position.w, position.w, 0.5;",
"FLR position.w, position.w;",
"MUL position.y, position.w, 2.0;",
"FLR position.x, position.z;",
"SUB position.y, position.x, position.y;",
"FRC position.x, position.z;",
"SUB position.x, position.x, position.y;",
"ABS position.z, position.x;", NULL
"FLR position.w, position.z;",
"MUL position.w, position.w, 0.5;",
"FLR position.w, position.w;",
"MUL position.y, position.w, 2.0;",
"FLR position.x, position.z;",
"SUB position.y, position.x, position.y;",
"FRC position.x, position.z;",
"SUB position.x, position.x, position.y;",
"ABS position.z, position.x;", NULL
};
static const char *_gradient_init_stops[] = {
"MOV stop0, stops[0];",
"MOV stop1, stops[%d];", NULL
"MOV stop0, stops[0];",
"MOV stop1, stops[%d];", NULL
};
static const char *_gradient_lower_stop[] = {
"SLT position.x, stops[%d].z, position.z;",
"CMP stop0, -position.x, stops[%d], stop0;", NULL
"SLT position.x, stops[%d].z, position.z;",
"CMP stop0, -position.x, stops[%d], stop0;", NULL
};
static const char *_gradient_higher_stop[] = {
"SLT position.x, position.z, stops[%d].z;",
"CMP stop1, -position.x, stops[%d], stop1;", NULL
"SLT position.x, position.z, stops[%d].z;",
"CMP stop1, -position.x, stops[%d], stop1;", NULL
};
static const char *_gradient_fetch_and_interpolate[] = {
"TEX color, stop0, texture[%s], %s;",
"TEX second_color, stop1, texture[%s], %s;",
"TEX color, stop0, texture[%s], %s;",
"TEX second_color, stop1, texture[%s], %s;",
/* normalize gradient offset to color stop span */
"SUB position.z, position.z, stop0.z;",
"MUL_SAT position.z, position.z, stop0.w;",
/* normalize gradient offset to color stop span */
"SUB position.z, position.z, stop0.z;",
"MUL_SAT position.z, position.z, stop0.w;",
/* linear interpolation */
"LRP color, position.z, second_color, color;", NULL
/* linear interpolation */
"LRP color, position.z, second_color, color;", NULL
};
static struct _glitz_program_query {
glitz_gl_enum_t query;
glitz_gl_enum_t max_query;
glitz_gl_int_t min;
glitz_gl_enum_t query;
glitz_gl_enum_t max_query;
glitz_gl_int_t min;
} _program_limits[] = {
{ GLITZ_GL_PROGRAM_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_NATIVE_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_PARAMETERS,
GLITZ_GL_MAX_PROGRAM_PARAMETERS, 1 },
{ GLITZ_GL_PROGRAM_NATIVE_PARAMETERS,
GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 1 },
{ GLITZ_GL_PROGRAM_ALU_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_ALU_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_TEX_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_TEX_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_TEX_INDIRECTIONS,
GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_TEX_INDIRECTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS, 0 },
{ GLITZ_GL_PROGRAM_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_NATIVE_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_PARAMETERS,
GLITZ_GL_MAX_PROGRAM_PARAMETERS, 1 },
{ GLITZ_GL_PROGRAM_NATIVE_PARAMETERS,
GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 1 },
{ GLITZ_GL_PROGRAM_ALU_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_ALU_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_TEX_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_TEX_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_TEX_INDIRECTIONS,
GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_TEX_INDIRECTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS, 0 },
};
static glitz_bool_t
_glitz_program_under_limits (glitz_gl_proc_address_list_t *gl)
{
int i, n_limits;
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;
for (i = 0; i < n_limits; i++) {
glitz_gl_int_t value, max;
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
_program_limits[i].query, &value);
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
_program_limits[i].max_query, &max);
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
_program_limits[i].query, &value);
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
_program_limits[i].max_query, &max);
if (value < _program_limits[i].min)
return 0;
if (value < _program_limits[i].min)
return 0;
if (value >= max)
return 0;
}
if (value >= max)
return 0;
}
return 1;
return 1;
}
static glitz_gl_int_t
_glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
char *program_string,
int n_parameters)
char *program_string,
int n_parameters)
{
glitz_gl_int_t error, pid = -1;
glitz_gl_uint_t program;
glitz_gl_int_t error, pid = -1;
glitz_gl_uint_t program;
/* clear error flags */
while (gl->get_error () != GLITZ_GL_NO_ERROR);
/* clear error flags */
while (gl->get_error () != GLITZ_GL_NO_ERROR);
gl->gen_programs (1, &program);
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, program);
gl->program_string (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_PROGRAM_FORMAT_ASCII,
strlen (program_string),
program_string);
if (gl->get_error () == GLITZ_GL_NO_ERROR) {
gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
gl->gen_programs (1, &program);
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, program);
gl->program_string (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_PROGRAM_FORMAT_ASCII,
strlen (program_string),
program_string);
if (gl->get_error () == GLITZ_GL_NO_ERROR) {
gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
if (error == -1) {
glitz_gl_int_t value;
if (error == -1) {
glitz_gl_int_t value;
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_PROGRAM_UNDER_NATIVE_LIMITS,
&value);
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_PROGRAM_UNDER_NATIVE_LIMITS,
&value);
if (value == GLITZ_GL_TRUE) {
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_MAX_PROGRAM_LOCAL_PARAMETERS,
&value);
if (value == GLITZ_GL_TRUE) {
gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_MAX_PROGRAM_LOCAL_PARAMETERS,
&value);
if (value >= n_parameters) {
if (_glitz_program_under_limits (gl))
pid = program;
}
}
if (value >= n_parameters) {
if (_glitz_program_under_limits (gl))
pid = program;
}
}
}
}
}
if (pid == -1) {
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0);
gl->delete_programs (1, &program);
}
if (pid == -1) {
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0);
gl->delete_programs (1, &program);
}
return pid;
return pid;
}
static void
_string_array_to_char_array (char *dst, const char *src[])
{
int i, n;
int i, n;
for (i = 0; src[i]; i++) {
n = strlen (src[i]);
memcpy (dst, src[i], n);
dst += n;
}
*dst = '\0';
for (i = 0; src[i]; i++) {
n = strlen (src[i]);
memcpy (dst, src[i], n);
dst += n;
}
*dst = '\0';
}
/* these should be more than enough */
@ -388,231 +389,234 @@ _string_array_to_char_array (char *dst, const char *src[])
static glitz_gl_uint_t
_glitz_create_fragment_program (glitz_composite_op_t *op,
int fp_type,
int id,
const glitz_program_expand_t *expand)
int fp_type,
int id,
const glitz_program_expand_t *expand)
{
char buffer[1024], *program = NULL, *tex, *p = NULL;
char *texture_type, *extra_declarations;
const glitz_in_op_t *in;
glitz_gl_uint_t fp;
int i;
char buffer[1024], *program = NULL, *tex, *p = NULL;
char *texture_type, *extra_declarations;
const glitz_in_op_t *in;
glitz_gl_uint_t fp;
int i;
switch (op->type) {
case GLITZ_COMBINE_TYPE_ARGBF:
case GLITZ_COMBINE_TYPE_ARGBF_SOLID:
case GLITZ_COMBINE_TYPE_ARGBF_SOLIDC:
i = 0;
tex = "0";
break;
case GLITZ_COMBINE_TYPE_ARGB_ARGBF:
case GLITZ_COMBINE_TYPE_SOLID_ARGBF:
i = 1;
tex = "0";
break;
case GLITZ_COMBINE_TYPE_ARGBF_ARGB:
case GLITZ_COMBINE_TYPE_ARGBF_ARGBC:
i = 0;
tex = "1";
break;
default:
return 0;
}
switch (op->type) {
case GLITZ_COMBINE_TYPE_ARGBF:
case GLITZ_COMBINE_TYPE_ARGBF_SOLID:
case GLITZ_COMBINE_TYPE_ARGBF_SOLIDC:
i = 0;
tex = "0";
break;
case GLITZ_COMBINE_TYPE_ARGB_ARGBF:
case GLITZ_COMBINE_TYPE_SOLID_ARGBF:
i = 1;
tex = "0";
break;
case GLITZ_COMBINE_TYPE_ARGBF_ARGB:
case GLITZ_COMBINE_TYPE_ARGBF_ARGBC:
i = 0;
tex = "1";
break;
default:
return 0;
}
texture_type = expand[i].texture;
extra_declarations = expand[i].declarations;
in = &expand[i].in;
switch (fp_type) {
case GLITZ_FP_CONVOLUTION:
program = malloc (CONVOLUTION_BASE_SIZE + CONVOLUTION_SAMPLE_SIZE * id);
if (program == NULL)
return 0;
p = program;
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _convolution_header);
p += sprintf (p, buffer, id, id - 1, tex, extra_declarations);
_string_array_to_char_array (buffer, _convolution_sample_first);
p += sprintf (p, buffer, tex, texture_type);
_string_array_to_char_array (buffer, _convolution_sample);
for (i = 1; i < id; i++)
p += sprintf (p, buffer, i, i, tex, texture_type, i);
break;
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
case GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT:
id += 2;
/* fall-through */
case GLITZ_FP_LINEAR_GRADIENT_NEAREST:
case GLITZ_FP_LINEAR_GRADIENT_REPEAT:
case GLITZ_FP_LINEAR_GRADIENT_REFLECT:
case GLITZ_FP_RADIAL_GRADIENT_NEAREST:
case GLITZ_FP_RADIAL_GRADIENT_REPEAT:
case GLITZ_FP_RADIAL_GRADIENT_REFLECT:
program = malloc (GRADIENT_BASE_SIZE + GRADIENT_STOP_SIZE * id);
if (program == NULL)
return 0;
p = program;
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _gradient_header);
p += sprintf (p, buffer, id, id, tex, extra_declarations);
texture_type = expand[i].texture;
extra_declarations = expand[i].declarations;
in = &expand[i].in;
switch (fp_type) {
case GLITZ_FP_CONVOLUTION:
program = malloc (CONVOLUTION_BASE_SIZE +
CONVOLUTION_SAMPLE_SIZE * id);
if (program == NULL)
return 0;
p = program;
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _convolution_header);
p += sprintf (p, buffer, id, id - 1, tex, extra_declarations);
_string_array_to_char_array (buffer, _convolution_sample_first);
p += sprintf (p, buffer, tex, texture_type);
_string_array_to_char_array (buffer, _convolution_sample);
for (i = 1; i < id; i++)
p += sprintf (p, buffer, i, i, tex, texture_type, i);
break;
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
case GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT:
id += 2;
/* fall-through */
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);
break;
default:
_string_array_to_char_array (buffer, _radial_gradient_calculations);
break;
}
p += sprintf (p, buffer);
switch (fp_type) {
case GLITZ_FP_LINEAR_GRADIENT_REPEAT:
case GLITZ_FP_RADIAL_GRADIENT_NEAREST:
case GLITZ_FP_RADIAL_GRADIENT_REPEAT:
_string_array_to_char_array (buffer, _gradient_fill_repeat);
p += sprintf (p, buffer);
break;
case GLITZ_FP_LINEAR_GRADIENT_REFLECT:
case GLITZ_FP_RADIAL_GRADIENT_REFLECT:
_string_array_to_char_array (buffer, _gradient_fill_reflect);
p += sprintf (p, buffer);
break;
program = malloc (GRADIENT_BASE_SIZE + GRADIENT_STOP_SIZE * id);
if (program == NULL)
return 0;
p = program;
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _gradient_header);
p += sprintf (p, buffer, id, id, tex, extra_declarations);
switch (fp_type) {
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
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);
break;
default:
_string_array_to_char_array (buffer,
_radial_gradient_calculations);
break;
}
p += sprintf (p, buffer);
switch (fp_type) {
case GLITZ_FP_LINEAR_GRADIENT_REPEAT:
case GLITZ_FP_RADIAL_GRADIENT_REPEAT:
_string_array_to_char_array (buffer, _gradient_fill_repeat);
p += sprintf (p, buffer);
break;
case GLITZ_FP_LINEAR_GRADIENT_REFLECT:
case GLITZ_FP_RADIAL_GRADIENT_REFLECT:
_string_array_to_char_array (buffer, _gradient_fill_reflect);
p += sprintf (p, buffer);
break;
default:
break;
}
_string_array_to_char_array (buffer, _gradient_init_stops);
p += sprintf (p, buffer, id - 1);
_string_array_to_char_array (buffer, _gradient_lower_stop);
for (i = 1; i < (id - 1); i++)
p += sprintf (p, buffer, i, i);
_string_array_to_char_array (buffer, _gradient_higher_stop);
for (i = 1; i < (id - 1); i++)
p += sprintf (p, buffer, id - i - 1, id - i - 1);
_string_array_to_char_array (buffer, _gradient_fetch_and_interpolate);
p += sprintf (p, buffer, tex, texture_type, tex, texture_type);
id++;
break;
default:
break;
return 0;
}
_string_array_to_char_array (buffer, _gradient_init_stops);
p += sprintf (p, buffer, id - 1);
if (program == NULL)
return 0;
_string_array_to_char_array (buffer, _gradient_lower_stop);
for (i = 1; i < (id - 1); i++)
p += sprintf (p, buffer, i, i);
p += sprintf (p, "%s", in->fetch);
if (op->per_component)
p += sprintf (p, "%s", in->dot_product);
p += sprintf (p, "%s", in->mult);
sprintf (p, "END");
_string_array_to_char_array (buffer, _gradient_higher_stop);
for (i = 1; i < (id - 1); i++)
p += sprintf (p, buffer, id - i - 1, id - i - 1);
fp = _glitz_compile_arb_fragment_program (op->gl, program, id);
_string_array_to_char_array (buffer, _gradient_fetch_and_interpolate);
p += sprintf (p, buffer, tex, texture_type, tex, texture_type);
free (program);
id++;
break;
default:
return 0;
}
if (program == NULL)
return 0;
p += sprintf (p, "%s", in->fetch);
if (op->per_component)
p += sprintf (p, "%s", in->dot_product);
p += sprintf (p, "%s", in->mult);
sprintf (p, "END");
fp = _glitz_compile_arb_fragment_program (op->gl, program, id);
free (program);
return fp;
return fp;
}
void
glitz_program_map_init (glitz_program_map_t *map)
{
memset (map, 0, sizeof (glitz_program_map_t));
memset (map, 0, sizeof (glitz_program_map_t));
}
void
glitz_program_map_fini (glitz_gl_proc_address_list_t *gl,
glitz_program_map_t *map)
glitz_program_map_t *map)
{
glitz_gl_uint_t program;
int i, j, k, x, y;
glitz_gl_uint_t program;
int i, j, k, x, y;
for (i = 0; i < GLITZ_COMBINE_TYPES; i++) {
for (j = 0; j < GLITZ_FP_TYPES; j++) {
for (x = 0; x < GLITZ_TEXTURE_LAST; x++) {
for (y = 0; y < GLITZ_TEXTURE_LAST; y++) {
glitz_program_t *p = &map->filters[i][j].fp[x][y];
for (i = 0; i < GLITZ_COMBINE_TYPES; i++) {
for (j = 0; j < GLITZ_FP_TYPES; j++) {
for (x = 0; x < GLITZ_TEXTURE_LAST; x++) {
for (y = 0; y < GLITZ_TEXTURE_LAST; y++) {
glitz_program_t *p = &map->filters[i][j].fp[x][y];
if (p->name) {
for (k = 0; k < p->size; k++)
if (p->name[k] > 0) {
program = p->name[k];
gl->delete_programs (1, &program);
}
if (p->name) {
for (k = 0; k < p->size; k++)
if (p->name[k] > 0) {
program = p->name[k];
gl->delete_programs (1, &program);
}
free (p->name);
}
}
}
free (p->name);
}
}
}
}
}
}
}
#define TEXTURE_INDEX(surface) \
((surface)? \
(((surface)->texture.target == GLITZ_GL_TEXTURE_2D)? \
GLITZ_TEXTURE_2D: \
GLITZ_TEXTURE_RECT \
) : \
GLITZ_TEXTURE_NONE \
)
#define TEXTURE_INDEX(surface) \
((surface)? \
(((surface)->texture.target == GLITZ_GL_TEXTURE_2D)? \
GLITZ_TEXTURE_2D: \
GLITZ_TEXTURE_RECT \
) : \
GLITZ_TEXTURE_NONE \
)
glitz_gl_uint_t
glitz_get_fragment_program (glitz_composite_op_t *op,
int fp_type,
int id)
int fp_type,
int id)
{
glitz_program_map_t *map;
glitz_program_t *program;
int t0 = TEXTURE_INDEX (op->src);
int t1 = TEXTURE_INDEX (op->mask);
glitz_program_map_t *map;
glitz_program_t *program;
int t0 = TEXTURE_INDEX (op->src);
int t1 = TEXTURE_INDEX (op->mask);
map = op->dst->drawable->backend->program_map;
program = &map->filters[op->type][fp_type].fp[t0][t1];
map = op->dst->drawable->backend->program_map;
program = &map->filters[op->type][fp_type].fp[t0][t1];
if (program->size < id) {
int old_size;
if (program->size < id) {
int old_size;
program->name = realloc (program->name,
id * sizeof (glitz_gl_uint_t));
if (program->name == NULL) {
glitz_surface_status_add (op->dst, GLITZ_STATUS_NO_MEMORY_MASK);
return 0;
program->name = realloc (program->name,
id * sizeof (glitz_gl_uint_t));
if (program->name == NULL) {
glitz_surface_status_add (op->dst, GLITZ_STATUS_NO_MEMORY_MASK);
return 0;
}
old_size = program->size;
program->size = id;
memset (program->name + old_size, 0,
(program->size - old_size) * sizeof (glitz_gl_uint_t));
}
old_size = program->size;
program->size = id;
memset (program->name + old_size, 0,
(program->size - old_size) * sizeof (glitz_gl_uint_t));
}
if (program->name[id - 1] == 0) {
glitz_surface_push_current (op->dst, GLITZ_CONTEXT_CURRENT);
if (program->name[id - 1] == 0) {
glitz_surface_push_current (op->dst, GLITZ_CONTEXT_CURRENT);
program->name[id - 1] =
_glitz_create_fragment_program (op, fp_type, id,
_program_expand_map[t0][t1]);
program->name[id - 1] =
_glitz_create_fragment_program (op, fp_type, id,
_program_expand_map[t0][t1]);
glitz_surface_pop_current (op->dst);
}
glitz_surface_pop_current (op->dst);
}
if (program->name[id - 1] > 0)
return program->name[id - 1];
else
return 0;
if (program->name[id - 1] > 0)
return program->name[id - 1];
else
return 0;
}

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

@ -29,17 +29,17 @@
#include "glitzint.h"
#define STORE_16(dst, size, src) \
dst = ((size) ? \
((((((1L << (size)) - 1L) * (src)) / 0xffff) * 0xffff) / \
((1L << (size)) - 1L)) : \
dst)
#define STORE_16(dst, size, src) \
dst = ((size) ? \
((((((1L << (size)) - 1L) * (src)) / 0xffff) * 0xffff) / \
((1L << (size)) - 1L)) : \
dst)
static glitz_buffer_t *
_glitz_minimum_buffer (glitz_surface_t *surface,
const glitz_rectangle_t *rects,
int n_rects,
unsigned int *pixel)
const glitz_rectangle_t *rects,
int n_rects,
unsigned int *pixel)
{
glitz_buffer_t *buffer;
int i, size = 0;
@ -47,26 +47,26 @@ _glitz_minimum_buffer (glitz_surface_t *surface,
while (n_rects--)
{
i = rects->width * rects->height;
if (i > size)
size = i;
i = rects->width * rects->height;
if (i > size)
size = i;
rects++;
rects++;
}
if (size <= 1)
return glitz_buffer_create_for_data (pixel);
return glitz_buffer_create_for_data (pixel);
buffer = glitz_pixel_buffer_create (surface->drawable, NULL,
size * sizeof (unsigned int),
GLITZ_BUFFER_HINT_STATIC_DRAW);
size * sizeof (unsigned int),
GLITZ_BUFFER_HINT_STATIC_DRAW);
if (!buffer)
return NULL;
return NULL;
data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY);
while (size--)
*data++ = *pixel;
*data++ = *pixel;
glitz_buffer_unmap (buffer);
@ -75,214 +75,213 @@ _glitz_minimum_buffer (glitz_surface_t *surface,
void
glitz_set_rectangles (glitz_surface_t *dst,
const glitz_color_t *color,
const glitz_rectangle_t *rects,
int n_rects)
const glitz_color_t *color,
const glitz_rectangle_t *rects,
int n_rects)
{
GLITZ_GL_SURFACE (dst);
if (n_rects < 1)
return;
return;
if (SURFACE_SOLID (dst))
{
glitz_color_t old = dst->solid;
glitz_box_t *clip = dst->clip;
int n_clip = dst->n_clip;
glitz_color_t old = dst->solid;
glitz_box_t *clip = dst->clip;
int n_clip = dst->n_clip;
for (; n_clip; clip++, n_clip--)
{
if (clip->x1 > 0 ||
clip->y1 > 0 ||
clip->x2 < 1 ||
clip->y2 < 1)
continue;
for (; n_clip; clip++, n_clip--)
{
if (clip->x1 > 0 ||
clip->y1 > 0 ||
clip->x2 < 1 ||
clip->y2 < 1)
continue;
for (; n_rects; rects++, n_rects--)
{
if (rects->x > 0 ||
rects->y > 0 ||
(rects->x + rects->width) < 1 ||
(rects->y + rects->height) < 1)
continue;
for (; n_rects; rects++, n_rects--)
{
if (rects->x > 0 ||
rects->y > 0 ||
(rects->x + rects->width) < 1 ||
(rects->y + rects->height) < 1)
continue;
STORE_16 (dst->solid.red,
dst->format->color.red_size,
color->red);
STORE_16 (dst->solid.green,
dst->format->color.green_size,
color->green);
STORE_16 (dst->solid.blue,
dst->format->color.blue_size,
color->blue);
STORE_16 (dst->solid.alpha,
dst->format->color.alpha_size,
color->alpha);
STORE_16 (dst->solid.red,
dst->format->color.red_size,
color->red);
STORE_16 (dst->solid.green,
dst->format->color.green_size,
color->green);
STORE_16 (dst->solid.blue,
dst->format->color.blue_size,
color->blue);
STORE_16 (dst->solid.alpha,
dst->format->color.alpha_size,
color->alpha);
if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK)
{
dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK;
glitz_surface_damage (dst, &dst->box,
GLITZ_DAMAGE_TEXTURE_MASK |
GLITZ_DAMAGE_DRAWABLE_MASK);
}
else
{
if (dst->solid.red != old.red ||
dst->solid.green != old.green ||
dst->solid.blue != old.blue ||
dst->solid.alpha != old.alpha)
glitz_surface_damage (dst, &dst->box,
GLITZ_DAMAGE_TEXTURE_MASK |
GLITZ_DAMAGE_DRAWABLE_MASK);
}
break;
}
break;
}
if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK)
{
dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK;
glitz_surface_damage (dst, &dst->box,
GLITZ_DAMAGE_TEXTURE_MASK |
GLITZ_DAMAGE_DRAWABLE_MASK);
}
else
{
if (dst->solid.red != old.red ||
dst->solid.green != old.green ||
dst->solid.blue != old.blue ||
dst->solid.alpha != old.alpha)
glitz_surface_damage (dst, &dst->box,
GLITZ_DAMAGE_TEXTURE_MASK |
GLITZ_DAMAGE_DRAWABLE_MASK);
}
break;
}
break;
}
}
else
{
static glitz_pixel_format_t pf = {
{
32,
0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff
},
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
};
glitz_buffer_t *buffer = NULL;
glitz_box_t box;
glitz_bool_t drawable = 0;
static glitz_pixel_format_t pf = {
{
32,
0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff
},
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
};
glitz_buffer_t *buffer = NULL;
glitz_box_t box;
glitz_bool_t drawable = 0;
if (n_rects == 1 && rects->width <= 1 && rects->height <= 1)
{
glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT);
}
else
{
drawable = glitz_surface_push_current (dst,
GLITZ_DRAWABLE_CURRENT);
}
if (n_rects == 1 && rects->width <= 1 && rects->height <= 1)
{
glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT);
}
else
{
drawable = glitz_surface_push_current (dst,
GLITZ_DRAWABLE_CURRENT);
}
if (drawable)
{
glitz_box_t *clip;
int n_clip;
int target_height = SURFACE_DRAWABLE_HEIGHT (dst);
if (drawable)
{
glitz_box_t *clip;
int n_clip;
gl->clear_color (color->red / (glitz_gl_clampf_t) 0xffff,
color->green / (glitz_gl_clampf_t) 0xffff,
color->blue / (glitz_gl_clampf_t) 0xffff,
color->alpha / (glitz_gl_clampf_t) 0xffff);
gl->clear_color (color->red / (glitz_gl_clampf_t) 0xffff,
color->green / (glitz_gl_clampf_t) 0xffff,
color->blue / (glitz_gl_clampf_t) 0xffff,
color->alpha / (glitz_gl_clampf_t) 0xffff);
while (n_rects--)
{
clip = dst->clip;
n_clip = dst->n_clip;
while (n_clip--)
{
box.x1 = clip->x1 + dst->x_clip;
box.y1 = clip->y1 + dst->y_clip;
box.x2 = clip->x2 + dst->x_clip;
box.y2 = clip->y2 + dst->y_clip;
while (n_rects--)
{
clip = dst->clip;
n_clip = dst->n_clip;
while (n_clip--)
{
box.x1 = clip->x1 + dst->x_clip;
box.y1 = clip->y1 + dst->y_clip;
box.x2 = clip->x2 + dst->x_clip;
box.y2 = clip->y2 + dst->y_clip;
if (dst->box.x1 > box.x1)
box.x1 = dst->box.x1;
if (dst->box.y1 > box.y1)
box.y1 = dst->box.y1;
if (dst->box.x2 < box.x2)
box.x2 = dst->box.x2;
if (dst->box.y2 < box.y2)
box.y2 = dst->box.y2;
if (dst->box.x1 > box.x1)
box.x1 = dst->box.x1;
if (dst->box.y1 > box.y1)
box.y1 = dst->box.y1;
if (dst->box.x2 < box.x2)
box.x2 = dst->box.x2;
if (dst->box.y2 < box.y2)
box.y2 = dst->box.y2;
if (rects->x > box.x1)
box.x1 = rects->x;
if (rects->y > box.y1)
box.y1 = rects->y;
if (rects->x + rects->width < box.x2)
box.x2 = rects->x + rects->width;
if (rects->y + rects->height < box.y2)
box.y2 = rects->y + rects->height;
if (rects->x > box.x1)
box.x1 = rects->x;
if (rects->y > box.y1)
box.y1 = rects->y;
if (rects->x + rects->width < box.x2)
box.x2 = rects->x + rects->width;
if (rects->y + rects->height < box.y2)
box.y2 = rects->y + rects->height;
if (box.x1 < box.x2 && box.y1 < box.y2)
{
gl->scissor (box.x1,
target_height - dst->y - box.y2,
box.x2 - box.x1,
box.y2 - box.y1);
if (box.x1 < box.x2 && box.y1 < box.y2)
{
gl->scissor (box.x1,
dst->attached->height - dst->y - box.y2,
box.x2 - box.x1,
box.y2 - box.y1);
gl->clear (GLITZ_GL_COLOR_BUFFER_BIT);
gl->clear (GLITZ_GL_COLOR_BUFFER_BIT);
glitz_surface_damage (dst, &box,
GLITZ_DAMAGE_TEXTURE_MASK |
GLITZ_DAMAGE_SOLID_MASK);
}
glitz_surface_damage (dst, &box,
GLITZ_DAMAGE_TEXTURE_MASK |
GLITZ_DAMAGE_SOLID_MASK);
}
clip++;
}
rects++;
}
}
else
{
unsigned int pixel =
((((unsigned int) color->alpha * 0xff) / 0xffff) << 24) |
((((unsigned int) color->red * 0xff) / 0xffff) << 16) |
((((unsigned int) color->green * 0xff) / 0xffff) << 8) |
((((unsigned int) color->blue * 0xff) / 0xffff));
int x1, y1, x2, y2;
clip++;
}
rects++;
}
}
else
{
unsigned int pixel =
((((unsigned int) color->alpha * 0xff) / 0xffff) << 24) |
((((unsigned int) color->red * 0xff) / 0xffff) << 16) |
((((unsigned int) color->green * 0xff) / 0xffff) << 8) |
((((unsigned int) color->blue * 0xff) / 0xffff));
int x1, y1, x2, y2;
buffer = _glitz_minimum_buffer (dst, rects, n_rects, &pixel);
if (!buffer)
{
glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK);
return;
}
buffer = _glitz_minimum_buffer (dst, rects, n_rects, &pixel);
if (!buffer)
{
glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK);
return;
}
while (n_rects--)
{
x1 = rects->x;
y1 = rects->y;
x2 = x1 + rects->width;
y2 = y1 + rects->height;
while (n_rects--)
{
x1 = rects->x;
y1 = rects->y;
x2 = x1 + rects->width;
y2 = y1 + rects->height;
if (x1 < 0)
x1 = 0;
if (y1 < 0)
y1 = 0;
if (x2 > dst->box.x2)
x2 = dst->box.x2;
if (y2 > dst->box.y2)
y2 = dst->box.y2;
if (x1 < 0)
x1 = 0;
if (y1 < 0)
y1 = 0;
if (x2 > dst->box.x2)
x2 = dst->box.x2;
if (y2 > dst->box.y2)
y2 = dst->box.y2;
if (x1 < x2 && y1 < y2)
glitz_set_pixels (dst,
x1, y1,
x2 - x1, y2 - y1,
&pf, buffer);
if (x1 < x2 && y1 < y2)
glitz_set_pixels (dst,
x1, y1,
x2 - x1, y2 - y1,
&pf, buffer);
rects++;
}
rects++;
}
if (buffer)
glitz_buffer_destroy (buffer);
}
glitz_surface_pop_current (dst);
if (buffer)
glitz_buffer_destroy (buffer);
}
glitz_surface_pop_current (dst);
}
}
slim_hidden_def(glitz_set_rectangles);
void
glitz_set_rectangle (glitz_surface_t *dst,
const glitz_color_t *color,
int x,
int y,
unsigned int width,
unsigned int height)
const glitz_color_t *color,
int x,
int y,
unsigned int width,
unsigned int height)
{
glitz_rectangle_t rect;

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

@ -31,41 +31,41 @@
#define REGION_ALLOC_CHUNK 16
#define BOX_SUBSUMS_BOX(b1, b2) \
((b2)->x1 >= (b1)->x1 && \
(b2)->x2 <= (b1)->x2 && \
(b2)->y1 >= (b1)->y1 && \
(b2)->y2 <= (b1)->y2)
#define BOX_SUBSUMS_BOX(b1, b2) \
((b2)->x1 >= (b1)->x1 && \
(b2)->x2 <= (b1)->x2 && \
(b2)->y1 >= (b1)->y1 && \
(b2)->y2 <= (b1)->y2)
#define BOX_INTERSECTS_BOX(b1, b2) \
((b1)->x1 < (b2)->x2 && \
(b1)->x2 > (b2)->x1 && \
(b1)->y1 < (b2)->y2 && \
(b1)->y2 > (b2)->y1)
#define BOX_INTERSECTS_BOX(b1, b2) \
((b1)->x1 < (b2)->x2 && \
(b1)->x2 > (b2)->x1 && \
(b1)->y1 < (b2)->y2 && \
(b1)->y2 > (b2)->y1)
#define BOX_CLOSE_TO_BOX(b1, b2) \
((b1)->x1 < ((b2)->x2 + 1) && \
(b1)->x2 > ((b2)->x1 - 1) && \
(b1)->y1 < ((b2)->y2 + 1) && \
(b1)->y2 > ((b2)->y1 - 1))
#define BOX_CLOSE_TO_BOX(b1, b2) \
((b1)->x1 < ((b2)->x2 + 1) && \
(b1)->x2 > ((b2)->x1 - 1) && \
(b1)->y1 < ((b2)->y2 + 1) && \
(b1)->y2 > ((b2)->y1 - 1))
#define BOX_NEXT_TO_BOX(b1, b2) \
((((b1)->x1 == (b2)->x2 || \
(b1)->x2 == (b2)->x1) && \
(b1)->y1 == (b2)->y1 && \
(b1)->y2 == (b2)->y2) || \
(((b1)->y1 == (b2)->y2 || \
(b1)->y2 == (b2)->y1) && \
(b1)->x1 == (b2)->x1 && \
(b1)->x2 == (b2)->x2))
#define BOX_NEXT_TO_BOX(b1, b2) \
((((b1)->x1 == (b2)->x2 || \
(b1)->x2 == (b2)->x1) && \
(b1)->y1 == (b2)->y1 && \
(b1)->y2 == (b2)->y2) || \
(((b1)->y1 == (b2)->y2 || \
(b1)->y2 == (b2)->y1) && \
(b1)->x1 == (b2)->x1 && \
(b1)->x2 == (b2)->x2))
#define MERGE_BOXES(d, b1, b2) \
{ \
(d)->x1 = MIN ((b1)->x1, (b2)->x1); \
(d)->y1 = MIN ((b1)->y1, (b2)->y1); \
(d)->x2 = MAX ((b1)->x2, (b2)->x2); \
(d)->y2 = MAX ((b1)->y2, (b2)->y2); \
}
#define MERGE_BOXES(d, b1, b2) \
{ \
(d)->x1 = MIN ((b1)->x1, (b2)->x1); \
(d)->y1 = MIN ((b1)->y1, (b2)->y1); \
(d)->x2 = MAX ((b1)->x2, (b2)->x2); \
(d)->y2 = MAX ((b1)->y2, (b2)->y2); \
}
/*
* No real union, boxes that intersect are just joined into bigger boxes.
@ -74,93 +74,94 @@
*/
glitz_status_t
glitz_region_union (glitz_region_t *region,
glitz_box_t *ubox)
glitz_box_t *ubox)
{
if (region->n_box == 0) {
region->extents = *ubox;
region->box = &region->extents;
region->n_box = 1;
if (region->n_box == 0) {
region->extents = *ubox;
region->box = &region->extents;
region->n_box = 1;
return GLITZ_STATUS_SUCCESS;
}
if (BOX_CLOSE_TO_BOX (ubox, &region->extents)) {
glitz_box_t *box, *new_box, *dst_box;
int n_box;
box = region->box;
n_box = region->n_box;
while (n_box--) {
if (BOX_SUBSUMS_BOX (box, ubox))
return GLITZ_STATUS_SUCCESS;
box++;
}
box = region->box;
n_box = region->n_box;
new_box = ubox;
dst_box = NULL;
while (n_box--) {
if (BOX_INTERSECTS_BOX (box, new_box) ||
BOX_NEXT_TO_BOX (box, new_box)) {
if (dst_box) {
/*
* Remove box from region
*/
region->n_box--;
if (region->n_box == 1) {
MERGE_BOXES (&region->extents, box, new_box);
region->box = &region->extents;
return GLITZ_STATUS_SUCCESS;
} else {
MERGE_BOXES (dst_box, box, new_box);
if (n_box)
memmove (box, box + 1,
n_box * sizeof (glitz_box_t));
}
continue;
} else {
dst_box = box;
MERGE_BOXES (dst_box, box, new_box);
new_box = dst_box;
}
}
box++;
}
if (dst_box) {
if (region->n_box > 1)
MERGE_BOXES (&region->extents, &region->extents, ubox);
return GLITZ_STATUS_SUCCESS;
}
}
/*
* Add box to region
*/
if (region->size < (region->n_box + 1)) {
region->size += REGION_ALLOC_CHUNK;
region->data = (void *) realloc (region->data,
sizeof (glitz_box_t) * region->size);
if (!region->data)
return GLITZ_STATUS_NO_MEMORY;
}
region->box = (glitz_box_t *) region->data;
region->box[region->n_box] = *ubox;
if (region->n_box == 1)
region->box[0] = region->extents;
region->n_box++;
MERGE_BOXES (&region->extents, &region->extents, ubox);
return GLITZ_STATUS_SUCCESS;
}
if (BOX_CLOSE_TO_BOX (ubox, &region->extents)) {
glitz_box_t *box, *new_box, *dst_box;
int n_box;
box = region->box;
n_box = region->n_box;
while (n_box--) {
if (BOX_SUBSUMS_BOX (box, ubox))
return GLITZ_STATUS_SUCCESS;
box++;
}
box = region->box;
n_box = region->n_box;
new_box = ubox;
dst_box = NULL;
while (n_box--) {
if (BOX_INTERSECTS_BOX (box, new_box) ||
BOX_NEXT_TO_BOX (box, new_box)) {
if (dst_box) {
/*
* Remove box from region
*/
region->n_box--;
if (region->n_box == 1) {
MERGE_BOXES (&region->extents, box, new_box);
region->box = &region->extents;
return GLITZ_STATUS_SUCCESS;
} else {
MERGE_BOXES (dst_box, box, new_box);
if (n_box)
memmove (box, box + 1, n_box * sizeof (glitz_box_t));
}
continue;
} else {
dst_box = box;
MERGE_BOXES (dst_box, box, new_box);
new_box = dst_box;
}
}
box++;
}
if (dst_box) {
if (region->n_box > 1)
MERGE_BOXES (&region->extents, &region->extents, ubox);
return GLITZ_STATUS_SUCCESS;
}
}
/*
* Add box to region
*/
if (region->size < (region->n_box + 1)) {
region->size += REGION_ALLOC_CHUNK;
region->data = (void *) realloc (region->data,
sizeof (glitz_box_t) * region->size);
if (!region->data)
return GLITZ_STATUS_NO_MEMORY;
}
region->box = (glitz_box_t *) region->data;
region->box[region->n_box] = *ubox;
if (region->n_box == 1)
region->box[0] = region->extents;
region->n_box++;
MERGE_BOXES (&region->extents, &region->extents, ubox);
return GLITZ_STATUS_SUCCESS;
}

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

@ -34,57 +34,57 @@
unsigned long
glitz_status_to_status_mask (glitz_status_t status)
{
switch (status) {
case GLITZ_STATUS_NO_MEMORY:
return GLITZ_STATUS_NO_MEMORY_MASK;
case GLITZ_STATUS_BAD_COORDINATE:
return GLITZ_STATUS_BAD_COORDINATE_MASK;
case GLITZ_STATUS_NOT_SUPPORTED:
return GLITZ_STATUS_NOT_SUPPORTED_MASK;
case GLITZ_STATUS_CONTENT_DESTROYED:
return GLITZ_STATUS_CONTENT_DESTROYED_MASK;
case GLITZ_STATUS_SUCCESS:
break;
}
switch (status) {
case GLITZ_STATUS_NO_MEMORY:
return GLITZ_STATUS_NO_MEMORY_MASK;
case GLITZ_STATUS_BAD_COORDINATE:
return GLITZ_STATUS_BAD_COORDINATE_MASK;
case GLITZ_STATUS_NOT_SUPPORTED:
return GLITZ_STATUS_NOT_SUPPORTED_MASK;
case GLITZ_STATUS_CONTENT_DESTROYED:
return GLITZ_STATUS_CONTENT_DESTROYED_MASK;
case GLITZ_STATUS_SUCCESS:
break;
}
return 0;
return 0;
}
glitz_status_t
glitz_status_pop_from_mask (unsigned long *mask)
{
if (*mask & GLITZ_STATUS_NO_MEMORY_MASK) {
*mask &= ~GLITZ_STATUS_NO_MEMORY_MASK;
return GLITZ_STATUS_NO_MEMORY;
} else if (*mask & GLITZ_STATUS_BAD_COORDINATE_MASK) {
*mask &= ~GLITZ_STATUS_BAD_COORDINATE_MASK;
return GLITZ_STATUS_BAD_COORDINATE;
} else if (*mask & GLITZ_STATUS_NOT_SUPPORTED_MASK) {
*mask &= ~GLITZ_STATUS_NOT_SUPPORTED_MASK;
return GLITZ_STATUS_NOT_SUPPORTED;
} else if (*mask & GLITZ_STATUS_CONTENT_DESTROYED_MASK) {
*mask &= ~GLITZ_STATUS_CONTENT_DESTROYED_MASK;
return GLITZ_STATUS_CONTENT_DESTROYED;
}
if (*mask & GLITZ_STATUS_NO_MEMORY_MASK) {
*mask &= ~GLITZ_STATUS_NO_MEMORY_MASK;
return GLITZ_STATUS_NO_MEMORY;
} else if (*mask & GLITZ_STATUS_BAD_COORDINATE_MASK) {
*mask &= ~GLITZ_STATUS_BAD_COORDINATE_MASK;
return GLITZ_STATUS_BAD_COORDINATE;
} else if (*mask & GLITZ_STATUS_NOT_SUPPORTED_MASK) {
*mask &= ~GLITZ_STATUS_NOT_SUPPORTED_MASK;
return GLITZ_STATUS_NOT_SUPPORTED;
} else if (*mask & GLITZ_STATUS_CONTENT_DESTROYED_MASK) {
*mask &= ~GLITZ_STATUS_CONTENT_DESTROYED_MASK;
return GLITZ_STATUS_CONTENT_DESTROYED;
}
return GLITZ_STATUS_SUCCESS;
return GLITZ_STATUS_SUCCESS;
}
const char *
glitz_status_string (glitz_status_t status)
{
switch (status) {
case GLITZ_STATUS_SUCCESS:
return "success";
case GLITZ_STATUS_NO_MEMORY:
return "out of memory";
case GLITZ_STATUS_BAD_COORDINATE:
return "bad coordinate";
case GLITZ_STATUS_NOT_SUPPORTED:
return "not supported";
case GLITZ_STATUS_CONTENT_DESTROYED:
return "content destroyed";
}
switch (status) {
case GLITZ_STATUS_SUCCESS:
return "success";
case GLITZ_STATUS_NO_MEMORY:
return "out of memory";
case GLITZ_STATUS_BAD_COORDINATE:
return "bad coordinate";
case GLITZ_STATUS_NOT_SUPPORTED:
return "not supported";
case GLITZ_STATUS_CONTENT_DESTROYED:
return "content destroyed";
}
return "<unknown error status>";
return "<unknown error status>";
}

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

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

@ -31,317 +31,444 @@
void
glitz_texture_init (glitz_texture_t *texture,
int width,
int height,
glitz_gl_int_t texture_format,
unsigned long feature_mask,
glitz_bool_t unnormalized)
int width,
int height,
glitz_gl_int_t texture_format,
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;
if (feature_mask & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)
{
texture->box.x1 = texture->box.y1 = 0;
texture->box.x2 = texture->width = width;
texture->box.y2 = texture->height = height;
texture->flags = GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
GLITZ_TEXTURE_FLAG_PADABLE_MASK;
texture->box.x1 = texture->box.y1 = 0;
texture->box.x2 = texture->width = width;
texture->box.y2 = texture->height = height;
texture->flags = GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
GLITZ_TEXTURE_FLAG_PADABLE_MASK;
}
else
{
texture->box.x1 = texture->box.y1 = 1;
texture->box.x2 = width + 1;
texture->box.y2 = height + 1;
texture->width = width + 2;
texture->height = height + 2;
texture->flags = 0;
texture->box.x1 = texture->box.y1 = 1;
texture->box.x2 = width + 1;
texture->box.y2 = height + 1;
texture->width = width + 2;
texture->height = height + 2;
texture->flags = 0;
}
if (!unnormalized &&
((feature_mask & GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK) ||
(POWER_OF_TWO (texture->width) && POWER_OF_TWO (texture->height))))
((feature_mask & GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK) ||
(POWER_OF_TWO (texture->width) && POWER_OF_TWO (texture->height))))
{
texture->target = GLITZ_GL_TEXTURE_2D;
texture->target = GLITZ_GL_TEXTURE_2D;
}
else
{
texture->flags &= ~GLITZ_TEXTURE_FLAG_REPEATABLE_MASK;
texture->flags &= ~GLITZ_TEXTURE_FLAG_REPEATABLE_MASK;
if (feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK)
{
texture->target = GLITZ_GL_TEXTURE_RECTANGLE;
}
else
{
texture->target = GLITZ_GL_TEXTURE_2D;
texture->flags &= ~GLITZ_TEXTURE_FLAG_PADABLE_MASK;
if (feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK)
{
texture->target = GLITZ_GL_TEXTURE_RECTANGLE;
}
else
{
texture->target = GLITZ_GL_TEXTURE_2D;
texture->flags &= ~GLITZ_TEXTURE_FLAG_PADABLE_MASK;
if (!POWER_OF_TWO (texture->width))
texture->width = glitz_uint_to_power_of_two (texture->width);
if (!POWER_OF_TWO (texture->width))
texture->width = glitz_uint_to_power_of_two (texture->width);
if (!POWER_OF_TWO (texture->height))
texture->height = glitz_uint_to_power_of_two (texture->height);
}
if (!POWER_OF_TWO (texture->height))
texture->height = glitz_uint_to_power_of_two (texture->height);
}
}
if (texture->target == GLITZ_GL_TEXTURE_2D)
{
texture->texcoord_width_unit = 1.0f / texture->width;
texture->texcoord_height_unit = 1.0f / texture->height;
texture->texcoord_width_unit = 1.0f / texture->width;
texture->texcoord_height_unit = 1.0f / texture->height;
}
else
{
texture->texcoord_width_unit = 1.0f;
texture->texcoord_height_unit = 1.0f;
texture->texcoord_width_unit = 1.0f;
texture->texcoord_height_unit = 1.0f;
}
}
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_enum_t proxy_target;
glitz_gl_int_t value, max;
glitz_texture_t *texture,
glitz_gl_int_t max_2d,
glitz_gl_int_t max_rect)
{
glitz_gl_enum_t proxy_target;
glitz_gl_int_t value, max;
if (texture->target == GLITZ_GL_TEXTURE_2D) {
max = max_2d;
proxy_target = GLITZ_GL_PROXY_TEXTURE_2D;
} else {
max = max_rect;
proxy_target = GLITZ_GL_PROXY_TEXTURE_RECTANGLE;
}
if (texture->target == GLITZ_GL_TEXTURE_2D) {
max = max_2d;
proxy_target = GLITZ_GL_PROXY_TEXTURE_2D;
} else {
max = max_rect;
proxy_target = GLITZ_GL_PROXY_TEXTURE_RECTANGLE;
}
if (texture->width > max || texture->height > max) {
texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK;
return;
}
if (texture->width > max || texture->height > max) {
texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK;
return;
}
gl->tex_image_2d (proxy_target, 0,
texture->format, texture->width, texture->height,
0, GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
gl->get_tex_level_parameter_iv (proxy_target, 0,
GLITZ_GL_TEXTURE_WIDTH, &value);
if (value != texture->width) {
texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK;
return;
}
gl->tex_image_2d (proxy_target, 0,
texture->format, texture->width, texture->height,
0, GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
gl->get_tex_level_parameter_iv (proxy_target, 0,
GLITZ_GL_TEXTURE_WIDTH, &value);
if (value != texture->width) {
texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK;
return;
}
gl->get_tex_level_parameter_iv (proxy_target, 0,
GLITZ_GL_TEXTURE_HEIGHT, &value);
if (value != texture->height)
texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK;
gl->get_tex_level_parameter_iv (proxy_target, 0,
GLITZ_GL_TEXTURE_HEIGHT, &value);
if (value != texture->height)
texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK;
}
void
glitz_texture_allocate (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture)
glitz_texture_t *texture)
{
char *data = NULL;
char *data = NULL;
if (!texture->name)
gl->gen_textures (1, &texture->name);
if (!texture->name)
gl->gen_textures (1, &texture->name);
texture->flags |= GLITZ_TEXTURE_FLAG_ALLOCATED_MASK;
texture->flags |= GLITZ_TEXTURE_FLAG_ALLOCATED_MASK;
glitz_texture_bind (gl, texture);
glitz_texture_bind (gl, texture);
if (texture->box.x2 != texture->width ||
texture->box.y2 != texture->height) {
data = malloc (texture->width * texture->height);
if (data)
memset (data, 0, texture->width * texture->height);
gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
}
gl->tex_image_2d (texture->target, 0, texture->format,
texture->width, texture->height, 0,
GLITZ_GL_ALPHA, GLITZ_GL_UNSIGNED_BYTE, data);
gl->tex_parameter_i (texture->target,
GLITZ_GL_TEXTURE_MAG_FILTER,
texture->param.filter[0]);
gl->tex_parameter_i (texture->target,
GLITZ_GL_TEXTURE_MIN_FILTER,
texture->param.filter[1]);
glitz_texture_unbind (gl, texture);
if (texture->box.x2 != texture->width ||
texture->box.y2 != texture->height) {
data = malloc (texture->width * texture->height);
if (data)
memset (data, 0, texture->width * texture->height);
gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
}
gl->tex_image_2d (texture->target, 0, texture->format,
texture->width, texture->height, 0,
GLITZ_GL_ALPHA, GLITZ_GL_UNSIGNED_BYTE, data);
gl->tex_parameter_i (texture->target,
GLITZ_GL_TEXTURE_MAG_FILTER,
GLITZ_GL_NEAREST);
gl->tex_parameter_i (texture->target,
GLITZ_GL_TEXTURE_MIN_FILTER,
GLITZ_GL_NEAREST);
texture->filter = GLITZ_GL_NEAREST;
glitz_texture_unbind (gl, texture);
if (data)
free (data);
free (data);
}
void
glitz_texture_fini (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture)
glitz_texture_t *texture)
{
if (texture->name)
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;
}
if (texture->name)
gl->delete_textures (1, &texture->name);
}
void
glitz_texture_bind (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture)
glitz_texture_t *texture)
{
gl->disable (GLITZ_GL_TEXTURE_RECTANGLE);
gl->disable (GLITZ_GL_TEXTURE_2D);
gl->disable (GLITZ_GL_TEXTURE_RECTANGLE);
gl->disable (GLITZ_GL_TEXTURE_2D);
if (!texture->name)
return;
if (!texture->name)
return;
gl->enable (texture->target);
gl->bind_texture (texture->target, texture->name);
gl->enable (texture->target);
gl->bind_texture (texture->target, texture->name);
}
void
glitz_texture_unbind (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture)
glitz_texture_t *texture)
{
gl->bind_texture (texture->target, 0);
gl->disable (texture->target);
gl->bind_texture (texture->target, 0);
gl->disable (texture->target);
}
void
glitz_texture_copy_drawable (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture,
glitz_drawable_t *drawable,
int x_drawable,
int y_drawable,
int width,
int height,
int x_texture,
int y_texture)
glitz_texture_t *texture,
glitz_drawable_t *drawable,
int x_drawable,
int y_drawable,
int width,
int height,
int x_texture,
int y_texture)
{
gl->copy_tex_sub_image_2d (texture->target, 0,
texture->box.x1 + x_texture,
texture->box.y2 - y_texture - height,
x_drawable,
drawable->height - y_drawable - height,
width, height);
gl->copy_tex_sub_image_2d (texture->target, 0,
texture->box.x1 + x_texture,
texture->box.y2 - y_texture - height,
x_drawable,
drawable->height - y_drawable - height,
width, height);
}
void
glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture,
glitz_geometry_t *geometry,
int x_src,
int y_src,
unsigned long flags,
glitz_int_coordinate_t *coord)
glitz_texture_t *texture,
glitz_geometry_t *geometry,
int x_src,
int y_src,
unsigned long flags,
glitz_int_coordinate_t *coord)
{
glitz_vec4_t plane;
if (flags & GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK)
{
plane.v[1] = plane.v[2] = 0.0f;
plane.v[1] = plane.v[2] = 0.0f;
if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK)
{
plane.v[0] = 1.0f;
plane.v[3] = -x_src;
}
else
{
plane.v[0] = texture->texcoord_width_unit;
if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK)
{
plane.v[0] = 1.0f;
plane.v[3] = -x_src;
}
else
{
plane.v[0] = texture->texcoord_width_unit;
if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK)
plane.v[3] = -(x_src) * texture->texcoord_width_unit;
else
plane.v[3] = -(x_src - texture->box.x1) *
texture->texcoord_width_unit;
}
if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK)
plane.v[3] = -(x_src) * texture->texcoord_width_unit;
else
plane.v[3] = -(x_src - texture->box.x1) *
texture->texcoord_width_unit;
}
gl->tex_gen_i (GLITZ_GL_S, GLITZ_GL_TEXTURE_GEN_MODE,
GLITZ_GL_EYE_LINEAR);
gl->tex_gen_fv (GLITZ_GL_S, GLITZ_GL_EYE_PLANE, plane.v);
gl->tex_gen_i (GLITZ_GL_S, GLITZ_GL_TEXTURE_GEN_MODE,
GLITZ_GL_EYE_LINEAR);
gl->tex_gen_fv (GLITZ_GL_S, GLITZ_GL_EYE_PLANE, plane.v);
gl->enable (GLITZ_GL_TEXTURE_GEN_S);
gl->enable (GLITZ_GL_TEXTURE_GEN_S);
}
else
gl->disable (GLITZ_GL_TEXTURE_GEN_S);
gl->disable (GLITZ_GL_TEXTURE_GEN_S);
if (flags & GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK)
{
plane.v[0] = plane.v[2] = 0.0f;
if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK)
{
plane.v[1] = 1.0f;
plane.v[3] = -y_src;
}
else
{
plane.v[1] = -texture->texcoord_height_unit;
plane.v[0] = plane.v[2] = 0.0f;
if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK)
{
plane.v[1] = 1.0f;
plane.v[3] = -y_src;
}
else
{
plane.v[1] = -texture->texcoord_height_unit;
if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK)
plane.v[3] = (y_src + texture->box.y2 - texture->box.y1) *
texture->texcoord_height_unit;
else
plane.v[3] = (y_src + texture->box.y2) *
texture->texcoord_height_unit;
}
if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK)
plane.v[3] = (y_src + texture->box.y2 - texture->box.y1) *
texture->texcoord_height_unit;
else
plane.v[3] = (y_src + texture->box.y2) *
texture->texcoord_height_unit;
}
gl->tex_gen_i (GLITZ_GL_T, GLITZ_GL_TEXTURE_GEN_MODE,
GLITZ_GL_EYE_LINEAR);
gl->tex_gen_fv (GLITZ_GL_T, GLITZ_GL_EYE_PLANE, plane.v);
gl->tex_gen_i (GLITZ_GL_T, GLITZ_GL_TEXTURE_GEN_MODE,
GLITZ_GL_EYE_LINEAR);
gl->tex_gen_fv (GLITZ_GL_T, GLITZ_GL_EYE_PLANE, plane.v);
gl->enable (GLITZ_GL_TEXTURE_GEN_T);
gl->enable (GLITZ_GL_TEXTURE_GEN_T);
}
else
gl->disable (GLITZ_GL_TEXTURE_GEN_T);
gl->disable (GLITZ_GL_TEXTURE_GEN_T);
if (!(flags & GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK))
{
unsigned char *ptr;
unsigned char *ptr;
gl->enable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY);
gl->enable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY);
ptr = glitz_buffer_bind (geometry->buffer, GLITZ_GL_ARRAY_BUFFER);
ptr += coord->offset;
ptr = glitz_buffer_bind (geometry->buffer, GLITZ_GL_ARRAY_BUFFER);
ptr += coord->offset;
gl->tex_coord_pointer (coord->size,
coord->type,
geometry->stride,
(void *) ptr);
gl->tex_coord_pointer (coord->size,
coord->type,
geometry->stride,
(void *) ptr);
} else
gl->disable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY);
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;
}

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

@ -30,9 +30,9 @@
#include "glitzint.h"
/* whether 't' is a well defined not obviously empty trapezoid */
#define TRAPEZOID_VALID(t) ((t)->left.p1.y != (t)->left.p2.y && \
(t)->right.p1.y != (t)->right.p2.y && \
(int) ((t)->bottom - (t)->top) > 0)
#define TRAPEZOID_VALID(t) ((t)->left.p1.y != (t)->left.p2.y && \
(t)->right.p1.y != (t)->right.p2.y && \
(int) ((t)->bottom - (t)->top) > 0)
/* whether 't' is a well defined not obviously empty trap */
#define TRAP_VALID(t) ((int) ((t)->bottom.y - (t)->top.y) > 0)
@ -46,57 +46,57 @@ typedef struct _glitz_edge {
int hyp;
} glitz_edge_t;
#define EDGE_INIT(e, p1x, p1y, p2x, p2y) \
(e)->hyp = 1; \
(e)->dx = (p2x) - (p1x); \
(e)->dy = (p2y) - (p1y); \
if ((e)->dy) \
(e)->kx = (e)->dx / (e)->dy; \
else \
(e)->kx = 0; \
(e)->x0 = (p1x) - (e)->kx * (p1y); \
if ((e)->dx) \
(e)->ky = (e)->dy / (e)->dx; \
else \
(e)->ky = 0; \
#define EDGE_INIT(e, p1x, p1y, p2x, p2y) \
(e)->hyp = 1; \
(e)->dx = (p2x) - (p1x); \
(e)->dy = (p2y) - (p1y); \
if ((e)->dy) \
(e)->kx = (e)->dx / (e)->dy; \
else \
(e)->kx = 0; \
(e)->x0 = (p1x) - (e)->kx * (p1y); \
if ((e)->dx) \
(e)->ky = (e)->dy / (e)->dx; \
else \
(e)->ky = 0; \
(e)->y0 = (p1y) - (e)->ky * (p1x)
#define EDGE_X(e, _y) (((e)->kx * (_y)) + (e)->x0)
#define EDGE_Y(e, _x) (((e)->ky * (_x)) + (e)->y0)
#define EDGE_INTERSECT_BOX(upper_x, lower_y, left_y, right_y, \
box_x1, box_x2, box_y1, box_y2, \
max_x, max_y, \
_x1, _y1, _x2, _y2) \
if (upper_x < (box_x1)) \
{ \
(_x1) = 0.0f; \
(_y1) = (left_y) - (box_y1); \
} \
else if ((upper_x) > (box_x2)) \
{ \
(_x1) = (max_x); \
(_y1) = (right_y) - (box_y1); \
} \
else \
{ \
(_x1) = (upper_x) - (box_x1); \
(_y1) = 0.0f; \
} \
if ((lower_x) < (box_x1)) \
{ \
(_x2) = 0.0f; \
(_y2) = (left_y) - (box_y1); \
} \
else if ((lower_x) > (box_x2)) \
{ \
(_x2) = (max_x); \
(_y2) = (right_y) - (box_y1); \
} \
else \
{ \
(_x2) = (lower_x) - (box_x1); \
(_y2) = (max_y); \
#define EDGE_INTERSECT_BOX(upper_x, lower_y, left_y, right_y, \
box_x1, box_x2, box_y1, box_y2, \
max_x, max_y, \
_x1, _y1, _x2, _y2) \
if (upper_x < (box_x1)) \
{ \
(_x1) = 0.0f; \
(_y1) = (left_y) - (box_y1); \
} \
else if ((upper_x) > (box_x2)) \
{ \
(_x1) = (max_x); \
(_y1) = (right_y) - (box_y1); \
} \
else \
{ \
(_x1) = (upper_x) - (box_x1); \
(_y1) = 0.0f; \
} \
if ((lower_x) < (box_x1)) \
{ \
(_x2) = 0.0f; \
(_y2) = (left_y) - (box_y1); \
} \
else if ((lower_x) > (box_x2)) \
{ \
(_x2) = (max_x); \
(_y2) = (right_y) - (box_y1); \
} \
else \
{ \
(_x2) = (lower_x) - (box_x1); \
(_y2) = (max_y); \
}
#define AREA_ABOVE_LEFT(x1, y1, x2, y2, bottom) \
@ -110,11 +110,11 @@ typedef struct _glitz_edge {
*/
static glitz_float_t
_glitz_pixel_area (glitz_float_t pixel_x,
glitz_float_t pixel_y,
glitz_float_t top,
glitz_float_t bottom,
glitz_edge_t *left,
glitz_edge_t *right)
glitz_float_t pixel_y,
glitz_float_t top,
glitz_float_t bottom,
glitz_edge_t *left,
glitz_edge_t *right)
{
glitz_float_t area;
glitz_float_t upper_x, lower_x;
@ -124,117 +124,117 @@ _glitz_pixel_area (glitz_float_t pixel_x,
glitz_float_t x1, x2, y1, y2;
if (bottom >= pixel_y_1)
bottom = 1.0f;
bottom = 1.0f;
else
bottom = bottom - pixel_y;
bottom = bottom - pixel_y;
if (top <= pixel_y)
top = 0.0f;
top = 0.0f;
else
top = top - pixel_y;
top = top - pixel_y;
if (right->ky)
{
upper_x = EDGE_X (right, pixel_y);
lower_x = EDGE_X (right, pixel_y_1);
upper_x = EDGE_X (right, pixel_y);
lower_x = EDGE_X (right, pixel_y_1);
left_y = EDGE_Y (right, pixel_x);
right_y = EDGE_Y (right, pixel_x_1);
left_y = EDGE_Y (right, pixel_x);
right_y = EDGE_Y (right, pixel_x_1);
EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y,
pixel_x, pixel_x_1, pixel_y, pixel_y_1,
1.0f, 1.0f, x1, y1, x2, y2);
EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y,
pixel_x, pixel_x_1, pixel_y, pixel_y_1,
1.0f, 1.0f, x1, y1, x2, y2);
if (bottom <= y1)
{
if (left_y > right_y)
area = bottom;
else
area = 0.0f;
}
else
{
if (bottom < y2)
{
x2 -= right->kx * (y2 - bottom);
y2 = bottom;
}
area = AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom);
}
if (bottom <= y1)
{
if (left_y > right_y)
area = bottom;
else
area = 0.0f;
}
else
{
if (bottom < y2)
{
x2 -= right->kx * (y2 - bottom);
y2 = bottom;
}
area = AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom);
}
if (top <= y1)
{
if (left_y > right_y)
area -= top;
}
else
{
if (top < y2)
{
x2 -= right->kx * (y2 - top);
y2 = top;
}
if (top <= y1)
{
if (left_y > right_y)
area -= top;
}
else
{
if (top < y2)
{
x2 -= right->kx * (y2 - top);
y2 = top;
}
area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, top);
}
area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, top);
}
}
else
{
/* Vertical Edge */
if (right->x0 < pixel_x_1)
area = (right->x0 - pixel_x) * (bottom - top);
else
area = bottom - top;
/* Vertical Edge */
if (right->x0 < pixel_x_1)
area = (right->x0 - pixel_x) * (bottom - top);
else
area = bottom - top;
}
if (left->kx)
{
upper_x = EDGE_X (left, pixel_y);
lower_x = EDGE_X (left, pixel_y_1);
upper_x = EDGE_X (left, pixel_y);
lower_x = EDGE_X (left, pixel_y_1);
left_y = EDGE_Y (left, pixel_x);
right_y = EDGE_Y (left, pixel_x_1);
left_y = EDGE_Y (left, pixel_x);
right_y = EDGE_Y (left, pixel_x_1);
EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y,
pixel_x, pixel_x_1, pixel_y, pixel_y_1,
1.0f, 1.0f, x1, y1, x2, y2);
EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y,
pixel_x, pixel_x_1, pixel_y, pixel_y_1,
1.0f, 1.0f, x1, y1, x2, y2);
if (bottom <= y1)
{
if (left_y > right_y)
area -= bottom;
}
else
{
if (bottom < y2)
{
x2 -= left->kx * (y2 - bottom);
y2 = bottom;
}
area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom);
}
if (bottom <= y1)
{
if (left_y > right_y)
area -= bottom;
}
else
{
if (bottom < y2)
{
x2 -= left->kx * (y2 - bottom);
y2 = bottom;
}
area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom);
}
if (top <= y1)
{
if (left_y > right_y)
area += top;
}
else
{
if (top < y2)
{
x2 -= left->kx * (y2 - top);
y2 = top;
}
if (top <= y1)
{
if (left_y > right_y)
area += top;
}
else
{
if (top < y2)
{
x2 -= left->kx * (y2 - top);
y2 = top;
}
area += AREA_ABOVE_LEFT (x1, y1, x2, y2, top);
}
area += AREA_ABOVE_LEFT (x1, y1, x2, y2, top);
}
}
else
{
/* Vertical Edge */
if (left->x0 > pixel_x)
area -= (left->x0 - pixel_x) * (bottom - top);
/* Vertical Edge */
if (left->x0 > pixel_x)
area -= (left->x0 - pixel_x) * (bottom - top);
}
return area;
@ -242,40 +242,40 @@ _glitz_pixel_area (glitz_float_t pixel_x,
#define TRAPINIT(trap, _top, _bottom, _left, _right) \
if (!TRAPEZOID_VALID (trap)) \
continue; \
\
continue; \
\
(_top) = FIXED_TO_FLOAT ((trap)->top); \
(_bottom) = FIXED_TO_FLOAT ((trap)->bottom); \
\
\
(_left)->tx = FIXED_TO_FLOAT ((trap)->left.p1.x); \
(_left)->bx = FIXED_TO_FLOAT ((trap)->left.p1.y); \
\
\
(_right)->tx = FIXED_TO_FLOAT ((trap)->right.p1.x); \
(_right)->bx = FIXED_TO_FLOAT ((trap)->right.p1.y); \
\
\
EDGE_INIT (_left, \
(_left)->tx, (_left)->bx, \
FIXED_TO_FLOAT ((trap)->left.p2.x), \
FIXED_TO_FLOAT ((trap)->left.p2.y)); \
\
(_left)->tx, (_left)->bx, \
FIXED_TO_FLOAT ((trap)->left.p2.x), \
FIXED_TO_FLOAT ((trap)->left.p2.y)); \
\
EDGE_INIT (_right, \
(_right)->tx, (_right)->bx, \
FIXED_TO_FLOAT ((trap)->right.p2.x), \
FIXED_TO_FLOAT ((trap)->right.p2.y)); \
\
(_right)->tx, (_right)->bx, \
FIXED_TO_FLOAT ((trap)->right.p2.x), \
FIXED_TO_FLOAT ((trap)->right.p2.y)); \
\
if ((_left)->dx) \
{ \
(_left)->tx = EDGE_X (_left, _top); \
(_left)->bx = EDGE_X (_left, _bottom); \
(_left)->tx = EDGE_X (_left, _top); \
(_left)->bx = EDGE_X (_left, _bottom); \
} else \
(_left)->tx = (_left)->bx = (_left)->x0; \
\
(_left)->tx = (_left)->bx = (_left)->x0; \
\
if ((_right)->dx) \
{ \
(_right)->tx = EDGE_X (_right, _top); \
(_right)->bx = EDGE_X (_right, _bottom); \
(_right)->tx = EDGE_X (_right, _top); \
(_right)->bx = EDGE_X (_right, _bottom); \
} else \
(_right)->tx = (_right)->bx = (_right)->x0
(_right)->tx = (_right)->bx = (_right)->x0
#define TRAP glitz_trapezoid_t
@ -306,26 +306,26 @@ _glitz_pixel_area (glitz_float_t pixel_x,
#undef TRAP
#undef TRAPINIT
#define TRAPINIT(trap, _top, _bottom, _left, _right) \
if (!TRAP_VALID (trap)) \
continue; \
\
(_top) = FIXED_TO_FLOAT ((trap)->top.y); \
(_bottom) = FIXED_TO_FLOAT ((trap)->bottom.y); \
\
(_left)->tx = FIXED_TO_FLOAT ((trap)->top.left); \
(_left)->bx = FIXED_TO_FLOAT ((trap)->bottom.left); \
\
(_right)->tx = FIXED_TO_FLOAT ((trap)->top.right); \
(_right)->bx = FIXED_TO_FLOAT ((trap)->bottom.right); \
\
EDGE_INIT (_left, \
(_left)->tx, _top, \
(_left)->bx, _bottom); \
\
EDGE_INIT (_right, \
(_right)->tx, _top, \
(_right)->bx, _bottom)
#define TRAPINIT(trap, _top, _bottom, _left, _right) \
if (!TRAP_VALID (trap)) \
continue; \
\
(_top) = FIXED_TO_FLOAT ((trap)->top.y); \
(_bottom) = FIXED_TO_FLOAT ((trap)->bottom.y); \
\
(_left)->tx = FIXED_TO_FLOAT ((trap)->top.left); \
(_left)->bx = FIXED_TO_FLOAT ((trap)->bottom.left); \
\
(_right)->tx = FIXED_TO_FLOAT ((trap)->top.right); \
(_right)->bx = FIXED_TO_FLOAT ((trap)->bottom.right); \
\
EDGE_INIT (_left, \
(_left)->tx, _top, \
(_left)->bx, _bottom); \
\
EDGE_INIT (_right, \
(_right)->tx, _top, \
(_right)->bx, _bottom)
#define TRAP glitz_trap_t
@ -358,58 +358,13 @@ _glitz_pixel_area (glitz_float_t pixel_x,
int
glitz_add_trapezoids (glitz_buffer_t *buffer,
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trapezoid_t *traps,
int n_traps,
int *n_added)
{
int count, n = n_traps;
uint8_t *ptr;
*n_added = 0;
ptr = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY);
if (!ptr)
return 0;
ptr += offset;
switch (type) {
case GLITZ_DATA_TYPE_SHORT:
count = _glitz_add_trapezoids_short (ptr, size, mask, traps, &n_traps);
break;
case GLITZ_DATA_TYPE_INT:
count = _glitz_add_trapezoids_int (ptr, size, mask, traps, &n_traps);
break;
case GLITZ_DATA_TYPE_DOUBLE:
count = _glitz_add_trapezoids_double (ptr, size, mask,
traps, &n_traps);
break;
default:
count = _glitz_add_trapezoids_float (ptr, size, mask, traps, &n_traps);
break;
}
if (glitz_buffer_unmap (buffer))
return 0;
*n_added = n - n_traps;
return count;
}
int
glitz_add_traps (glitz_buffer_t *buffer,
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trap_t *traps,
int n_traps,
int *n_added)
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trapezoid_t *traps,
int n_traps,
int *n_added)
{
int count, n = n_traps;
uint8_t *ptr;
@ -424,21 +379,66 @@ glitz_add_traps (glitz_buffer_t *buffer,
switch (type) {
case GLITZ_DATA_TYPE_SHORT:
count = _glitz_add_traps_short (ptr, size, mask, traps, &n_traps);
break;
count = _glitz_add_trapezoids_short (ptr, size, mask, traps, &n_traps);
break;
case GLITZ_DATA_TYPE_INT:
count = _glitz_add_traps_int (ptr, size, mask, traps, &n_traps);
break;
count = _glitz_add_trapezoids_int (ptr, size, mask, traps, &n_traps);
break;
case GLITZ_DATA_TYPE_DOUBLE:
count = _glitz_add_traps_double (ptr, size, mask, traps, &n_traps);
break;
count = _glitz_add_trapezoids_double (ptr, size, mask,
traps, &n_traps);
break;
default:
count = _glitz_add_traps_float (ptr, size, mask, traps, &n_traps);
break;
count = _glitz_add_trapezoids_float (ptr, size, mask, traps, &n_traps);
break;
}
if (glitz_buffer_unmap (buffer))
return 0;
return 0;
*n_added = n - n_traps;
return count;
}
int
glitz_add_traps (glitz_buffer_t *buffer,
int offset,
unsigned int size,
glitz_data_type_t type,
glitz_surface_t *mask,
glitz_trap_t *traps,
int n_traps,
int *n_added)
{
int count, n = n_traps;
uint8_t *ptr;
*n_added = 0;
ptr = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY);
if (!ptr)
return 0;
ptr += offset;
switch (type) {
case GLITZ_DATA_TYPE_SHORT:
count = _glitz_add_traps_short (ptr, size, mask, traps, &n_traps);
break;
case GLITZ_DATA_TYPE_INT:
count = _glitz_add_traps_int (ptr, size, mask, traps, &n_traps);
break;
case GLITZ_DATA_TYPE_DOUBLE:
count = _glitz_add_traps_double (ptr, size, mask, traps, &n_traps);
break;
default:
count = _glitz_add_traps_float (ptr, size, mask, traps, &n_traps);
break;
}
if (glitz_buffer_unmap (buffer))
return 0;
*n_added = n - n_traps;

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

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

@ -33,335 +33,369 @@
#include <string.h>
static glitz_extension_map gl_extensions[] = {
{ 0.0, "GL_ARB_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
{ 0.0, "GL_EXT_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
{ 0.0, "GL_NV_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
{ 0.0, "GL_ARB_texture_non_power_of_two",
GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK },
{ 0.0, "GL_ARB_texture_mirrored_repeat",
GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK },
{ 0.0, "GL_ARB_texture_border_clamp",
GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK },
{ 0.0, "GL_ARB_texture_env_combine",
GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK },
{ 0.0, "GL_EXT_texture_env_combine",
GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK },
{ 0.0, "GL_ARB_texture_env_dot3", GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK },
{ 0.0, "GL_ARB_multisample", GLITZ_FEATURE_MULTISAMPLE_MASK },
{ 0.0, "GL_NV_multisample_filter_hint",
GLITZ_FEATURE_MULTISAMPLE_FILTER_HINT_MASK },
{ 0.0, "GL_ARB_multitexture", GLITZ_FEATURE_MULTITEXTURE_MASK },
{ 0.0, "GL_EXT_multi_draw_arrays", GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK },
{ 0.0, "GL_ARB_fragment_program", GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK },
{ 0.0, "GL_ARB_vertex_buffer_object",
GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK },
{ 0.0, "GL_ARB_pixel_buffer_object",
GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK },
{ 0.0, "GL_EXT_pixel_buffer_object",
GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK },
{ 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, NULL, 0 }
{ 0.0, "GL_ARB_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
{ 0.0, "GL_EXT_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
{ 0.0, "GL_NV_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
{ 0.0, "GL_ARB_texture_non_power_of_two",
GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK },
{ 0.0, "GL_ARB_texture_mirrored_repeat",
GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK },
{ 0.0, "GL_ARB_texture_border_clamp",
GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK },
{ 0.0, "GL_ARB_texture_env_combine",
GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK },
{ 0.0, "GL_EXT_texture_env_combine",
GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK },
{ 0.0, "GL_ARB_texture_env_dot3", GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK },
{ 0.0, "GL_ARB_multisample", GLITZ_FEATURE_MULTISAMPLE_MASK },
{ 0.0, "GL_NV_multisample_filter_hint",
GLITZ_FEATURE_MULTISAMPLE_FILTER_HINT_MASK },
{ 0.0, "GL_ARB_multitexture", GLITZ_FEATURE_MULTITEXTURE_MASK },
{ 0.0, "GL_EXT_multi_draw_arrays", GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK },
{ 0.0, "GL_ARB_fragment_program", GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK },
{ 0.0, "GL_ARB_vertex_buffer_object",
GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK },
{ 0.0, "GL_ARB_pixel_buffer_object",
GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK },
{ 0.0, "GL_EXT_pixel_buffer_object",
GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK },
{ 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, NULL, 0 }
};
static glitz_bool_t
_glitz_extension_check (const char *extensions,
const char *ext_name)
const char *ext_name)
{
char *end;
char *p = (char *) extensions;
int ext_name_len = strlen (ext_name);
char *end;
char *p = (char *) extensions;
int ext_name_len = strlen (ext_name);
if (! p)
return 0;
if (! p)
return 0;
end = p + strlen (p);
end = p + strlen (p);
while (p < end) {
int n = strcspn (p, " ");
while (p < end) {
int n = strcspn (p, " ");
if ((ext_name_len == n) && (strncmp (ext_name, p, n) == 0)) {
return 1;
if ((ext_name_len == n) && (strncmp (ext_name, p, n) == 0)) {
return 1;
}
p += (n + 1);
}
p += (n + 1);
}
return 0;
return 0;
}
unsigned long
glitz_extensions_query (glitz_gl_float_t version,
const char *extensions_string,
glitz_extension_map *extensions_map)
const char *extensions_string,
glitz_extension_map *extensions_map)
{
unsigned long mask = 0;
int i;
unsigned long mask = 0;
int i;
for (i = 0; extensions_map[i].name; i++)
if (((extensions_map[i].version > 1.0) &&
(version >= extensions_map[i].version)) ||
_glitz_extension_check (extensions_string, extensions_map[i].name))
mask |= extensions_map[i].mask;
for (i = 0; extensions_map[i].name; i++)
if (((extensions_map[i].version > 1.0) &&
(version >= extensions_map[i].version)) ||
_glitz_extension_check (extensions_string, extensions_map[i].name))
mask |= extensions_map[i].mask;
return mask;
return mask;
}
static glitz_status_t
_glitz_query_gl_extensions (glitz_gl_proc_address_list_t *gl,
glitz_gl_float_t *gl_version,
unsigned long *feature_mask)
glitz_gl_float_t *gl_version,
unsigned long *feature_mask)
{
const char *gl_extensions_string;
const char *gl_extensions_string;
*gl_version = atof ((const char *) gl->get_string (GLITZ_GL_VERSION));
if (*gl_version < 1.2f)
return GLITZ_STATUS_NOT_SUPPORTED;
*gl_version = atof ((const char *) gl->get_string (GLITZ_GL_VERSION));
if (*gl_version < 1.2f)
return GLITZ_STATUS_NOT_SUPPORTED;
gl_extensions_string = (const char *) gl->get_string (GLITZ_GL_EXTENSIONS);
gl_extensions_string = (const char *) gl->get_string (GLITZ_GL_EXTENSIONS);
*feature_mask = glitz_extensions_query (*gl_version,
gl_extensions_string,
gl_extensions);
*feature_mask = glitz_extensions_query (*gl_version,
gl_extensions_string,
gl_extensions);
if ((*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) &&
(*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK)) {
glitz_gl_int_t max_texture_units;
if ((*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) &&
(*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK)) {
glitz_gl_int_t max_texture_units;
gl->get_integer_v (GLITZ_GL_MAX_TEXTURE_UNITS, &max_texture_units);
if (max_texture_units >= 3)
*feature_mask |= GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK;
}
gl->get_integer_v (GLITZ_GL_MAX_TEXTURE_UNITS, &max_texture_units);
if (max_texture_units >= 3)
*feature_mask |= GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK;
}
return GLITZ_STATUS_SUCCESS;
return GLITZ_STATUS_SUCCESS;
}
static void
_glitz_gl_proc_address_lookup (glitz_backend_t *backend,
glitz_get_proc_address_proc_t get_proc_address,
void *closure)
glitz_get_proc_address_proc_t get_proc_address,
void *closure)
{
if (backend->feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) {
if (backend->gl_version >= 1.4f) {
backend->gl.blend_color = (glitz_gl_blend_color_t)
get_proc_address ("glBlendColor", closure);
} else {
backend->gl.blend_color = (glitz_gl_blend_color_t)
get_proc_address ("glBlendColorEXT", closure);
if (backend->feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) {
if (backend->gl_version >= 1.4f) {
backend->gl->blend_color = (glitz_gl_blend_color_t)
get_proc_address ("glBlendColor", closure);
} else {
backend->gl->blend_color = (glitz_gl_blend_color_t)
get_proc_address ("glBlendColorEXT", closure);
}
if (!backend->gl->blend_color)
backend->feature_mask &= ~GLITZ_FEATURE_BLEND_COLOR_MASK;
}
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)
get_proc_address ("glActiveTexture", closure);
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)
get_proc_address ("glActiveTextureARB", closure);
backend->gl->client_active_texture =
(glitz_gl_client_active_texture_t)
get_proc_address ("glClientActiveTextureARB", closure);
}
if (backend->feature_mask & GLITZ_FEATURE_MULTITEXTURE_MASK) {
if (backend->gl_version >= 1.3f) {
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)
get_proc_address ("glClientActiveTexture", closure);
} else {
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)
get_proc_address ("glClientActiveTextureARB", closure);
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;
}
}
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;
}
}
if (backend->feature_mask & GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK) {
backend->gl->multi_draw_arrays = (glitz_gl_multi_draw_arrays_t)
get_proc_address ("glMultiDrawArraysEXT", closure);
if (backend->feature_mask & GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK) {
backend->gl.multi_draw_arrays = (glitz_gl_multi_draw_arrays_t)
get_proc_address ("glMultiDrawArraysEXT", closure);
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)
get_proc_address ("glGenProgramsARB", closure);
backend->gl.delete_programs = (glitz_gl_delete_programs_t)
get_proc_address ("glDeleteProgramsARB", closure);
backend->gl.program_string = (glitz_gl_program_string_t)
get_proc_address ("glProgramStringARB", closure);
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)
get_proc_address ("glProgramLocalParameter4fvARB", closure);
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))
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)
get_proc_address ("glGenBuffers", closure);
backend->gl.delete_buffers = (glitz_gl_delete_buffers_t)
get_proc_address ("glDeleteBuffers", closure);
backend->gl.bind_buffer = (glitz_gl_bind_buffer_t)
get_proc_address ("glBindBuffer", closure);
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)
get_proc_address ("glBufferSubData", closure);
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)
get_proc_address ("glMapBuffer", closure);
backend->gl.unmap_buffer = (glitz_gl_unmap_buffer_t)
get_proc_address ("glUnmapBuffer", closure);
} else {
backend->gl.gen_buffers = (glitz_gl_gen_buffers_t)
get_proc_address ("glGenBuffersARB", closure);
backend->gl.delete_buffers = (glitz_gl_delete_buffers_t)
get_proc_address ("glDeleteBuffersARB", closure);
backend->gl.bind_buffer = (glitz_gl_bind_buffer_t)
get_proc_address ("glBindBufferARB", closure);
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)
get_proc_address ("glBufferSubDataARB", closure);
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)
get_proc_address ("glMapBufferARB", closure);
backend->gl.unmap_buffer = (glitz_gl_unmap_buffer_t)
get_proc_address ("glUnmapBufferARB", closure);
if (!backend->gl->multi_draw_arrays)
backend->feature_mask &= ~GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK;
}
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_FRAGMENT_PROGRAM_MASK) {
backend->gl->gen_programs = (glitz_gl_gen_programs_t)
get_proc_address ("glGenProgramsARB", closure);
backend->gl->delete_programs = (glitz_gl_delete_programs_t)
get_proc_address ("glDeleteProgramsARB", closure);
backend->gl->program_string = (glitz_gl_program_string_t)
get_proc_address ("glProgramStringARB", closure);
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)
get_proc_address ("glProgramLocalParameter4fvARB", closure);
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))
backend->feature_mask &= ~GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK;
}
}
if (backend->feature_mask & GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) {
backend->gl.gen_framebuffers = (glitz_gl_gen_framebuffers_t)
get_proc_address ("glGenFramebuffersEXT", closure);
backend->gl.delete_framebuffers = (glitz_gl_delete_framebuffers_t)
get_proc_address ("glDeleteFramebuffersEXT", closure);
backend->gl.bind_framebuffer = (glitz_gl_bind_framebuffer_t)
get_proc_address ("glBindFramebufferEXT", 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);
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)
get_proc_address ("glGenBuffers", closure);
backend->gl->delete_buffers = (glitz_gl_delete_buffers_t)
get_proc_address ("glDeleteBuffers", closure);
backend->gl->bind_buffer = (glitz_gl_bind_buffer_t)
get_proc_address ("glBindBuffer", closure);
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)
get_proc_address ("glBufferSubData", closure);
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)
get_proc_address ("glMapBuffer", closure);
backend->gl->unmap_buffer = (glitz_gl_unmap_buffer_t)
get_proc_address ("glUnmapBuffer", closure);
} else {
backend->gl->gen_buffers = (glitz_gl_gen_buffers_t)
get_proc_address ("glGenBuffersARB", closure);
backend->gl->delete_buffers = (glitz_gl_delete_buffers_t)
get_proc_address ("glDeleteBuffersARB", closure);
backend->gl->bind_buffer = (glitz_gl_bind_buffer_t)
get_proc_address ("glBindBufferARB", closure);
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)
get_proc_address ("glBufferSubDataARB", closure);
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)
get_proc_address ("glMapBufferARB", closure);
backend->gl->unmap_buffer = (glitz_gl_unmap_buffer_t)
get_proc_address ("glUnmapBufferARB", closure);
}
if ((!backend->gl.gen_framebuffers) ||
(!backend->gl.delete_framebuffers) ||
(!backend->gl.bind_framebuffer) ||
(!backend->gl.check_framebuffer_status) ||
(!backend->gl.framebuffer_texture_2d))
backend->feature_mask &= ~GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK;
}
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)
get_proc_address ("glGenFramebuffersEXT", closure);
backend->gl->delete_framebuffers = (glitz_gl_delete_framebuffers_t)
get_proc_address ("glDeleteFramebuffersEXT", closure);
backend->gl->bind_framebuffer = (glitz_gl_bind_framebuffer_t)
get_proc_address ("glBindFramebufferEXT", closure);
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->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->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;
}
}
void
glitz_backend_init (glitz_backend_t *backend,
glitz_get_proc_address_proc_t get_proc_address,
void *closure)
glitz_get_proc_address_proc_t get_proc_address,
void *closure)
{
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,
&backend->formats,
&backend->texture_formats,
&backend->n_formats);
}
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,
&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->max_texture_2d_size);
backend->gl->get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS,
backend->max_viewport_dims);
if (backend->feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK)
backend->gl.get_integer_v (GLITZ_GL_MAX_RECTANGLE_TEXTURE_SIZE,
&backend->max_texture_rect_size);
else
backend->max_texture_rect_size = 0;
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->max_texture_rect_size);
else
backend->max_texture_rect_size = 0;
}
unsigned int
glitz_uint_to_power_of_two (unsigned int x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x + 1);
return (x + 1);
}
void
glitz_set_raster_pos (glitz_gl_proc_address_list_t *gl,
glitz_float_t x,
glitz_float_t y)
glitz_float_t x,
glitz_float_t y)
{
gl->push_attrib (GLITZ_GL_TRANSFORM_BIT | GLITZ_GL_VIEWPORT_BIT);
gl->matrix_mode (GLITZ_GL_PROJECTION);
gl->push_matrix ();
gl->load_identity ();
gl->matrix_mode (GLITZ_GL_MODELVIEW);
gl->push_matrix ();
gl->load_identity ();
gl->depth_range (0, 1);
gl->viewport (-1, -1, 2, 2);
gl->push_attrib (GLITZ_GL_TRANSFORM_BIT | GLITZ_GL_VIEWPORT_BIT);
gl->matrix_mode (GLITZ_GL_PROJECTION);
gl->push_matrix ();
gl->load_identity ();
gl->matrix_mode (GLITZ_GL_MODELVIEW);
gl->push_matrix ();
gl->load_identity ();
gl->depth_range (0, 1);
gl->viewport (-1, -1, 2, 2);
gl->raster_pos_2f (0, 0);
gl->bitmap (0, 0, 1, 1, x, y, NULL);
gl->raster_pos_2f (0, 0);
gl->bitmap (0, 0, 1, 1, x, y, NULL);
gl->pop_matrix ();
gl->matrix_mode (GLITZ_GL_PROJECTION);
gl->pop_matrix ();
gl->pop_attrib ();
gl->pop_matrix ();
gl->matrix_mode (GLITZ_GL_PROJECTION);
gl->pop_matrix ();
gl->pop_attrib ();
}
void
glitz_clamp_value (glitz_float_t *value,
glitz_float_t min, glitz_float_t max)
glitz_float_t min, glitz_float_t max)
{
if (*value < min)
*value = min;
else if (*value > max)
*value = max;
if (*value < min)
*value = min;
else if (*value > max)
*value = max;
}
void
glitz_initiate_state (glitz_gl_proc_address_list_t *gl)
{
gl->hint (GLITZ_GL_PERSPECTIVE_CORRECTION_HINT, GLITZ_GL_FASTEST);
gl->disable (GLITZ_GL_CULL_FACE);
gl->depth_mask (GLITZ_GL_FALSE);
gl->polygon_mode (GLITZ_GL_FRONT_AND_BACK, GLITZ_GL_FILL);
gl->disable (GLITZ_GL_POLYGON_SMOOTH);
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->enable (GLITZ_GL_SCISSOR_TEST);
gl->disable (GLITZ_GL_STENCIL_TEST);
gl->enable_client_state (GLITZ_GL_VERTEX_ARRAY);
gl->disable (GLITZ_GL_DEPTH_TEST);
gl->hint (GLITZ_GL_PERSPECTIVE_CORRECTION_HINT, GLITZ_GL_FASTEST);
gl->disable (GLITZ_GL_CULL_FACE);
gl->depth_mask (GLITZ_GL_FALSE);
gl->polygon_mode (GLITZ_GL_FRONT_AND_BACK, GLITZ_GL_FILL);
gl->disable (GLITZ_GL_POLYGON_SMOOTH);
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->enable (GLITZ_GL_SCISSOR_TEST);
gl->disable (GLITZ_GL_STENCIL_TEST);
gl->enable_client_state (GLITZ_GL_VERTEX_ARRAY);
gl->disable (GLITZ_GL_DEPTH_TEST);
}

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

@ -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;
@ -307,52 +314,81 @@ typedef struct _glitz_region_t {
extern glitz_status_t __internal_linkage
glitz_region_union (glitz_region_t *region,
glitz_box_t *box);
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,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
void
(*destroy) (void *drawable);
void
glitz_bool_t
(*push_current) (void *drawable,
glitz_surface_t *surface,
glitz_constraint_t constraint);
glitz_surface_t *surface,
glitz_constraint_t constraint);
glitz_surface_t *
(*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);
glitz_drawable_format_t *format);
void
(*destroy_context) (void *context);
void
(*copy_context) (void *src,
void *dst,
unsigned long mask);
void *dst,
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);
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;
@ -368,17 +405,21 @@ typedef struct glitz_backend {
} glitz_backend_t;
struct _glitz_drawable {
glitz_backend_t *backend;
int ref_count;
glitz_drawable_format_t *format;
int width, height;
glitz_rectangle_t viewport;
glitz_bool_t update_all;
glitz_backend_t *backend;
int ref_count;
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,30 +446,43 @@ 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;
int width;
int height;
glitz_box_t box;
glitz_box_t box;
glitz_float_t texcoord_width_unit;
glitz_float_t texcoord_height_unit;
glitz_float_t texcoord_width_unit;
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;
@ -634,135 +681,144 @@ typedef struct _glitz_extension_map {
extern void __internal_linkage
glitz_set_operator (glitz_gl_proc_address_list_t *gl,
glitz_operator_t op);
glitz_operator_t op);
unsigned long
glitz_extensions_query (glitz_gl_float_t version,
const char *extensions_string,
glitz_extension_map *extensions_map);
const char *extensions_string,
glitz_extension_map *extensions_map);
typedef glitz_function_pointer_t (* glitz_get_proc_address_proc_t)
(const char *name, void *closure);
void
glitz_backend_init (glitz_backend_t *backend,
glitz_get_proc_address_proc_t get_proc_address,
void *closure);
glitz_get_proc_address_proc_t get_proc_address,
void *closure);
extern unsigned int __internal_linkage
glitz_uint_to_power_of_two (unsigned int x);
extern void __internal_linkage
glitz_set_raster_pos (glitz_gl_proc_address_list_t *gl,
glitz_float_t x,
glitz_float_t y);
glitz_float_t x,
glitz_float_t y);
extern void __internal_linkage
glitz_clamp_value (glitz_float_t *value,
glitz_float_t min,
glitz_float_t max);
glitz_float_t min,
glitz_float_t max);
void
glitz_initiate_state (glitz_gl_proc_address_list_t *gl);
void
glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
int *n_formats);
glitz_format_t **formats,
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,
int n_formats,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
glitz_drawable_format_find (glitz_int_drawable_format_t *formats,
int n_formats,
unsigned long mask,
const glitz_int_drawable_format_t *templ,
int count);
void
glitz_texture_init (glitz_texture_t *texture,
int width,
int height,
glitz_gl_int_t texture_format,
unsigned long feature_mask,
glitz_bool_t unnormalized);
int width,
int height,
glitz_gl_int_t texture_format,
unsigned long feature_mask,
glitz_bool_t unnormalized);
void
glitz_texture_fini (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture);
glitz_texture_t *texture);
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_texture_t *texture,
glitz_gl_int_t max_2d,
glitz_gl_int_t max_rect);
void
glitz_texture_allocate (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture);
glitz_texture_t *texture);
extern void __internal_linkage
glitz_texture_ensure_filter (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_ensure_parameters (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture,
glitz_texture_parameters_t *param);
void
glitz_texture_bind (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture);
glitz_texture_t *texture);
void
glitz_texture_unbind (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture);
glitz_texture_t *texture);
void
glitz_texture_copy_drawable (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture,
glitz_drawable_t *drawable,
int x_drawable,
int y_drawable,
int width,
int height,
int x_texture,
int y_texture);
glitz_texture_t *texture,
glitz_drawable_t *drawable,
int x_drawable,
int y_drawable,
int width,
int height,
int x_texture,
int y_texture);
void
glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
glitz_texture_t *texture,
glitz_geometry_t *geometry,
int x_src,
int y_src,
unsigned long flags,
glitz_int_coordinate_t *coord);
glitz_texture_t *texture,
glitz_geometry_t *geometry,
int x_src,
int y_src,
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);
glitz_bool_t allocate);
extern void __internal_linkage
glitz_surface_sync_solid (glitz_surface_t *surface);
extern glitz_bool_t __internal_linkage
glitz_surface_push_current (glitz_surface_t *surface,
glitz_constraint_t constraint);
glitz_constraint_t constraint);
extern void __internal_linkage
glitz_surface_pop_current (glitz_surface_t *surface);
extern void __internal_linkage
glitz_surface_damage (glitz_surface_t *surface,
glitz_box_t *box,
int what);
glitz_box_t *box,
int what);
extern void __internal_linkage
glitz_surface_sync_drawable (glitz_surface_t *surface);
extern void __internal_linkage
glitz_surface_status_add (glitz_surface_t *surface,
int flags);
int flags);
extern unsigned long __internal_linkage
glitz_status_to_status_mask (glitz_status_t status);
@ -775,19 +831,19 @@ glitz_program_map_init (glitz_program_map_t *map);
void
glitz_program_map_fini (glitz_gl_proc_address_list_t *gl,
glitz_program_map_t *map);
glitz_program_map_t *map);
extern glitz_gl_uint_t __internal_linkage
glitz_get_fragment_program (glitz_composite_op_t *op,
int fp_type,
int id);
int fp_type,
int id);
extern void __internal_linkage
glitz_composite_op_init (glitz_composite_op_t *op,
glitz_operator_t render_op,
glitz_surface_t *src,
glitz_surface_t *mask,
glitz_surface_t *dst);
glitz_operator_t render_op,
glitz_surface_t *src,
glitz_surface_t *mask,
glitz_surface_t *dst);
extern void __internal_linkage
glitz_composite_enable (glitz_composite_op_t *op);
@ -797,71 +853,69 @@ glitz_composite_disable (glitz_composite_op_t *op);
extern void __internal_linkage *
glitz_buffer_bind (glitz_buffer_t *buffer,
glitz_gl_enum_t target);
glitz_gl_enum_t target);
extern void __internal_linkage
glitz_buffer_unbind (glitz_buffer_t *buffer);
extern glitz_status_t __internal_linkage
glitz_filter_set_params (glitz_surface_t *surface,
glitz_filter_t filter,
glitz_fixed16_16_t *params,
int n_params);
glitz_filter_t filter,
glitz_fixed16_16_t *params,
int n_params);
extern void __internal_linkage
glitz_filter_set_type (glitz_surface_t *surface,
glitz_filter_t filter);
glitz_filter_t filter);
extern glitz_gl_uint_t __internal_linkage
glitz_filter_get_vertex_program (glitz_surface_t *surface,
glitz_composite_op_t *op);
glitz_composite_op_t *op);
extern glitz_gl_uint_t __internal_linkage
glitz_filter_get_fragment_program (glitz_surface_t *surface,
glitz_composite_op_t *op);
glitz_composite_op_t *op);
extern void __internal_linkage
glitz_filter_enable (glitz_surface_t *surface,
glitz_composite_op_t *op);
glitz_composite_op_t *op);
extern void __internal_linkage
glitz_geometry_enable_none (glitz_gl_proc_address_list_t *gl,
glitz_surface_t *dst,
glitz_box_t *box);
glitz_surface_t *dst,
glitz_box_t *box);
extern void __internal_linkage
glitz_geometry_enable (glitz_gl_proc_address_list_t *gl,
glitz_surface_t *dst,
glitz_box_t *box);
glitz_surface_t *dst,
glitz_box_t *box);
extern void __internal_linkage
glitz_geometry_disable (glitz_surface_t *dst);
extern void __internal_linkage
glitz_geometry_draw_arrays (glitz_gl_proc_address_list_t *gl,
glitz_surface_t *dst,
glitz_geometry_type_t type,
glitz_box_t *bounds,
int damage);
glitz_surface_t *dst,
glitz_geometry_type_t type,
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,
glitz_drawable_t *drawable);
glitz_drawable_t *drawable);
void
_glitz_context_fini (glitz_context_t *context);
@ -953,14 +1007,15 @@ typedef glitz_fixed_16_16 glitz_fixed;
#define sqrtf(_X) ((float)sqrt((double)(_X)))
#endif
/* Avoid unnecessary PLT entries. */
/* 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,11 +47,18 @@ glitz_glx_fini (void);
/* glitz_glx_format.c */
glitz_drawable_format_t *
glitz_glx_find_drawable_format (Display *display,
int screen,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
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,
int count);
glitz_drawable_format_t *
glitz_glx_find_drawable_format_for_visual (Display *display,
@ -60,26 +67,26 @@ glitz_glx_find_drawable_format_for_visual (Display *display,
XVisualInfo *
glitz_glx_get_visual_info_from_format (Display *display,
int screen,
glitz_drawable_format_t *format);
int screen,
glitz_drawable_format_t *format);
/* glitz_glx_drawable.c */
glitz_drawable_t *
glitz_glx_create_drawable_for_window (Display *display,
int screen,
glitz_drawable_format_t *format,
Window window,
unsigned int width,
unsigned int height);
int screen,
glitz_drawable_format_t *format,
Window window,
unsigned int width,
unsigned int height);
glitz_drawable_t *
glitz_glx_create_pbuffer_drawable (Display *display,
int screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
int screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
#if defined(__cplusplus) || defined(c_plusplus)

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

@ -35,402 +35,448 @@ extern glitz_gl_proc_address_list_t _glitz_glx_gl_proc_address;
static void
_glitz_glx_context_create (glitz_glx_screen_info_t *screen_info,
XID visualid,
GLXContext share_list,
glitz_glx_context_t *context)
XID visualid,
GLXContext share_list,
glitz_glx_context_t *context)
{
int vis_info_count, i;
XVisualInfo *vis_infos;
int vis_info_count, i;
XVisualInfo *vis_infos;
vis_infos = XGetVisualInfo (screen_info->display_info->display,
0, NULL, &vis_info_count);
for (i = 0; i < vis_info_count; i++) {
if (vis_infos[i].visual->visualid == visualid)
break;
}
vis_infos = XGetVisualInfo (screen_info->display_info->display,
0, NULL, &vis_info_count);
for (i = 0; i < vis_info_count; i++) {
if (vis_infos[i].visual->visualid == visualid)
break;
}
context->context = glXCreateContext (screen_info->display_info->display,
&vis_infos[i], share_list,
GLITZ_GL_TRUE);
context->id = visualid;
context->fbconfig = (GLXFBConfig) 0;
context->context = glXCreateContext (screen_info->display_info->display,
&vis_infos[i], share_list,
GLITZ_GL_TRUE);
context->id = visualid;
context->fbconfig = (GLXFBConfig) 0;
XFree (vis_infos);
XFree (vis_infos);
}
static void
_glitz_glx_context_create_using_fbconfig (glitz_glx_screen_info_t *screen_info,
XID fbconfigid,
GLXContext share_list,
glitz_glx_context_t *context)
XID fbconfigid,
GLXContext share_list,
glitz_glx_context_t *context)
{
GLXFBConfig *fbconfigs;
int i, n_fbconfigs;
XVisualInfo *vinfo = NULL;
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
GLXFBConfig *fbconfigs;
int i, n_fbconfigs;
XVisualInfo *vinfo = NULL;
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
fbconfigs = glx->get_fbconfigs (screen_info->display_info->display,
screen_info->screen, &n_fbconfigs);
for (i = 0; i < n_fbconfigs; i++) {
int value;
fbconfigs = glx->get_fbconfigs (screen_info->display_info->display,
screen_info->screen, &n_fbconfigs);
for (i = 0; i < n_fbconfigs; i++) {
int value;
glx->get_fbconfig_attrib (screen_info->display_info->display, fbconfigs[i],
GLX_FBCONFIG_ID, &value);
if (value == (int) fbconfigid)
break;
}
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,
fbconfigs[i]);
if (i < n_fbconfigs)
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,
vinfo, share_list, GLITZ_GL_TRUE);
XFree (vinfo);
} else if (glx->create_new_context)
context->context =
glx->create_new_context (screen_info->display_info->display,
fbconfigs[i], GLX_RGBA_TYPE, share_list,
GLITZ_GL_TRUE);
context->id = fbconfigid;
if (vinfo) {
context->context =
glXCreateContext (screen_info->display_info->display,
vinfo, share_list, GLITZ_GL_TRUE);
XFree (vinfo);
} else if (glx->create_new_context)
context->context =
glx->create_new_context (screen_info->display_info->display,
fbconfigs[i], GLX_RGBA_TYPE, share_list,
GLITZ_GL_TRUE);
if (context->context)
context->fbconfig = fbconfigs[i];
else
context->fbconfig = (GLXFBConfig) 0;
if (context->context)
context->fbconfig = fbconfigs[i];
else
context->fbconfig = (GLXFBConfig) 0;
if (fbconfigs)
XFree (fbconfigs);
if (fbconfigs)
XFree (fbconfigs);
}
static glitz_context_t *
_glitz_glx_create_context (void *abstract_drawable,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
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];
glitz_glx_context_t *context;
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
abstract_drawable;
glitz_glx_screen_info_t *screen_info = drawable->screen_info;
unsigned long format_id =
screen_info->formats[format->id].u.uval;
glitz_glx_context_t *context;
context = malloc (sizeof (glitz_glx_context_t));
if (!context)
return NULL;
context = malloc (sizeof (glitz_glx_context_t));
if (!context)
return NULL;
_glitz_context_init (&context->base, &drawable->base);
_glitz_context_init (&context->base, &drawable->base);
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
_glitz_glx_context_create_using_fbconfig (screen_info,
format_id,
screen_info->root_context,
context);
else
_glitz_glx_context_create (screen_info,
format_id,
screen_info->root_context,
context);
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
_glitz_glx_context_create_using_fbconfig (screen_info,
format_id,
screen_info->root_context,
context);
else
_glitz_glx_context_create (screen_info,
format_id,
screen_info->root_context,
context);
return (glitz_context_t *) context;
return (glitz_context_t *) context;
}
static void
_glitz_glx_context_destroy (void *abstract_context)
{
glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context;
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
context->base.drawable;
glitz_glx_context_t *context = (glitz_glx_context_t *) 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)
{
glXMakeCurrent (drawable->screen_info->display_info->display,
None, NULL);
if (drawable->screen_info->display_info->thread_info->cctx ==
&context->base)
{
glXMakeCurrent (drawable->screen_info->display_info->display,
None, NULL);
drawable->screen_info->display_info->thread_info->cctx = NULL;
}
drawable->screen_info->display_info->thread_info->cctx = NULL;
}
glXDestroyContext (drawable->screen_info->display_info->display,
context->context);
glXDestroyContext (drawable->screen_info->display_info->display,
context->context);
_glitz_context_fini (&context->base);
_glitz_context_fini (&context->base);
free (context);
free (context);
}
static void
_glitz_glx_copy_context (void *abstract_src,
void *abstract_dst,
unsigned long mask)
void *abstract_dst,
unsigned long mask)
{
glitz_glx_context_t *src = (glitz_glx_context_t *) abstract_src;
glitz_glx_context_t *dst = (glitz_glx_context_t *) abstract_dst;
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
src->base.drawable;
glitz_glx_context_t *src = (glitz_glx_context_t *) abstract_src;
glitz_glx_context_t *dst = (glitz_glx_context_t *) abstract_dst;
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
src->base.drawable;
glXCopyContext (drawable->screen_info->display_info->display,
src->context, dst->context, mask);
glXCopyContext (drawable->screen_info->display_info->display,
src->context, dst->context, mask);
}
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_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;
if ((glXGetCurrentContext () != context->context) ||
(glXGetCurrentDrawable () != drawable->drawable))
{
if (display_info->thread_info->cctx)
{
glitz_context_t *ctx = display_info->thread_info->cctx;
if (drawable->base.width != drawable->width ||
drawable->base.height != drawable->height)
_glitz_glx_drawable_update_size (drawable,
drawable->base.width,
drawable->base.height);
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
}
glXMakeCurrent (display_info->display, drawable->drawable,
context->context);
}
if ((glXGetCurrentContext () != context->context) ||
(glXGetCurrentDrawable () != drawable->drawable))
{
if (display_info->thread_info->cctx)
{
glitz_context_t *ctx = display_info->thread_info->cctx;
display_info->thread_info->cctx = &context->base;
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
}
glXMakeCurrent (display_info->display, drawable->drawable,
context->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)
const char *name)
{
glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context;
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
context->base.drawable;
glitz_glx_context_t *context = (glitz_glx_context_t *) 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);
return glitz_glx_get_proc_address (name, drawable->screen_info);
}
glitz_glx_context_t *
glitz_glx_context_get (glitz_glx_screen_info_t *screen_info,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
glitz_glx_context_t *context;
glitz_glx_context_t **contexts = screen_info->contexts;
int index, n_contexts = screen_info->n_contexts;
XID format_id;
glitz_glx_context_t *context;
glitz_glx_context_t **contexts = screen_info->contexts;
int index, n_contexts = screen_info->n_contexts;
unsigned long format_id;
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->id == screen_info->format_ids[format->id])
return *contexts;
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->id == screen_info->formats[format->id].u.uval)
return *contexts;
index = screen_info->n_contexts++;
index = screen_info->n_contexts++;
screen_info->contexts =
realloc (screen_info->contexts,
sizeof (glitz_glx_context_t *) * screen_info->n_contexts);
if (!screen_info->contexts)
return NULL;
screen_info->contexts =
realloc (screen_info->contexts,
sizeof (glitz_glx_context_t *) * screen_info->n_contexts);
if (!screen_info->contexts)
return NULL;
context = malloc (sizeof (glitz_glx_context_t));
if (!context)
return NULL;
context = malloc (sizeof (glitz_glx_context_t));
if (!context)
return NULL;
screen_info->contexts[index] = context;
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,
format_id,
screen_info->root_context,
context);
else
_glitz_glx_context_create (screen_info,
format_id,
screen_info->root_context,
context);
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
_glitz_glx_context_create_using_fbconfig (screen_info,
format_id,
screen_info->root_context,
context);
else
_glitz_glx_context_create (screen_info,
format_id,
screen_info->root_context,
context);
if (!screen_info->root_context)
screen_info->root_context = context->context;
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.swap_buffers = glitz_glx_swap_buffers;
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;
context->backend.destroy_context = _glitz_glx_context_destroy;
context->backend.copy_context = _glitz_glx_copy_context;
context->backend.make_current = _glitz_glx_make_current;
context->backend.get_proc_address = _glitz_glx_context_get_proc_address;
context->backend.create_context = _glitz_glx_create_context;
context->backend.destroy_context = _glitz_glx_context_destroy;
context->backend.copy_context = _glitz_glx_copy_context;
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.n_drawable_formats = screen_info->n_formats;
context->backend.drawable_formats = NULL;
context->backend.n_drawable_formats = 0;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
if (screen_info->n_formats)
{
int size;
context->backend.program_map = &screen_info->program_map;
context->backend.feature_mask = 0;
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->initialized = 0;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
return context;
context->backend.program_map = &screen_info->program_map;
context->backend.feature_mask = 0;
context->initialized = 0;
return context;
}
void
glitz_glx_context_destroy (glitz_glx_screen_info_t *screen_info,
glitz_glx_context_t *context)
glitz_glx_context_t *context)
{
if (context->backend.formats)
free (context->backend.formats);
if (context->backend.drawable_formats)
free (context->backend.drawable_formats);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
if (context->backend.formats)
free (context->backend.formats);
glXDestroyContext (screen_info->display_info->display,
context->context);
free (context);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
glXDestroyContext (screen_info->display_info->display,
context->context);
free (context);
}
static void
_glitz_glx_context_initialize (glitz_glx_screen_info_t *screen_info,
glitz_glx_context_t *context)
glitz_glx_context_t *context)
{
const char *version;
const char *version;
glitz_backend_init (&context->backend,
glitz_glx_get_proc_address,
(void *) screen_info);
glitz_backend_init (&context->backend,
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);
glitz_initiate_state (&_glitz_glx_gl_proc_address);
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. */
if (strstr (version, "NVIDIA 61.11") ||
strstr (version, "NVIDIA 66.29"))
version = (const char *)
context->backend.gl->get_string (GLITZ_GL_VERSION);
if (version)
{
context->backend.feature_mask &=
~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK;
/* 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"))
{
context->backend.feature_mask &=
~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK;
}
}
}
context->initialized = 1;
context->initialized = 1;
}
static void
_glitz_glx_context_make_current (glitz_glx_drawable_t *drawable,
glitz_bool_t finish)
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 ();
if (finish)
glFinish ();
if (display_info->thread_info->cctx)
{
glitz_context_t *ctx = display_info->thread_info->cctx;
if (display_info->thread_info->cctx)
{
glitz_context_t *ctx = display_info->thread_info->cctx;
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
if (ctx->lose_current)
ctx->lose_current (ctx->closure);
display_info->thread_info->cctx = NULL;
}
display_info->thread_info->cctx = NULL;
}
glXMakeCurrent (display_info->display,
drawable->drawable,
drawable->context->context);
glXMakeCurrent (display_info->display,
drawable->drawable,
drawable->context->context);
drawable->base.update_all = 1;
drawable->base.update_all = 1;
if (!drawable->context->initialized)
_glitz_glx_context_initialize (drawable->screen_info, drawable->context);
if (!drawable->context->initialized)
_glitz_glx_context_initialize (drawable->screen_info,
drawable->context);
}
static void
_glitz_glx_context_update (glitz_glx_drawable_t *drawable,
glitz_constraint_t constraint)
glitz_constraint_t constraint)
{
glitz_glx_display_info_t *dinfo = drawable->screen_info->display_info;
GLXContext context = NULL;
switch (constraint) {
case GLITZ_NONE:
break;
break;
case GLITZ_ANY_CONTEXT_CURRENT:
if (!dinfo->thread_info->cctx)
context = glXGetCurrentContext ();
if (!dinfo->thread_info->cctx)
context = glXGetCurrentContext ();
if (context == (GLXContext) 0)
_glitz_glx_context_make_current (drawable, 0);
break;
case GLITZ_CONTEXT_CURRENT:
if (!dinfo->thread_info->cctx)
context = glXGetCurrentContext ();
if (context == (GLXContext) 0)
_glitz_glx_context_make_current (drawable, 0);
break;
case GLITZ_CONTEXT_CURRENT:
if (!dinfo->thread_info->cctx)
context = glXGetCurrentContext ();
if (context != drawable->context->context)
_glitz_glx_context_make_current (drawable, (context)? 1: 0);
break;
if (context != drawable->context->context)
_glitz_glx_context_make_current (drawable, (context)? 1: 0);
break;
case GLITZ_DRAWABLE_CURRENT:
if (!dinfo->thread_info->cctx)
context = glXGetCurrentContext ();
if (!dinfo->thread_info->cctx)
context = glXGetCurrentContext ();
if ((context != drawable->context->context) ||
(glXGetCurrentDrawable () != drawable->drawable))
_glitz_glx_context_make_current (drawable, (context)? 1: 0);
break;
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);
break;
}
}
void
glitz_bool_t
glitz_glx_push_current (void *abstract_drawable,
glitz_surface_t *surface,
glitz_constraint_t constraint)
glitz_surface_t *surface,
glitz_constraint_t constraint)
{
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable;
glitz_glx_context_info_t *context_info;
int index;
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
abstract_drawable;
glitz_glx_context_info_t *context_info;
int index;
index = drawable->screen_info->context_stack_size++;
index = drawable->screen_info->context_stack_size++;
context_info = &drawable->screen_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
context_info = &drawable->screen_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
_glitz_glx_context_update (context_info->drawable, 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_context_info_t *context_info = NULL;
int index;
glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *)
abstract_drawable;
glitz_glx_context_info_t *context_info = NULL;
int index;
drawable->screen_info->context_stack_size--;
index = drawable->screen_info->context_stack_size - 1;
drawable->screen_info->context_stack_size--;
index = drawable->screen_info->context_stack_size - 1;
context_info = &drawable->screen_info->context_stack[index];
context_info = &drawable->screen_info->context_stack[index];
if (context_info->drawable)
_glitz_glx_context_update (context_info->drawable,
context_info->constraint);
if (context_info->drawable)
_glitz_glx_context_update (context_info->drawable,
context_info->constraint);
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
return NULL;
return NULL;
}

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

@ -31,172 +31,212 @@
static glitz_glx_drawable_t *
_glitz_glx_create_drawable (glitz_glx_screen_info_t *screen_info,
glitz_glx_context_t *context,
glitz_drawable_format_t *format,
GLXDrawable glx_drawable,
GLXPbuffer glx_pbuffer,
int width,
int height)
glitz_glx_context_t *context,
glitz_drawable_format_t *format,
GLXDrawable glx_drawable,
GLXPbuffer glx_pbuffer,
int width,
int height)
{
glitz_glx_drawable_t *drawable;
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 = (glitz_glx_drawable_t *) malloc (sizeof (glitz_glx_drawable_t));
if (drawable == NULL)
return NULL;
drawable->screen_info = screen_info;
drawable->context = context;
drawable->drawable = glx_drawable;
drawable->pbuffer = glx_pbuffer;
drawable->width = width;
drawable->height = height;
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;
_glitz_drawable_init (&drawable->base,
&screen_info->formats[format->id],
&context->backend,
width, height);
glitz_drawable_update_size (&drawable->base, width, height);
if (!context->initialized) {
glitz_glx_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_glx_pop_current (drawable);
}
if (!context->initialized) {
glitz_glx_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_glx_pop_current (drawable);
}
if (width > context->backend.max_viewport_dims[0] ||
height > context->backend.max_viewport_dims[1]) {
free (drawable);
return NULL;
}
if (width > context->max_viewport_dims[0] ||
height > context->max_viewport_dims[1]) {
free (drawable);
return NULL;
}
screen_info->drawables++;
screen_info->drawables++;
return drawable;
}
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,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_glx_drawable_t *drawable;
glitz_glx_context_t *context;
GLXPbuffer pbuffer;
glitz_glx_drawable_t *drawable;
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;
context = glitz_glx_context_get (screen_info, format);
if (!context)
return NULL;
pbuffer = glitz_glx_pbuffer_create (screen_info, context->fbconfig,
(int) width, (int) height);
if (!pbuffer)
return NULL;
pbuffer = glitz_glx_pbuffer_create (screen_info, context->fbconfig,
(int) width, (int) height);
if (!pbuffer)
return NULL;
drawable = _glitz_glx_create_drawable (screen_info, context, format,
pbuffer, pbuffer,
width, height);
if (!drawable) {
glitz_glx_pbuffer_destroy (screen_info, pbuffer);
return NULL;
}
drawable = _glitz_glx_create_drawable (screen_info, context, format,
pbuffer, pbuffer,
width, height);
if (!drawable) {
glitz_glx_pbuffer_destroy (screen_info, pbuffer);
return NULL;
}
return &drawable->base;
return &drawable->base;
}
glitz_drawable_t *
glitz_glx_create_pbuffer (void *abstract_templ,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_glx_drawable_t *templ = (glitz_glx_drawable_t *) abstract_templ;
glitz_glx_drawable_t *templ = (glitz_glx_drawable_t *) abstract_templ;
return _glitz_glx_create_pbuffer_drawable (templ->screen_info, format,
width, height);
return _glitz_glx_create_pbuffer_drawable (templ->screen_info, format,
width, height);
}
glitz_drawable_t *
glitz_glx_create_drawable_for_window (Display *display,
int screen,
glitz_drawable_format_t *format,
Window window,
unsigned int width,
unsigned int height)
int screen,
glitz_drawable_format_t *format,
Window window,
unsigned int width,
unsigned int height)
{
glitz_glx_drawable_t *drawable;
glitz_glx_screen_info_t *screen_info;
glitz_glx_context_t *context;
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;
screen_info = glitz_glx_screen_info_get (display, screen);
if (!screen_info)
return NULL;
context = glitz_glx_context_get (screen_info, format);
if (!context)
return NULL;
if (format->id >= screen_info->n_formats)
return NULL;
drawable = _glitz_glx_create_drawable (screen_info, context, format,
window, (GLXPbuffer) 0,
width, height);
if (!drawable)
return NULL;
iformat = &screen_info->formats[format->id];
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK))
return NULL;
return &drawable->base;
context = glitz_glx_context_get (screen_info, format);
if (!context)
return NULL;
drawable = _glitz_glx_create_drawable (screen_info, context, format,
window, (GLXPbuffer) 0,
width, height);
if (!drawable)
return NULL;
return &drawable->base;
}
slim_hidden_def(glitz_glx_create_drawable_for_window);
glitz_drawable_t *
glitz_glx_create_pbuffer_drawable (Display *display,
int screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
int screen,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_glx_screen_info_t *screen_info;
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;
screen_info = glitz_glx_screen_info_get (display, screen);
if (!screen_info)
return NULL;
return _glitz_glx_create_pbuffer_drawable (screen_info, format,
width, height);
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);
}
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) {
/*
* 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,
&drawable->screen_info->program_map);
glitz_glx_pop_current (abstract_drawable);
}
drawable->screen_info->drawables--;
if (drawable->screen_info->drawables == 0) {
/*
* 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,
&drawable->screen_info->program_map);
glitz_glx_pop_current (abstract_drawable);
}
if (glXGetCurrentDrawable () == drawable->drawable)
glXMakeCurrent (drawable->screen_info->display_info->display, None, NULL);
if (glXGetCurrentDrawable () == drawable->drawable)
glXMakeCurrent (drawable->screen_info->display_info->display,
None, NULL);
if (drawable->pbuffer)
glitz_glx_pbuffer_destroy (drawable->screen_info, drawable->pbuffer);
if (drawable->pbuffer)
glitz_glx_pbuffer_destroy (drawable->screen_info, drawable->pbuffer);
free (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);
glXSwapBuffers (drawable->screen_info->display_info->display,
drawable->drawable);
return 1;
}

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

@ -30,41 +30,42 @@
#include "glitz_glxint.h"
static glitz_extension_map glx_extensions[] = {
{ 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",
GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK },
{ 0.0, "GLX_ARB_multisample", GLITZ_GLX_FEATURE_MULTISAMPLE_MASK },
{ 0.0, NULL, 0 }
{ 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",
GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK },
{ 0.0, "GLX_ARB_multisample", GLITZ_GLX_FEATURE_MULTISAMPLE_MASK },
{ 0.0, NULL, 0 }
};
void
glitz_glx_query_extensions (glitz_glx_screen_info_t *screen_info,
glitz_gl_float_t glx_version)
glitz_gl_float_t glx_version)
{
const char *glx_extensions_string;
const char *glx_extensions_string;
glx_extensions_string =
glXQueryExtensionsString (screen_info->display_info->display,
screen_info->screen);
glx_extensions_string =
glXQueryExtensionsString (screen_info->display_info->display,
screen_info->screen);
screen_info->glx_feature_mask =
glitz_extensions_query (glx_version,
glx_extensions_string,
glx_extensions);
screen_info->glx_feature_mask =
glitz_extensions_query (glx_version,
glx_extensions_string,
glx_extensions);
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) {
const char *vendor;
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) {
const char *vendor;
vendor = glXGetClientString (screen_info->display_info->display,
GLX_VENDOR);
vendor = glXGetClientString (screen_info->display_info->display,
GLX_VENDOR);
if (vendor) {
if (vendor) {
/* NVIDIA's driver seem to support multisample with pbuffers */
if (!strncmp ("NVIDIA", vendor, 6))
screen_info->glx_feature_mask |=
GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK;
/* NVIDIA's driver seem to support multisample with pbuffers */
if (!strncmp ("NVIDIA", vendor, 6))
screen_info->glx_feature_mask |=
GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK;
}
}
}
}

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

@ -34,289 +34,354 @@
static int
_glitz_glx_format_compare (const void *elem1,
const void *elem2)
const void *elem2)
{
int i, score[2];
glitz_drawable_format_t *format[2];
glitz_int_drawable_format_t *format[2];
int i, score[2];
format[0] = (glitz_drawable_format_t *) elem1;
format[1] = (glitz_drawable_format_t *) elem2;
i = score[0] = score[1] = 0;
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)
score[i] += 5;
score[i] += 10;
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]->d.color.alpha_size)
{
if (format[i]->d.color.alpha_size >= 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->d.stencil_size)
score[i] += 5;
if (format[i]->d.depth_size)
score[i] += 5;
if (format[i]->d.doublebuffer)
score[i] += 10;
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 & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)
score[i] += 10;
if (format[i]->caveat)
score[i] -= 1000;
}
if (format[i]->color.green_size) {
if (format[i]->color.green_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)
score[i] += 5;
if (format[i]->depth_size)
score[i] += 5;
if (format[i]->doublebuffer)
score[i] += 10;
if (format[i]->types.window)
score[i] += 10;
if (format[i]->types.pbuffer)
score[i] += 10;
if (format[i]->samples > 1)
score[i] -= (20 - format[i]->samples);
}
return score[1] - score[0];
return score[1] - score[0];
}
static void
_glitz_add_format (glitz_glx_screen_info_t *screen_info,
glitz_drawable_format_t *format,
XID id)
_glitz_add_format (glitz_glx_screen_info_t *screen_info,
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) {
screen_info->formats[n] = *format;
screen_info->formats[n].id = n;
screen_info->format_ids[n] = id;
screen_info->n_formats++;
realloc (screen_info->formats,
sizeof (glitz_int_drawable_format_t) * (n + 1));
if (screen_info->formats)
{
screen_info->formats[n] = *format;
screen_info->formats[n].d.id = n;
screen_info->n_formats++;
}
}
static void
_glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
{
Display *display;
glitz_drawable_format_t format;
XVisualInfo visual_templ;
XVisualInfo *visuals;
int i, num_visuals;
Display *display;
glitz_int_drawable_format_t format;
XVisualInfo visual_templ;
XVisualInfo *visuals;
int i, num_visuals;
display = screen_info->display_info->display;
display = screen_info->display_info->display;
visual_templ.screen = screen_info->screen;
visuals = XGetVisualInfo (display, VisualScreenMask,
&visual_templ, &num_visuals);
visual_templ.screen = screen_info->screen;
visuals = XGetVisualInfo (display, VisualScreenMask,
&visual_templ, &num_visuals);
/* No pbuffers without fbconfigs */
format.types.window = 1;
format.types.pbuffer = 0;
format.id = 0;
/* No pbuffers without fbconfigs */
format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
format.d.id = 0;
for (i = 0; i < num_visuals; i++) {
int value;
for (i = 0; i < num_visuals; i++)
{
int value;
if ((glXGetConfig (display, &visuals[i], GLX_USE_GL, &value) != 0) ||
(value == 0))
continue;
if ((glXGetConfig (display, &visuals[i], GLX_USE_GL, &value) != 0) ||
(value == 0))
continue;
glXGetConfig (display, &visuals[i], GLX_RGBA, &value);
if (value == 0)
continue;
glXGetConfig (display, &visuals[i], GLX_RGBA, &value);
if (value == 0)
continue;
/* Stereo is not supported yet */
glXGetConfig (display, &visuals[i], GLX_STEREO, &value);
if (value != 0)
continue;
/* Stereo is not supported yet */
glXGetConfig (display, &visuals[i], GLX_STEREO, &value);
if (value != 0)
continue;
glXGetConfig (display, &visuals[i], GLX_RED_SIZE, &value);
format.color.red_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_GREEN_SIZE, &value);
format.color.green_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_BLUE_SIZE, &value);
format.color.blue_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_ALPHA_SIZE, &value);
format.color.alpha_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_DEPTH_SIZE, &value);
format.depth_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_STENCIL_SIZE, &value);
format.stencil_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_DOUBLEBUFFER, &value);
format.doublebuffer = (value) ? 1: 0;
glXGetConfig (display, &visuals[i], GLX_RED_SIZE, &value);
format.d.color.red_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_GREEN_SIZE, &value);
format.d.color.green_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_BLUE_SIZE, &value);
format.d.color.blue_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_ALPHA_SIZE, &value);
format.d.color.alpha_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_DEPTH_SIZE, &value);
format.d.depth_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_STENCIL_SIZE, &value);
format.d.stencil_size = (unsigned short) value;
glXGetConfig (display, &visuals[i], GLX_DOUBLEBUFFER, &value);
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) {
glXGetConfig (display, &visuals[i], GLX_SAMPLES_ARB, &value);
format.samples = (unsigned short) (value > 1)? value: 1;
} else
format.samples = 1;
} else
format.samples = 1;
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;
_glitz_add_format (screen_info, &format, visuals[i].visualid);
}
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.d.samples = (unsigned short) (value > 1)? value: 1;
}
else
format.d.samples = 1;
}
else
format.d.samples = 1;
if (visuals)
XFree (visuals);
format.u.uval = visuals[i].visualid;
_glitz_add_format (screen_info, &format);
}
if (visuals)
XFree (visuals);
}
static glitz_status_t
_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;
GLXFBConfig *fbconfigs;
int i, num_configs;
XID id;
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
Display *display;
glitz_int_drawable_format_t format;
GLXFBConfig *fbconfigs;
int i, num_configs;
display = screen_info->display_info->display;
display = screen_info->display_info->display;
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;
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;
return GLITZ_STATUS_NOT_SUPPORTED;
}
return GLITZ_STATUS_NOT_SUPPORTED;
}
for (i = 0; i < num_configs; i++) {
int value;
for (i = 0; i < num_configs; i++)
{
int value;
if ((glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_RENDER_TYPE, &value) != 0) ||
(!(value & GLX_RGBA_BIT)))
continue;
if ((glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_RENDER_TYPE, &value) != 0) ||
(!(value & GLX_RGBA_BIT)))
continue;
/* Stereo is not supported yet */
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STEREO, &value);
if (value != 0)
continue;
/* Stereo is not supported yet */
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STEREO, &value);
if (value != 0)
continue;
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_DRAWABLE_TYPE, &value);
if (!((value & GLX_WINDOW_BIT) || (value & GLX_PBUFFER_BIT)))
continue;
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_DRAWABLE_TYPE, &value);
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;
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.id = 0;
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) {
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_SAMPLES_ARB, &value);
format.samples = (unsigned short) (value > 1)? value: 1;
if (format.samples > 1) {
if (!(screen_info->glx_feature_mask &
GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK))
format.types.pbuffer = 0;
}
} else
format.samples = 1;
} else
format.samples = 1;
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_FBCONFIG_ID,
&value);
format.u.uval = value;
_glitz_add_format (screen_info, &format, id);
}
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_RED_SIZE, &value);
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 (fbconfigs)
XFree (fbconfigs);
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)
{
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_SAMPLES_ARB, &value);
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 &= ~GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
}
}
else
format.d.samples = 1;
}
else
format.d.samples = 1;
return GLITZ_STATUS_SUCCESS;
_glitz_add_format (screen_info, &format);
}
if (fbconfigs)
XFree (fbconfigs);
return GLITZ_STATUS_SUCCESS;
}
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;
glitz_status_t status = GLITZ_STATUS_NOT_SUPPORTED;
int i;
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
status = _glitz_glx_query_formats_using_fbconfigs (screen_info);
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
status = _glitz_glx_query_formats_using_fbconfigs (screen_info);
if (status)
_glitz_glx_query_formats (screen_info);
if (status)
_glitz_glx_query_formats (screen_info);
if (!screen_info->n_formats)
return;
if (!screen_info->n_formats)
return;
qsort (screen_info->formats, screen_info->n_formats,
sizeof (glitz_drawable_format_t), _glitz_glx_format_compare);
qsort (screen_info->formats, screen_info->n_formats,
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,
int screen,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
glitz_glx_find_window_format (Display *display,
int screen,
unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
{
glitz_glx_screen_info_t *screen_info =
glitz_glx_screen_info_get (display, screen);
glitz_int_drawable_format_t itempl;
glitz_glx_screen_info_t *screen_info =
glitz_glx_screen_info_get (display, screen);
return glitz_drawable_format_find (screen_info->formats,
screen_info->n_formats,
mask, templ, count);
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, &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,
int screen,
VisualID visual_id)
int screen,
VisualID visual_id)
{
glitz_drawable_format_t *format = NULL;
glitz_glx_screen_info_t *screen_info;
@ -324,54 +389,54 @@ glitz_glx_find_drawable_format_for_visual (Display *display,
screen_info = glitz_glx_screen_info_get (display, screen);
if (!screen_info)
return NULL;
return NULL;
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
{
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
GLXFBConfig *fbconfigs;
int fid, n_fbconfigs;
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
GLXFBConfig *fbconfigs;
int fid, n_fbconfigs;
fid = -1;
fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs);
for (i = 0; i < n_fbconfigs; i++)
{
XVisualInfo *visinfo;
fid = -1;
fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs);
for (i = 0; i < n_fbconfigs; i++)
{
XVisualInfo *visinfo;
visinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]);
if (visinfo && visinfo->visualid == visual_id)
{
int value;
visinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]);
if (visinfo && visinfo->visualid == visual_id)
{
int value;
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_FBCONFIG_ID, &value);
for (fid = 0; fid < screen_info->n_formats; fid++)
{
if (screen_info->format_ids[fid] == value)
{
format = screen_info->formats + fid;
break;
}
}
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_FBCONFIG_ID, &value);
for (fid = 0; fid < screen_info->n_formats; fid++)
{
if (screen_info->formats[fid].u.uval == value)
{
format = &screen_info->formats[fid].d;
break;
}
}
if (format)
break;
}
}
if (format)
break;
}
}
if (fbconfigs)
XFree (fbconfigs);
if (fbconfigs)
XFree (fbconfigs);
}
else
{
for (i = 0; i < screen_info->n_formats; i++)
{
if (visual_id == screen_info->format_ids[i])
{
format = screen_info->formats + i;
break;
}
}
for (i = 0; i < screen_info->n_formats; i++)
{
if (visual_id == screen_info->formats[i].u.uval)
{
format = &screen_info->formats[i].d;
break;
}
}
}
return format;
@ -380,44 +445,48 @@ slim_hidden_def(glitz_glx_find_drawable_format_for_visual);
XVisualInfo *
glitz_glx_get_visual_info_from_format (Display *display,
int screen,
glitz_drawable_format_t *format)
int screen,
glitz_drawable_format_t *format)
{
XVisualInfo *vinfo = NULL;
glitz_glx_screen_info_t *screen_info =
glitz_glx_screen_info_get (display, screen);
glitz_glx_static_proc_address_list_t *glx = &screen_info->glx;
XVisualInfo *vinfo = NULL;
glitz_glx_screen_info_t *screen_info =
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) {
GLXFBConfig *fbconfigs;
int i, n_fbconfigs;
int fbconfigid = screen_info->format_ids[format->id];
if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK)
{
GLXFBConfig *fbconfigs;
int i, n_fbconfigs;
int fbconfigid = screen_info->formats[format->id].u.uval;
fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs);
for (i = 0; i < n_fbconfigs; i++) {
int value;
fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs);
for (i = 0; i < n_fbconfigs; i++)
{
int value;
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_FBCONFIG_ID, &value);
if (value == fbconfigid)
break;
glx->get_fbconfig_attrib (display, fbconfigs[i],
GLX_FBCONFIG_ID, &value);
if (value == fbconfigid)
break;
}
if (i < n_fbconfigs)
vinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]);
if (fbconfigs)
XFree (fbconfigs);
}
else
{
XVisualInfo templ;
int n_items;
templ.visualid = screen_info->formats[format->id].u.uval;
vinfo = XGetVisualInfo (display, VisualIDMask, &templ, &n_items);
}
if (i < n_fbconfigs)
vinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]);
if (fbconfigs)
XFree (fbconfigs);
} else {
XVisualInfo templ;
int n_items;
templ.visualid = screen_info->format_ids[format->id];
vinfo = XGetVisualInfo (display, VisualIDMask, &templ, &n_items);
}
return vinfo;
return vinfo;
}
slim_hidden_def(glitz_glx_get_visual_info_from_format);

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

@ -34,219 +34,244 @@
glitz_gl_proc_address_list_t _glitz_glx_gl_proc_address = {
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(glitz_gl_bind_texture_t) glBindTexture,
(glitz_gl_tex_image_2d_t) glTexImage2D,
(glitz_gl_tex_parameter_i_t) glTexParameteri,
(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,
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(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,
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(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
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(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_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
glitz_glx_get_proc_address (const char *name,
void *closure)
void *closure)
{
glitz_glx_screen_info_t *screen_info = (glitz_glx_screen_info_t *) closure;
glitz_glx_thread_info_t *info = screen_info->display_info->thread_info;
glitz_function_pointer_t address = NULL;
glitz_glx_screen_info_t *screen_info = (glitz_glx_screen_info_t *) closure;
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)
info->dlhand = dlopen (info->gl_library, RTLD_LAZY);
if (!address) {
if (!info->dlhand)
info->dlhand = dlopen (info->gl_library, RTLD_LAZY);
if (info->dlhand) {
dlerror ();
address = (glitz_function_pointer_t) dlsym (info->dlhand, name);
if (dlerror () != NULL)
address = NULL;
if (info->dlhand) {
dlerror ();
address = (glitz_function_pointer_t) dlsym (info->dlhand, name);
if (dlerror () != NULL)
address = NULL;
}
}
}
return address;
return address;
}
static void
_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 ("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)
glitz_glx_get_proc_address ("glXCreateNewContext",
(void *) 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 ("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)
glitz_glx_get_proc_address ("glXCreateNewContext",
(void *) screen_info);
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)
glitz_glx_get_proc_address ("glXDestroyPbuffer",
(void *) screen_info);
screen_info->glx.query_drawable = (glitz_glx_query_drawable_t)
glitz_glx_get_proc_address ("glXQueryDrawable",
(void *) screen_info);
}
} else {
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)
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)
glitz_glx_get_proc_address ("glXCreateContextWithConfigSGIX",
(void *) screen_info);
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)
glitz_glx_get_proc_address ("glXDestroyPbuffer",
(void *) screen_info);
screen_info->glx.query_drawable =
(glitz_glx_query_drawable_t)
glitz_glx_get_proc_address ("glXQueryDrawable",
(void *) screen_info);
}
} else {
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)
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)
glitz_glx_get_proc_address ("glXCreateContextWithConfigSGIX",
(void *) screen_info);
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)
glitz_glx_get_proc_address ("glXDestroyGLXPbufferSGIX",
(void *) screen_info);
screen_info->glx.query_drawable = (glitz_glx_query_drawable_t)
glitz_glx_get_proc_address ("glXQueryGLXPbufferSGIX",
(void *) screen_info);
}
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)
glitz_glx_get_proc_address ("glXDestroyGLXPbufferSGIX",
(void *) screen_info);
screen_info->glx.query_drawable = (glitz_glx_query_drawable_t)
glitz_glx_get_proc_address ("glXQueryGLXPbufferSGIX",
(void *) screen_info);
}
}
if ((!screen_info->glx.create_pbuffer) ||
(!screen_info->glx.destroy_pbuffer) ||
(!screen_info->glx.query_drawable))
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK;
if ((!screen_info->glx.get_fbconfigs) ||
(!screen_info->glx.get_fbconfig_attrib) ||
(!screen_info->glx.get_visual_from_fbconfig) ||
(!screen_info->glx.create_new_context)) {
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_FBCONFIG_MASK;
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK;
}
} else
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK;
if (screen_info->glx_feature_mask &
GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK) {
if (screen_info->glx_version >= 1.3f) {
screen_info->glx.make_context_current =
(glitz_glx_make_context_current_t)
glitz_glx_get_proc_address ("glXMakeContextCurrent",
(void *) screen_info);
} else {
screen_info->glx.make_context_current =
(glitz_glx_make_context_current_t)
glitz_glx_get_proc_address ("glXMakeCurrentReadSGI",
(void *) screen_info);
}
if (!screen_info->glx.make_context_current)
screen_info->glx_feature_mask &=
~GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK;
}
if ((!screen_info->glx.create_pbuffer) ||
(!screen_info->glx.destroy_pbuffer) ||
(!screen_info->glx.query_drawable))
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK;
if (screen_info->glx_feature_mask &
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);
} else {
screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t)
glitz_glx_get_proc_address ("glXGetProcAddressARB",
(void *) screen_info);
}
if ((!screen_info->glx.get_fbconfigs) ||
(!screen_info->glx.get_fbconfig_attrib) ||
(!screen_info->glx.get_visual_from_fbconfig) ||
(!screen_info->glx.create_new_context)) {
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_FBCONFIG_MASK;
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK;
if (!screen_info->glx.get_proc_address)
screen_info->glx_feature_mask &=
~GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK;
}
} else
screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK;
if (screen_info->glx_feature_mask &
GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK) {
if (screen_info->glx_version >= 1.3f) {
screen_info->glx.make_context_current =
(glitz_glx_make_context_current_t)
glitz_glx_get_proc_address ("glXMakeContextCurrent",
(void *) screen_info);
} else {
screen_info->glx.make_context_current =
(glitz_glx_make_context_current_t)
glitz_glx_get_proc_address ("glXMakeCurrentReadSGI",
(void *) screen_info);
}
if (!screen_info->glx.make_context_current)
screen_info->glx_feature_mask &=
~GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK;
}
if (screen_info->glx_feature_mask &
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);
} else {
screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t)
glitz_glx_get_proc_address ("glXGetProcAddressARB",
(void *) screen_info);
}
if (!screen_info->glx.get_proc_address)
screen_info->glx_feature_mask &=
~GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK;
}
}
static void
@ -258,27 +283,27 @@ _glitz_glx_screen_destroy (glitz_glx_screen_info_t *screen_info);
static void
_glitz_glx_thread_info_fini (glitz_glx_thread_info_t *thread_info)
{
int i;
int i;
for (i = 0; i < thread_info->n_displays; i++)
_glitz_glx_display_destroy (thread_info->displays[i]);
for (i = 0; i < thread_info->n_displays; i++)
_glitz_glx_display_destroy (thread_info->displays[i]);
free (thread_info->displays);
free (thread_info->displays);
thread_info->displays = NULL;
thread_info->n_displays = 0;
thread_info->displays = NULL;
thread_info->n_displays = 0;
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
if (thread_info->dlhand) {
dlclose (thread_info->dlhand);
thread_info->dlhand = NULL;
}
if (thread_info->dlhand) {
dlclose (thread_info->dlhand);
thread_info->dlhand = NULL;
}
thread_info->cctx = NULL;
thread_info->cctx = NULL;
}
#ifdef XTHREADS
@ -293,108 +318,108 @@ static xthread_key_t info_tsd;
static void
_glitz_glx_thread_info_init (glitz_glx_thread_info_t *thread_info)
{
thread_info->displays = NULL;
thread_info->n_displays = 0;
thread_info->gl_library = NULL;
thread_info->dlhand = NULL;
thread_info->cctx = NULL;
thread_info->displays = NULL;
thread_info->n_displays = 0;
thread_info->gl_library = NULL;
thread_info->dlhand = NULL;
thread_info->cctx = NULL;
}
static void
_glitz_glx_thread_info_destroy (glitz_glx_thread_info_t *thread_info)
{
xthread_set_specific (info_tsd, NULL);
xthread_set_specific (info_tsd, NULL);
if (thread_info) {
_glitz_glx_thread_info_fini (thread_info);
free (thread_info);
}
if (thread_info) {
_glitz_glx_thread_info_fini (thread_info);
free (thread_info);
}
}
static void
_tsd_destroy (void *p)
{
if (p) {
_glitz_glx_thread_info_fini ((glitz_glx_thread_info_t *) p);
free (p);
}
if (p) {
_glitz_glx_thread_info_fini ((glitz_glx_thread_info_t *) p);
free (p);
}
}
static glitz_glx_thread_info_t *
_glitz_glx_thread_info_get (const char *gl_library)
{
glitz_glx_thread_info_t *thread_info;
void *p;
glitz_glx_thread_info_t *thread_info;
void *p;
if (!tsd_initialized) {
xthread_key_create (&info_tsd, _tsd_destroy);
tsd_initialized = 1;
}
xthread_get_specific (info_tsd, &p);
if (p == NULL) {
thread_info = malloc (sizeof (glitz_glx_thread_info_t));
_glitz_glx_thread_info_init (thread_info);
xthread_set_specific (info_tsd, thread_info);
} else
thread_info = (glitz_glx_thread_info_t *) p;
if (gl_library) {
int len = strlen (gl_library);
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
if (!tsd_initialized) {
xthread_key_create (&info_tsd, _tsd_destroy);
tsd_initialized = 1;
}
thread_info->gl_library = malloc (len + 1);
if (thread_info->gl_library) {
memcpy (thread_info->gl_library, gl_library, len);
thread_info->gl_library[len] = '\0';
}
}
xthread_get_specific (info_tsd, &p);
return thread_info;
if (p == NULL) {
thread_info = malloc (sizeof (glitz_glx_thread_info_t));
_glitz_glx_thread_info_init (thread_info);
xthread_set_specific (info_tsd, thread_info);
} else
thread_info = (glitz_glx_thread_info_t *) p;
if (gl_library) {
int len = strlen (gl_library);
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
thread_info->gl_library = malloc (len + 1);
if (thread_info->gl_library) {
memcpy (thread_info->gl_library, gl_library, len);
thread_info->gl_library[len] = '\0';
}
}
return thread_info;
}
#else
/* not thread safe */
static glitz_glx_thread_info_t thread_info = {
NULL,
0,
NULL,
NULL
NULL,
0,
NULL,
NULL
};
static void
_glitz_glx_thread_info_destroy (glitz_glx_thread_info_t *thread_info)
{
if (thread_info)
_glitz_glx_thread_info_fini (thread_info);
if (thread_info)
_glitz_glx_thread_info_fini (thread_info);
}
static glitz_glx_thread_info_t *
_glitz_glx_thread_info_get (const char *gl_library)
{
if (gl_library) {
int len = strlen (gl_library);
if (gl_library) {
int len = strlen (gl_library);
if (thread_info.gl_library) {
free (thread_info.gl_library);
thread_info.gl_library = NULL;
if (thread_info.gl_library) {
free (thread_info.gl_library);
thread_info.gl_library = NULL;
}
thread_info.gl_library = malloc (len + 1);
if (thread_info.gl_library) {
memcpy (thread_info.gl_library, gl_library, len);
thread_info.gl_library[len] = '\0';
}
}
thread_info.gl_library = malloc (len + 1);
if (thread_info.gl_library) {
memcpy (thread_info.gl_library, gl_library, len);
thread_info.gl_library[len] = '\0';
}
}
return &thread_info;
return &thread_info;
}
#endif
@ -402,143 +427,142 @@ _glitz_glx_thread_info_get (const char *gl_library)
static glitz_glx_display_info_t *
_glitz_glx_display_info_get (Display *display)
{
glitz_glx_display_info_t *display_info;
glitz_glx_thread_info_t *thread_info = _glitz_glx_thread_info_get (NULL);
glitz_glx_display_info_t **displays = thread_info->displays;
int index, n_displays = thread_info->n_displays;
glitz_glx_display_info_t *display_info;
glitz_glx_thread_info_t *thread_info = _glitz_glx_thread_info_get (NULL);
glitz_glx_display_info_t **displays = thread_info->displays;
int index, n_displays = thread_info->n_displays;
for (; n_displays; n_displays--, displays++)
if ((*displays)->display == display)
return *displays;
for (; n_displays; n_displays--, displays++)
if ((*displays)->display == display)
return *displays;
index = thread_info->n_displays++;
index = thread_info->n_displays++;
thread_info->displays =
realloc (thread_info->displays,
sizeof (glitz_glx_display_info_t *) * thread_info->n_displays);
thread_info->displays =
realloc (thread_info->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;
display_info = malloc (sizeof (glitz_glx_display_info_t));
thread_info->displays[index] = display_info;
display_info->thread_info = thread_info;
display_info->display = display;
display_info->screens = NULL;
display_info->n_screens = 0;
display_info->thread_info = thread_info;
display_info->display = display;
display_info->screens = NULL;
display_info->n_screens = 0;
return display_info;
return display_info;
}
static void
_glitz_glx_display_destroy (glitz_glx_display_info_t *display_info)
{
int i;
int i;
for (i = 0; i < display_info->n_screens; i++)
_glitz_glx_screen_destroy (display_info->screens[i]);
for (i = 0; i < display_info->n_screens; i++)
_glitz_glx_screen_destroy (display_info->screens[i]);
if (display_info->screens)
free (display_info->screens);
if (display_info->screens)
free (display_info->screens);
free (display_info);
free (display_info);
}
glitz_glx_screen_info_t *
glitz_glx_screen_info_get (Display *display,
int screen)
int screen)
{
glitz_glx_screen_info_t *screen_info;
glitz_glx_display_info_t *display_info =
_glitz_glx_display_info_get (display);
glitz_glx_screen_info_t **screens = display_info->screens;
int error_base, event_base, index, n_screens = display_info->n_screens;
glitz_glx_screen_info_t *screen_info;
glitz_glx_display_info_t *display_info =
_glitz_glx_display_info_get (display);
glitz_glx_screen_info_t **screens = display_info->screens;
int error_base, event_base, index, n_screens = display_info->n_screens;
for (; n_screens; n_screens--, screens++)
if ((*screens)->screen == screen)
return *screens;
for (; n_screens; n_screens--, screens++)
if ((*screens)->screen == screen)
return *screens;
index = display_info->n_screens++;
index = display_info->n_screens++;
display_info->screens =
realloc (display_info->screens,
sizeof (glitz_glx_screen_info_t *) * display_info->n_screens);
display_info->screens =
realloc (display_info->screens,
sizeof (glitz_glx_screen_info_t *) * display_info->n_screens);
screen_info = malloc (sizeof (glitz_glx_screen_info_t));
display_info->screens[index] = screen_info;
screen_info = malloc (sizeof (glitz_glx_screen_info_t));
display_info->screens[index] = screen_info;
screen_info->display_info = display_info;
screen_info->screen = screen;
screen_info->drawables = 0;
screen_info->formats = NULL;
screen_info->format_ids = NULL;
screen_info->n_formats = 0;
screen_info->display_info = display_info;
screen_info->screen = screen;
screen_info->drawables = 0;
screen_info->formats = NULL;
screen_info->n_formats = 0;
screen_info->contexts = NULL;
screen_info->n_contexts = 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);
glitz_program_map_init (&screen_info->program_map);
screen_info->root_context = (GLXContext) 0;
screen_info->glx_feature_mask = 0;
screen_info->root_context = (GLXContext) 0;
screen_info->glx_feature_mask = 0;
if (glXQueryExtension (display, &error_base, &event_base)) {
int major, minor;
if (glXQueryExtension (display, &error_base, &event_base)) {
int major, minor;
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_proc_address_lookup (screen_info);
glitz_glx_query_formats (screen_info);
}
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_proc_address_lookup (screen_info);
glitz_glx_query_formats (screen_info);
}
}
}
}
screen_info->context_stack_size = 1;
screen_info->context_stack->drawable = NULL;
screen_info->context_stack->surface = NULL;
screen_info->context_stack->constraint = GLITZ_NONE;
screen_info->context_stack_size = 1;
screen_info->context_stack->drawable = NULL;
screen_info->context_stack->surface = NULL;
screen_info->context_stack->constraint = GLITZ_NONE;
return screen_info;
return screen_info;
}
static void
_glitz_glx_screen_destroy (glitz_glx_screen_info_t *screen_info)
{
Display *display = screen_info->display_info->display;
int i;
Display *display = screen_info->display_info->display;
int i;
if (screen_info->root_context)
glXMakeCurrent (display, None, NULL);
if (screen_info->root_context)
glXMakeCurrent (display, None, NULL);
for (i = 0; i < screen_info->n_contexts; i++)
glitz_glx_context_destroy (screen_info, screen_info->contexts[i]);
for (i = 0; i < screen_info->n_contexts; i++)
glitz_glx_context_destroy (screen_info, screen_info->contexts[i]);
if (screen_info->contexts)
free (screen_info->contexts);
if (screen_info->contexts)
free (screen_info->contexts);
if (screen_info->formats)
free (screen_info->formats);
if (screen_info->formats)
free (screen_info->formats);
if (screen_info->format_ids)
free (screen_info->format_ids);
free (screen_info);
free (screen_info);
}
void
glitz_glx_init (const char *gl_library)
{
_glitz_glx_thread_info_get (gl_library);
_glitz_glx_thread_info_get (gl_library);
}
slim_hidden_def(glitz_glx_init);
void
glitz_glx_fini (void)
{
glitz_glx_thread_info_t *info = _glitz_glx_thread_info_get (NULL);
glitz_glx_thread_info_t *info = _glitz_glx_thread_info_get (NULL);
_glitz_glx_thread_info_destroy (info);
_glitz_glx_thread_info_destroy (info);
}
slim_hidden_def(glitz_glx_fini);

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

@ -31,37 +31,37 @@
GLXPbuffer
glitz_glx_pbuffer_create (glitz_glx_screen_info_t *screen_info,
GLXFBConfig fbconfig,
int width,
int height)
GLXFBConfig fbconfig,
int width,
int height)
{
if (fbconfig) {
int attributes[9];
Display *dpy = screen_info->display_info->display;
attributes[0] = GLX_PBUFFER_WIDTH;
attributes[1] = width;
if (fbconfig) {
int attributes[9];
attributes[2] = GLX_PBUFFER_HEIGHT;
attributes[3] = height;
attributes[0] = GLX_PBUFFER_WIDTH;
attributes[1] = width;
attributes[4] = GLX_LARGEST_PBUFFER;
attributes[5] = 0;
attributes[2] = GLX_PBUFFER_HEIGHT;
attributes[3] = height;
attributes[6] = GLX_PRESERVED_CONTENTS;
attributes[7] = 1;
attributes[8] = 0;
attributes[4] = GLX_LARGEST_PBUFFER;
attributes[5] = 0;
return
screen_info->glx.create_pbuffer (screen_info->display_info->display,
fbconfig, attributes);
} else
return (GLXPbuffer) 0;
attributes[6] = GLX_PRESERVED_CONTENTS;
attributes[7] = 1;
attributes[8] = 0;
return screen_info->glx.create_pbuffer (dpy, fbconfig, attributes);
} else
return (GLXPbuffer) 0;
}
void
glitz_glx_pbuffer_destroy (glitz_glx_screen_info_t *screen_info,
GLXPbuffer pbuffer)
GLXPbuffer pbuffer)
{
screen_info->glx.destroy_pbuffer (screen_info->display_info->display,
pbuffer);
screen_info->glx.destroy_pbuffer (screen_info->display_info->display,
pbuffer);
}

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