зеркало из https://github.com/mozilla/pjs.git
Merge from org.mozilla.cvs.cairo branch.
- Cairo 1.1.1 - Updated thebes, gfx/src/thebes - Fixes to plugins with thebes gfx under linux - Native theme fixes with thebes rendering (NOTE: widget changes only enabled when building with thebes, otherwise all old code)
This commit is contained in:
Родитель
04ff4a140c
Коммит
8994df8c7d
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -3932,6 +3932,7 @@ AC_SUBST(MOC)
|
|||
if test "$MOZ_ENABLE_CAIRO_GFX"
|
||||
then
|
||||
AC_DEFINE(MOZ_THEBES)
|
||||
AC_DEFINE(MOZ_CAIRO_GFX)
|
||||
fi
|
||||
|
||||
if test "$MOZ_ENABLE_GTK" \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Snapshots of cairo, libpixman, and glitz for mozilla usage. Where possible,
|
||||
Snapshots of cairo and glitz for mozilla usage. Where possible,
|
||||
these should be official releases from the cairo project as-is. If
|
||||
changes are necessary, they should be documented below and the patch
|
||||
file included in this directory.
|
||||
|
@ -10,29 +10,10 @@ http://www.cairographics.org/.
|
|||
|
||||
VERSIONS:
|
||||
|
||||
cairo 0.9.1
|
||||
libpixman 0.1.5
|
||||
glitz 0.4.0
|
||||
cairo 1.1.1 (cvs)
|
||||
glitz 0.5.0
|
||||
|
||||
***** NOTE FOR VISUAL C++ 6.0 *****
|
||||
|
||||
VC6 cannot build pixman correctly for various reasons. There is a static
|
||||
win32 pixman library provided in libpixman/src/pixman-vc71.lib that will
|
||||
be used instead of building on all Win32/Visual C++ builds. Building with
|
||||
VC7.1, gcc/mingw, or anything else other than VC6 is fine.
|
||||
|
||||
PATCHES:
|
||||
|
||||
stdint.h - select between inttypes.h, stdint.h, and mozstdint.h.
|
||||
|
||||
dash-dos.diff - prevent DOS attack with dasharray.
|
||||
|
||||
alphablend.diff - check for AlphaBlend usability at runtime (win32)
|
||||
|
||||
feature-tests.diff - change #if to #ifdef, and change
|
||||
cairo-features.h.in to #define things based on mozilla configure
|
||||
tests
|
||||
|
||||
allow-null-surface.diff - allow creating a cairo_t with a NULL
|
||||
target surface
|
||||
atsui-empty.diff - prevent OS-X crash with empty string
|
||||
VC6 cannot build pixman from cairo. Therefore, VC6 builds are not supported
|
||||
if cairo is enabled. Please upgrade to VC7.1/8.
|
||||
|
|
|
@ -43,6 +43,8 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
VISIBILITY_FLAGS =
|
||||
|
||||
MODULE = cairo
|
||||
LIBRARY_NAME = mozcairo
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
@ -79,6 +81,7 @@ CSRCS = \
|
|||
cairo-pen.c \
|
||||
cairo-polygon.c \
|
||||
cairo-region.c \
|
||||
cairo-scaled-font.c \
|
||||
cairo-slope.c \
|
||||
cairo-spline.c \
|
||||
cairo-surface.c \
|
||||
|
@ -87,7 +90,7 @@ CSRCS = \
|
|||
cairo-wideint.c \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = cairo.h cairo-features.h
|
||||
EXPORTS = cairo.h cairo-features.h cairo-platform.h
|
||||
|
||||
|
||||
ifeq ($(MOZ_GFX_TOOLKIT),windows)
|
||||
|
|
|
@ -100,27 +100,19 @@ _arc_max_angle_for_tolerance_normalized (double tolerance)
|
|||
return angle;
|
||||
}
|
||||
|
||||
/* XXX: The computation here if bogus. Correct math (with proof!) is
|
||||
* available in _cairo_pen_vertices_needed. */
|
||||
static int
|
||||
_arc_segments_needed (double angle,
|
||||
double radius,
|
||||
cairo_matrix_t *ctm,
|
||||
double tolerance)
|
||||
{
|
||||
double l1, l2, lmax;
|
||||
double max_angle;
|
||||
double major_axis, max_angle;
|
||||
|
||||
_cairo_matrix_compute_eigen_values (ctm, &l1, &l2);
|
||||
|
||||
l1 = fabs (l1);
|
||||
l2 = fabs (l2);
|
||||
if (l1 > l2)
|
||||
lmax = l1;
|
||||
else
|
||||
lmax = l2;
|
||||
|
||||
max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / (radius * lmax));
|
||||
/* the error is amplified by at most the length of the
|
||||
* major axis of the circle; see cairo-pen.c for a more detailed analysis
|
||||
* of this. */
|
||||
major_axis = _cairo_matrix_transformed_circle_major_axis (ctm, radius);
|
||||
max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / major_axis);
|
||||
|
||||
return (int) ceil (angle / max_angle);
|
||||
}
|
||||
|
|
|
@ -38,35 +38,85 @@
|
|||
#include "cairo-atsui.h"
|
||||
#include "cairoint.h"
|
||||
#include "cairo.h"
|
||||
#if 0
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
|
||||
* here so we can use older SDKs.
|
||||
*/
|
||||
#ifndef FixedToFloat
|
||||
#define fixed1 ((Fixed) 0x00010000L)
|
||||
#define FixedToFloat(a) ((float)(a) / fixed1)
|
||||
#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1))
|
||||
#endif
|
||||
typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
|
||||
typedef struct _cairo_atsui_font cairo_atsui_font_t;
|
||||
|
||||
typedef struct {
|
||||
static cairo_status_t _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
||||
ATSUFontID font_id,
|
||||
ATSUStyle style,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font_out);
|
||||
|
||||
struct _cairo_atsui_font {
|
||||
cairo_scaled_font_t base;
|
||||
|
||||
cairo_matrix_t scale;
|
||||
ATSUStyle style;
|
||||
ATSUStyle unscaled_style;
|
||||
ATSUFontID fontID;
|
||||
} cairo_atsui_font_t;
|
||||
};
|
||||
|
||||
|
||||
struct _cairo_atsui_font_face {
|
||||
cairo_font_face_t base;
|
||||
ATSUFontID font_id;
|
||||
};
|
||||
|
||||
static void
|
||||
_cairo_atsui_font_face_destroy (void *abstract_face)
|
||||
{
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_face_scaled_font_create (void *abstract_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font)
|
||||
{
|
||||
cairo_atsui_font_face_t *font_face = abstract_face;
|
||||
OSStatus err;
|
||||
ATSUAttributeTag styleTags[] = { kATSUFontTag };
|
||||
ATSUAttributeValuePtr styleValues[] = { &font_face->font_id };
|
||||
ByteCount styleSizes[] = { sizeof(ATSUFontID) };
|
||||
ATSUStyle style;
|
||||
|
||||
err = ATSUCreateStyle (&style);
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(styleTags) / sizeof(styleTags[0]),
|
||||
styleTags, styleSizes, styleValues);
|
||||
|
||||
return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
|
||||
font_matrix, ctm, options, font);
|
||||
}
|
||||
|
||||
static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
|
||||
_cairo_atsui_font_face_destroy,
|
||||
_cairo_atsui_font_face_scaled_font_create
|
||||
};
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
|
||||
{
|
||||
cairo_atsui_font_face_t *font_face;
|
||||
|
||||
font_face = malloc (sizeof (cairo_atsui_font_face_t));
|
||||
if (!font_face) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
font_face->font_id = font_id;
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_atsui_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
typedef struct cairo_ATSUI_glyph_path_callback_info_t {
|
||||
cairo_path_fixed_t *path;
|
||||
cairo_matrix_t scale;
|
||||
} cairo_ATSUI_glyph_path_callback_info_t;
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend;
|
||||
|
||||
static CGAffineTransform
|
||||
CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
|
||||
|
@ -82,7 +132,6 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
|
|||
ATSUStyle style;
|
||||
OSStatus err;
|
||||
|
||||
|
||||
// Set the style's size
|
||||
CGAffineTransform theTransform =
|
||||
CGAffineTransformMakeWithCairoFontScale(scale);
|
||||
|
@ -103,6 +152,86 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
|
|||
return style;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
|
||||
{
|
||||
ATSFontRef atsFont;
|
||||
ATSFontMetrics metrics;
|
||||
OSStatus err;
|
||||
|
||||
atsFont = FMGetATSFontRefFromFont(font->fontID);
|
||||
|
||||
if (atsFont) {
|
||||
err =
|
||||
ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault,
|
||||
&metrics);
|
||||
|
||||
if (err == noErr) {
|
||||
cairo_font_extents_t extents;
|
||||
|
||||
extents.ascent = metrics.ascent;
|
||||
extents.descent = metrics.descent;
|
||||
extents.height = metrics.capHeight;
|
||||
extents.max_x_advance = metrics.maxAdvanceWidth;
|
||||
|
||||
// The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
|
||||
extents.max_y_advance = 0.0;
|
||||
|
||||
_cairo_scaled_font_set_metrics (&font->base, &extents);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
||||
ATSUFontID font_id,
|
||||
ATSUStyle style,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font_out)
|
||||
{
|
||||
cairo_atsui_font_t *font = NULL;
|
||||
cairo_matrix_t scale;
|
||||
OSStatus err;
|
||||
cairo_status_t status;
|
||||
|
||||
font = malloc(sizeof(cairo_atsui_font_t));
|
||||
|
||||
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
|
||||
&cairo_atsui_scaled_font_backend);
|
||||
|
||||
cairo_matrix_multiply(&scale, font_matrix, ctm);
|
||||
font->style = CreateSizedCopyOfStyle(style, &scale);
|
||||
|
||||
Fixed theSize = FloatToFixed(1.0);
|
||||
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
|
||||
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
|
||||
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(theFontStyleTags) /
|
||||
sizeof(ATSUAttributeTag), theFontStyleTags,
|
||||
theFontStyleSizes, theFontStyleValues);
|
||||
|
||||
font->unscaled_style = style;
|
||||
|
||||
font->fontID = font_id;
|
||||
font->scale = scale;
|
||||
|
||||
*font_out = &font->base;
|
||||
|
||||
status = _cairo_atsui_font_set_metrics (font);
|
||||
if (status) {
|
||||
cairo_scaled_font_destroy (&font->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
||||
|
@ -111,12 +240,10 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
|||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font_out)
|
||||
{
|
||||
cairo_atsui_font_t *font = NULL;
|
||||
ATSUStyle style;
|
||||
ATSUFontID fontID;
|
||||
OSStatus err;
|
||||
Boolean isItalic, isBold;
|
||||
cairo_matrix_t scale;
|
||||
const char *family = toy_face->family;
|
||||
|
||||
err = ATSUCreateStyle(&style);
|
||||
|
@ -173,43 +300,19 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
|||
kFontNoLanguageCode, &fontID);
|
||||
}
|
||||
|
||||
|
||||
ATSUAttributeTag styleTags[] =
|
||||
{ kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
|
||||
ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
|
||||
ByteCount styleSizes[] =
|
||||
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
|
||||
|
||||
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(styleTags) / sizeof(styleTags[0]),
|
||||
styleTags, styleSizes, styleValues);
|
||||
|
||||
font = malloc(sizeof(cairo_atsui_font_t));
|
||||
|
||||
_cairo_scaled_font_init(&font->base, toy_face, font_matrix, ctm, options,
|
||||
&cairo_atsui_scaled_font_backend);
|
||||
|
||||
cairo_matrix_multiply(&scale, font_matrix, ctm);
|
||||
font->style = CreateSizedCopyOfStyle(style, &scale);
|
||||
|
||||
Fixed theSize = FloatToFixed(1.0);
|
||||
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
|
||||
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
|
||||
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(theFontStyleTags) /
|
||||
sizeof(ATSUAttributeTag), theFontStyleTags,
|
||||
theFontStyleSizes, theFontStyleValues);
|
||||
|
||||
font->unscaled_style = style;
|
||||
|
||||
font->fontID = fontID;
|
||||
font->scale = scale;
|
||||
|
||||
*font_out = &font->base;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
|
||||
font_matrix, ctm, options, font_out);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -226,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 (&matrix, 0.5, 0.5);
|
||||
* cairo_pattern_set_matrix (pattern, &matrix);
|
||||
* </programlisting></informalexample>
|
||||
*
|
||||
* Meanwhile, using values of 2.0 rather than 0.5 in the code above
|
||||
|
@ -717,10 +739,8 @@ void
|
|||
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
|
||||
const cairo_matrix_t *matrix)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->matrix = *matrix;
|
||||
}
|
||||
|
@ -741,10 +761,8 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
|
|||
void
|
||||
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->filter = filter;
|
||||
}
|
||||
|
@ -758,10 +776,8 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern)
|
|||
void
|
||||
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->extend = extend;
|
||||
}
|
||||
|
@ -781,24 +797,6 @@ _cairo_pattern_transform (cairo_pattern_t *pattern,
|
|||
cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
|
||||
}
|
||||
|
||||
#define INTERPOLATE_COLOR_NEAREST(c1, c2, factor) \
|
||||
((factor < 32768)? c1: c2)
|
||||
|
||||
static void
|
||||
_cairo_pattern_shader_nearest (unsigned char *color0,
|
||||
unsigned char *color1,
|
||||
cairo_fixed_t factor,
|
||||
uint32_t *pixel)
|
||||
{
|
||||
*pixel =
|
||||
((INTERPOLATE_COLOR_NEAREST (color0[3], color1[3], factor) << 24) |
|
||||
(INTERPOLATE_COLOR_NEAREST (color0[0], color1[0], factor) << 16) |
|
||||
(INTERPOLATE_COLOR_NEAREST (color0[1], color1[1], factor) << 8) |
|
||||
(INTERPOLATE_COLOR_NEAREST (color0[2], color1[2], factor) << 0));
|
||||
}
|
||||
|
||||
#undef INTERPOLATE_COLOR_NEAREST
|
||||
|
||||
#define INTERPOLATE_COLOR_LINEAR(c1, c2, factor) \
|
||||
(((c2 * factor) + (c1 * (65536 - factor))) / 65536)
|
||||
|
||||
|
@ -814,24 +812,6 @@ _cairo_pattern_shader_linear (unsigned char *color0,
|
|||
(INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
|
||||
}
|
||||
|
||||
#define E_MINUS_ONE 1.7182818284590452354
|
||||
|
||||
static void
|
||||
_cairo_pattern_shader_gaussian (unsigned char *color0,
|
||||
unsigned char *color1,
|
||||
cairo_fixed_t factor,
|
||||
uint32_t *pixel)
|
||||
{
|
||||
double f = ((double) factor) / 65536.0;
|
||||
|
||||
factor = (cairo_fixed_t) (((exp (f * f) - 1.0) / E_MINUS_ONE) * 65536);
|
||||
|
||||
*pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) |
|
||||
(INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) |
|
||||
(INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) |
|
||||
(INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
|
||||
}
|
||||
|
||||
#undef INTERPOLATE_COLOR_LINEAR
|
||||
|
||||
static int
|
||||
|
@ -889,24 +869,6 @@ _cairo_pattern_shader_init (cairo_gradient_pattern_t *pattern,
|
|||
op->n_stops = pattern->n_stops;
|
||||
op->extend = pattern->base.extend;
|
||||
|
||||
/* XXX: this is wrong, the filter should not be used for selecting
|
||||
color stop interpolation function. function should always be 'linear'
|
||||
and filter should be used for computing pixels. */
|
||||
switch (pattern->base.filter) {
|
||||
case CAIRO_FILTER_FAST:
|
||||
case CAIRO_FILTER_NEAREST:
|
||||
op->shader_function = _cairo_pattern_shader_nearest;
|
||||
break;
|
||||
case CAIRO_FILTER_GAUSSIAN:
|
||||
op->shader_function = _cairo_pattern_shader_gaussian;
|
||||
break;
|
||||
case CAIRO_FILTER_GOOD:
|
||||
case CAIRO_FILTER_BEST:
|
||||
case CAIRO_FILTER_BILINEAR:
|
||||
op->shader_function = _cairo_pattern_shader_linear;
|
||||
break;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -982,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, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&dn, 3.0f, ¶ms, &n_params);
|
||||
m = dm;
|
||||
n = dn;
|
||||
_glitz_filter_params_set (&dm, 3.0f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&dn, 3.0f, ¶ms, &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, ¶ms, &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, ¶ms, &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, ¶ms, &n_params);
|
||||
glitz_clamp_value (&radius, 0.0f, 1024.0f);
|
||||
_glitz_filter_params_set (&radius, 1.0f, ¶ms, &n_params);
|
||||
glitz_clamp_value (&radius, 0.0f, 1024.0f);
|
||||
|
||||
_glitz_filter_params_set (&sigma, radius / 2.0f, ¶ms, &n_params);
|
||||
glitz_clamp_value (&sigma, 0.0f, 1024.0f);
|
||||
_glitz_filter_params_set (&sigma, radius / 2.0f, ¶ms, &n_params);
|
||||
glitz_clamp_value (&sigma, 0.0f, 1024.0f);
|
||||
|
||||
_glitz_filter_params_set (&alpha, radius, ¶ms, &n_params);
|
||||
glitz_clamp_value (&alpha, 0.0f, 1024.0f);
|
||||
_glitz_filter_params_set (&alpha, radius, ¶ms, &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, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&start_y, 0.0f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&stop_x, 1.0f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&stop_y, 0.0f, ¶ms, &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, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&vecs->v[1], 0.5f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&r0, 0.0f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&r1, 0.5f, ¶ms, &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, ¶ms,
|
||||
&n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[0], x_default, ¶ms,
|
||||
&n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[1], y_default, ¶ms,
|
||||
&n_params);
|
||||
|
||||
glitz_clamp_value (&vecs[i].v[2], 0.0f, 1.0f);
|
||||
glitz_clamp_value (&vecs[i].v[0], 0.0f, surface->box.x2 - 1.0f);
|
||||
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, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&start_y, 0.0f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&stop_x, 1.0f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&stop_y, 0.0f, ¶ms, &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, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&vecs->v[1], 0.5f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&r0, 0.0f, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&r1, 0.5f, ¶ms, &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, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[0], x_default, ¶ms, &n_params);
|
||||
_glitz_filter_params_set (&vecs[i].v[1], y_default, ¶ms, &n_params);
|
||||
|
||||
glitz_clamp_value (&vecs[i].v[2], 0.0f, 1.0f);
|
||||
glitz_clamp_value (&vecs[i].v[0], 0.0f, surface->box.x2 - 1.0f);
|
||||
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 = ®ion->extents;
|
||||
region->n_box = 1;
|
||||
if (region->n_box == 0) {
|
||||
region->extents = *ubox;
|
||||
region->box = ®ion->extents;
|
||||
region->n_box = 1;
|
||||
|
||||
return GLITZ_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (BOX_CLOSE_TO_BOX (ubox, ®ion->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 (®ion->extents, box, new_box);
|
||||
region->box = ®ion->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 (®ion->extents, ®ion->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 (®ion->extents, ®ion->extents, ubox);
|
||||
|
||||
return GLITZ_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (BOX_CLOSE_TO_BOX (ubox, ®ion->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 (®ion->extents, box, new_box);
|
||||
region->box = ®ion->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 (®ion->extents, ®ion->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 (®ion->extents, ®ion->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, ¶m->border_color,
|
||||
sizeof (glitz_color_t)))
|
||||
{
|
||||
glitz_vec4_t vec;
|
||||
|
||||
vec.v[0] = (glitz_float_t) param->border_color.red / 0xffff;
|
||||
vec.v[1] = (glitz_float_t) param->border_color.green / 0xffff;
|
||||
vec.v[2] = (glitz_float_t) param->border_color.blue / 0xffff;
|
||||
vec.v[3] = (glitz_float_t) param->border_color.alpha / 0xffff;
|
||||
|
||||
gl->tex_parameter_fv (texture->target,
|
||||
GLITZ_GL_TEXTURE_BORDER_COLOR,
|
||||
vec.v);
|
||||
|
||||
texture->param.border_color = param->border_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glitz_texture_target_t
|
||||
glitz_texture_object_get_target (glitz_texture_object_t *texture)
|
||||
{
|
||||
if (texture->surface->texture.target == GLITZ_GL_TEXTURE_2D)
|
||||
return GLITZ_TEXTURE_TARGET_2D;
|
||||
|
||||
return GLITZ_TEXTURE_TARGET_RECT;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче