mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1149728. Move CreateXForOffscreen functions. r=jrmuizel (87d69e4b7c) - missing part of Bug 1179280. Update ANGLE (ee6228fa90) - missing bit of Bug 1191042 - Use CreateOffscreen for WebGL instead of CreateHeadless. - r=jrmuizel (87c26edf2c) - add back XP bits (f198a909bd) - put back SQLITE_ENABLE_DBSTAT_VTAB checks (a06fd5b7a9) - Bug 1197387 - Use glXGetProcAddress to link against GLX_ARB_create_context_robustness. r=jgilbert (651b85207d) - add back feature report (a0a33bb8e5) - Bug 1209022 - Fix AA handling in EGL's CreateOffscreen. - r=jrmuizel (64d4e0f65a) - Bug 1171228 - Expose WEBGL_debug_renderer_info to web content on non-RELEASE_BUILDs. - r=kamidphish, sr=jst (e7405ef944) - Bug 1175257 - Remove the fails-if(B2G) annotation on capturestream.html. (80bf24c623) - Bug 1177726 - Inflate the bounds when stroking the canvas text. r=jmuizelaar (15969cb828) - Bug 1183363 - Make EnsureWritablePath and EnsureUserSpacePath always imply EnsureTarget. r=Basimply EnsureTarget. r=Bas (12d825cf30) - Bug 1183363 - Add canvas crashtest. r=Bas (69b6099607) - Bug 1186689 - check for OOM on destination array before mapping source to avoid needing unmap. r=bas (7a3ed105d6) - Bug 1206161 - Make sure the DrawTarget is available when creating a CanvasLayer so that we can check for SkiaGL. r=Bas (fdf15fd552) - Bug 232227 - Do not expose system colors to CSS or canvas. r=jmuizelaar r=enndeakin tor-r=arthuredelstein (dfd6f07fd8) - Bug 1209206 (part 1) - Remove mgfx namespace synonym. (5916056863) - Bug 1209206 (part 2) - Rename and re-comment HasNonOpaqueColor(). r=jdaggett. (768a0d549b) - Bug 1209206 (part 3) - Use sinf() and cosf() instead of sin() and cos() in a couple of places. r=Bas. (7af9ebaa7f) - No bug - Remove outdated comment and additional comment questioning its relevance. r=me DONTBUILD (6f7eca8452) - Bug 1145934 - Update obsolete glyph-run assertion. r=jdaggett (ce2442e64b) - Bug 1182361 p1 - move old generic lookup methods into gfxPangoFontGroup. r=heycam (ef39e6fd52) - Bug 1182361 p2 - count generic lookups. r=heycam (53050ad6e8) - bug 1180010 make some methods protected and non-virtual r=jdaggett (815e503481) - Bug 1165179 - use all style matched faces within a font family. r=heycam (d2711db48b) - Bug 1182361 p3 - move generic lookup methods to platform fontlist. r=heycam (63b974a000) - Bug 1182361 p4 - move pref font util methods to platform fontlist. r=heycam (23d7352442) - Bug 1182361 p5 - cache pref fonts per langGroup. r=heycam (c4244432cb) - Bug 1182361 p6 - eliminate old pref font caching. r=heycam (c5293f0b8d) - Bug 1182361 p7 - fixups based on review comments. r=heycam (51a2204179) - Bug 1170688 - Move initialization of text-run parameters until *after* the draw target has been updated; r=jfkthame (e523ff6e96) - Bug 1157629 - Fix uninitialized member warning in BufferAlphaColor. r=jdaggett (a564effd24) - Bug 1184282 - Remove break suggested inside cluster warning. r=roc (54da46a09f) - Bug 1197650 - remove duplicate validity check for newly created fonts. r=m_kato (5ffb28a313) - Bug 1171357 - log font matching for textruns. r=m_kato (2354cd36f6) - Bug 1185812 - rejigger the ordering of fonts within a family to avoid obscure faces. r=heycam (0518f4ef64) - Bug 1167697 - Mark refs to gfxFontEntry in UserFontCache as MOZ_NON_OWNING_REF. r=jtd (1fdcccdac2) - bits of Bug 1073209 - Eliminate usage of CreateSamplingRestrictedDrawable (9058557527) - and sync gfx/gl to same state as af-frontend branch
This commit is contained in:
@@ -6452,6 +6452,35 @@ then
|
||||
if test "x$ac_cv_sqlite_enable_unlock_notify" = "xno"; then
|
||||
AC_MSG_ERROR([System SQLite library is not compiled with SQLITE_ENABLE_UNLOCK_NOTIFY.])
|
||||
fi
|
||||
|
||||
dnl =========================================
|
||||
dnl === SQLITE_ENABLE_DBSTAT_VTAB check ===
|
||||
dnl =========================================
|
||||
dnl check to see if the system SQLite package is compiled with
|
||||
dnl SQLITE_ENABLE_DBSTAT_VTAB.
|
||||
AC_MSG_CHECKING(for SQLITE_ENABLE_DBSTAT_VTAB support in system SQLite)
|
||||
_SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $SQLITE_CFLAGS"
|
||||
_SAVE_LIBS="$LIBS"
|
||||
LIBS="$LIBS $SQLITE_LIBS"
|
||||
AC_CACHE_VAL(ac_cv_sqlite_dbstat_vtab,[
|
||||
AC_TRY_RUN([
|
||||
#include "sqlite3.h"
|
||||
|
||||
int main(int argc, char **argv){
|
||||
return !sqlite3_compileoption_used("SQLITE_ENABLE_DBSTAT_VTAB");
|
||||
}],
|
||||
ac_cv_sqlite_dbstat_vtab=yes,
|
||||
ac_cv_sqlite_dbstat_vtab=no,
|
||||
ac_cv_sqlite_dbstat_vtab=no
|
||||
)
|
||||
])
|
||||
AC_MSG_RESULT($ac_cv_sqlite_dbstat_vtab)
|
||||
CFLAGS="$_SAVE_CFLAGS"
|
||||
LIBS="$_SAVE_LIBS"
|
||||
if test "x$ac_cv_sqlite_dbstat_vtab" = "xno"; then
|
||||
AC_MSG_ERROR([System SQLite library is not compiled with SQLITE_ENABLE_DBSTAT_VTAB.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_NATIVE_SQLITE"; then
|
||||
|
||||
@@ -37,7 +37,8 @@ SOURCES += [
|
||||
# concurrent connections, especially when they use shared cache.
|
||||
# Note: Be sure to update the configure.in checks when these change!
|
||||
for var in ('SQLITE_SECURE_DELETE', 'SQLITE_THREADSAFE', 'SQLITE_CORE',
|
||||
'SQLITE_ENABLE_FTS3', 'SQLITE_ENABLE_UNLOCK_NOTIFY'):
|
||||
'SQLITE_ENABLE_FTS3', 'SQLITE_ENABLE_UNLOCK_NOTIFY',
|
||||
'SQLITE_ENABLE_DBSTAT_VTAB'):
|
||||
DEFINES[var] = 1
|
||||
|
||||
DEFINES['SQLITE_DEFAULT_PAGE_SIZE'] = 32768
|
||||
|
||||
@@ -152,8 +152,6 @@ using namespace mozilla::image;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
namespace mgfx = mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@@ -297,10 +295,10 @@ public:
|
||||
|
||||
AdjustedTargetForFilter(CanvasRenderingContext2D *ctx,
|
||||
DrawTarget *aFinalTarget,
|
||||
const mgfx::IntPoint& aFilterSpaceToTargetOffset,
|
||||
const mgfx::IntRect& aPreFilterBounds,
|
||||
const mgfx::IntRect& aPostFilterBounds,
|
||||
mgfx::CompositionOp aCompositionOp)
|
||||
const gfx::IntPoint& aFilterSpaceToTargetOffset,
|
||||
const gfx::IntRect& aPreFilterBounds,
|
||||
const gfx::IntRect& aPostFilterBounds,
|
||||
gfx::CompositionOp aCompositionOp)
|
||||
: mCtx(nullptr)
|
||||
, mCompositionOp(aCompositionOp)
|
||||
{
|
||||
@@ -348,7 +346,7 @@ public:
|
||||
|
||||
// Return a SourceSurface that contains the FillPaint or StrokePaint source.
|
||||
already_AddRefed<SourceSurface>
|
||||
DoSourcePaint(mgfx::IntRect& aRect, CanvasRenderingContext2D::Style aStyle)
|
||||
DoSourcePaint(gfx::IntRect& aRect, CanvasRenderingContext2D::Style aStyle)
|
||||
{
|
||||
if (aRect.IsEmpty()) {
|
||||
return nullptr;
|
||||
@@ -367,8 +365,8 @@ public:
|
||||
dt->SetTransform(transform);
|
||||
|
||||
if (transform.Invert()) {
|
||||
mgfx::Rect dtBounds(0, 0, aRect.width, aRect.height);
|
||||
mgfx::Rect fillRect = transform.TransformBounds(dtBounds);
|
||||
gfx::Rect dtBounds(0, 0, aRect.width, aRect.height);
|
||||
gfx::Rect fillRect = transform.TransformBounds(dtBounds);
|
||||
dt->FillRect(fillRect, CanvasGeneralPattern().ForStyle(mCtx, aStyle, dt));
|
||||
}
|
||||
return dt->Snapshot();
|
||||
@@ -390,9 +388,9 @@ public:
|
||||
AutoRestoreTransform autoRestoreTransform(mFinalTarget);
|
||||
mFinalTarget->SetTransform(Matrix());
|
||||
|
||||
mgfx::FilterSupport::RenderFilterDescription(
|
||||
gfx::FilterSupport::RenderFilterDescription(
|
||||
mFinalTarget, mCtx->CurrentState().filter,
|
||||
mgfx::Rect(mPostFilterBounds),
|
||||
gfx::Rect(mPostFilterBounds),
|
||||
snapshot, mSourceGraphicRect,
|
||||
fillPaint, mFillPaintRect,
|
||||
strokePaint, mStrokePaintRect,
|
||||
@@ -410,12 +408,12 @@ private:
|
||||
RefPtr<DrawTarget> mTarget;
|
||||
RefPtr<DrawTarget> mFinalTarget;
|
||||
CanvasRenderingContext2D *mCtx;
|
||||
mgfx::IntRect mSourceGraphicRect;
|
||||
mgfx::IntRect mFillPaintRect;
|
||||
mgfx::IntRect mStrokePaintRect;
|
||||
mgfx::IntRect mPostFilterBounds;
|
||||
mgfx::IntPoint mOffset;
|
||||
mgfx::CompositionOp mCompositionOp;
|
||||
gfx::IntRect mSourceGraphicRect;
|
||||
gfx::IntRect mFillPaintRect;
|
||||
gfx::IntRect mStrokePaintRect;
|
||||
gfx::IntRect mPostFilterBounds;
|
||||
gfx::IntPoint mOffset;
|
||||
gfx::CompositionOp mCompositionOp;
|
||||
};
|
||||
|
||||
/* This is an RAII based class that can be used as a drawtarget for
|
||||
@@ -429,8 +427,8 @@ public:
|
||||
|
||||
AdjustedTargetForShadow(CanvasRenderingContext2D *ctx,
|
||||
DrawTarget *aFinalTarget,
|
||||
const mgfx::Rect& aBounds,
|
||||
mgfx::CompositionOp aCompositionOp)
|
||||
const gfx::Rect& aBounds,
|
||||
gfx::CompositionOp aCompositionOp)
|
||||
: mCtx(nullptr)
|
||||
, mCompositionOp(aCompositionOp)
|
||||
{
|
||||
@@ -441,7 +439,7 @@ public:
|
||||
|
||||
mSigma = state.ShadowBlurSigma();
|
||||
|
||||
mgfx::Rect bounds = aBounds;
|
||||
gfx::Rect bounds = aBounds;
|
||||
|
||||
int32_t blurRadius = state.ShadowBlurRadius();
|
||||
|
||||
@@ -488,7 +486,7 @@ public:
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
mgfx::IntPoint OffsetToFinalDT()
|
||||
gfx::IntPoint OffsetToFinalDT()
|
||||
{
|
||||
return mTempRect.TopLeft();
|
||||
}
|
||||
@@ -498,8 +496,8 @@ private:
|
||||
RefPtr<DrawTarget> mFinalTarget;
|
||||
CanvasRenderingContext2D *mCtx;
|
||||
Float mSigma;
|
||||
mgfx::IntRect mTempRect;
|
||||
mgfx::CompositionOp mCompositionOp;
|
||||
gfx::IntRect mTempRect;
|
||||
gfx::CompositionOp mCompositionOp;
|
||||
};
|
||||
|
||||
/* This is an RAII based class that can be used as a drawtarget for
|
||||
@@ -519,7 +517,7 @@ public:
|
||||
typedef CanvasRenderingContext2D::ContextState ContextState;
|
||||
|
||||
explicit AdjustedTarget(CanvasRenderingContext2D* ctx,
|
||||
const mgfx::Rect *aBounds = nullptr)
|
||||
const gfx::Rect *aBounds = nullptr)
|
||||
{
|
||||
mTarget = ctx->mTarget;
|
||||
|
||||
@@ -529,21 +527,21 @@ public:
|
||||
// calculate what their maximum required bounds would need to be if we
|
||||
// were to fill the whole canvas. Everything outside those bounds we don't
|
||||
// need to render.
|
||||
mgfx::Rect r(0, 0, ctx->mWidth, ctx->mHeight);
|
||||
mgfx::Rect maxSourceNeededBoundsForShadow =
|
||||
gfx::Rect r(0, 0, ctx->mWidth, ctx->mHeight);
|
||||
gfx::Rect maxSourceNeededBoundsForShadow =
|
||||
MaxSourceNeededBoundsForShadow(r, ctx);
|
||||
mgfx::Rect maxSourceNeededBoundsForFilter =
|
||||
gfx::Rect maxSourceNeededBoundsForFilter =
|
||||
MaxSourceNeededBoundsForFilter(maxSourceNeededBoundsForShadow, ctx);
|
||||
|
||||
mgfx::Rect bounds = maxSourceNeededBoundsForFilter;
|
||||
gfx::Rect bounds = maxSourceNeededBoundsForFilter;
|
||||
if (aBounds) {
|
||||
bounds = bounds.Intersect(*aBounds);
|
||||
}
|
||||
mgfx::Rect boundsAfterFilter = BoundsAfterFilter(bounds, ctx);
|
||||
gfx::Rect boundsAfterFilter = BoundsAfterFilter(bounds, ctx);
|
||||
|
||||
mozilla::gfx::CompositionOp op = ctx->CurrentState().op;
|
||||
|
||||
mgfx::IntPoint offsetToFinalDT;
|
||||
gfx::IntPoint offsetToFinalDT;
|
||||
|
||||
// First set up the shadow draw target, because the shadow goes outside.
|
||||
// It applies to the post-filter results, if both a filter and a shadow
|
||||
@@ -556,20 +554,20 @@ public:
|
||||
|
||||
// If we also have a filter, the filter needs to be drawn with OP_OVER
|
||||
// because shadow drawing already applies op on the result.
|
||||
op = mgfx::CompositionOp::OP_OVER;
|
||||
op = gfx::CompositionOp::OP_OVER;
|
||||
}
|
||||
|
||||
// Now set up the filter draw target.
|
||||
if (ctx->NeedToApplyFilter()) {
|
||||
bounds.RoundOut();
|
||||
|
||||
mgfx::IntRect intBounds;
|
||||
gfx::IntRect intBounds;
|
||||
if (!bounds.ToIntRect(&intBounds)) {
|
||||
return;
|
||||
}
|
||||
mFilterTarget = MakeUnique<AdjustedTargetForFilter>(
|
||||
ctx, mTarget, offsetToFinalDT, intBounds,
|
||||
mgfx::RoundedToInt(boundsAfterFilter), op);
|
||||
gfx::RoundedToInt(boundsAfterFilter), op);
|
||||
mTarget = mFilterTarget->DT();
|
||||
}
|
||||
}
|
||||
@@ -594,8 +592,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
mgfx::Rect
|
||||
MaxSourceNeededBoundsForFilter(const mgfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
|
||||
gfx::Rect
|
||||
MaxSourceNeededBoundsForFilter(const gfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
|
||||
{
|
||||
if (!ctx->NeedToApplyFilter()) {
|
||||
return aDestBounds;
|
||||
@@ -606,21 +604,21 @@ private:
|
||||
nsIntRegion strokePaintNeededRegion;
|
||||
|
||||
FilterSupport::ComputeSourceNeededRegions(
|
||||
ctx->CurrentState().filter, mgfx::RoundedToInt(aDestBounds),
|
||||
ctx->CurrentState().filter, gfx::RoundedToInt(aDestBounds),
|
||||
sourceGraphicNeededRegion, fillPaintNeededRegion, strokePaintNeededRegion);
|
||||
|
||||
return mgfx::Rect(sourceGraphicNeededRegion.GetBounds());
|
||||
return gfx::Rect(sourceGraphicNeededRegion.GetBounds());
|
||||
}
|
||||
|
||||
mgfx::Rect
|
||||
MaxSourceNeededBoundsForShadow(const mgfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
|
||||
gfx::Rect
|
||||
MaxSourceNeededBoundsForShadow(const gfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
|
||||
{
|
||||
if (!ctx->NeedToDrawShadow()) {
|
||||
return aDestBounds;
|
||||
}
|
||||
|
||||
const ContextState &state = ctx->CurrentState();
|
||||
mgfx::Rect sourceBounds = aDestBounds - state.shadowOffset;
|
||||
gfx::Rect sourceBounds = aDestBounds - state.shadowOffset;
|
||||
sourceBounds.Inflate(state.ShadowBlurRadius());
|
||||
|
||||
// Union the shadow source with the original rect because we're going to
|
||||
@@ -628,25 +626,25 @@ private:
|
||||
return sourceBounds.Union(aDestBounds);
|
||||
}
|
||||
|
||||
mgfx::Rect
|
||||
BoundsAfterFilter(const mgfx::Rect& aBounds, CanvasRenderingContext2D *ctx)
|
||||
gfx::Rect
|
||||
BoundsAfterFilter(const gfx::Rect& aBounds, CanvasRenderingContext2D *ctx)
|
||||
{
|
||||
if (!ctx->NeedToApplyFilter()) {
|
||||
return aBounds;
|
||||
}
|
||||
|
||||
mgfx::Rect bounds(aBounds);
|
||||
gfx::Rect bounds(aBounds);
|
||||
bounds.RoundOut();
|
||||
|
||||
mgfx::IntRect intBounds;
|
||||
gfx::IntRect intBounds;
|
||||
if (!bounds.ToIntRect(&intBounds)) {
|
||||
return mgfx::Rect();
|
||||
return gfx::Rect();
|
||||
}
|
||||
|
||||
nsIntRegion extents =
|
||||
mgfx::FilterSupport::ComputePostFilterExtents(ctx->CurrentState().filter,
|
||||
intBounds);
|
||||
return mgfx::Rect(extents.GetBounds());
|
||||
gfx::FilterSupport::ComputePostFilterExtents(ctx->CurrentState().filter,
|
||||
intBounds);
|
||||
return gfx::Rect(extents.GetBounds());
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> mTarget;
|
||||
@@ -676,7 +674,9 @@ CanvasGradient::AddColorStop(float offset, const nsAString& colorstr, ErrorResul
|
||||
}
|
||||
|
||||
nscolor color;
|
||||
if (!nsRuleNode::ComputeColor(value, nullptr, nullptr, color)) {
|
||||
nsCOMPtr<nsIPresShell> presShell = mContext ? mContext->GetPresShell() : nullptr;
|
||||
if (!nsRuleNode::ComputeColor(value, presShell ? presShell->GetPresContext() : nullptr,
|
||||
nullptr, color)) {
|
||||
rv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return;
|
||||
}
|
||||
@@ -948,6 +948,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
|
||||
, mZero(false), mOpaque(false)
|
||||
, mResetLayer(true)
|
||||
, mIPC(false)
|
||||
, mIsSkiaGL(false)
|
||||
, mDrawObserver(nullptr)
|
||||
, mIsEntireFrameInvalid(false)
|
||||
, mPredictManyRedrawCalls(false)
|
||||
@@ -1137,7 +1138,7 @@ CanvasRenderingContext2D::Redraw()
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::Redraw(const mgfx::Rect &r)
|
||||
CanvasRenderingContext2D::Redraw(const gfx::Rect &r)
|
||||
{
|
||||
mIsCapturedFrameInvalid = true;
|
||||
|
||||
@@ -1185,8 +1186,7 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r)
|
||||
return;
|
||||
}
|
||||
|
||||
mgfx::Rect newr =
|
||||
mTarget->GetTransform().TransformBounds(ToRect(r));
|
||||
gfx::Rect newr = mTarget->GetTransform().TransformBounds(ToRect(r));
|
||||
Redraw(newr);
|
||||
}
|
||||
|
||||
@@ -1233,7 +1233,7 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
|
||||
mRenderingMode = attemptedMode;
|
||||
|
||||
// Restore the content from the old DrawTarget
|
||||
mgfx::Rect r(0, 0, mWidth, mHeight);
|
||||
gfx::Rect r(0, 0, mWidth, mHeight);
|
||||
mTarget->DrawSurface(snapshot, r, r);
|
||||
|
||||
// Restore the clips and transform
|
||||
@@ -1378,6 +1378,8 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||
}
|
||||
}
|
||||
|
||||
mIsSkiaGL = false;
|
||||
|
||||
// Check that the dimensions are sane
|
||||
IntSize size(mWidth, mHeight);
|
||||
if (size.width <= gfxPrefs::MaxCanvasSize() &&
|
||||
@@ -1411,6 +1413,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||
if (mTarget) {
|
||||
AddDemotableContext(this);
|
||||
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
||||
mIsSkiaGL = true;
|
||||
} else {
|
||||
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
|
||||
mode = RenderingMode::SoftwareBackendMode;
|
||||
@@ -1445,15 +1448,15 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||
JS_updateMallocCounter(context, mWidth * mHeight * 4);
|
||||
}
|
||||
|
||||
mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
|
||||
if (mTarget->GetBackendType() == mgfx::BackendType::CAIRO) {
|
||||
mTarget->ClearRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
|
||||
if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) {
|
||||
// Cairo doesn't play well with huge clips. When given a very big clip it
|
||||
// will try to allocate big mask surface without taking the target
|
||||
// size into account which can cause OOM. See bug 1034593.
|
||||
// This limits the clip extents to the size of the canvas.
|
||||
// A fix in Cairo would probably be preferable, but requires somewhat
|
||||
// invasive changes.
|
||||
mTarget->PushClipRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
|
||||
mTarget->PushClipRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
|
||||
}
|
||||
// Force a full layer transaction since we didn't have a layer before
|
||||
// and now we might need one.
|
||||
@@ -1578,9 +1581,9 @@ CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *shell,
|
||||
mTarget = sErrorTarget;
|
||||
}
|
||||
|
||||
if (mTarget->GetBackendType() == mgfx::BackendType::CAIRO) {
|
||||
if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) {
|
||||
// Cf comment in EnsureTarget
|
||||
mTarget->PushClipRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
|
||||
mTarget->PushClipRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -2540,7 +2543,7 @@ CanvasRenderingContext2D::ClearRect(double x, double y, double w,
|
||||
return;
|
||||
}
|
||||
|
||||
mTarget->ClearRect(mgfx::Rect(x, y, w, h));
|
||||
mTarget->ClearRect(gfx::Rect(x, y, w, h));
|
||||
|
||||
RedrawUser(gfxRect(x, y, w, h));
|
||||
}
|
||||
@@ -2601,16 +2604,16 @@ CanvasRenderingContext2D::FillRect(double x, double y, double w,
|
||||
}
|
||||
}
|
||||
|
||||
mgfx::Rect bounds;
|
||||
gfx::Rect bounds;
|
||||
|
||||
EnsureTarget();
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds = mgfx::Rect(x, y, w, h);
|
||||
bounds = gfx::Rect(x, y, w, h);
|
||||
bounds = mTarget->GetTransform().TransformBounds(bounds);
|
||||
}
|
||||
|
||||
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
|
||||
FillRect(mgfx::Rect(x, y, w, h),
|
||||
FillRect(gfx::Rect(x, y, w, h),
|
||||
CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
|
||||
DrawOptions(state.globalAlpha, UsedOperation()));
|
||||
|
||||
@@ -2623,7 +2626,7 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
|
||||
{
|
||||
const ContextState &state = CurrentState();
|
||||
|
||||
mgfx::Rect bounds;
|
||||
gfx::Rect bounds;
|
||||
|
||||
if (!w && !h) {
|
||||
return;
|
||||
@@ -2639,8 +2642,8 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
|
||||
}
|
||||
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
|
||||
w + state.lineWidth, h + state.lineWidth);
|
||||
bounds = gfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
|
||||
w + state.lineWidth, h + state.lineWidth);
|
||||
bounds = mTarget->GetTransform().TransformBounds(bounds);
|
||||
}
|
||||
|
||||
@@ -2679,14 +2682,14 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
|
||||
}
|
||||
|
||||
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
|
||||
StrokeRect(mgfx::Rect(x, y, w, h),
|
||||
CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, UsedOperation()));
|
||||
StrokeRect(gfx::Rect(x, y, w, h),
|
||||
CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, UsedOperation()));
|
||||
|
||||
Redraw();
|
||||
}
|
||||
@@ -2707,14 +2710,13 @@ CanvasRenderingContext2D::BeginPath()
|
||||
void
|
||||
CanvasRenderingContext2D::Fill(const CanvasWindingRule& winding)
|
||||
{
|
||||
EnsureTarget();
|
||||
EnsureUserSpacePath(winding);
|
||||
|
||||
if (!mPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
mgfx::Rect bounds;
|
||||
gfx::Rect bounds;
|
||||
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds = mPath->GetBounds(mTarget->GetTransform());
|
||||
@@ -2737,7 +2739,7 @@ void CanvasRenderingContext2D::Fill(const CanvasPath& path, const CanvasWindingR
|
||||
return;
|
||||
}
|
||||
|
||||
mgfx::Rect bounds;
|
||||
gfx::Rect bounds;
|
||||
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds = gfxpath->GetBounds(mTarget->GetTransform());
|
||||
@@ -2753,7 +2755,6 @@ void CanvasRenderingContext2D::Fill(const CanvasPath& path, const CanvasWindingR
|
||||
void
|
||||
CanvasRenderingContext2D::Stroke()
|
||||
{
|
||||
EnsureTarget();
|
||||
EnsureUserSpacePath();
|
||||
|
||||
if (!mPath) {
|
||||
@@ -2767,7 +2768,7 @@ CanvasRenderingContext2D::Stroke()
|
||||
state.dash.Length(), state.dash.Elements(),
|
||||
state.dashOffset);
|
||||
|
||||
mgfx::Rect bounds;
|
||||
gfx::Rect bounds;
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds =
|
||||
mPath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
|
||||
@@ -2798,7 +2799,7 @@ CanvasRenderingContext2D::Stroke(const CanvasPath& path)
|
||||
state.dash.Length(), state.dash.Elements(),
|
||||
state.dashOffset);
|
||||
|
||||
mgfx::Rect bounds;
|
||||
gfx::Rect bounds;
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds =
|
||||
gfxpath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
|
||||
@@ -2889,8 +2890,6 @@ bool CanvasRenderingContext2D::DrawCustomFocusRing(mozilla::dom::Element& aEleme
|
||||
void
|
||||
CanvasRenderingContext2D::Clip(const CanvasWindingRule& winding)
|
||||
{
|
||||
EnsureTarget();
|
||||
|
||||
EnsureUserSpacePath(winding);
|
||||
|
||||
if (!mPath) {
|
||||
@@ -3048,6 +3047,8 @@ CanvasRenderingContext2D::Ellipse(double aX, double aY, double aRadiusX, double
|
||||
void
|
||||
CanvasRenderingContext2D::EnsureWritablePath()
|
||||
{
|
||||
EnsureTarget();
|
||||
|
||||
if (mDSPathBuilder) {
|
||||
return;
|
||||
}
|
||||
@@ -3066,7 +3067,6 @@ CanvasRenderingContext2D::EnsureWritablePath()
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureTarget();
|
||||
if (!mPath) {
|
||||
NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
|
||||
mPathBuilder = mTarget->CreatePathBuilder(fillRule);
|
||||
@@ -3087,8 +3087,9 @@ CanvasRenderingContext2D::EnsureUserSpacePath(const CanvasWindingRule& winding)
|
||||
if(winding == CanvasWindingRule::Evenodd)
|
||||
fillRule = FillRule::FILL_EVEN_ODD;
|
||||
|
||||
EnsureTarget();
|
||||
|
||||
if (!mPath && !mPathBuilder && !mDSPathBuilder) {
|
||||
EnsureTarget();
|
||||
mPathBuilder = mTarget->CreatePathBuilder(fillRule);
|
||||
}
|
||||
|
||||
@@ -3364,6 +3365,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
|
||||
{
|
||||
RefPtr<gfx::Path> path;
|
||||
if (options.mPath) {
|
||||
EnsureTarget();
|
||||
path = options.mPath->GetPath(CanvasWindingRule::Nonzero, mTarget);
|
||||
}
|
||||
|
||||
@@ -3379,7 +3381,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
|
||||
}
|
||||
|
||||
// get the bounds of the current path. They are relative to the canvas
|
||||
mgfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
|
||||
gfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
|
||||
if ((bounds.width == 0) || (bounds.height == 0) || !bounds.IsFinite()) {
|
||||
// The specified region has no pixels.
|
||||
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
@@ -3443,7 +3445,7 @@ CanvasRenderingContext2D::GetHitRegionRect(Element* aElement, nsRect& aRect)
|
||||
for (unsigned int x = 0; x < mHitRegionsOptions.Length(); x++) {
|
||||
RegionInfo& info = mHitRegionsOptions[x];
|
||||
if (info.mElement == aElement) {
|
||||
mgfx::Rect bounds(info.mPath->GetBounds());
|
||||
gfx::Rect bounds(info.mPath->GetBounds());
|
||||
gfxRect rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
aRect = nsLayoutUtils::RoundGfxRectToAppRect(rect, AppUnitsPerCSSPixel());
|
||||
|
||||
@@ -3707,12 +3709,18 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
|
||||
buffer.mGlyphs = &glyphBuf.front();
|
||||
buffer.mNumGlyphs = 1;
|
||||
const ContextState& state = *mState;
|
||||
AdjustedTarget target(mCtx, &bounds);
|
||||
|
||||
const StrokeOptions strokeOpts(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset);
|
||||
|
||||
// We need to adjust the bounds for the adjusted target
|
||||
bounds.Inflate(MaxStrokeExtents(strokeOpts, mCtx->mTarget->GetTransform()));
|
||||
|
||||
AdjustedTarget target(mCtx, &bounds);
|
||||
|
||||
CanvasGeneralPattern cgp;
|
||||
const Pattern& patForStyle
|
||||
(cgp.ForStyle(mCtx, CanvasRenderingContext2D::Style::STROKE, mCtx->mTarget));
|
||||
@@ -4289,11 +4297,11 @@ bool CanvasRenderingContext2D::IsPointInStroke(const CanvasPath& mPath, double x
|
||||
// On entry, aSourceRect is relative to aSurface, and on return aSourceRect is
|
||||
// relative to the returned surface.
|
||||
static already_AddRefed<SourceSurface>
|
||||
ExtractSubrect(SourceSurface* aSurface, mgfx::Rect* aSourceRect, DrawTarget* aTargetDT)
|
||||
ExtractSubrect(SourceSurface* aSurface, gfx::Rect* aSourceRect, DrawTarget* aTargetDT)
|
||||
{
|
||||
mgfx::Rect roundedOutSourceRect = *aSourceRect;
|
||||
gfx::Rect roundedOutSourceRect = *aSourceRect;
|
||||
roundedOutSourceRect.RoundOut();
|
||||
mgfx::IntRect roundedOutSourceRectInt;
|
||||
gfx::IntRect roundedOutSourceRectInt;
|
||||
if (!roundedOutSourceRect.ToIntRect(&roundedOutSourceRectInt)) {
|
||||
RefPtr<SourceSurface> surface(aSurface);
|
||||
return surface.forget();
|
||||
@@ -4617,19 +4625,19 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
||||
Filter filter;
|
||||
|
||||
if (CurrentState().imageSmoothingEnabled)
|
||||
filter = mgfx::Filter::LINEAR;
|
||||
filter = gfx::Filter::LINEAR;
|
||||
else
|
||||
filter = mgfx::Filter::POINT;
|
||||
filter = gfx::Filter::POINT;
|
||||
|
||||
mgfx::Rect bounds;
|
||||
gfx::Rect bounds;
|
||||
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds = mgfx::Rect(dx, dy, dw, dh);
|
||||
bounds = gfx::Rect(dx, dy, dw, dh);
|
||||
bounds = mTarget->GetTransform().TransformBounds(bounds);
|
||||
}
|
||||
|
||||
if (srcSurf) {
|
||||
mgfx::Rect sourceRect(sx, sy, sw, sh);
|
||||
gfx::Rect sourceRect(sx, sy, sw, sh);
|
||||
if (element == mCanvasElement) {
|
||||
// srcSurf is a snapshot of mTarget. If we draw to mTarget now, we'll
|
||||
// trigger a COW copy of the whole canvas into srcSurf. That's a huge
|
||||
@@ -4640,14 +4648,14 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
||||
}
|
||||
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
|
||||
DrawSurface(srcSurf,
|
||||
mgfx::Rect(dx, dy, dw, dh),
|
||||
gfx::Rect(dx, dy, dw, dh),
|
||||
sourceRect,
|
||||
DrawSurfaceOptions(filter),
|
||||
DrawOptions(CurrentState().globalAlpha, UsedOperation()));
|
||||
} else {
|
||||
DrawDirectlyToCanvas(drawInfo, &bounds,
|
||||
mgfx::Rect(dx, dy, dw, dh),
|
||||
mgfx::Rect(sx, sy, sw, sh),
|
||||
gfx::Rect(dx, dy, dw, dh),
|
||||
gfx::Rect(sx, sy, sw, sh),
|
||||
imgSize);
|
||||
}
|
||||
|
||||
@@ -4657,9 +4665,9 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
||||
void
|
||||
CanvasRenderingContext2D::DrawDirectlyToCanvas(
|
||||
const nsLayoutUtils::DirectDrawInfo& image,
|
||||
mgfx::Rect* bounds,
|
||||
mgfx::Rect dest,
|
||||
mgfx::Rect src,
|
||||
gfx::Rect* bounds,
|
||||
gfx::Rect dest,
|
||||
gfx::Rect src,
|
||||
gfx::IntSize imgSize)
|
||||
{
|
||||
MOZ_ASSERT(src.width > 0 && src.height > 0,
|
||||
@@ -4925,10 +4933,10 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
|
||||
return;
|
||||
}
|
||||
|
||||
mgfx::Rect destRect(0, 0, w, h);
|
||||
mgfx::Rect sourceRect(0, 0, sw, sh);
|
||||
gfx::Rect destRect(0, 0, w, h);
|
||||
gfx::Rect sourceRect(0, 0, sw, sh);
|
||||
mTarget->DrawSurface(source, destRect, sourceRect,
|
||||
DrawSurfaceOptions(mgfx::Filter::POINT),
|
||||
DrawSurfaceOptions(gfx::Filter::POINT),
|
||||
DrawOptions(GlobalAlpha(), CompositionOp::OP_OVER,
|
||||
AntialiasMode::NONE));
|
||||
mTarget->Flush();
|
||||
@@ -5066,9 +5074,9 @@ CanvasRenderingContext2D::DrawWidgetAsOnScreen(nsGlobalWindow& aWindow,
|
||||
return;
|
||||
}
|
||||
|
||||
mgfx::Rect sourceRect(mgfx::Point(0, 0), mgfx::Size(snapshot->GetSize()));
|
||||
gfx::Rect sourceRect(gfx::Point(0, 0), gfx::Size(snapshot->GetSize()));
|
||||
mTarget->DrawSurface(snapshot, sourceRect, sourceRect,
|
||||
DrawSurfaceOptions(mgfx::Filter::POINT),
|
||||
DrawSurfaceOptions(gfx::Filter::POINT),
|
||||
DrawOptions(GlobalAlpha(), CompositionOp::OP_OVER,
|
||||
AntialiasMode::NONE));
|
||||
mTarget->Flush();
|
||||
@@ -5201,21 +5209,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
IntRect srcRect(0, 0, mWidth, mHeight);
|
||||
IntRect destRect(aX, aY, aWidth, aHeight);
|
||||
IntRect srcReadRect = srcRect.Intersect(destRect);
|
||||
RefPtr<DataSourceSurface> readback;
|
||||
DataSourceSurface::MappedSurface rawData;
|
||||
if (!srcReadRect.IsEmpty() && !mZero) {
|
||||
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
|
||||
if (snapshot) {
|
||||
readback = snapshot->GetDataSurface();
|
||||
}
|
||||
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> darray(aCx, JS_NewUint8ClampedArray(aCx, len.value()));
|
||||
if (!darray) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@@ -5226,6 +5219,21 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
IntRect srcRect(0, 0, mWidth, mHeight);
|
||||
IntRect destRect(aX, aY, aWidth, aHeight);
|
||||
IntRect srcReadRect = srcRect.Intersect(destRect);
|
||||
RefPtr<DataSourceSurface> readback;
|
||||
DataSourceSurface::MappedSurface rawData;
|
||||
if (!srcReadRect.IsEmpty()) {
|
||||
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
|
||||
if (snapshot) {
|
||||
readback = snapshot->GetDataSurface();
|
||||
}
|
||||
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
IntRect dstWriteRect = srcReadRect;
|
||||
dstWriteRect.MoveBy(-aX, -aY);
|
||||
|
||||
@@ -5244,10 +5252,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
|
||||
srcStride = aWidth * 4;
|
||||
}
|
||||
|
||||
// NOTE! dst is the same as src, and this relies on reading
|
||||
// from src and advancing that ptr before writing to dst.
|
||||
// NOTE! I'm not sure that it is, I think this comment might have been
|
||||
// inherited from Thebes canvas and is no longer true
|
||||
uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
|
||||
|
||||
uint8_t a,r,g,b;
|
||||
@@ -5518,7 +5522,7 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
|
||||
dirtyRect.width, dirtyRect.height),
|
||||
IntPoint(dirtyRect.x, dirtyRect.y));
|
||||
|
||||
Redraw(mgfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
|
||||
Redraw(gfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -5618,9 +5622,11 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
{
|
||||
if (mOpaque) {
|
||||
if (mOpaque || mIsSkiaGL) {
|
||||
// If we're opaque then make sure we have a surface so we paint black
|
||||
// instead of transparent.
|
||||
// If we're using SkiaGL, then SkiaGLTex() below needs the target to
|
||||
// be accessible.
|
||||
EnsureTarget();
|
||||
}
|
||||
|
||||
|
||||
@@ -723,6 +723,9 @@ protected:
|
||||
bool mResetLayer;
|
||||
// This is needed for drawing in drawAsyncXULElement
|
||||
bool mIPC;
|
||||
// True if the current DrawTarget is using skia-gl, used so we can avoid
|
||||
// requesting the DT from mBufferProvider to check.
|
||||
bool mIsSkiaGL;
|
||||
|
||||
nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;
|
||||
|
||||
|
||||
@@ -159,6 +159,20 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
|
||||
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
|
||||
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
|
||||
|
||||
case WebGLExtensionID::WEBGL_debug_renderer_info:
|
||||
{
|
||||
bool isEnabled = true;
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
// Keep this disabled on Release and Beta for now. (see bug 1171228)
|
||||
isEnabled = false;
|
||||
#endif
|
||||
if (Preferences::GetBool("webgl.disable-debug-renderer-info", false))
|
||||
isEnabled = false;
|
||||
|
||||
return isEnabled;
|
||||
}
|
||||
case WebGLExtensionID::WEBGL_depth_texture:
|
||||
// WEBGL_depth_texture supports DEPTH_STENCIL textures
|
||||
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
|
||||
|
||||
@@ -4,16 +4,19 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLShader.h"
|
||||
#include "WebGLProgram.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLRenderbuffer.h"
|
||||
#include "WebGLTexture.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsString.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLProgram.h"
|
||||
#include "WebGLRenderbuffer.h"
|
||||
#include "WebGLShader.h"
|
||||
#include "WebGLTexture.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -57,6 +60,18 @@ WebGLContext::Enable(GLenum cap)
|
||||
gl->fEnable(cap);
|
||||
}
|
||||
|
||||
static JS::Value
|
||||
StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv)
|
||||
{
|
||||
JSString* jsStr = JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length());
|
||||
if (!jsStr) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
return JS::StringValue(jsStr);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::GetStencilBits(GLint* out_stencilBits)
|
||||
{
|
||||
@@ -176,19 +191,47 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
}
|
||||
}
|
||||
|
||||
// Privileged string params exposed by WEBGL_debug_renderer_info:
|
||||
// Privileged string params exposed by WEBGL_debug_renderer_info.
|
||||
// The privilege check is done in WebGLContext::IsExtensionSupported.
|
||||
// So here we just have to check that the extension is enabled.
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
|
||||
switch (pname) {
|
||||
case UNMASKED_VENDOR_WEBGL:
|
||||
case UNMASKED_RENDERER_WEBGL:
|
||||
GLenum glstringname = LOCAL_GL_NONE;
|
||||
if (pname == UNMASKED_VENDOR_WEBGL) {
|
||||
glstringname = LOCAL_GL_VENDOR;
|
||||
} else if (pname == UNMASKED_RENDERER_WEBGL) {
|
||||
glstringname = LOCAL_GL_RENDERER;
|
||||
{
|
||||
const char* overridePref = nullptr;
|
||||
GLenum driverEnum = LOCAL_GL_NONE;
|
||||
|
||||
switch (pname) {
|
||||
case UNMASKED_RENDERER_WEBGL:
|
||||
overridePref = "webgl.renderer-string-override";
|
||||
driverEnum = LOCAL_GL_RENDERER;
|
||||
break;
|
||||
case UNMASKED_VENDOR_WEBGL:
|
||||
overridePref = "webgl.vendor-string-override";
|
||||
driverEnum = LOCAL_GL_VENDOR;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("bad `pname`");
|
||||
}
|
||||
|
||||
bool hasRetVal = false;
|
||||
|
||||
nsAutoString ret;
|
||||
if (overridePref) {
|
||||
nsresult res = Preferences::GetString(overridePref, &ret);
|
||||
if (NS_SUCCEEDED(res) && ret.Length() > 0)
|
||||
hasRetVal = true;
|
||||
}
|
||||
|
||||
if (!hasRetVal) {
|
||||
const char* chars = reinterpret_cast<const char*>(gl->fGetString(driverEnum));
|
||||
ret = NS_ConvertASCIItoUTF16(chars);
|
||||
hasRetVal = true;
|
||||
}
|
||||
|
||||
return StringValue(cx, ret, rv);
|
||||
}
|
||||
const GLchar* string = (const GLchar*) gl->fGetString(glstringname);
|
||||
return StringValue(cx, string, rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.rect(2, 6, 9, 8);
|
||||
ctx.setTransform(1, 2, 3, 0, 4, 1);
|
||||
setTimeout(function() {
|
||||
ctx.moveTo(0, 1);
|
||||
ctx.isPointInPath(0, 0, 'evenodd');
|
||||
}, 0);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();">
|
||||
<canvas id="canvas"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
@@ -22,3 +22,4 @@ load 896047-2.html
|
||||
load 916128-1.html
|
||||
load 934939-1.html
|
||||
load 1099143-1.html
|
||||
load 1183363.html
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
<html>
|
||||
<script>
|
||||
|
||||
var Cu = parent.Components.utils;
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
// This gives us `AppConstants` in the global scope.
|
||||
// We need this because we only expose debug_renderer_info #ifndef MOZ_RELEASE_BUILD.
|
||||
// This should match AppConstants.RELEASE_BUILD.
|
||||
|
||||
// This file has the portion of the test_webgl_renderer_info chrome mochitest
|
||||
// that has to run as non-chrome to check that this WebGL extension is not exposed to content
|
||||
|
||||
@@ -28,30 +34,58 @@ function run() {
|
||||
const UNMASKED_VENDOR_WEBGL = 0x9245;
|
||||
const UNMASKED_RENDERER_WEBGL = 0x9246;
|
||||
|
||||
var shouldHaveRendererInfo = false;
|
||||
if (!AppConstants.RELEASE_BUILD)
|
||||
shouldHaveRendererInfo = true;
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
var gl = canvas.getContext("experimental-webgl");
|
||||
|
||||
ok(!gl.getError(), "getError on newly created WebGL context should return NO_ERROR");
|
||||
|
||||
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
|
||||
"Should not be able to query UNMASKED_VENDOR_WEBGL without having enabled the WEBGL_debug_renderer_info extension");
|
||||
"Should not be able to query UNMASKED_VENDOR_WEBGL without having enabled the"
|
||||
+ " WEBGL_debug_renderer_info extension");
|
||||
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
|
||||
"Should not be able to query UNMASKED_RENDERER_WEBGL without having enabled the WEBGL_debug_renderer_info extension");
|
||||
"Should not be able to query UNMASKED_RENDERER_WEBGL without having enabled the"
|
||||
+ " WEBGL_debug_renderer_info extension");
|
||||
|
||||
var exts = gl.getSupportedExtensions();
|
||||
ok(exts.indexOf("WEBGL_debug_renderer_info") == -1,
|
||||
"WEBGL_debug_renderer_info should not be listed by getSupportedExtensions in non-chrome contexts");
|
||||
var debugRendererInfoExtension = gl.getExtension("WEBGL_debug_renderer_info");
|
||||
ok(!debugRendererInfoExtension,
|
||||
"WEBGL_debug_renderer_info should not be available through getExtension in non-chrome contexts");
|
||||
if (shouldHaveRendererInfo) {
|
||||
ok(exts.indexOf("WEBGL_debug_renderer_info") != -1,
|
||||
"WEBGL_debug_renderer_info should be listed by getSupportedExtensions in"
|
||||
+ " non-chrome contexts on non-RELEASE_BUILDs");
|
||||
|
||||
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
|
||||
"Should not be able to query UNMASKED_VENDOR_WEBGL if enabling WEBGL_debug_renderer_info failed");
|
||||
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
|
||||
"Should not be able to query UNMASKED_RENDERER_WEBGL if enabling WEBGL_debug_renderer_info failed");
|
||||
var ext = gl.getExtension("WEBGL_debug_renderer_info");
|
||||
ok(!!ext,
|
||||
"WEBGL_debug_renderer_info should be available through getExtension in non-chrome"
|
||||
+ " contexts on non-RELEASE_BUILDs");
|
||||
|
||||
ok(gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.NO_ERROR,
|
||||
"Should be able to query UNMASKED_VENDOR_WEBGL if enabling"
|
||||
+ " WEBGL_debug_renderer_info succeeded");
|
||||
ok(gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.NO_ERROR,
|
||||
"Should be able to query UNMASKED_RENDERER_WEBGL if enabling"
|
||||
+ " WEBGL_debug_renderer_info succeeded");
|
||||
} else {
|
||||
ok(exts.indexOf("WEBGL_debug_renderer_info") == -1,
|
||||
"WEBGL_debug_renderer_info should not be listed by getSupportedExtensions in"
|
||||
+ " non-chrome contexts");
|
||||
var ext = gl.getExtension("WEBGL_debug_renderer_info");
|
||||
ok(!ext,
|
||||
"WEBGL_debug_renderer_info should not be available through getExtension in"
|
||||
+ " non-chrome contexts");
|
||||
|
||||
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
|
||||
"Should not be able to query UNMASKED_VENDOR_WEBGL if enabling"
|
||||
+ " WEBGL_debug_renderer_info failed");
|
||||
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
|
||||
"Should not be able to query UNMASKED_RENDERER_WEBGL if enabling"
|
||||
+ " WEBGL_debug_renderer_info failed");
|
||||
|
||||
}
|
||||
window.postMessage({allTestsFinished: true}, "*");
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -43,13 +43,13 @@ function checkChromeCase(canvas) {
|
||||
var exts = gl.getSupportedExtensions();
|
||||
ok(exts.indexOf("WEBGL_debug_renderer_info") != -1,
|
||||
"WEBGL_debug_renderer_info should be listed by getSupportedExtensions in chrome contexts");
|
||||
var debugRendererInfoExtension = gl.getExtension("WEBGL_debug_renderer_info");
|
||||
ok(debugRendererInfoExtension,
|
||||
var ext = gl.getExtension("WEBGL_debug_renderer_info");
|
||||
ok(ext,
|
||||
"WEBGL_debug_renderer_info should be available through getExtension in chrome contexts");
|
||||
|
||||
ok(debugRendererInfoExtension.UNMASKED_VENDOR_WEBGL == UNMASKED_VENDOR_WEBGL,
|
||||
ok(ext.UNMASKED_VENDOR_WEBGL == UNMASKED_VENDOR_WEBGL,
|
||||
"UNMASKED_VENDOR_WEBGL has the correct value");
|
||||
ok(debugRendererInfoExtension.UNMASKED_RENDERER_WEBGL == UNMASKED_RENDERER_WEBGL,
|
||||
ok(ext.UNMASKED_RENDERER_WEBGL == UNMASKED_RENDERER_WEBGL,
|
||||
"UNMASKED_RENDERER_WEBGL has the correct value");
|
||||
|
||||
ok(isNonEmptyString(gl.getParameter(UNMASKED_VENDOR_WEBGL)) && gl.getError() == gl.NO_ERROR,
|
||||
@@ -67,7 +67,7 @@ function main()
|
||||
// Now run the non-chrome code to verify the security of this WebGL chrome-only extension.
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = "http://mochi.test:8888/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
|
||||
iframe.src = "chrome://mochitests/content/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
|
||||
|
||||
iframe.onload = function () {
|
||||
|
||||
|
||||
@@ -213,6 +213,7 @@ skip-if = toolkit != 'cocoa'
|
||||
[test_2d.path.rect.zero.6.html]
|
||||
disabled = bug 407107
|
||||
[test_2d.strokeRect.zero.5.html]
|
||||
[test_bug232227.html]
|
||||
[test_bug613794.html]
|
||||
[test_bug753758.html]
|
||||
[test_bug764125.html]
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase for bug 1177726</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<canvas id="c" width="400" height="200">
|
||||
<p>No canvas.</p>
|
||||
</canvas>
|
||||
|
||||
<script>
|
||||
var canvas = document.getElementsByTagName("canvas")[0];
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.font = "120px 'Helvetica'";
|
||||
ctx.lineWidth = 15;
|
||||
ctx.lineJoin = "round";
|
||||
|
||||
ctx.strokeText("Ehsan", 20, 110);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase for bug 1177726</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<canvas id="c" width="400" height="200">
|
||||
<p>No canvas.</p>
|
||||
</canvas>
|
||||
|
||||
<script>
|
||||
var canvas = document.getElementsByTagName("canvas")[0];
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.shadowColor = 'white';
|
||||
ctx.shadowOffsetX = 5;
|
||||
ctx.shadowOffsetY = 5;
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.font = "120px 'Helvetica'";
|
||||
ctx.lineWidth = 15;
|
||||
ctx.lineJoin = "round";
|
||||
|
||||
ctx.strokeText("Ehsan", 20, 110);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -157,4 +157,6 @@ pref(canvas.focusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion
|
||||
pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion<15,8,500) skip-if(winWidget) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html
|
||||
|
||||
# Check that captureStream() displays in a local video element
|
||||
pref(canvas.capturestream.enabled,true) fails-if(B2G) skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
|
||||
pref(canvas.capturestream.enabled,true) skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
|
||||
|
||||
fuzzy-if(Android,3,40) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=232227
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 232227</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=232227">Mozilla Bug 232227</a>
|
||||
<!-- CSS system colors -->
|
||||
<!--<table cellspacing=0 border=1>
|
||||
<caption>CSS system colors</caption>
|
||||
<canvas id=colorTestCanvas width=1 height=1 style="display:none"></canvas> -->
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 232227 **/
|
||||
|
||||
function beginTest() {
|
||||
var colorNames = [
|
||||
[ "ActiveBorder", 0xB4, 0xB4, 0xB4 ],
|
||||
[ "ActiveCaption", 0x99, 0xB4, 0xD1 ],
|
||||
[ "AppWorkspace", 0xAB, 0xAB, 0xAB ],
|
||||
[ "Background", 0x00, 0x00, 0x00 ],
|
||||
[ "ButtonFace", 0xF0, 0xF0, 0xF0 ],
|
||||
[ "ButtonHighlight", 0xFF, 0xFF, 0xFF ],
|
||||
[ "ButtonShadow", 0xA0, 0xA0, 0xA0 ],
|
||||
[ "ButtonText", 0x00, 0x00, 0x00 ],
|
||||
[ "CaptionText", 0x00, 0x00, 0x00 ],
|
||||
[ "GrayText", 0x6D, 0x6D, 0x6D ],
|
||||
[ "Highlight", 0x33, 0x99, 0xFF ],
|
||||
[ "HighlightText", 0xFF, 0xFF, 0xFF ],
|
||||
[ "InactiveBorder", 0xF4, 0xF7, 0xFC ],
|
||||
[ "InactiveCaption", 0xBF, 0xCD, 0xDB ],
|
||||
[ "InactiveCaptionText", 0x43, 0x4E, 0x54 ],
|
||||
[ "InfoBackground", 0xFF, 0xFF, 0xE1 ],
|
||||
[ "InfoText", 0x00, 0x00, 0x00 ],
|
||||
[ "Menu", 0xF0, 0xF0, 0xF0 ],
|
||||
[ "MenuText", 0x00, 0x00, 0x00 ],
|
||||
[ "Scrollbar", 0xC8, 0xC8, 0xC8 ],
|
||||
[ "ThreeDDarkShadow", 0x69, 0x69, 0x69 ],
|
||||
[ "ThreeDFace", 0xF0, 0xF0, 0xF0 ],
|
||||
[ "ThreeDHighlight", 0xFF, 0xFF, 0xFF ],
|
||||
[ "ThreeDLightShadow", 0xE3, 0xE3, 0xE3 ],
|
||||
[ "ThreeDShadow", 0xA0, 0xA0, 0xA0 ],
|
||||
[ "Window", 0xFF, 0xFF, 0xFF ],
|
||||
[ "WindowFrame", 0x64, 0x64, 0x64 ],
|
||||
[ "WindowText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-ButtonDefault", 0x69, 0x69, 0x69 ],
|
||||
[ "-moz-ButtonHoverFace", 0xF0, 0xF0, 0xF0 ],
|
||||
[ "-moz-ButtonHoverText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-CellHighlight", 0xF0, 0xF0, 0xF0 ],
|
||||
[ "-moz-CellHighlightText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-Combobox", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-ComboboxText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-Dialog", 0xF0, 0xF0, 0xF0 ],
|
||||
[ "-moz-DialogText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-DragTargetZone", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-EvenTreeRow", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-Field", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-FieldText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-MenuHover", 0x33, 0x99, 0xFF ],
|
||||
[ "-moz-MenuHoverText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-MenubarText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-MenubarHoverText", 0x00, 0x00, 0x00 ],
|
||||
[ "-moz-NativeHyperlinkText", 0x00, 0x66, 0xCC ],
|
||||
[ "-moz-OddTreeRow", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-html-CellHighlight", 0x33, 0x99, 0xFF ],
|
||||
[ "-moz-html-CellHighlightText", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-mac-chrome-active", 0xB2, 0xB2, 0xB2 ],
|
||||
[ "-moz-mac-chrome-inactive", 0xE1, 0xE1, 0xE1 ],
|
||||
[ "-moz-mac-focusring", 0x60, 0x9D, 0xD7 ],
|
||||
[ "-moz-mac-menuselect", 0x38, 0x75, 0xD7 ],
|
||||
[ "-moz-mac-menushadow", 0xA3, 0xA3, 0xA3 ],
|
||||
[ "-moz-mac-menutextdisable", 0x88, 0x88, 0x88 ],
|
||||
[ "-moz-mac-menutextselect", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-mac-DisabledToolbarText", 0x3F, 0x3F, 0x3F ],
|
||||
[ "-moz-mac-AlternatePrimaryHighlight", 0x3F, 0x3F, 0x3F ],
|
||||
[ "-moz-mac-SecondaryHighlight", 0xD4, 0xD4, 0xD4 ],
|
||||
[ "-moz-win-MediaText", 0xFF, 0xFF, 0xFF ],
|
||||
[ "-moz-win-CommunicationsText", 0xFF, 0xFF, 0xFF ],
|
||||
|
||||
// These five are configured via Tools -> Options -> Content -> Colors.
|
||||
//"-moz-ActiveHyperlinkText",
|
||||
//"-moz-HyperLinkText",
|
||||
//"-moz-VisitedHyperlinkText",
|
||||
//"-moz-default-background-color",
|
||||
//"-moz-default-color",
|
||||
];
|
||||
|
||||
var colorTestCanvas = document.createElement("canvas");
|
||||
colorTestCanvas.width = colorTestCanvas.height = 1;
|
||||
colorTestCanvas = colorTestCanvas.getContext("2d");
|
||||
|
||||
var colorTestDiv = document.createElement("div");
|
||||
document.body.appendChild(colorTestDiv); // ie
|
||||
|
||||
for (var i in colorNames) {
|
||||
(function(colorName, r, g, b) {
|
||||
// test value
|
||||
var ctest = "rgb(" + r + ", " + g + ", " + b + ")";
|
||||
|
||||
// computed value
|
||||
colorTestDiv.style.backgroundColor = "#FF00FE";
|
||||
try {
|
||||
colorTestDiv.style.backgroundColor = colorName;
|
||||
} catch (ex) {} // ie
|
||||
var c1;
|
||||
if (window.getComputedStyle) {
|
||||
c1 = getComputedStyle(colorTestDiv, null).backgroundColor;
|
||||
} else { // ie
|
||||
var range = document.body.createTextRange();
|
||||
range.moveToElementText(colorTestDiv);
|
||||
c1 = range.queryCommandValue("BackColor");
|
||||
c1 = "rgb(" + (c1 & 0xFF) + ", " + ((c1 >> 8) & 0xFF) + ", " + ((c1 >> 16) & 0xFF) + ")";
|
||||
}
|
||||
if (c1 != "rgb(255, 0, 254)") {
|
||||
is(c1, ctest, "Stand-in computed color: " + colorName + " is correct.");
|
||||
}
|
||||
|
||||
// canvas
|
||||
if (colorTestCanvas) {
|
||||
colorTestCanvas.fillStyle = colorName;
|
||||
colorTestCanvas.fillRect(0, 0, 1, 1);
|
||||
var c2 = colorTestCanvas.getImageData(0, 0, 1, 1).data;
|
||||
c2 = "rgb(" + c2[0] + ", " + c2[1] + ", " + c2[2] + ")";
|
||||
|
||||
// combine
|
||||
if (c2 != c1 && c2 != "rgb(0, 0, 0)") {
|
||||
is(c2, ctest, "Stand-in canvas color: " + colorName + " is correct.");
|
||||
}
|
||||
}
|
||||
})(colorNames[i][0], colorNames[i][1], colorNames[i][2], colorNames[i][3]);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "ui.use_standins_for_native_colors", true ],
|
||||
[ "ui.use_native_colors", true ],
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
|
||||
</script>
|
||||
<!-- </table> -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -22,6 +22,7 @@ skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in
|
||||
skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.3 aws only; bug 1030942
|
||||
[webgl-mochitest/test_noprog_draw.html]
|
||||
[webgl-mochitest/test_privileged_exts.html]
|
||||
[webgl-mochitest/test_renderer_strings.html]
|
||||
[webgl-mochitest/test_texsubimage_float.html]
|
||||
[webgl-mochitest/test_webgl_available.html]
|
||||
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
|
||||
|
||||
@@ -24,7 +24,7 @@ function TestExt(gl, name) {
|
||||
}
|
||||
|
||||
// Privileged extensions:
|
||||
TestExt(gl, 'WEBGL_debug_renderer_info');
|
||||
TestExt(gl, 'WEBGL_debug_shaders');
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
function AssertError(gl, expected, info) {
|
||||
var actual = gl.getError();
|
||||
while (gl.getError()) {}
|
||||
|
||||
ok(actual == expected,
|
||||
'For ' + info + ', expected 0x' + expected.toString(16) + ', got 0x'
|
||||
+ actual.toString(16));
|
||||
}
|
||||
|
||||
var gl;
|
||||
|
||||
var RENDERER_OVERRIDE = 'overridden renderer';
|
||||
var VENDOR_OVERRIDE = 'overridden vendor';
|
||||
|
||||
function TestExt() {
|
||||
var ext = gl.getExtension('WEBGL_debug_renderer_info');
|
||||
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
|
||||
AssertError(gl, 0, 'start of test');
|
||||
|
||||
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
|
||||
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
|
||||
ok(renderer,
|
||||
'UNMASKED_RENDERER_WEBGL value should not be empty, was \'' + renderer + '\'');
|
||||
|
||||
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
|
||||
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
|
||||
ok(vendor, 'UNMASKED_VENDOR_WEBGL value should not be empty, was \'' + vendor + '\'');
|
||||
|
||||
var prefArrArr = [
|
||||
['webgl.renderer-string-override', RENDERER_OVERRIDE],
|
||||
['webgl.vendor-string-override', VENDOR_OVERRIDE],
|
||||
];
|
||||
var prefEnv = {'set': prefArrArr};
|
||||
SpecialPowers.pushPrefEnv(prefEnv, TestOverrides);
|
||||
}
|
||||
|
||||
function TestOverrides() {
|
||||
var ext = gl.getExtension('WEBGL_debug_renderer_info');
|
||||
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
|
||||
AssertError(gl, 0, 'start of test');
|
||||
|
||||
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
|
||||
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
|
||||
ok(renderer == RENDERER_OVERRIDE,
|
||||
'UNMASKED_RENDERER_WEBGL value should be \'' + RENDERER_OVERRIDE + '\', was \''
|
||||
+ renderer + '\'');
|
||||
|
||||
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
|
||||
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
|
||||
ok(vendor == VENDOR_OVERRIDE,
|
||||
'UNMASKED_VENDOR_WEBGL value should be \'' + VENDOR_OVERRIDE + '\', was \'' + vendor
|
||||
+ '\'');
|
||||
|
||||
var prefArrArr = [
|
||||
['webgl.disable-debug-renderer-info', true],
|
||||
];
|
||||
var prefEnv = {'set': prefArrArr};
|
||||
SpecialPowers.pushPrefEnv(prefEnv, TestDisable);
|
||||
}
|
||||
|
||||
function TestDisable() {
|
||||
var ext = gl.getExtension('WEBGL_debug_renderer_info');
|
||||
ok(!ext, 'Should not have access to \'WEBGL_debug_renderer_info\'.');
|
||||
|
||||
ok(true, 'Test complete.');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
(function() {
|
||||
var canvas = document.createElement('canvas');
|
||||
gl = canvas.getContext('experimental-webgl');
|
||||
if (!gl) {
|
||||
todo(gl, 'Get WebGL working here first.');
|
||||
ok(true, 'Test complete.');
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var prefArrArr = [
|
||||
['webgl.disable-debug-renderer-info', false],
|
||||
];
|
||||
var prefEnv = {'set': prefArrArr};
|
||||
SpecialPowers.pushPrefEnv(prefEnv, TestExt);
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+2
-2
@@ -91,8 +91,8 @@ Matrix::Rotation(Float aAngle)
|
||||
{
|
||||
Matrix newMatrix;
|
||||
|
||||
Float s = sin(aAngle);
|
||||
Float c = cos(aAngle);
|
||||
Float s = sinf(aAngle);
|
||||
Float c = cosf(aAngle);
|
||||
|
||||
newMatrix._11 = c;
|
||||
newMatrix._12 = s;
|
||||
|
||||
+4
-4
@@ -267,8 +267,8 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
||||
}
|
||||
|
||||
Point endPoint;
|
||||
endPoint.x = aOrigin.x + aRadius * cos(aEndAngle);
|
||||
endPoint.y = aOrigin.y + aRadius * sin(aEndAngle);
|
||||
endPoint.x = aOrigin.x + aRadius * cosf(aEndAngle);
|
||||
endPoint.y = aOrigin.y + aRadius * sinf(aEndAngle);
|
||||
|
||||
D2D1_ARC_SIZE arcSize = D2D1_ARC_SIZE_SMALL;
|
||||
D2D1_SWEEP_DIRECTION direction =
|
||||
@@ -296,8 +296,8 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
||||
else {
|
||||
// draw small circles as two half-circles
|
||||
Point midPoint;
|
||||
midPoint.x = aOrigin.x + aRadius * cos(midAngle);
|
||||
midPoint.y = aOrigin.y + aRadius * sin(midAngle);
|
||||
midPoint.x = aOrigin.x + aRadius * cosf(midAngle);
|
||||
midPoint.y = aOrigin.y + aRadius * sinf(midAngle);
|
||||
|
||||
mSink->AddArc(D2D1::ArcSegment(D2DPoint(midPoint),
|
||||
D2D1::SizeF(aRadius, aRadius),
|
||||
|
||||
@@ -185,8 +185,8 @@ inline float EvalLanczos(int filter_size, float x) {
|
||||
x < std::numeric_limits<float>::epsilon())
|
||||
return 1.0f; // Special case the discontinuity at the origin.
|
||||
float xpi = x * static_cast<float>(M_PI);
|
||||
return (sin(xpi) / xpi) * // sinc(x)
|
||||
sin(xpi / filter_size) / (xpi / filter_size); // sinc(x/filter_size)
|
||||
return (sinf(xpi) / xpi) * // sinc(x)
|
||||
sinf(xpi / filter_size) / (xpi / filter_size); // sinc(x/filter_size)
|
||||
}
|
||||
|
||||
// Evaluates the Hamming filter of the given filter size window for the given
|
||||
@@ -212,8 +212,8 @@ inline float EvalHamming(int filter_size, float x) {
|
||||
return 1.0f; // Special case the sinc discontinuity at the origin.
|
||||
const float xpi = x * static_cast<float>(M_PI);
|
||||
|
||||
return ((sin(xpi) / xpi) * // sinc(x)
|
||||
(0.54f + 0.46f * cos(xpi / filter_size))); // hamming(x)
|
||||
return ((sinf(xpi) / xpi) * // sinc(x)
|
||||
(0.54f + 0.46f * cosf(xpi / filter_size))); // hamming(x)
|
||||
}
|
||||
|
||||
// ResizeFilter ----------------------------------------------------------------
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ CreateEGLImage(GLContext* gl, GLuint tex)
|
||||
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
|
||||
|
||||
EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
|
||||
EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
|
||||
EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
|
||||
EGLImage image = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
|
||||
eglContext,
|
||||
LOCAL_EGL_GL_TEXTURE_2D,
|
||||
@@ -42,7 +42,7 @@ EGLImageWrapper::Create(GLContext* gl, GLuint tex)
|
||||
|
||||
GLLibraryEGL& library = sEGLLibrary;
|
||||
EGLDisplay display = EGL_DISPLAY();
|
||||
EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
|
||||
EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
|
||||
EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
|
||||
EGLImage image = library.fCreateImage(display,
|
||||
eglContext,
|
||||
|
||||
@@ -30,119 +30,6 @@ using mozilla::layers::PlanarYCbCrData;
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
static void
|
||||
RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples,
|
||||
GLenum aInternalFormat, const gfx::IntSize& aSize)
|
||||
{
|
||||
if (aSamples) {
|
||||
aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
|
||||
aSamples,
|
||||
aInternalFormat,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
aInternalFormat,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint
|
||||
CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
|
||||
GLenum aType, const gfx::IntSize& aSize, bool linear)
|
||||
{
|
||||
GLuint tex = 0;
|
||||
aGL->fGenTextures(1, &tex);
|
||||
ScopedBindTexture autoTex(aGL, tex);
|
||||
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MIN_FILTER, linear ? LOCAL_GL_LINEAR
|
||||
: LOCAL_GL_NEAREST);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MAG_FILTER, linear ? LOCAL_GL_LINEAR
|
||||
: LOCAL_GL_NEAREST);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
aInternalFormat,
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
aFormat,
|
||||
aType,
|
||||
nullptr);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
GLuint
|
||||
CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
|
||||
const gfx::IntSize& aSize)
|
||||
{
|
||||
MOZ_ASSERT(aFormats.color_texInternalFormat);
|
||||
MOZ_ASSERT(aFormats.color_texFormat);
|
||||
MOZ_ASSERT(aFormats.color_texType);
|
||||
|
||||
return CreateTexture(aGL,
|
||||
aFormats.color_texInternalFormat,
|
||||
aFormats.color_texFormat,
|
||||
aFormats.color_texType,
|
||||
aSize);
|
||||
}
|
||||
|
||||
|
||||
GLuint
|
||||
CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
|
||||
const gfx::IntSize& aSize)
|
||||
{
|
||||
GLuint rb = 0;
|
||||
aGL->fGenRenderbuffers(1, &rb);
|
||||
ScopedBindRenderbuffer autoRB(aGL, rb);
|
||||
|
||||
RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize);
|
||||
|
||||
return rb;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
|
||||
const gfx::IntSize& aSize, bool aMultisample,
|
||||
GLuint* aColorMSRB, GLuint* aDepthRB,
|
||||
GLuint* aStencilRB)
|
||||
{
|
||||
GLsizei samples = aMultisample ? aFormats.samples : 0;
|
||||
if (aColorMSRB) {
|
||||
MOZ_ASSERT(aFormats.samples > 0);
|
||||
MOZ_ASSERT(aFormats.color_rbFormat);
|
||||
|
||||
*aColorMSRB = CreateRenderbuffer(aGL, aFormats.color_rbFormat, samples, aSize);
|
||||
}
|
||||
|
||||
if (aDepthRB &&
|
||||
aStencilRB &&
|
||||
aFormats.depthStencil)
|
||||
{
|
||||
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize);
|
||||
*aStencilRB = *aDepthRB;
|
||||
} else {
|
||||
if (aDepthRB) {
|
||||
MOZ_ASSERT(aFormats.depth);
|
||||
|
||||
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize);
|
||||
}
|
||||
|
||||
if (aStencilRB) {
|
||||
MOZ_ASSERT(aFormats.stencil);
|
||||
|
||||
*aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLBlitHelper::GLBlitHelper(GLContext* gl)
|
||||
: mGL(gl)
|
||||
, mTexBlit_Buffer(0)
|
||||
|
||||
@@ -27,48 +27,6 @@ namespace gl {
|
||||
|
||||
class GLContext;
|
||||
|
||||
/**
|
||||
* Helper function that creates a 2D texture aSize.width x aSize.height with
|
||||
* storage type specified by aFormats. Returns GL texture object id.
|
||||
*
|
||||
* See mozilla::gl::CreateTexture.
|
||||
*/
|
||||
GLuint CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
|
||||
const gfx::IntSize& aSize);
|
||||
|
||||
/**
|
||||
* Helper function that creates a 2D texture aSize.width x aSize.height with
|
||||
* storage type aInternalFormat. Returns GL texture object id.
|
||||
*
|
||||
* Initialize textyre parameters to:
|
||||
* GL_TEXTURE_MIN_FILTER = GL_LINEAR
|
||||
* GL_TEXTURE_MAG_FILTER = GL_LINEAR
|
||||
* GL_TEXTURE_WRAP_S = GL_CLAMP_TO_EDGE
|
||||
* GL_TEXTURE_WRAP_T = GL_CLAMP_TO_EDGE
|
||||
*/
|
||||
GLuint CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
|
||||
GLenum aType, const gfx::IntSize& aSize, bool linear = true);
|
||||
|
||||
/**
|
||||
* Helper function to create, potentially, multisample render buffers suitable
|
||||
* for offscreen rendering. Buffers of size aSize.width x aSize.height with
|
||||
* storage specified by aFormat. returns GL render buffer object id.
|
||||
*/
|
||||
GLuint CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
|
||||
const gfx::IntSize& aSize);
|
||||
|
||||
/**
|
||||
* Helper function to create, potentially, multisample render buffers suitable
|
||||
* for offscreen rendering. Buffers of size aSize.width x aSize.height with
|
||||
* storage specified by aFormats. GL render buffer object ids are returned via
|
||||
* aColorMSRB, aDepthRB, and aStencilRB
|
||||
*/
|
||||
void CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
|
||||
const gfx::IntSize& aSize, bool aMultisample,
|
||||
GLuint* aColorMSRB, GLuint* aDepthRB,
|
||||
GLuint* aStencilRB);
|
||||
|
||||
|
||||
/** Buffer blitting helper */
|
||||
class GLBlitHelper final
|
||||
{
|
||||
|
||||
+54
-1
@@ -304,7 +304,6 @@ GLContext::GLContext(const SurfaceCaps& caps,
|
||||
mRenderer(GLRenderer::Other),
|
||||
mHasRobustness(false),
|
||||
mTopError(LOCAL_GL_NO_ERROR),
|
||||
mLocalErrorScope(nullptr),
|
||||
mSharedContext(sharedContext),
|
||||
mCaps(caps),
|
||||
mScreen(nullptr),
|
||||
@@ -2933,5 +2932,59 @@ GLContext::IsDrawingToDefaultFramebuffer()
|
||||
return Screen()->IsDrawFramebufferDefault();
|
||||
}
|
||||
|
||||
GLuint
|
||||
CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
|
||||
GLenum aType, const gfx::IntSize& aSize, bool linear)
|
||||
{
|
||||
GLuint tex = 0;
|
||||
aGL->fGenTextures(1, &tex);
|
||||
ScopedBindTexture autoTex(aGL, tex);
|
||||
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MIN_FILTER, linear ? LOCAL_GL_LINEAR
|
||||
: LOCAL_GL_NEAREST);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_TEXTURE_MAG_FILTER, linear ? LOCAL_GL_LINEAR
|
||||
: LOCAL_GL_NEAREST);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
aInternalFormat,
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
aFormat,
|
||||
aType,
|
||||
nullptr);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
GLuint
|
||||
CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
|
||||
const gfx::IntSize& aSize)
|
||||
{
|
||||
MOZ_ASSERT(aFormats.color_texInternalFormat);
|
||||
MOZ_ASSERT(aFormats.color_texFormat);
|
||||
MOZ_ASSERT(aFormats.color_texType);
|
||||
|
||||
GLenum internalFormat = aFormats.color_texInternalFormat;
|
||||
GLenum unpackFormat = aFormats.color_texFormat;
|
||||
GLenum unpackType = aFormats.color_texType;
|
||||
if (aGL->IsANGLE()) {
|
||||
MOZ_ASSERT(internalFormat == LOCAL_GL_RGBA);
|
||||
MOZ_ASSERT(unpackFormat == LOCAL_GL_RGBA);
|
||||
MOZ_ASSERT(unpackType == LOCAL_GL_UNSIGNED_BYTE);
|
||||
internalFormat = LOCAL_GL_BGRA_EXT;
|
||||
unpackFormat = LOCAL_GL_BGRA_EXT;
|
||||
}
|
||||
|
||||
return CreateTexture(aGL, internalFormat, unpackFormat, unpackType, aSize);
|
||||
}
|
||||
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
+33
-11
@@ -7,12 +7,13 @@
|
||||
#ifndef GLCONTEXT_H_
|
||||
#define GLCONTEXT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <map>
|
||||
#include <bitset>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <string.h>
|
||||
@@ -619,7 +620,7 @@ public:
|
||||
class LocalErrorScope;
|
||||
|
||||
private:
|
||||
LocalErrorScope* mLocalErrorScope;
|
||||
std::stack<const LocalErrorScope*> mLocalErrorScopeStack;
|
||||
|
||||
public:
|
||||
class LocalErrorScope {
|
||||
@@ -632,8 +633,7 @@ public:
|
||||
: mGL(gl)
|
||||
, mHasBeenChecked(false)
|
||||
{
|
||||
MOZ_ASSERT(!mGL.mLocalErrorScope);
|
||||
mGL.mLocalErrorScope = this;
|
||||
mGL.mLocalErrorScopeStack.push(this);
|
||||
|
||||
mGL.FlushErrors();
|
||||
|
||||
@@ -653,10 +653,10 @@ public:
|
||||
|
||||
MOZ_ASSERT(mGL.fGetError() == LOCAL_GL_NO_ERROR);
|
||||
|
||||
mGL.mTopError = mOldTop;
|
||||
MOZ_ASSERT(mGL.mLocalErrorScopeStack.top() == this);
|
||||
mGL.mLocalErrorScopeStack.pop();
|
||||
|
||||
MOZ_ASSERT(mGL.mLocalErrorScope == this);
|
||||
mGL.mLocalErrorScope = nullptr;
|
||||
mGL.mTopError = mOldTop;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -738,7 +738,7 @@ private:
|
||||
}
|
||||
|
||||
if (err != LOCAL_GL_NO_ERROR &&
|
||||
!mLocalErrorScope)
|
||||
!mLocalErrorScopeStack.size())
|
||||
{
|
||||
printf_stderr("[gl:%p] %s: Generated unexpected %s error."
|
||||
" (0x%04x)\n", this, funcName,
|
||||
@@ -3652,6 +3652,28 @@ MarkBitfieldByStrings(const std::vector<nsCString>& strList,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that creates a 2D texture aSize.width x aSize.height with
|
||||
* storage type specified by aFormats. Returns GL texture object id.
|
||||
*
|
||||
* See mozilla::gl::CreateTexture.
|
||||
*/
|
||||
GLuint CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
|
||||
const gfx::IntSize& aSize);
|
||||
|
||||
/**
|
||||
* Helper function that creates a 2D texture aSize.width x aSize.height with
|
||||
* storage type aInternalFormat. Returns GL texture object id.
|
||||
*
|
||||
* Initialize textyre parameters to:
|
||||
* GL_TEXTURE_MIN_FILTER = GL_LINEAR
|
||||
* GL_TEXTURE_MAG_FILTER = GL_LINEAR
|
||||
* GL_TEXTURE_WRAP_S = GL_CLAMP_TO_EDGE
|
||||
* GL_TEXTURE_WRAP_T = GL_CLAMP_TO_EDGE
|
||||
*/
|
||||
GLuint CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
|
||||
GLenum aType, const gfx::IntSize& aSize, bool linear = true);
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
||||
+11
-10
@@ -92,16 +92,12 @@ public:
|
||||
// for the lifetime of this context.
|
||||
void HoldSurface(gfxASurface *aSurf);
|
||||
|
||||
EGLContext GetEGLContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
EGLSurface GetEGLSurface() {
|
||||
EGLSurface GetEGLSurface() const {
|
||||
return mSurface;
|
||||
}
|
||||
|
||||
EGLDisplay GetEGLDisplay() {
|
||||
return EGL_DISPLAY();
|
||||
EGLDisplay GetEGLDisplay() const {
|
||||
return sEGLLibrary.Display();
|
||||
}
|
||||
|
||||
bool BindTex2DOffscreen(GLContext *aOffscreen);
|
||||
@@ -112,15 +108,20 @@ public:
|
||||
CreateEGLPixmapOffscreenContext(const gfx::IntSize& size);
|
||||
|
||||
static already_AddRefed<GLContextEGL>
|
||||
CreateEGLPBufferOffscreenContext(const gfx::IntSize& size);
|
||||
CreateEGLPBufferOffscreenContext(const gfx::IntSize& size,
|
||||
const SurfaceCaps& minCaps);
|
||||
|
||||
protected:
|
||||
friend class GLContextProviderEGL;
|
||||
|
||||
EGLConfig mConfig;
|
||||
public:
|
||||
const EGLConfig mConfig;
|
||||
protected:
|
||||
EGLSurface mSurface;
|
||||
public:
|
||||
const EGLContext mContext;
|
||||
protected:
|
||||
EGLSurface mSurfaceOverride;
|
||||
EGLContext mContext;
|
||||
nsRefPtr<gfxASurface> mThebesSurface;
|
||||
bool mBound;
|
||||
|
||||
|
||||
+23
-36
@@ -9,7 +9,6 @@
|
||||
#include "GLContextTypes.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "SurfaceTypes.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
#include "nsSize.h" // for gfx::IntSize (needed by GLContextProviderImpl.h below)
|
||||
|
||||
@@ -18,16 +17,6 @@ class nsIWidget;
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
enum class CreateContextFlags : int8_t {
|
||||
NONE = 0,
|
||||
REQUIRE_COMPAT_PROFILE = 1 << 0,
|
||||
// Force the use of hardware backed GL, don't allow software implementations.
|
||||
FORCE_ENABLE_HARDWARE = 1 << 1,
|
||||
/* Don't force discrete GPU to be used (if applicable) */
|
||||
ALLOW_OFFLINE_RENDERER = 1 << 2,
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
|
||||
|
||||
#define IN_GL_CONTEXT_PROVIDER_H
|
||||
|
||||
// Null is always there
|
||||
@@ -36,47 +25,45 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderWGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWGL
|
||||
#define DEFAULT_IMPL WGL
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderWGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWGL
|
||||
#define DEFAULT_IMPL WGL
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(XP_WIN)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#ifndef GL_CONTEXT_PROVIDER_DEFAULT
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
|
||||
#endif
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GL_PROVIDER
|
||||
#define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT MOZ_GL_PROVIDER
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
|
||||
#define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT MOZ_GL_PROVIDER
|
||||
#endif
|
||||
|
||||
#ifdef GL_CONTEXT_PROVIDER_DEFAULT
|
||||
typedef GL_CONTEXT_PROVIDER_DEFAULT GLContextProvider;
|
||||
typedef GL_CONTEXT_PROVIDER_DEFAULT GLContextProvider;
|
||||
#else
|
||||
typedef GLContextProviderNull GLContextProvider;
|
||||
typedef GLContextProviderNull GLContextProvider;
|
||||
#endif
|
||||
|
||||
#undef IN_GL_CONTEXT_PROVIDER_H
|
||||
|
||||
@@ -319,16 +319,17 @@ GLContextProviderCGL::CreateHeadless(CreateContextFlags flags)
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateOffscreen(const IntSize& size,
|
||||
const SurfaceCaps& caps,
|
||||
const SurfaceCaps& minCaps,
|
||||
CreateContextFlags flags)
|
||||
{
|
||||
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
|
||||
if (!glContext->InitOffscreen(size, caps)) {
|
||||
NS_WARNING("Failed during InitOffscreen.");
|
||||
RefPtr<GLContext> gl = CreateHeadless(flags);
|
||||
if (!gl)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
if (!gl->InitOffscreen(size, minCaps))
|
||||
return nullptr;
|
||||
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
static nsRefPtr<GLContext> gGlobalContext;
|
||||
|
||||
+247
-136
@@ -3,116 +3,108 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "GLContextEGL.h"
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
#include <gdk/gdkx.h>
|
||||
// we're using default display for now
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW)))
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
|
||||
#else
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
#endif
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "libdisplay/GonkDisplay.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsScreenManagerGonk.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
#include <gdk/gdkx.h>
|
||||
// we're using default display for now
|
||||
#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)(aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
|
||||
#elif defined(MOZ_WIDGET_GONK)
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
#include "libdisplay/GonkDisplay.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsScreenManagerGonk.h"
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
/* from widget */
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID)
|
||||
/* from widget */
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
#include "AndroidBridge.h"
|
||||
#endif
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
|
||||
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "cutils/properties.h"
|
||||
#include <ui/GraphicBuffer.h>
|
||||
|
||||
# if defined(MOZ_WIDGET_GONK)
|
||||
# include "cutils/properties.h"
|
||||
# include <ui/GraphicBuffer.h>
|
||||
using namespace android;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace android;
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#define GLES2_LIB "libGLESv2.so"
|
||||
#define GLES2_LIB2 "libGLESv2.so.2"
|
||||
#define GLES2_LIB "libGLESv2.so"
|
||||
#define GLES2_LIB2 "libGLESv2.so.2"
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
#include "nsIFile.h"
|
||||
|
||||
#include "nsIFile.h"
|
||||
#define GLES2_LIB "libGLESv2.dll"
|
||||
|
||||
#define GLES2_LIB "libGLESv2.dll"
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// a little helper
|
||||
class AutoDestroyHWND {
|
||||
public:
|
||||
AutoDestroyHWND(HWND aWnd = nullptr)
|
||||
: mWnd(aWnd)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoDestroyHWND() {
|
||||
if (mWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
// a little helper
|
||||
class AutoDestroyHWND {
|
||||
public:
|
||||
AutoDestroyHWND(HWND aWnd = nullptr)
|
||||
: mWnd(aWnd)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
operator HWND() {
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND forget() {
|
||||
HWND w = mWnd;
|
||||
mWnd = nullptr;
|
||||
return w;
|
||||
}
|
||||
|
||||
HWND operator=(HWND aWnd) {
|
||||
if (mWnd && mWnd != aWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
~AutoDestroyHWND() {
|
||||
if (mWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
}
|
||||
mWnd = aWnd;
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND mWnd;
|
||||
};
|
||||
operator HWND() {
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND forget() {
|
||||
HWND w = mWnd;
|
||||
mWnd = nullptr;
|
||||
return w;
|
||||
}
|
||||
|
||||
HWND operator=(HWND aWnd) {
|
||||
if (mWnd && mWnd != aWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
mWnd = aWnd;
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND mWnd;
|
||||
};
|
||||
#else
|
||||
|
||||
#error "Platform not recognized"
|
||||
|
||||
#error "Platform not recognized"
|
||||
#endif
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "gfxFailure.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
#include "gfxFailure.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "GLBlitHelper.h"
|
||||
#include "GLContextEGL.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
#include "TextureImageEGL.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "GLBlitHelper.h"
|
||||
#include "TextureImageEGL.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
@@ -190,17 +182,15 @@ DestroySurface(EGLSurface oldSurface) {
|
||||
|
||||
static EGLSurface
|
||||
CreateSurfaceForWindow(nsIWidget* widget, const EGLConfig& config) {
|
||||
EGLSurface newSurface = EGL_NO_SURFACE;
|
||||
EGLSurface newSurface = nullptr;
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
mozilla::AndroidBridge::Bridge()->RegisterCompositor();
|
||||
newSurface = mozilla::AndroidBridge::Bridge()->CreateEGLSurfaceForCompositor();
|
||||
if (newSurface == EGL_NO_SURFACE) {
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
#elif defined(XP_WIN)
|
||||
#else
|
||||
MOZ_ASSERT(widget != nullptr);
|
||||
newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, GET_NATIVE_WINDOW(widget), 0);
|
||||
newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config,
|
||||
GET_NATIVE_WINDOW(widget), 0);
|
||||
#endif
|
||||
return newSurface;
|
||||
}
|
||||
@@ -215,8 +205,8 @@ GLContextEGL::GLContextEGL(
|
||||
: GLContext(caps, shareContext, isOffscreen)
|
||||
, mConfig(config)
|
||||
, mSurface(surface)
|
||||
, mSurfaceOverride(EGL_NO_SURFACE)
|
||||
, mContext(context)
|
||||
, mSurfaceOverride(EGL_NO_SURFACE)
|
||||
, mThebesSurface(nullptr)
|
||||
, mBound(false)
|
||||
, mIsPBuffer(false)
|
||||
@@ -351,7 +341,8 @@ GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
|
||||
}
|
||||
|
||||
mSurfaceOverride = surf;
|
||||
MakeCurrent(true);
|
||||
DebugOnly<bool> ok = MakeCurrent(true);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -425,7 +416,7 @@ GLContextEGL::RenewSurface() {
|
||||
// If we get here, then by definition we know that we want to get a new surface.
|
||||
ReleaseSurface();
|
||||
mSurface = mozilla::gl::CreateSurfaceForWindow(nullptr, mConfig); // the nullptr here is where we assume Android.
|
||||
if (mSurface == EGL_NO_SURFACE) {
|
||||
if (!mSurface) {
|
||||
return false;
|
||||
}
|
||||
return MakeCurrent(true);
|
||||
@@ -490,6 +481,10 @@ GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget)
|
||||
}
|
||||
|
||||
EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
|
||||
if (!surface) {
|
||||
MOZ_CRASH("Failed to create EGLSurface for window!\n");
|
||||
return nullptr;
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
@@ -780,8 +775,7 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
|
||||
}
|
||||
|
||||
EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
|
||||
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
if (!surface) {
|
||||
MOZ_CRASH("Failed to create EGLSurface!\n");
|
||||
return nullptr;
|
||||
}
|
||||
@@ -839,60 +833,144 @@ GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
|
||||
}
|
||||
#endif // defined(ANDROID)
|
||||
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size)
|
||||
static void
|
||||
FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16,
|
||||
nsTArray<EGLint>* out)
|
||||
{
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
|
||||
out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
|
||||
|
||||
const EGLint numConfigs = 1; // We only need one.
|
||||
EGLConfig configs[numConfigs];
|
||||
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
|
||||
out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);
|
||||
|
||||
out->AppendElement(LOCAL_EGL_RED_SIZE);
|
||||
if (bpp16) {
|
||||
out->AppendElement(alpha ? 4 : 5);
|
||||
} else {
|
||||
out->AppendElement(8);
|
||||
}
|
||||
|
||||
out->AppendElement(LOCAL_EGL_GREEN_SIZE);
|
||||
if (bpp16) {
|
||||
out->AppendElement(alpha ? 4 : 6);
|
||||
} else {
|
||||
out->AppendElement(8);
|
||||
}
|
||||
|
||||
out->AppendElement(LOCAL_EGL_BLUE_SIZE);
|
||||
if (bpp16) {
|
||||
out->AppendElement(alpha ? 4 : 5);
|
||||
} else {
|
||||
out->AppendElement(8);
|
||||
}
|
||||
|
||||
out->AppendElement(LOCAL_EGL_ALPHA_SIZE);
|
||||
if (alpha) {
|
||||
out->AppendElement(bpp16 ? 4 : 8);
|
||||
} else {
|
||||
out->AppendElement(0);
|
||||
}
|
||||
|
||||
out->AppendElement(LOCAL_EGL_DEPTH_SIZE);
|
||||
out->AppendElement(depth ? 16 : 0);
|
||||
|
||||
out->AppendElement(LOCAL_EGL_STENCIL_SIZE);
|
||||
out->AppendElement(stencil ? 8 : 0);
|
||||
|
||||
// EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
|
||||
out->AppendElement(LOCAL_EGL_NONE);
|
||||
out->AppendElement(0);
|
||||
|
||||
out->AppendElement(0);
|
||||
out->AppendElement(0);
|
||||
}
|
||||
|
||||
static GLint
|
||||
GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib)
|
||||
{
|
||||
EGLint bits = 0;
|
||||
egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
|
||||
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static EGLConfig
|
||||
ChooseConfig(GLLibraryEGL* egl, const SurfaceCaps& minCaps,
|
||||
SurfaceCaps* const out_configCaps)
|
||||
{
|
||||
nsTArray<EGLint> configAttribList;
|
||||
FillContextAttribs(minCaps.alpha, minCaps.depth, minCaps.stencil, minCaps.bpp16,
|
||||
&configAttribList);
|
||||
|
||||
const EGLint* configAttribs = configAttribList.Elements();
|
||||
|
||||
// We're guaranteed to get at least minCaps, and the sorting dictated by the spec for
|
||||
// eglChooseConfig reasonably assures that a reasonable 'best' config is on top.
|
||||
const EGLint kMaxConfigs = 1;
|
||||
EGLConfig configs[kMaxConfigs];
|
||||
EGLint foundConfigs = 0;
|
||||
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
|
||||
kEGLConfigAttribsOffscreenPBuffer,
|
||||
configs, numConfigs,
|
||||
&foundConfigs)
|
||||
if (!egl->fChooseConfig(egl->Display(), configAttribs, configs, kMaxConfigs,
|
||||
&foundConfigs)
|
||||
|| foundConfigs == 0)
|
||||
{
|
||||
NS_WARNING("No EGL Config for minimal PBuffer!");
|
||||
return EGL_NO_CONFIG;
|
||||
}
|
||||
|
||||
EGLConfig config = configs[0];
|
||||
|
||||
*out_configCaps = minCaps; // Pick up any preserve, etc.
|
||||
out_configCaps->color = true;
|
||||
out_configCaps->alpha = bool(GetAttrib(egl, config, LOCAL_EGL_ALPHA_SIZE));
|
||||
out_configCaps->depth = bool(GetAttrib(egl, config, LOCAL_EGL_DEPTH_SIZE));
|
||||
out_configCaps->stencil = bool(GetAttrib(egl, config, LOCAL_EGL_STENCIL_SIZE));
|
||||
out_configCaps->bpp16 = (GetAttrib(egl, config, LOCAL_EGL_RED_SIZE) < 8);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/*static*/ already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size,
|
||||
const SurfaceCaps& minCaps)
|
||||
{
|
||||
SurfaceCaps configCaps;
|
||||
EGLConfig config = ChooseConfig(&sEGLLibrary, minCaps, &configCaps);
|
||||
if (config == EGL_NO_CONFIG) {
|
||||
NS_WARNING("Failed to find a compatible config.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We absolutely don't care, so just pick the first one.
|
||||
config = configs[0];
|
||||
if (GLContext::ShouldSpew())
|
||||
sEGLLibrary.DumpEGLConfig(config);
|
||||
|
||||
mozilla::gfx::IntSize pbSize(size);
|
||||
surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
|
||||
LOCAL_EGL_NONE,
|
||||
pbSize);
|
||||
EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
|
||||
LOCAL_EGL_NONE,
|
||||
pbSize);
|
||||
if (!surface) {
|
||||
NS_WARNING("Failed to create PBuffer for context!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SurfaceCaps dummyCaps = SurfaceCaps::Any();
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateGLContext(dummyCaps,
|
||||
nullptr, true,
|
||||
config, surface);
|
||||
if (!glContext) {
|
||||
|
||||
RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(configCaps, nullptr, true,
|
||||
config, surface);
|
||||
if (!gl) {
|
||||
NS_WARNING("Failed to create GLContext from PBuffer");
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!glContext->Init()) {
|
||||
if (!gl->Init()) {
|
||||
NS_WARNING("Failed to initialize GLContext!");
|
||||
// GLContextEGL::dtor will destroy |surface| for us.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContextEGL>
|
||||
/*static*/ already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLPixmapOffscreenContext(const mozilla::gfx::IntSize& size)
|
||||
{
|
||||
gfxASurface *thebesSurface = nullptr;
|
||||
@@ -932,49 +1010,82 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const mozilla::gfx::IntSize& size)
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
/*static*/ already_AddRefed<GLContext>
|
||||
GLContextProviderEGL::CreateHeadless(CreateContextFlags flags)
|
||||
{
|
||||
if (!sEGLLibrary.EnsureInitialized(bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE))) {
|
||||
bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
|
||||
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
|
||||
nsRefPtr<GLContext> glContext;
|
||||
glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
|
||||
if (!glContext)
|
||||
return nullptr;
|
||||
|
||||
return glContext.forget();
|
||||
SurfaceCaps dummyCaps = SurfaceCaps::Any();
|
||||
return GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize, dummyCaps);
|
||||
}
|
||||
|
||||
// Under EGL, on Android, pbuffers are supported fine, though
|
||||
// often without the ability to texture from them directly.
|
||||
already_AddRefed<GLContext>
|
||||
/*static*/ already_AddRefed<GLContext>
|
||||
GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
|
||||
const SurfaceCaps& caps,
|
||||
const SurfaceCaps& minCaps,
|
||||
CreateContextFlags flags)
|
||||
{
|
||||
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
|
||||
if (!glContext)
|
||||
bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
|
||||
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware))
|
||||
return nullptr;
|
||||
|
||||
if (!glContext->InitOffscreen(size, caps))
|
||||
bool canOffscreenUseHeadless = true;
|
||||
if (sEGLLibrary.IsANGLE()) {
|
||||
// ANGLE needs to use PBuffers.
|
||||
canOffscreenUseHeadless = false;
|
||||
}
|
||||
|
||||
RefPtr<GLContext> gl;
|
||||
SurfaceCaps minOffscreenCaps = minCaps;
|
||||
|
||||
if (canOffscreenUseHeadless) {
|
||||
gl = CreateHeadless(flags);
|
||||
if (!gl)
|
||||
return nullptr;
|
||||
} else {
|
||||
SurfaceCaps minBackbufferCaps = minOffscreenCaps;
|
||||
if (minOffscreenCaps.antialias) {
|
||||
minBackbufferCaps.antialias = false;
|
||||
minBackbufferCaps.depth = false;
|
||||
minBackbufferCaps.stencil = false;
|
||||
}
|
||||
|
||||
gl = GLContextEGL::CreateEGLPBufferOffscreenContext(size, minBackbufferCaps);
|
||||
if (!gl)
|
||||
return nullptr;
|
||||
|
||||
// Pull the actual resulting caps to ensure that our offscreen matches our
|
||||
// backbuffer.
|
||||
minOffscreenCaps.alpha = gl->Caps().alpha;
|
||||
if (!minOffscreenCaps.antialias) {
|
||||
// Only update these if we don't have AA. If we do have AA, we ignore
|
||||
// backbuffer depth/stencil.
|
||||
minOffscreenCaps.depth = gl->Caps().depth;
|
||||
minOffscreenCaps.stencil = gl->Caps().stencil;
|
||||
}
|
||||
}
|
||||
|
||||
// Init the offscreen with the updated offscreen caps.
|
||||
if (!gl->InitOffscreen(size, minOffscreenCaps))
|
||||
return nullptr;
|
||||
|
||||
return glContext.forget();
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
// Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
|
||||
// and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
|
||||
// and 3) each EGL context eats 750k on B2G (bug 813783)
|
||||
GLContext*
|
||||
/*static*/ GLContext*
|
||||
GLContextProviderEGL::GetGlobalContext()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
/*static*/ void
|
||||
GLContextProviderEGL::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
+103
-88
@@ -76,6 +76,7 @@ GLXLibrary::EnsureInitialized()
|
||||
|
||||
if (!mOGLLibrary) {
|
||||
const char* libGLfilename = nullptr;
|
||||
bool forceFeatureReport = false;
|
||||
|
||||
// see e.g. bug 608526: it is intrinsically interesting to know whether we have dynamically linked to libGL.so.1
|
||||
// because at least the NVIDIA implementation requires an executable stack, which causes mprotect calls,
|
||||
@@ -86,11 +87,13 @@ GLXLibrary::EnsureInitialized()
|
||||
libGLfilename = "libGL.so.1";
|
||||
#endif
|
||||
|
||||
ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport);
|
||||
mOGLLibrary = PR_LoadLibrary(libGLfilename);
|
||||
if (!mOGLLibrary) {
|
||||
NS_WARNING("Couldn't load OpenGL shared library.");
|
||||
return false;
|
||||
}
|
||||
reporter.SetSuccessful();
|
||||
}
|
||||
|
||||
if (PR_GetEnv("MOZ_GLX_DEBUG")) {
|
||||
@@ -232,7 +235,9 @@ GLXLibrary::EnsureInitialized()
|
||||
}
|
||||
|
||||
if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness") &&
|
||||
GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) {
|
||||
GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_robustness,
|
||||
(GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress))
|
||||
{
|
||||
mHasRobustness = true;
|
||||
}
|
||||
|
||||
@@ -1123,75 +1128,96 @@ GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContextGLX>
|
||||
CreateOffscreenPixmapContext(const IntSize& size)
|
||||
static bool
|
||||
ChooseConfig(GLXLibrary* glx, Display* display, int screen, const SurfaceCaps& minCaps,
|
||||
ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
|
||||
GLXFBConfig* const out_config, int* const out_visid)
|
||||
{
|
||||
GLXLibrary& glx = sGLXLibrary;
|
||||
if (!glx.EnsureInitialized()) {
|
||||
return nullptr;
|
||||
}
|
||||
ScopedXFree<GLXFBConfig>& scopedConfigArr = *out_scopedConfigArr;
|
||||
|
||||
Display *display = DefaultXDisplay();
|
||||
int xscreen = DefaultScreen(display);
|
||||
if (minCaps.antialias)
|
||||
return false;
|
||||
|
||||
int attribs[] = {
|
||||
LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT,
|
||||
LOCAL_GLX_X_RENDERABLE, True,
|
||||
LOCAL_GLX_RED_SIZE, 8,
|
||||
LOCAL_GLX_GREEN_SIZE, 8,
|
||||
LOCAL_GLX_BLUE_SIZE, 8,
|
||||
LOCAL_GLX_ALPHA_SIZE, minCaps.alpha ? 8 : 0,
|
||||
LOCAL_GLX_DEPTH_SIZE, minCaps.depth ? 16 : 0,
|
||||
LOCAL_GLX_STENCIL_SIZE, minCaps.stencil ? 8 : 0,
|
||||
0
|
||||
};
|
||||
|
||||
int numConfigs = 0;
|
||||
scopedConfigArr = glx->xChooseFBConfig(display, screen, attribs, &numConfigs);
|
||||
if (!scopedConfigArr || !numConfigs)
|
||||
return false;
|
||||
|
||||
ScopedXFree<GLXFBConfig> cfgs;
|
||||
cfgs = glx.xChooseFBConfig(display,
|
||||
xscreen,
|
||||
attribs,
|
||||
&numConfigs);
|
||||
if (!cfgs) {
|
||||
return nullptr;
|
||||
}
|
||||
// Issues with glxChooseFBConfig selection and sorting:
|
||||
// * ALPHA_SIZE is sorted as 'largest total RGBA bits first'. If we don't request
|
||||
// alpha bits, we'll probably get RGBA anyways, since 32 is more than 24.
|
||||
// * DEPTH_SIZE is sorted largest first, including for `0` inputs.
|
||||
// * STENCIL_SIZE is smallest first, but it might return `8` even though we ask for
|
||||
// `0`.
|
||||
|
||||
MOZ_ASSERT(numConfigs > 0,
|
||||
"glXChooseFBConfig() failed to match our requested format and "
|
||||
"violated its spec!");
|
||||
|
||||
int visid = None;
|
||||
int chosenIndex = 0;
|
||||
// For now, we don't care about these. We *will* care when we do XPixmap sharing.
|
||||
|
||||
for (int i = 0; i < numConfigs; ++i) {
|
||||
int dtype;
|
||||
GLXFBConfig curConfig = scopedConfigArr[i];
|
||||
|
||||
if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_DRAWABLE_TYPE, &dtype) != Success
|
||||
|| !(dtype & LOCAL_GLX_PIXMAP_BIT))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid) != Success
|
||||
|| visid == 0)
|
||||
int visid;
|
||||
if (glx->xGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID, &visid)
|
||||
!= Success)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
chosenIndex = i;
|
||||
break;
|
||||
if (!visid)
|
||||
continue;
|
||||
|
||||
*out_config = curConfig;
|
||||
*out_visid = visid;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!visid) {
|
||||
NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!");
|
||||
return false;
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContextGLX>
|
||||
CreateOffscreenPixmapContext(const IntSize& size, const SurfaceCaps& minCaps)
|
||||
{
|
||||
GLXLibrary* glx = &sGLXLibrary;
|
||||
if (!glx->EnsureInitialized())
|
||||
return nullptr;
|
||||
|
||||
Display* display = DefaultXDisplay();
|
||||
int screen = DefaultScreen(display);
|
||||
|
||||
ScopedXFree<GLXFBConfig> scopedConfigArr;
|
||||
GLXFBConfig config;
|
||||
int visid;
|
||||
if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) {
|
||||
NS_WARNING("Failed to find a compatible config.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Visual *visual;
|
||||
Visual* visual;
|
||||
int depth;
|
||||
FindVisualAndDepth(display, visid, &visual, &depth);
|
||||
ScopedXErrorHandler xErrorHandler;
|
||||
GLXPixmap glxpixmap = 0;
|
||||
bool error = false;
|
||||
|
||||
IntSize dummySize(16, 16);
|
||||
nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
|
||||
visual,
|
||||
dummySize);
|
||||
if (xsurface->CairoStatus() != 0) {
|
||||
ScopedXErrorHandler xErrorHandler;
|
||||
bool error = false;
|
||||
// Must be declared before goto:
|
||||
Drawable drawable;
|
||||
GLXPixmap pixmap;
|
||||
|
||||
gfx::IntSize dummySize(16, 16);
|
||||
RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
|
||||
visual,
|
||||
dummySize);
|
||||
if (surface->CairoStatus() != 0) {
|
||||
error = true;
|
||||
goto DONE_CREATING_PIXMAP;
|
||||
}
|
||||
@@ -1199,73 +1225,60 @@ CreateOffscreenPixmapContext(const IntSize& size)
|
||||
// Handle slightly different signature between glXCreatePixmap and
|
||||
// its pre-GLX-1.3 extension equivalent (though given the ABI, we
|
||||
// might not need to).
|
||||
if (glx.GLXVersionCheck(1, 3)) {
|
||||
glxpixmap = glx.xCreatePixmap(display,
|
||||
cfgs[chosenIndex],
|
||||
xsurface->XDrawable(),
|
||||
nullptr);
|
||||
drawable = surface->XDrawable();
|
||||
if (glx->GLXVersionCheck(1, 3)) {
|
||||
pixmap = glx->xCreatePixmap(display, config, drawable, nullptr);
|
||||
} else {
|
||||
glxpixmap = glx.xCreateGLXPixmapWithConfig(display,
|
||||
cfgs[chosenIndex],
|
||||
xsurface->
|
||||
XDrawable());
|
||||
pixmap = glx->xCreateGLXPixmapWithConfig(display, config, drawable);
|
||||
}
|
||||
if (glxpixmap == 0) {
|
||||
|
||||
if (pixmap == 0) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
DONE_CREATING_PIXMAP:
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext;
|
||||
bool serverError = xErrorHandler.SyncAndGetError(display);
|
||||
if (error || serverError)
|
||||
return nullptr;
|
||||
|
||||
if (!error && // earlier recorded error
|
||||
!serverError)
|
||||
{
|
||||
// We might have an alpha channel, but it doesn't matter.
|
||||
SurfaceCaps dummyCaps = SurfaceCaps::Any();
|
||||
GLContextGLX* shareContext = GetGlobalContextGLX();
|
||||
|
||||
glContext = GLContextGLX::CreateGLContext(dummyCaps,
|
||||
shareContext,
|
||||
true,
|
||||
display,
|
||||
glxpixmap,
|
||||
cfgs[chosenIndex],
|
||||
true,
|
||||
xsurface);
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
GLContextGLX* shareContext = GetGlobalContextGLX();
|
||||
return GLContextGLX::CreateGLContext(minCaps, shareContext, true, display, pixmap,
|
||||
config, true, surface);
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
/*static*/ already_AddRefed<GLContext>
|
||||
GLContextProviderGLX::CreateHeadless(CreateContextFlags)
|
||||
{
|
||||
IntSize dummySize = IntSize(16, 16);
|
||||
nsRefPtr<GLContext> glContext = CreateOffscreenPixmapContext(dummySize);
|
||||
if (!glContext)
|
||||
return nullptr;
|
||||
|
||||
return glContext.forget();
|
||||
SurfaceCaps dummyCaps = SurfaceCaps::Any();
|
||||
return CreateOffscreenPixmapContext(dummySize, dummyCaps);
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
/*static*/ already_AddRefed<GLContext>
|
||||
GLContextProviderGLX::CreateOffscreen(const IntSize& size,
|
||||
const SurfaceCaps& caps,
|
||||
const SurfaceCaps& minCaps,
|
||||
CreateContextFlags flags)
|
||||
{
|
||||
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
|
||||
if (!glContext)
|
||||
SurfaceCaps minBackbufferCaps = minCaps;
|
||||
if (minCaps.antialias) {
|
||||
minBackbufferCaps.antialias = false;
|
||||
minBackbufferCaps.depth = false;
|
||||
minBackbufferCaps.stencil = false;
|
||||
}
|
||||
|
||||
RefPtr<GLContext> gl;
|
||||
gl = CreateOffscreenPixmapContext(size, minBackbufferCaps);
|
||||
if (!gl)
|
||||
return nullptr;
|
||||
|
||||
if (!glContext->InitOffscreen(size, caps))
|
||||
if (!gl->InitOffscreen(size, minCaps))
|
||||
return nullptr;
|
||||
|
||||
return glContext.forget();
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
GLContext*
|
||||
/*static*/ GLContext*
|
||||
GLContextProviderGLX::GetGlobalContext()
|
||||
{
|
||||
static bool checkedContextSharing = false;
|
||||
@@ -1286,17 +1299,19 @@ GLContextProviderGLX::GetGlobalContext()
|
||||
triedToCreateContext = true;
|
||||
|
||||
IntSize dummySize = IntSize(16, 16);
|
||||
SurfaceCaps dummyCaps = SurfaceCaps::Any();
|
||||
// StaticPtr doesn't support assignments from already_AddRefed,
|
||||
// so use a temporary nsRefPtr to make the reference counting
|
||||
// fall out correctly.
|
||||
nsRefPtr<GLContext> holder = CreateOffscreenPixmapContext(dummySize);
|
||||
RefPtr<GLContext> holder;
|
||||
holder = CreateOffscreenPixmapContext(dummySize, dummyCaps);
|
||||
gGlobalContext = holder;
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
}
|
||||
|
||||
void
|
||||
/*static*/ void
|
||||
GLContextProviderGLX::Shutdown()
|
||||
{
|
||||
gGlobalContext = nullptr;
|
||||
|
||||
@@ -54,16 +54,18 @@ public:
|
||||
* resource sharing can be avoided on the target platform, it will
|
||||
* be, in order to isolate the offscreen context.
|
||||
*
|
||||
* @param size The initial size of this offscreen context.
|
||||
* @param caps The SurfaceCaps for this offscreen context.
|
||||
* @param flags The set of CreateContextFlags to be used for this
|
||||
* offscreen context.
|
||||
* @param size The initial size of this offscreen context.
|
||||
* @param minCaps The required SurfaceCaps for this offscreen context. The resulting
|
||||
* context *may* have more/better caps than requested, but it cannot
|
||||
* have fewer/worse caps than requested.
|
||||
* @param flags The set of CreateContextFlags to be used for this
|
||||
* offscreen context.
|
||||
*
|
||||
* @return Context to use for offscreen rendering
|
||||
*/
|
||||
static already_AddRefed<GLContext>
|
||||
CreateOffscreen(const mozilla::gfx::IntSize& size,
|
||||
const SurfaceCaps& caps,
|
||||
const SurfaceCaps& minCaps,
|
||||
CreateContextFlags flags);
|
||||
|
||||
// Just create a context. We'll add offscreen stuff ourselves.
|
||||
|
||||
@@ -601,7 +601,7 @@ CreateWindowOffscreenContext()
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
/*static*/ already_AddRefed<GLContext>
|
||||
GLContextProviderWGL::CreateHeadless(CreateContextFlags)
|
||||
{
|
||||
if (!sWGLLib.EnsureInitialized()) {
|
||||
@@ -634,24 +634,24 @@ GLContextProviderWGL::CreateHeadless(CreateContextFlags)
|
||||
return retGL.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
/*static*/ already_AddRefed<GLContext>
|
||||
GLContextProviderWGL::CreateOffscreen(const IntSize& size,
|
||||
const SurfaceCaps& caps,
|
||||
const SurfaceCaps& minCaps,
|
||||
CreateContextFlags flags)
|
||||
{
|
||||
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
|
||||
if (!glContext)
|
||||
RefPtr<GLContext> gl = CreateHeadless(flags);
|
||||
if (!gl)
|
||||
return nullptr;
|
||||
|
||||
if (!glContext->InitOffscreen(size, caps))
|
||||
if (!gl->InitOffscreen(size, minCaps))
|
||||
return nullptr;
|
||||
|
||||
return glContext.forget();
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
static nsRefPtr<GLContextWGL> gGlobalContext;
|
||||
|
||||
GLContext *
|
||||
/*static*/ GLContext*
|
||||
GLContextProviderWGL::GetGlobalContext()
|
||||
{
|
||||
if (!sWGLLib.EnsureInitialized()) {
|
||||
@@ -679,7 +679,7 @@ GLContextProviderWGL::GetGlobalContext()
|
||||
return static_cast<GLContext*>(gGlobalContext);
|
||||
}
|
||||
|
||||
void
|
||||
/*static*/ void
|
||||
GLContextProviderWGL::Shutdown()
|
||||
{
|
||||
gGlobalContext = nullptr;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define GLCONTEXT_TYPES_H_
|
||||
|
||||
#include "GLTypes.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
@@ -43,6 +44,16 @@ struct GLFormats
|
||||
GLsizei samples;
|
||||
};
|
||||
|
||||
enum class CreateContextFlags : int8_t {
|
||||
NONE = 0,
|
||||
REQUIRE_COMPAT_PROFILE = 1 << 0,
|
||||
// Force the use of hardware backed GL, don't allow software implementations.
|
||||
FORCE_ENABLE_HARDWARE = 1 << 1,
|
||||
/* Don't force discrete GPU to be used (if applicable) */
|
||||
ALLOW_OFFLINE_RENDERER = 1 << 2,
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ static const char *sEGLExtensionNames[] = {
|
||||
"EGL_KHR_fence_sync",
|
||||
"EGL_ANDROID_native_fence_sync",
|
||||
"EGL_ANDROID_image_crop",
|
||||
"ANGLE_platform_angle",
|
||||
"ANGLE_platform_angle_d3d"
|
||||
"EGL_ANGLE_platform_angle",
|
||||
"EGL_ANGLE_platform_angle_d3d"
|
||||
};
|
||||
|
||||
#if defined(ANDROID)
|
||||
|
||||
+22
-30
@@ -17,40 +17,32 @@
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#ifdef XP_WIN
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HBITMAP EGLNativePixmapType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
#include <windows.h>
|
||||
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HBITMAP EGLNativePixmapType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
#else
|
||||
typedef void *EGLNativeDisplayType;
|
||||
typedef void *EGLNativePixmapType;
|
||||
typedef void *EGLNativeWindowType;
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef void* EGLNativePixmapType;
|
||||
typedef void* EGLNativeWindowType;
|
||||
|
||||
#ifdef ANDROID
|
||||
// We only need to explicitly dlopen egltrace
|
||||
// on android as we can use LD_PRELOAD or other tricks
|
||||
// on other platforms. We look for it in /data/local
|
||||
// as that's writeable by all users
|
||||
//
|
||||
// This should really go in GLLibraryEGL.cpp but we currently reference
|
||||
// APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
|
||||
// will come in subsequent patches on Bug 732865
|
||||
#define APITRACE_LIB "/data/local/tmp/egltrace.so"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
#endif // ANDROID
|
||||
#ifdef ANDROID
|
||||
// We only need to explicitly dlopen egltrace
|
||||
// on android as we can use LD_PRELOAD or other tricks
|
||||
// on other platforms. We look for it in /data/local
|
||||
// as that's writeable by all users
|
||||
//
|
||||
// This should really go in GLLibraryEGL.cpp but we currently reference
|
||||
// APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
|
||||
// will come in subsequent patches on Bug 732865
|
||||
#define APITRACE_LIB "/data/local/tmp/egltrace.so"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
|
||||
@@ -486,9 +486,16 @@ GLScreenBuffer::Swap(const gfx::IntSize& size)
|
||||
//uint32_t srcPixel = ReadPixel(src);
|
||||
//uint32_t destPixel = ReadPixel(dest);
|
||||
//printf_stderr("Before: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
|
||||
#ifdef DEBUG
|
||||
GLContext::LocalErrorScope errorScope(*mGL);
|
||||
#endif
|
||||
|
||||
SharedSurface::ProdCopy(src, dest, mFactory.get());
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!errorScope.GetError());
|
||||
#endif
|
||||
|
||||
//srcPixel = ReadPixel(src);
|
||||
//destPixel = ReadPixel(dest);
|
||||
//printf_stderr("After: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
|
||||
@@ -611,6 +618,79 @@ GLScreenBuffer::IsReadFramebufferDefault() const
|
||||
return SharedSurf()->mAttachType == AttachmentType::Screen;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
|
||||
static void
|
||||
RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples,
|
||||
GLenum aInternalFormat, const gfx::IntSize& aSize)
|
||||
{
|
||||
if (aSamples) {
|
||||
aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
|
||||
aSamples,
|
||||
aInternalFormat,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
aInternalFormat,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint
|
||||
CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
|
||||
const gfx::IntSize& aSize)
|
||||
{
|
||||
GLuint rb = 0;
|
||||
aGL->fGenRenderbuffers(1, &rb);
|
||||
ScopedBindRenderbuffer autoRB(aGL, rb);
|
||||
|
||||
RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize);
|
||||
|
||||
return rb;
|
||||
}
|
||||
|
||||
static void
|
||||
CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
|
||||
const gfx::IntSize& aSize, bool aMultisample,
|
||||
GLuint* aColorMSRB, GLuint* aDepthRB,
|
||||
GLuint* aStencilRB)
|
||||
{
|
||||
GLsizei samples = aMultisample ? aFormats.samples : 0;
|
||||
if (aColorMSRB) {
|
||||
MOZ_ASSERT(aFormats.samples > 0);
|
||||
MOZ_ASSERT(aFormats.color_rbFormat);
|
||||
|
||||
GLenum colorFormat = aFormats.color_rbFormat;
|
||||
if (aGL->IsANGLE()) {
|
||||
MOZ_ASSERT(colorFormat == LOCAL_GL_RGBA8);
|
||||
colorFormat = LOCAL_GL_BGRA8_EXT;
|
||||
}
|
||||
|
||||
*aColorMSRB = CreateRenderbuffer(aGL, colorFormat, samples, aSize);
|
||||
}
|
||||
|
||||
if (aDepthRB &&
|
||||
aStencilRB &&
|
||||
aFormats.depthStencil)
|
||||
{
|
||||
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize);
|
||||
*aStencilRB = *aDepthRB;
|
||||
} else {
|
||||
if (aDepthRB) {
|
||||
MOZ_ASSERT(aFormats.depth);
|
||||
|
||||
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize);
|
||||
}
|
||||
|
||||
if (aStencilRB) {
|
||||
MOZ_ASSERT(aFormats.stencil);
|
||||
|
||||
*aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// DrawBuffer
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class SharedSurfaceTextureClient;
|
||||
}
|
||||
} // namespace layers
|
||||
|
||||
namespace gl {
|
||||
|
||||
|
||||
+10
-159
@@ -41,17 +41,14 @@ CreatePBufferSurface(GLLibraryEGL* egl,
|
||||
}
|
||||
|
||||
/*static*/ UniquePtr<SharedSurface_ANGLEShareHandle>
|
||||
SharedSurface_ANGLEShareHandle::Create(GLContext* gl,
|
||||
EGLContext context, EGLConfig config,
|
||||
SharedSurface_ANGLEShareHandle::Create(GLContext* gl, EGLConfig config,
|
||||
const gfx::IntSize& size, bool hasAlpha)
|
||||
{
|
||||
GLLibraryEGL* egl = &sEGLLibrary;
|
||||
MOZ_ASSERT(egl);
|
||||
MOZ_ASSERT(egl->IsExtensionSupported(
|
||||
GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle));
|
||||
|
||||
if (!context || !config)
|
||||
return nullptr;
|
||||
MOZ_ASSERT(config);
|
||||
|
||||
EGLDisplay display = egl->Display();
|
||||
EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size);
|
||||
@@ -82,8 +79,8 @@ SharedSurface_ANGLEShareHandle::Create(GLContext* gl,
|
||||
}
|
||||
|
||||
typedef SharedSurface_ANGLEShareHandle ptrT;
|
||||
UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, context,
|
||||
pbuffer, shareHandle, keyedMutex, fence) );
|
||||
UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, pbuffer, shareHandle,
|
||||
keyedMutex, fence) );
|
||||
return Move(ret);
|
||||
}
|
||||
|
||||
@@ -97,7 +94,6 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
|
||||
GLLibraryEGL* egl,
|
||||
const gfx::IntSize& size,
|
||||
bool hasAlpha,
|
||||
EGLContext context,
|
||||
EGLSurface pbuffer,
|
||||
HANDLE shareHandle,
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
|
||||
@@ -109,7 +105,6 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
|
||||
hasAlpha,
|
||||
true)
|
||||
, mEGL(egl)
|
||||
, mContext(context)
|
||||
, mPBuffer(pbuffer)
|
||||
, mShareHandle(shareHandle)
|
||||
, mKeyedMutex(keyedMutex)
|
||||
@@ -283,137 +278,6 @@ SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(layers::SurfaceDescriptor* c
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Factory
|
||||
|
||||
static void
|
||||
FillPBufferAttribs_ByBits(nsTArray<EGLint>& aAttrs,
|
||||
int redBits, int greenBits,
|
||||
int blueBits, int alphaBits,
|
||||
int depthBits, int stencilBits)
|
||||
{
|
||||
aAttrs.Clear();
|
||||
|
||||
#if defined(A1) || defined(A2)
|
||||
#error The temp-macro names we want are already defined.
|
||||
#endif
|
||||
|
||||
#define A1(_x) do { aAttrs.AppendElement(_x); } while (0)
|
||||
#define A2(_x,_y) do { A1(_x); A1(_y); } while (0)
|
||||
|
||||
A2(LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT);
|
||||
A2(LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT);
|
||||
|
||||
A2(LOCAL_EGL_RED_SIZE, redBits);
|
||||
A2(LOCAL_EGL_GREEN_SIZE, greenBits);
|
||||
A2(LOCAL_EGL_BLUE_SIZE, blueBits);
|
||||
A2(LOCAL_EGL_ALPHA_SIZE, alphaBits);
|
||||
|
||||
A2(LOCAL_EGL_DEPTH_SIZE, depthBits);
|
||||
A2(LOCAL_EGL_STENCIL_SIZE, stencilBits);
|
||||
|
||||
A1(LOCAL_EGL_NONE);
|
||||
#undef A1
|
||||
#undef A2
|
||||
}
|
||||
|
||||
static void
|
||||
FillPBufferAttribs_BySizes(nsTArray<EGLint>& attribs,
|
||||
bool bpp16, bool hasAlpha,
|
||||
int depthBits, int stencilBits)
|
||||
{
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int alpha = 0;
|
||||
|
||||
if (bpp16) {
|
||||
if (hasAlpha) {
|
||||
red = green = blue = alpha = 4;
|
||||
} else {
|
||||
red = 5;
|
||||
green = 6;
|
||||
blue = 5;
|
||||
}
|
||||
} else {
|
||||
red = green = blue = 8;
|
||||
if (hasAlpha)
|
||||
alpha = 8;
|
||||
}
|
||||
|
||||
FillPBufferAttribs_ByBits(attribs, red, green, blue, alpha, depthBits,
|
||||
stencilBits);
|
||||
}
|
||||
|
||||
static bool
|
||||
DoesAttribBitsMatchCapBool(GLLibraryEGL* egl, EGLConfig config, EGLint attrib,
|
||||
bool capBool)
|
||||
{
|
||||
EGLint bits = 0;
|
||||
egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
|
||||
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
|
||||
|
||||
bool hasBits = !!bits;
|
||||
|
||||
return hasBits == capBool;
|
||||
}
|
||||
|
||||
static EGLConfig
|
||||
ChooseConfig(GLContext* gl, GLLibraryEGL* egl, const SurfaceCaps& caps)
|
||||
{
|
||||
MOZ_ASSERT(egl);
|
||||
MOZ_ASSERT(caps.color);
|
||||
|
||||
// We might want 24-bit depth, but we're only (fairly) sure to get 16-bit.
|
||||
int depthBits = caps.depth ? 16 : 0;
|
||||
int stencilBits = caps.stencil ? 8 : 0;
|
||||
|
||||
// Ok, now we have everything.
|
||||
nsTArray<EGLint> attribs(32);
|
||||
FillPBufferAttribs_BySizes(attribs, caps.bpp16, caps.alpha, depthBits,
|
||||
stencilBits);
|
||||
|
||||
// Time to try to get this config:
|
||||
EGLConfig configs[64];
|
||||
int numConfigs = sizeof(configs)/sizeof(EGLConfig);
|
||||
int foundConfigs = 0;
|
||||
|
||||
if (!egl->fChooseConfig(egl->Display(), attribs.Elements(), configs,
|
||||
numConfigs, &foundConfigs) ||
|
||||
!foundConfigs)
|
||||
{
|
||||
NS_WARNING("No configs found for the requested formats.");
|
||||
return EGL_NO_CONFIG;
|
||||
}
|
||||
|
||||
// The requests passed to ChooseConfig are treated as minimums. If you ask
|
||||
// for 0 bits of alpha, we might still get 8 bits.
|
||||
EGLConfig config = EGL_NO_CONFIG;
|
||||
for (int i = 0; i < foundConfigs; i++) {
|
||||
EGLConfig cur = configs[i];
|
||||
if (!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_ALPHA_SIZE,
|
||||
caps.alpha) ||
|
||||
!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_DEPTH_SIZE,
|
||||
caps.depth) ||
|
||||
!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_STENCIL_SIZE,
|
||||
caps.stencil))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
config = cur;
|
||||
break;
|
||||
}
|
||||
|
||||
if (config == EGL_NO_CONFIG) {
|
||||
NS_WARNING("No acceptable EGLConfig found.");
|
||||
return EGL_NO_CONFIG;
|
||||
}
|
||||
|
||||
if (gl->DebugMode()) {
|
||||
egl->DumpEGLConfig(config);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/*static*/ UniquePtr<SurfaceFactory_ANGLEShareHandle>
|
||||
SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
|
||||
const RefPtr<layers::ISurfaceAllocator>& allocator,
|
||||
@@ -427,13 +291,10 @@ SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
|
||||
if (!egl->IsExtensionSupported(ext))
|
||||
return nullptr;
|
||||
|
||||
bool success;
|
||||
EGLConfig config = GLContextEGL::Cast(gl)->mConfig;
|
||||
|
||||
typedef SurfaceFactory_ANGLEShareHandle ptrT;
|
||||
UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, &success) );
|
||||
|
||||
if (!success)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, config) );
|
||||
return Move(ret);
|
||||
}
|
||||
|
||||
@@ -442,22 +303,12 @@ SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
|
||||
const RefPtr<layers::ISurfaceAllocator>& allocator,
|
||||
const layers::TextureFlags& flags,
|
||||
GLLibraryEGL* egl,
|
||||
bool* const out_success)
|
||||
EGLConfig config)
|
||||
: SurfaceFactory(SharedSurfaceType::EGLSurfaceANGLE, gl, caps, allocator, flags)
|
||||
, mProdGL(gl)
|
||||
, mEGL(egl)
|
||||
{
|
||||
MOZ_ASSERT(out_success);
|
||||
*out_success = false;
|
||||
|
||||
mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext();
|
||||
mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps);
|
||||
if (mConfig == EGL_NO_CONFIG)
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(mConfig && mContext);
|
||||
*out_success = true;
|
||||
}
|
||||
, mConfig(config)
|
||||
{ }
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
@@ -23,7 +23,6 @@ class SharedSurface_ANGLEShareHandle
|
||||
{
|
||||
public:
|
||||
static UniquePtr<SharedSurface_ANGLEShareHandle> Create(GLContext* gl,
|
||||
EGLContext context,
|
||||
EGLConfig config,
|
||||
const gfx::IntSize& size,
|
||||
bool hasAlpha);
|
||||
@@ -36,7 +35,6 @@ public:
|
||||
|
||||
protected:
|
||||
GLLibraryEGL* const mEGL;
|
||||
const EGLContext mContext;
|
||||
const EGLSurface mPBuffer;
|
||||
public:
|
||||
const HANDLE mShareHandle;
|
||||
@@ -51,7 +49,6 @@ protected:
|
||||
GLLibraryEGL* egl,
|
||||
const gfx::IntSize& size,
|
||||
bool hasAlpha,
|
||||
EGLContext context,
|
||||
EGLSurface pbuffer,
|
||||
HANDLE shareHandle,
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
|
||||
@@ -94,8 +91,7 @@ class SurfaceFactory_ANGLEShareHandle
|
||||
protected:
|
||||
GLContext* const mProdGL;
|
||||
GLLibraryEGL* const mEGL;
|
||||
EGLContext mContext;
|
||||
EGLConfig mConfig;
|
||||
const EGLConfig mConfig;
|
||||
|
||||
public:
|
||||
static UniquePtr<SurfaceFactory_ANGLEShareHandle> Create(GLContext* gl,
|
||||
@@ -107,13 +103,11 @@ protected:
|
||||
SurfaceFactory_ANGLEShareHandle(GLContext* gl, const SurfaceCaps& caps,
|
||||
const RefPtr<layers::ISurfaceAllocator>& allocator,
|
||||
const layers::TextureFlags& flags, GLLibraryEGL* egl,
|
||||
bool* const out_success);
|
||||
EGLConfig config);
|
||||
|
||||
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
|
||||
bool hasAlpha = mReadCaps.alpha;
|
||||
return SharedSurface_ANGLEShareHandle::Create(mProdGL,
|
||||
mContext, mConfig,
|
||||
size, hasAlpha);
|
||||
return SharedSurface_ANGLEShareHandle::Create(mProdGL, mConfig, size, hasAlpha);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps,
|
||||
const RefPtr<layers::ISurfaceAllocator>& allocator,
|
||||
const layers::TextureFlags& flags)
|
||||
{
|
||||
EGLContext context = GLContextEGL::Cast(prodGL)->GetEGLContext();
|
||||
EGLContext context = GLContextEGL::Cast(prodGL)->mContext;
|
||||
|
||||
typedef SurfaceFactory_EGLImage ptrT;
|
||||
UniquePtr<ptrT> ret;
|
||||
|
||||
@@ -27,10 +27,7 @@ SharedSurface_Basic::Create(GLContext* gl,
|
||||
gl->MakeCurrent();
|
||||
|
||||
GLContext::LocalErrorScope localError(*gl);
|
||||
GLuint tex = CreateTexture(gl, formats.color_texInternalFormat,
|
||||
formats.color_texFormat,
|
||||
formats.color_texType,
|
||||
size);
|
||||
GLuint tex = CreateTextureForOffscreen(gl, formats, size);
|
||||
|
||||
GLenum err = localError.GetError();
|
||||
MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY);
|
||||
|
||||
+7
-7
@@ -71,7 +71,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
'WGLLibrary.h',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'GLContextProviderEGL.cpp',
|
||||
'GLContextProviderWGL.cpp',
|
||||
'SharedSurfaceANGLE.cpp',
|
||||
]
|
||||
if CONFIG['MOZ_ENABLE_SKIA_GPU']:
|
||||
@@ -113,10 +113,6 @@ elif gl_provider == 'GLX':
|
||||
EXPORTS += [
|
||||
'SharedSurfaceGLX.h'
|
||||
]
|
||||
else:
|
||||
UNIFIED_SOURCES += [
|
||||
'GLContextProvider%s.cpp' % gl_provider,
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AndroidNativeWindow.cpp',
|
||||
@@ -127,6 +123,7 @@ UNIFIED_SOURCES += [
|
||||
'GLBlitHelper.cpp',
|
||||
'GLContext.cpp',
|
||||
'GLContextFeatures.cpp',
|
||||
'GLContextProviderEGL.cpp',
|
||||
'GLContextTypes.cpp',
|
||||
'GLDebugUtils.cpp',
|
||||
'GLLibraryEGL.cpp',
|
||||
@@ -153,9 +150,12 @@ if CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']:
|
||||
if CONFIG['MOZ_D3DCOMPILER_XP_DLL']:
|
||||
DEFINES['MOZ_D3DCOMPILER_XP_DLL'] = CONFIG['MOZ_D3DCOMPILER_XP_DLL']
|
||||
|
||||
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
|
||||
|
||||
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
CFLAGS += CONFIG['TK_CFLAGS']
|
||||
|
||||
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
del DEFINES['UNICODE']
|
||||
|
||||
@@ -1144,7 +1144,7 @@ gfxFT2FontList::FindFonts()
|
||||
gfxFontCache *fc = gfxFontCache::GetCache();
|
||||
if (fc)
|
||||
fc->AgeAllGenerations();
|
||||
mPrefFonts.Clear();
|
||||
ClearLangGroupPrefFonts();
|
||||
mCodepointsWithNoFonts.reset();
|
||||
|
||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||
|
||||
@@ -410,6 +410,7 @@ public:
|
||||
uint32_t fallbackSystem;
|
||||
uint32_t textrunConst;
|
||||
uint32_t textrunDestr;
|
||||
uint32_t genericLookups;
|
||||
};
|
||||
|
||||
uint32_t reflowCount;
|
||||
@@ -443,6 +444,7 @@ public:
|
||||
cumulative.fallbackSystem += current.fallbackSystem;
|
||||
cumulative.textrunConst += current.textrunConst;
|
||||
cumulative.textrunDestr += current.textrunDestr;
|
||||
cumulative.genericLookups += current.genericLookups;
|
||||
memset(¤t, 0, sizeof(current));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -210,4 +210,16 @@ enum {
|
||||
#define NS_FONT_SUB_SUPER_SMALL_SIZE (20.0)
|
||||
#define NS_FONT_SUB_SUPER_LARGE_SIZE (45.0)
|
||||
|
||||
// pref lang id's for font prefs
|
||||
enum eFontPrefLang {
|
||||
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) eFontPrefLang_ ## enum_id_
|
||||
#include "gfxFontPrefLangList.h"
|
||||
#undef FONT_PREF_LANG
|
||||
|
||||
, eFontPrefLang_CJKSet // special code for CJK set
|
||||
, eFontPrefLang_First = eFontPrefLang_Western
|
||||
, eFontPrefLang_Last = eFontPrefLang_Others
|
||||
, eFontPrefLang_Count = (eFontPrefLang_Last - eFontPrefLang_First + 1)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1334,9 +1334,9 @@ gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||
|
||||
uint32_t minDistance = 0xffffffff;
|
||||
gfxFontEntry* matched = nullptr;
|
||||
// iterate in reverse order so that the last-defined font is the first one
|
||||
// in the fontlist used for matching, as per CSS Fonts spec
|
||||
for (int32_t i = count - 1; i >= 0; i--) {
|
||||
// iterate in forward order so that faces like 'Bold' are matched before
|
||||
// matching style distance faces such as 'Bold Outline' (see bug 1185812)
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
fe = mAvailableFonts[i];
|
||||
uint32_t distance =
|
||||
WeightDistance(aFontStyle.weight, fe->Weight()) +
|
||||
|
||||
@@ -29,7 +29,7 @@ enum FontFamilyType {
|
||||
eFamily_named_quoted,
|
||||
|
||||
// generics
|
||||
eFamily_serif,
|
||||
eFamily_serif, // pref font code relies on this ordering!!!
|
||||
eFamily_sans_serif,
|
||||
eFamily_monospace,
|
||||
eFamily_cursive,
|
||||
@@ -37,7 +37,11 @@ enum FontFamilyType {
|
||||
|
||||
// special
|
||||
eFamily_moz_variable,
|
||||
eFamily_moz_fixed
|
||||
eFamily_moz_fixed,
|
||||
|
||||
eFamily_generic_first = eFamily_serif,
|
||||
eFamily_generic_last = eFamily_fantasy,
|
||||
eFamily_generic_count = (eFamily_fantasy - eFamily_serif + 1)
|
||||
};
|
||||
|
||||
enum QuotedName { eQuotedName, eUnquotedName };
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#include "gfxFontconfigUtils.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "gfxFontConstants.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsILanguageAtomService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <cairo-ft.h>
|
||||
@@ -1281,9 +1284,140 @@ gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
}
|
||||
|
||||
void
|
||||
gfxPangoFontGroup::FindPlatformFont(const nsAString& fontName,
|
||||
bool aUseFontSet,
|
||||
void *aClosure)
|
||||
gfxPangoFontGroup::FindGenericFontsPFG(FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
void *aClosure)
|
||||
{
|
||||
nsAutoTArray<nsString, 5> resolvedGenerics;
|
||||
ResolveGenericFontNamesPFG(aGenericType, aLanguage, resolvedGenerics);
|
||||
uint32_t g = 0, numGenerics = resolvedGenerics.Length();
|
||||
for (g = 0; g < numGenerics; g++) {
|
||||
FindPlatformFontPFG(resolvedGenerics[g], false, aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxPangoFontGroup::ResolveGenericFontNamesPFG(FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
nsTArray<nsString>& aGenericFamilies)
|
||||
{
|
||||
static const char kGeneric_serif[] = "serif";
|
||||
static const char kGeneric_sans_serif[] = "sans-serif";
|
||||
static const char kGeneric_monospace[] = "monospace";
|
||||
static const char kGeneric_cursive[] = "cursive";
|
||||
static const char kGeneric_fantasy[] = "fantasy";
|
||||
|
||||
// treat -moz-fixed as monospace
|
||||
if (aGenericType == eFamily_moz_fixed) {
|
||||
aGenericType = eFamily_monospace;
|
||||
}
|
||||
|
||||
// type should be standard generic type at this point
|
||||
NS_ASSERTION(aGenericType >= eFamily_serif &&
|
||||
aGenericType <= eFamily_fantasy,
|
||||
"standard generic font family type required");
|
||||
|
||||
// create the lang string
|
||||
nsIAtom *langGroupAtom = nullptr;
|
||||
nsAutoCString langGroupString;
|
||||
if (aLanguage) {
|
||||
if (!gLangService) {
|
||||
CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
|
||||
}
|
||||
if (gLangService) {
|
||||
nsresult rv;
|
||||
langGroupAtom = gLangService->GetLanguageGroup(aLanguage, &rv);
|
||||
}
|
||||
}
|
||||
if (!langGroupAtom) {
|
||||
langGroupAtom = nsGkAtoms::Unicode;
|
||||
}
|
||||
langGroupAtom->ToUTF8String(langGroupString);
|
||||
|
||||
// map generic type to string
|
||||
const char *generic = nullptr;
|
||||
switch (aGenericType) {
|
||||
case eFamily_serif:
|
||||
generic = kGeneric_serif;
|
||||
break;
|
||||
case eFamily_sans_serif:
|
||||
generic = kGeneric_sans_serif;
|
||||
break;
|
||||
case eFamily_monospace:
|
||||
generic = kGeneric_monospace;
|
||||
break;
|
||||
case eFamily_cursive:
|
||||
generic = kGeneric_cursive;
|
||||
break;
|
||||
case eFamily_fantasy:
|
||||
generic = kGeneric_fantasy;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!generic) {
|
||||
return;
|
||||
}
|
||||
|
||||
aGenericFamilies.Clear();
|
||||
|
||||
// load family for "font.name.generic.lang"
|
||||
nsAutoCString prefFontName("font.name.");
|
||||
prefFontName.Append(generic);
|
||||
prefFontName.Append('.');
|
||||
prefFontName.Append(langGroupString);
|
||||
gfxFontUtils::AppendPrefsFontList(prefFontName.get(),
|
||||
aGenericFamilies);
|
||||
|
||||
// if lang has pref fonts, also load fonts for "font.name-list.generic.lang"
|
||||
if (!aGenericFamilies.IsEmpty()) {
|
||||
nsAutoCString prefFontListName("font.name-list.");
|
||||
prefFontListName.Append(generic);
|
||||
prefFontListName.Append('.');
|
||||
prefFontListName.Append(langGroupString);
|
||||
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(),
|
||||
aGenericFamilies);
|
||||
}
|
||||
|
||||
#if 0 // dump out generic mappings
|
||||
printf("%s ===> ", prefFontName.get());
|
||||
for (uint32_t k = 0; k < aGenericFamilies.Length(); k++) {
|
||||
if (k > 0) printf(", ");
|
||||
printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]).get());
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void gfxPangoFontGroup::EnumerateFontListPFG(nsIAtom *aLanguage, void *aClosure)
|
||||
{
|
||||
// initialize fonts in the font family list
|
||||
const nsTArray<FontFamilyName>& fontlist = mFamilyList.GetFontlist();
|
||||
|
||||
// lookup fonts in the fontlist
|
||||
uint32_t i, numFonts = fontlist.Length();
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
const FontFamilyName& name = fontlist[i];
|
||||
if (name.IsNamed()) {
|
||||
FindPlatformFontPFG(name.mName, true, aClosure);
|
||||
} else {
|
||||
FindGenericFontsPFG(name.mType, aLanguage, aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
// if necessary, append default generic onto the end
|
||||
if (mFamilyList.GetDefaultFontType() != eFamily_none &&
|
||||
!mFamilyList.HasDefaultGeneric()) {
|
||||
FindGenericFontsPFG(mFamilyList.GetDefaultFontType(),
|
||||
aLanguage, aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPangoFontGroup::FindPlatformFontPFG(const nsAString& fontName,
|
||||
bool aUseFontSet,
|
||||
void *aClosure)
|
||||
{
|
||||
nsTArray<nsString> *list = static_cast<nsTArray<nsString>*>(aClosure);
|
||||
|
||||
@@ -1360,8 +1494,8 @@ gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
|
||||
}
|
||||
|
||||
nsAutoTArray<nsString, 20> fcFamilyList;
|
||||
EnumerateFontList(langGroup ? langGroup.get() : mStyle.language.get(),
|
||||
&fcFamilyList);
|
||||
EnumerateFontListPFG(langGroup ? langGroup.get() : mStyle.language.get(),
|
||||
&fcFamilyList);
|
||||
|
||||
// To consider: A fontset cache here could be helpful.
|
||||
|
||||
|
||||
@@ -94,9 +94,27 @@ private:
|
||||
return mSizeAdjustFactor;
|
||||
}
|
||||
|
||||
virtual void FindPlatformFont(const nsAString& aName,
|
||||
bool aUseFontSet,
|
||||
void *aClosure);
|
||||
// old helper methods from gfxFontGroup, moved here so that those methods
|
||||
// can be revamped without affecting the legacy code here
|
||||
|
||||
// iterate over the fontlist, lookup names and expand generics
|
||||
void EnumerateFontListPFG(nsIAtom *aLanguage, void *aClosure);
|
||||
|
||||
// expand a generic to a list of specific names based on prefs
|
||||
void FindGenericFontsPFG(mozilla::FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
void *aClosure);
|
||||
|
||||
// lookup and add a font with a given name (i.e. *not* a generic!)
|
||||
void FindPlatformFontPFG(const nsAString& aName,
|
||||
bool aUseFontSet,
|
||||
void *aClosure);
|
||||
|
||||
static void
|
||||
ResolveGenericFontNamesPFG(mozilla::FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
nsTArray<nsString>& aGenericFamilies);
|
||||
|
||||
|
||||
friend class gfxSystemFcFontEntry;
|
||||
static FT_Library GetFTLibrary();
|
||||
|
||||
@@ -364,27 +364,6 @@ MemoryPressureObserver::Observe(nsISupports *aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// xxx - this can probably be eliminated by reworking pref font handling code
|
||||
static const char *gPrefLangNames[] = {
|
||||
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) str_
|
||||
#include "gfxFontPrefLangList.h"
|
||||
#undef FONT_PREF_LANG
|
||||
};
|
||||
|
||||
static nsIAtom* PrefLangToLangGroups(uint32_t aIndex)
|
||||
{
|
||||
// static array here avoids static constructor
|
||||
static nsIAtom* gPrefLangToLangGroups[] = {
|
||||
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) nsGkAtoms::atom_id_
|
||||
#include "gfxFontPrefLangList.h"
|
||||
#undef FONT_PREF_LANG
|
||||
};
|
||||
|
||||
return aIndex < ArrayLength(gPrefLangToLangGroups)
|
||||
? gPrefLangToLangGroups[aIndex]
|
||||
: nsGkAtoms::Unicode;
|
||||
}
|
||||
|
||||
gfxPlatform::gfxPlatform()
|
||||
: mTileWidth(-1)
|
||||
, mTileHeight(-1)
|
||||
@@ -1364,160 +1343,6 @@ gfxPlatform::MakePlatformFont(const nsAString& aFontName,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArrayLen, PrefFontCallback aCallback,
|
||||
void *aClosure)
|
||||
{
|
||||
NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < aLangArrayLen; i++) {
|
||||
eFontPrefLang prefLang = aLangArray[i];
|
||||
const char *langGroup = GetPrefLangName(prefLang);
|
||||
|
||||
nsAutoCString prefName;
|
||||
|
||||
prefName.AssignLiteral("font.default.");
|
||||
prefName.Append(langGroup);
|
||||
nsAdoptingCString genericDotLang = Preferences::GetCString(prefName.get());
|
||||
|
||||
genericDotLang.Append('.');
|
||||
genericDotLang.Append(langGroup);
|
||||
|
||||
// fetch font.name.xxx value
|
||||
prefName.AssignLiteral("font.name.");
|
||||
prefName.Append(genericDotLang);
|
||||
nsAdoptingCString nameValue = Preferences::GetCString(prefName.get());
|
||||
if (nameValue) {
|
||||
if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(nameValue), aClosure))
|
||||
return false;
|
||||
}
|
||||
|
||||
// fetch font.name-list.xxx value
|
||||
prefName.AssignLiteral("font.name-list.");
|
||||
prefName.Append(genericDotLang);
|
||||
nsAdoptingCString nameListValue = Preferences::GetCString(prefName.get());
|
||||
if (nameListValue && !nameListValue.Equals(nameValue)) {
|
||||
const char kComma = ',';
|
||||
const char *p, *p_end;
|
||||
nsAutoCString list(nameListValue);
|
||||
list.BeginReading(p);
|
||||
list.EndReading(p_end);
|
||||
while (p < p_end) {
|
||||
while (nsCRT::IsAsciiSpace(*p)) {
|
||||
if (++p == p_end)
|
||||
break;
|
||||
}
|
||||
if (p == p_end)
|
||||
break;
|
||||
const char *start = p;
|
||||
while (++p != p_end && *p != kComma)
|
||||
/* nothing */ ;
|
||||
nsAutoCString fontName(Substring(start, p));
|
||||
fontName.CompressWhitespace(false, true);
|
||||
if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(fontName), aClosure))
|
||||
return false;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
eFontPrefLang
|
||||
gfxPlatform::GetFontPrefLangFor(const char* aLang)
|
||||
{
|
||||
if (!aLang || !aLang[0]) {
|
||||
return eFontPrefLang_Others;
|
||||
}
|
||||
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); ++i) {
|
||||
if (!PL_strcasecmp(gPrefLangNames[i], aLang)) {
|
||||
return eFontPrefLang(i);
|
||||
}
|
||||
}
|
||||
return eFontPrefLang_Others;
|
||||
}
|
||||
|
||||
eFontPrefLang
|
||||
gfxPlatform::GetFontPrefLangFor(nsIAtom *aLang)
|
||||
{
|
||||
if (!aLang)
|
||||
return eFontPrefLang_Others;
|
||||
nsAutoCString lang;
|
||||
aLang->ToUTF8String(lang);
|
||||
return GetFontPrefLangFor(lang.get());
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
gfxPlatform::GetLangGroupForPrefLang(eFontPrefLang aLang)
|
||||
{
|
||||
// the special CJK set pref lang should be resolved into separate
|
||||
// calls to individual CJK pref langs before getting here
|
||||
NS_ASSERTION(aLang != eFontPrefLang_CJKSet, "unresolved CJK set pref lang");
|
||||
|
||||
return PrefLangToLangGroups(uint32_t(aLang));
|
||||
}
|
||||
|
||||
const char*
|
||||
gfxPlatform::GetPrefLangName(eFontPrefLang aLang)
|
||||
{
|
||||
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
|
||||
return gPrefLangNames[uint32_t(aLang)];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
eFontPrefLang
|
||||
gfxPlatform::GetFontPrefLangFor(uint8_t aUnicodeRange)
|
||||
{
|
||||
switch (aUnicodeRange) {
|
||||
case kRangeSetLatin: return eFontPrefLang_Western;
|
||||
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
|
||||
case kRangeGreek: return eFontPrefLang_Greek;
|
||||
case kRangeHebrew: return eFontPrefLang_Hebrew;
|
||||
case kRangeArabic: return eFontPrefLang_Arabic;
|
||||
case kRangeThai: return eFontPrefLang_Thai;
|
||||
case kRangeKorean: return eFontPrefLang_Korean;
|
||||
case kRangeJapanese: return eFontPrefLang_Japanese;
|
||||
case kRangeSChinese: return eFontPrefLang_ChineseCN;
|
||||
case kRangeTChinese: return eFontPrefLang_ChineseTW;
|
||||
case kRangeDevanagari: return eFontPrefLang_Devanagari;
|
||||
case kRangeTamil: return eFontPrefLang_Tamil;
|
||||
case kRangeArmenian: return eFontPrefLang_Armenian;
|
||||
case kRangeBengali: return eFontPrefLang_Bengali;
|
||||
case kRangeCanadian: return eFontPrefLang_Canadian;
|
||||
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
|
||||
case kRangeGeorgian: return eFontPrefLang_Georgian;
|
||||
case kRangeGujarati: return eFontPrefLang_Gujarati;
|
||||
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
|
||||
case kRangeKhmer: return eFontPrefLang_Khmer;
|
||||
case kRangeMalayalam: return eFontPrefLang_Malayalam;
|
||||
case kRangeOriya: return eFontPrefLang_Oriya;
|
||||
case kRangeTelugu: return eFontPrefLang_Telugu;
|
||||
case kRangeKannada: return eFontPrefLang_Kannada;
|
||||
case kRangeSinhala: return eFontPrefLang_Sinhala;
|
||||
case kRangeTibetan: return eFontPrefLang_Tibetan;
|
||||
case kRangeSetCJK: return eFontPrefLang_CJKSet;
|
||||
default: return eFontPrefLang_Others;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::IsLangCJK(eFontPrefLang aLang)
|
||||
{
|
||||
switch (aLang) {
|
||||
case eFontPrefLang_Japanese:
|
||||
case eFontPrefLang_ChineseTW:
|
||||
case eFontPrefLang_ChineseCN:
|
||||
case eFontPrefLang_ChineseHK:
|
||||
case eFontPrefLang_Korean:
|
||||
case eFontPrefLang_CJKSet:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::layers::DiagnosticTypes
|
||||
gfxPlatform::GetLayerDiagnosticTypes()
|
||||
{
|
||||
@@ -1537,143 +1362,6 @@ gfxPlatform::GetLayerDiagnosticTypes()
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
|
||||
{
|
||||
if (IsLangCJK(aCharLang)) {
|
||||
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
|
||||
} else {
|
||||
AppendPrefLang(aPrefLangs, aLen, aCharLang);
|
||||
}
|
||||
|
||||
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
|
||||
{
|
||||
// prefer the lang specified by the page *if* CJK
|
||||
if (IsLangCJK(aPageLang)) {
|
||||
AppendPrefLang(aPrefLangs, aLen, aPageLang);
|
||||
}
|
||||
|
||||
// if not set up, set up the default CJK order, based on accept lang settings and locale
|
||||
if (mCJKPrefLangs.Length() == 0) {
|
||||
|
||||
// temp array
|
||||
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
|
||||
uint32_t tempLen = 0;
|
||||
|
||||
// Add the CJK pref fonts from accept languages, the order should be same order
|
||||
nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
|
||||
if (!list.IsEmpty()) {
|
||||
const char kComma = ',';
|
||||
const char *p, *p_end;
|
||||
list.BeginReading(p);
|
||||
list.EndReading(p_end);
|
||||
while (p < p_end) {
|
||||
while (nsCRT::IsAsciiSpace(*p)) {
|
||||
if (++p == p_end)
|
||||
break;
|
||||
}
|
||||
if (p == p_end)
|
||||
break;
|
||||
const char *start = p;
|
||||
while (++p != p_end && *p != kComma)
|
||||
/* nothing */ ;
|
||||
nsAutoCString lang(Substring(start, p));
|
||||
lang.CompressWhitespace(false, true);
|
||||
eFontPrefLang fpl = gfxPlatform::GetFontPrefLangFor(lang.get());
|
||||
switch (fpl) {
|
||||
case eFontPrefLang_Japanese:
|
||||
case eFontPrefLang_Korean:
|
||||
case eFontPrefLang_ChineseCN:
|
||||
case eFontPrefLang_ChineseHK:
|
||||
case eFontPrefLang_ChineseTW:
|
||||
AppendPrefLang(tempPrefLangs, tempLen, fpl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
do { // to allow 'break' to abort this block if a call fails
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILocaleService> ls =
|
||||
do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsILocale> appLocale;
|
||||
rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
nsString localeStr;
|
||||
rv = appLocale->
|
||||
GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
const nsAString& lang = Substring(localeStr, 0, 2);
|
||||
if (lang.EqualsLiteral("ja")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
} else if (lang.EqualsLiteral("zh")) {
|
||||
const nsAString& region = Substring(localeStr, 3, 2);
|
||||
if (region.EqualsLiteral("CN")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
} else if (region.EqualsLiteral("TW")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
} else if (region.EqualsLiteral("HK")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
}
|
||||
} else if (lang.EqualsLiteral("ko")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
// last resort... (the order is same as old gfx.)
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
|
||||
// copy into the cached array
|
||||
uint32_t j;
|
||||
for (j = 0; j < tempLen; j++) {
|
||||
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// append in cached CJK langs
|
||||
uint32_t i, numCJKlangs = mCJKPrefLangs.Length();
|
||||
|
||||
for (i = 0; i < numCJKlangs; i++) {
|
||||
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang)
|
||||
{
|
||||
if (aLen >= kMaxLenPrefLangList) return;
|
||||
|
||||
// make sure
|
||||
uint32_t i = 0;
|
||||
while (i < aLen && aPrefLangs[i] != aAddLang) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == aLen) {
|
||||
aPrefLangs[aLen] = aAddLang;
|
||||
aLen++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::InitBackendPrefs(uint32_t aCanvasBitmask, BackendType aCanvasDefault,
|
||||
uint32_t aContentBitmask, BackendType aContentDefault)
|
||||
|
||||
@@ -70,15 +70,6 @@ BackendTypeBit(BackendType b)
|
||||
|
||||
extern cairo_user_data_key_t kDrawTarget;
|
||||
|
||||
// pref lang id's for font prefs
|
||||
enum eFontPrefLang {
|
||||
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) eFontPrefLang_ ## enum_id_
|
||||
#include "gfxFontPrefLangList.h"
|
||||
#undef FONT_PREF_LANG
|
||||
|
||||
, eFontPrefLang_CJKSet // special code for CJK set
|
||||
};
|
||||
|
||||
enum eCMSMode {
|
||||
eCMSMode_Off = 0, // No color management
|
||||
eCMSMode_All = 1, // Color manage everything
|
||||
@@ -436,41 +427,6 @@ public:
|
||||
|
||||
virtual bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) { return false; }
|
||||
|
||||
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
|
||||
void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
||||
|
||||
/**
|
||||
* Iterate over pref fonts given a list of lang groups. For a single lang
|
||||
* group, multiple pref fonts are possible. If error occurs, returns false,
|
||||
* true otherwise. Callback returns false to abort process.
|
||||
*/
|
||||
typedef bool (*PrefFontCallback) (eFontPrefLang aLang, const nsAString& aName,
|
||||
void *aClosure);
|
||||
static bool ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArrayLen,
|
||||
PrefFontCallback aCallback,
|
||||
void *aClosure);
|
||||
|
||||
// convert a lang group to enum constant (i.e. "zh-TW" ==> eFontPrefLang_ChineseTW)
|
||||
static eFontPrefLang GetFontPrefLangFor(const char* aLang);
|
||||
|
||||
// convert a lang group atom to enum constant
|
||||
static eFontPrefLang GetFontPrefLangFor(nsIAtom *aLang);
|
||||
|
||||
// convert an enum constant to a lang group atom
|
||||
static nsIAtom* GetLangGroupForPrefLang(eFontPrefLang aLang);
|
||||
|
||||
// convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW ==> "zh-TW")
|
||||
static const char* GetPrefLangName(eFontPrefLang aLang);
|
||||
|
||||
// map a Unicode range (based on char code) to a font language for Preferences
|
||||
static eFontPrefLang GetFontPrefLangFor(uint8_t aUnicodeRange);
|
||||
|
||||
// returns true if a pref lang is CJK
|
||||
static bool IsLangCJK(eFontPrefLang aLang);
|
||||
|
||||
// helper method to add a pref lang to an array, if not already in array
|
||||
static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang);
|
||||
|
||||
// returns a list of commonly used fonts for a given character
|
||||
// these are *possible* matches, no cmap-checking is done at this level
|
||||
virtual void GetCommonFallbackFonts(uint32_t /*aCh*/, uint32_t /*aNextCh*/,
|
||||
@@ -677,9 +633,6 @@ protected:
|
||||
gfxPlatform();
|
||||
virtual ~gfxPlatform();
|
||||
|
||||
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
|
||||
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
||||
|
||||
/**
|
||||
* Initialized hardware vsync based on each platform.
|
||||
*/
|
||||
@@ -794,7 +747,6 @@ private:
|
||||
void PopulateScreenInfo();
|
||||
|
||||
nsRefPtr<gfxASurface> mScreenReferenceSurface;
|
||||
nsTArray<uint32_t> mCJKPrefLangs;
|
||||
nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
|
||||
nsCOMPtr<nsIObserver> mFontPrefsObserver;
|
||||
nsCOMPtr<nsIObserver> mMemoryPressureObserver;
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include "gfxTextRun.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsILocaleService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsUnicodeRange.h"
|
||||
#include "nsUnicodeProperties.h"
|
||||
@@ -94,6 +98,16 @@ static const char* kObservedPrefs[] = {
|
||||
nullptr
|
||||
};
|
||||
|
||||
// xxx - this can probably be eliminated by reworking pref font handling code
|
||||
static const char *gPrefLangNames[] = {
|
||||
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) str_
|
||||
#include "gfxFontPrefLangList.h"
|
||||
#undef FONT_PREF_LANG
|
||||
};
|
||||
|
||||
static_assert(MOZ_ARRAY_LENGTH(gPrefLangNames) == uint32_t(eFontPrefLang_Count),
|
||||
"size of pref lang name array doesn't match pref lang enum size");
|
||||
|
||||
class gfxFontListPrefObserver final : public nsIObserver {
|
||||
~gfxFontListPrefObserver() {}
|
||||
public:
|
||||
@@ -113,7 +127,7 @@ gfxFontListPrefObserver::Observe(nsISupports *aSubject,
|
||||
NS_ASSERTION(!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), "invalid topic");
|
||||
// XXX this could be made to only clear out the cache for the prefs that were changed
|
||||
// but it probably isn't that big a deal.
|
||||
gfxPlatformFontList::PlatformFontList()->ClearPrefFonts();
|
||||
gfxPlatformFontList::PlatformFontList()->ClearLangGroupPrefFonts();
|
||||
gfxFontCache::GetCache()->AgeAllGenerations();
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -162,7 +176,7 @@ gfxPlatformFontList::MemoryReporter::CollectReports(
|
||||
|
||||
gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
|
||||
: mFontFamilies(64), mOtherFamilyNames(16),
|
||||
mPrefFonts(8), mBadUnderlineFamilyNames(8), mSharedCmaps(8),
|
||||
mBadUnderlineFamilyNames(8), mSharedCmaps(8),
|
||||
mStartIndex(0), mIncrement(1), mNumFamilies(0), mFontlistInitCount(0)
|
||||
{
|
||||
mOtherFamilyNamesInitialized = false;
|
||||
@@ -187,11 +201,15 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
|
||||
gfxPlatformFontList::~gfxPlatformFontList()
|
||||
{
|
||||
mSharedCmaps.Clear();
|
||||
ClearLangGroupPrefFonts();
|
||||
NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
|
||||
Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
|
||||
NS_RELEASE(gFontListPrefObserver);
|
||||
}
|
||||
|
||||
// number of CSS generic font families
|
||||
const uint32_t kNumGenerics = 5;
|
||||
|
||||
nsresult
|
||||
gfxPlatformFontList::InitFontList()
|
||||
{
|
||||
@@ -216,7 +234,7 @@ gfxPlatformFontList::InitFontList()
|
||||
mExtraNames->mPostscriptNames.Clear();
|
||||
}
|
||||
mFaceNameListsInitialized = false;
|
||||
mPrefFonts.Clear();
|
||||
ClearLangGroupPrefFonts();
|
||||
mReplacementCharFallbackFamily = nullptr;
|
||||
CancelLoader();
|
||||
|
||||
@@ -703,18 +721,6 @@ gfxPlatformFontList::FindFontForFamily(const nsAString& aFamily, const gfxFontSt
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatformFontList::GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> > *array)
|
||||
{
|
||||
return mPrefFonts.Get(uint32_t(aLangGroup), array);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> >& array)
|
||||
{
|
||||
mPrefFonts.Put(uint32_t(aLangGroup), array);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName)
|
||||
{
|
||||
@@ -801,6 +807,419 @@ gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::ResolveGenericFontNames(
|
||||
FontFamilyType aGenericType,
|
||||
eFontPrefLang aPrefLang,
|
||||
nsTArray<nsRefPtr<gfxFontFamily>>* aGenericFamilies
|
||||
)
|
||||
{
|
||||
const char* langGroupStr = GetPrefLangName(aPrefLang);
|
||||
|
||||
static const char kGeneric_serif[] = "serif";
|
||||
static const char kGeneric_sans_serif[] = "sans-serif";
|
||||
static const char kGeneric_monospace[] = "monospace";
|
||||
static const char kGeneric_cursive[] = "cursive";
|
||||
static const char kGeneric_fantasy[] = "fantasy";
|
||||
|
||||
// type should be standard generic type at this point
|
||||
NS_ASSERTION(aGenericType >= eFamily_serif &&
|
||||
aGenericType <= eFamily_fantasy,
|
||||
"standard generic font family type required");
|
||||
|
||||
// map generic type to string
|
||||
const char *generic = nullptr;
|
||||
switch (aGenericType) {
|
||||
case eFamily_serif:
|
||||
generic = kGeneric_serif;
|
||||
break;
|
||||
case eFamily_sans_serif:
|
||||
generic = kGeneric_sans_serif;
|
||||
break;
|
||||
case eFamily_monospace:
|
||||
generic = kGeneric_monospace;
|
||||
break;
|
||||
case eFamily_cursive:
|
||||
generic = kGeneric_cursive;
|
||||
break;
|
||||
case eFamily_fantasy:
|
||||
generic = kGeneric_fantasy;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!generic) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoTArray<nsString,4> genericFamilies;
|
||||
|
||||
// load family for "font.name.generic.lang"
|
||||
nsAutoCString prefFontName("font.name.");
|
||||
prefFontName.Append(generic);
|
||||
prefFontName.Append('.');
|
||||
prefFontName.Append(langGroupStr);
|
||||
gfxFontUtils::AppendPrefsFontList(prefFontName.get(), genericFamilies);
|
||||
|
||||
// load fonts for "font.name-list.generic.lang"
|
||||
nsAutoCString prefFontListName("font.name-list.");
|
||||
prefFontListName.Append(generic);
|
||||
prefFontListName.Append('.');
|
||||
prefFontListName.Append(langGroupStr);
|
||||
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(), genericFamilies);
|
||||
|
||||
nsIAtom* langGroup = GetLangGroupForPrefLang(aPrefLang);
|
||||
NS_ASSERTION(langGroup, "null lang group for pref lang");
|
||||
|
||||
// lookup and add platform fonts uniquely
|
||||
for (const nsString& genericFamily : genericFamilies) {
|
||||
nsRefPtr<gfxFontFamily> family =
|
||||
FindFamily(genericFamily, langGroup, false);
|
||||
if (family) {
|
||||
bool notFound = true;
|
||||
for (const gfxFontFamily* f : *aGenericFamilies) {
|
||||
if (f == family) {
|
||||
notFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (notFound) {
|
||||
aGenericFamilies->AppendElement(family);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // dump out generic mappings
|
||||
printf("%s ===> ", prefFontName.get());
|
||||
for (uint32_t k = 0; k < aGenericFamilies->Length(); k++) {
|
||||
if (k > 0) printf(", ");
|
||||
printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]->Name()).get());
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<gfxFontFamily>>*
|
||||
gfxPlatformFontList::GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
|
||||
eFontPrefLang aPrefLang)
|
||||
{
|
||||
// treat -moz-fixed as monospace
|
||||
if (aGenericType == eFamily_moz_fixed) {
|
||||
aGenericType = eFamily_monospace;
|
||||
}
|
||||
|
||||
PrefFontList* prefFonts = mLangGroupPrefFonts[aPrefLang][aGenericType];
|
||||
if (MOZ_UNLIKELY(!prefFonts)) {
|
||||
prefFonts = new PrefFontList;
|
||||
ResolveGenericFontNames(aGenericType, aPrefLang, prefFonts);
|
||||
mLangGroupPrefFonts[aPrefLang][aGenericType] = prefFonts;
|
||||
}
|
||||
return prefFonts;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::AddGenericFonts(mozilla::FontFamilyType aGenericType,
|
||||
nsIAtom* aLanguage,
|
||||
nsTArray<gfxFontFamily*>& aFamilyList)
|
||||
{
|
||||
// map lang ==> langGroup
|
||||
nsIAtom *langGroup = nullptr;
|
||||
if (aLanguage) {
|
||||
if (!mLangService) {
|
||||
mLangService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
|
||||
}
|
||||
if (mLangService) {
|
||||
nsresult rv;
|
||||
langGroup = mLangService->GetLanguageGroup(aLanguage, &rv);
|
||||
}
|
||||
}
|
||||
if (!langGroup) {
|
||||
langGroup = nsGkAtoms::Unicode;
|
||||
}
|
||||
|
||||
// langGroup ==> prefLang
|
||||
eFontPrefLang prefLang = GetFontPrefLangFor(langGroup);
|
||||
|
||||
// lookup pref fonts
|
||||
nsTArray<nsRefPtr<gfxFontFamily>>* prefFonts =
|
||||
GetPrefFontsLangGroup(aGenericType, prefLang);
|
||||
|
||||
if (!prefFonts->IsEmpty()) {
|
||||
aFamilyList.AppendElements(*prefFonts);
|
||||
}
|
||||
}
|
||||
|
||||
static nsIAtom* PrefLangToLangGroups(uint32_t aIndex)
|
||||
{
|
||||
// static array here avoids static constructor
|
||||
static nsIAtom* gPrefLangToLangGroups[] = {
|
||||
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) nsGkAtoms::atom_id_
|
||||
#include "gfxFontPrefLangList.h"
|
||||
#undef FONT_PREF_LANG
|
||||
};
|
||||
|
||||
return aIndex < ArrayLength(gPrefLangToLangGroups)
|
||||
? gPrefLangToLangGroups[aIndex]
|
||||
: nsGkAtoms::Unicode;
|
||||
}
|
||||
|
||||
eFontPrefLang
|
||||
gfxPlatformFontList::GetFontPrefLangFor(const char* aLang)
|
||||
{
|
||||
if (!aLang || !aLang[0]) {
|
||||
return eFontPrefLang_Others;
|
||||
}
|
||||
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); ++i) {
|
||||
if (!PL_strcasecmp(gPrefLangNames[i], aLang)) {
|
||||
return eFontPrefLang(i);
|
||||
}
|
||||
}
|
||||
return eFontPrefLang_Others;
|
||||
}
|
||||
|
||||
eFontPrefLang
|
||||
gfxPlatformFontList::GetFontPrefLangFor(nsIAtom *aLang)
|
||||
{
|
||||
if (!aLang)
|
||||
return eFontPrefLang_Others;
|
||||
nsAutoCString lang;
|
||||
aLang->ToUTF8String(lang);
|
||||
return GetFontPrefLangFor(lang.get());
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
gfxPlatformFontList::GetLangGroupForPrefLang(eFontPrefLang aLang)
|
||||
{
|
||||
// the special CJK set pref lang should be resolved into separate
|
||||
// calls to individual CJK pref langs before getting here
|
||||
NS_ASSERTION(aLang != eFontPrefLang_CJKSet, "unresolved CJK set pref lang");
|
||||
|
||||
return PrefLangToLangGroups(uint32_t(aLang));
|
||||
}
|
||||
|
||||
const char*
|
||||
gfxPlatformFontList::GetPrefLangName(eFontPrefLang aLang)
|
||||
{
|
||||
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
|
||||
return gPrefLangNames[uint32_t(aLang)];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
eFontPrefLang
|
||||
gfxPlatformFontList::GetFontPrefLangFor(uint8_t aUnicodeRange)
|
||||
{
|
||||
switch (aUnicodeRange) {
|
||||
case kRangeSetLatin: return eFontPrefLang_Western;
|
||||
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
|
||||
case kRangeGreek: return eFontPrefLang_Greek;
|
||||
case kRangeHebrew: return eFontPrefLang_Hebrew;
|
||||
case kRangeArabic: return eFontPrefLang_Arabic;
|
||||
case kRangeThai: return eFontPrefLang_Thai;
|
||||
case kRangeKorean: return eFontPrefLang_Korean;
|
||||
case kRangeJapanese: return eFontPrefLang_Japanese;
|
||||
case kRangeSChinese: return eFontPrefLang_ChineseCN;
|
||||
case kRangeTChinese: return eFontPrefLang_ChineseTW;
|
||||
case kRangeDevanagari: return eFontPrefLang_Devanagari;
|
||||
case kRangeTamil: return eFontPrefLang_Tamil;
|
||||
case kRangeArmenian: return eFontPrefLang_Armenian;
|
||||
case kRangeBengali: return eFontPrefLang_Bengali;
|
||||
case kRangeCanadian: return eFontPrefLang_Canadian;
|
||||
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
|
||||
case kRangeGeorgian: return eFontPrefLang_Georgian;
|
||||
case kRangeGujarati: return eFontPrefLang_Gujarati;
|
||||
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
|
||||
case kRangeKhmer: return eFontPrefLang_Khmer;
|
||||
case kRangeMalayalam: return eFontPrefLang_Malayalam;
|
||||
case kRangeOriya: return eFontPrefLang_Oriya;
|
||||
case kRangeTelugu: return eFontPrefLang_Telugu;
|
||||
case kRangeKannada: return eFontPrefLang_Kannada;
|
||||
case kRangeSinhala: return eFontPrefLang_Sinhala;
|
||||
case kRangeTibetan: return eFontPrefLang_Tibetan;
|
||||
case kRangeSetCJK: return eFontPrefLang_CJKSet;
|
||||
default: return eFontPrefLang_Others;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatformFontList::IsLangCJK(eFontPrefLang aLang)
|
||||
{
|
||||
switch (aLang) {
|
||||
case eFontPrefLang_Japanese:
|
||||
case eFontPrefLang_ChineseTW:
|
||||
case eFontPrefLang_ChineseCN:
|
||||
case eFontPrefLang_ChineseHK:
|
||||
case eFontPrefLang_Korean:
|
||||
case eFontPrefLang_CJKSet:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
|
||||
{
|
||||
if (IsLangCJK(aCharLang)) {
|
||||
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
|
||||
} else {
|
||||
AppendPrefLang(aPrefLangs, aLen, aCharLang);
|
||||
}
|
||||
|
||||
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
|
||||
{
|
||||
// prefer the lang specified by the page *if* CJK
|
||||
if (IsLangCJK(aPageLang)) {
|
||||
AppendPrefLang(aPrefLangs, aLen, aPageLang);
|
||||
}
|
||||
|
||||
// if not set up, set up the default CJK order, based on accept lang settings and locale
|
||||
if (mCJKPrefLangs.Length() == 0) {
|
||||
|
||||
// temp array
|
||||
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
|
||||
uint32_t tempLen = 0;
|
||||
|
||||
// Add the CJK pref fonts from accept languages, the order should be same order
|
||||
nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
|
||||
if (!list.IsEmpty()) {
|
||||
const char kComma = ',';
|
||||
const char *p, *p_end;
|
||||
list.BeginReading(p);
|
||||
list.EndReading(p_end);
|
||||
while (p < p_end) {
|
||||
while (nsCRT::IsAsciiSpace(*p)) {
|
||||
if (++p == p_end)
|
||||
break;
|
||||
}
|
||||
if (p == p_end)
|
||||
break;
|
||||
const char *start = p;
|
||||
while (++p != p_end && *p != kComma)
|
||||
/* nothing */ ;
|
||||
nsAutoCString lang(Substring(start, p));
|
||||
lang.CompressWhitespace(false, true);
|
||||
eFontPrefLang fpl = gfxPlatformFontList::GetFontPrefLangFor(lang.get());
|
||||
switch (fpl) {
|
||||
case eFontPrefLang_Japanese:
|
||||
case eFontPrefLang_Korean:
|
||||
case eFontPrefLang_ChineseCN:
|
||||
case eFontPrefLang_ChineseHK:
|
||||
case eFontPrefLang_ChineseTW:
|
||||
AppendPrefLang(tempPrefLangs, tempLen, fpl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
do { // to allow 'break' to abort this block if a call fails
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILocaleService> ls =
|
||||
do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsILocale> appLocale;
|
||||
rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
nsString localeStr;
|
||||
rv = appLocale->
|
||||
GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
const nsAString& lang = Substring(localeStr, 0, 2);
|
||||
if (lang.EqualsLiteral("ja")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
} else if (lang.EqualsLiteral("zh")) {
|
||||
const nsAString& region = Substring(localeStr, 3, 2);
|
||||
if (region.EqualsLiteral("CN")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
} else if (region.EqualsLiteral("TW")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
} else if (region.EqualsLiteral("HK")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
}
|
||||
} else if (lang.EqualsLiteral("ko")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
// last resort... (the order is same as old gfx.)
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
|
||||
// copy into the cached array
|
||||
uint32_t j;
|
||||
for (j = 0; j < tempLen; j++) {
|
||||
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// append in cached CJK langs
|
||||
uint32_t i, numCJKlangs = mCJKPrefLangs.Length();
|
||||
|
||||
for (i = 0; i < numCJKlangs; i++) {
|
||||
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang)
|
||||
{
|
||||
if (aLen >= kMaxLenPrefLangList) return;
|
||||
|
||||
// make sure
|
||||
uint32_t i = 0;
|
||||
while (i < aLen && aPrefLangs[i] != aAddLang) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == aLen) {
|
||||
aPrefLangs[aLen] = aAddLang;
|
||||
aLen++;
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::FontFamilyType
|
||||
gfxPlatformFontList::GetDefaultGeneric(eFontPrefLang aLang)
|
||||
{
|
||||
// initialize lang group pref font defaults (i.e. serif/sans-serif)
|
||||
if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) {
|
||||
mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames));
|
||||
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); i++) {
|
||||
nsAutoCString prefDefaultFontType("font.default.");
|
||||
prefDefaultFontType.Append(GetPrefLangName(eFontPrefLang(i)));
|
||||
nsAdoptingCString serifOrSans =
|
||||
Preferences::GetCString(prefDefaultFontType.get());
|
||||
if (serifOrSans.EqualsLiteral("sans-serif")) {
|
||||
mDefaultGenericsLangGroup[i] = eFamily_sans_serif;
|
||||
} else {
|
||||
mDefaultGenericsLangGroup[i] = eFamily_serif;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
|
||||
return mDefaultGenericsLangGroup[uint32_t(aLang)];
|
||||
}
|
||||
return eFamily_serif;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames)
|
||||
{
|
||||
@@ -952,6 +1371,19 @@ gfxPlatformFontList::RebuildLocalFonts()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::ClearLangGroupPrefFonts()
|
||||
{
|
||||
for (uint32_t i = eFontPrefLang_First;
|
||||
i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
|
||||
auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
|
||||
for (uint32_t j = eFamily_generic_first;
|
||||
j < eFamily_generic_first + eFamily_generic_count; j++) {
|
||||
prefFontsLangGroup[j] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Support for memory reporting
|
||||
|
||||
// this is also used by subclasses that hold additional font tables
|
||||
@@ -1008,21 +1440,24 @@ gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
aMallocSizeOf);
|
||||
}
|
||||
|
||||
for (uint32_t i = eFontPrefLang_First;
|
||||
i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
|
||||
auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
|
||||
for (uint32_t j = eFamily_generic_first;
|
||||
j < eFamily_generic_first + eFamily_generic_count; j++) {
|
||||
PrefFontList* pf = prefFontsLangGroup[j];
|
||||
if (pf) {
|
||||
aSizes->mFontListSize +=
|
||||
pf->ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
|
||||
aSizes->mFontListSize +=
|
||||
mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mPrefFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mPrefFonts.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// Again, we only care about the size of the array itself; we don't
|
||||
// follow the refPtrs stored in it, because they point to entries
|
||||
// already owned and accounted-for by the main font list.
|
||||
aSizes->mFontListSize +=
|
||||
iter.Data().ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mBadUnderlineFamilyNames.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
|
||||
@@ -13,11 +13,15 @@
|
||||
#include "gfxFontUtils.h"
|
||||
#include "gfxFontInfoLoader.h"
|
||||
#include "gfxFont.h"
|
||||
#include "gfxFontConstants.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxFontFamilyList.h"
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/RangedArray.h"
|
||||
#include "nsILanguageAtomService.h"
|
||||
|
||||
class CharMapHashKey : public PLDHashEntryHdr
|
||||
{
|
||||
@@ -116,7 +120,7 @@ public:
|
||||
|
||||
void UpdateFontList();
|
||||
|
||||
void ClearPrefFonts() { mPrefFonts.Clear(); }
|
||||
void ClearLangGroupPrefFonts();
|
||||
|
||||
virtual void GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray);
|
||||
|
||||
@@ -131,9 +135,6 @@ public:
|
||||
|
||||
gfxFontEntry* FindFontForFamily(const nsAString& aFamily, const gfxFontStyle* aStyle, bool& aNeedsBold);
|
||||
|
||||
bool GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> > *array);
|
||||
void SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> >& array);
|
||||
|
||||
// name lookup table methods
|
||||
|
||||
void AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName);
|
||||
@@ -199,6 +200,43 @@ public:
|
||||
aLoaderState = (uint32_t) mState;
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddGenericFonts(mozilla::FontFamilyType aGenericType,
|
||||
nsIAtom* aLanguage,
|
||||
nsTArray<gfxFontFamily*>& aFamilyList);
|
||||
|
||||
nsTArray<nsRefPtr<gfxFontFamily>>*
|
||||
GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
|
||||
eFontPrefLang aPrefLang);
|
||||
|
||||
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
|
||||
void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
||||
|
||||
// convert a lang group to enum constant (i.e. "zh-TW" ==> eFontPrefLang_ChineseTW)
|
||||
static eFontPrefLang GetFontPrefLangFor(const char* aLang);
|
||||
|
||||
// convert a lang group atom to enum constant
|
||||
static eFontPrefLang GetFontPrefLangFor(nsIAtom *aLang);
|
||||
|
||||
// convert an enum constant to a lang group atom
|
||||
static nsIAtom* GetLangGroupForPrefLang(eFontPrefLang aLang);
|
||||
|
||||
// convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW ==> "zh-TW")
|
||||
static const char* GetPrefLangName(eFontPrefLang aLang);
|
||||
|
||||
// map a Unicode range (based on char code) to a font language for Preferences
|
||||
static eFontPrefLang GetFontPrefLangFor(uint8_t aUnicodeRange);
|
||||
|
||||
// returns true if a pref lang is CJK
|
||||
static bool IsLangCJK(eFontPrefLang aLang);
|
||||
|
||||
// helper method to add a pref lang to an array, if not already in array
|
||||
static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang);
|
||||
|
||||
// default serif/sans-serif choice based on font.default.xxx prefs
|
||||
mozilla::FontFamilyType
|
||||
GetDefaultGeneric(eFontPrefLang aLang);
|
||||
|
||||
protected:
|
||||
class MemoryReporter final : public nsIMemoryReporter
|
||||
{
|
||||
@@ -241,6 +279,9 @@ protected:
|
||||
// if system fallback is used, no need to load all cmaps
|
||||
virtual bool UsesSystemFallback() { return false; }
|
||||
|
||||
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
|
||||
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
||||
|
||||
// verifies that a family contains a non-zero font count
|
||||
gfxFontFamily* CheckFamily(gfxFontFamily *aFamily);
|
||||
|
||||
@@ -287,6 +328,11 @@ protected:
|
||||
|
||||
void RebuildLocalFonts();
|
||||
|
||||
void
|
||||
ResolveGenericFontNames(mozilla::FontFamilyType aGenericType,
|
||||
eFontPrefLang aPrefLang,
|
||||
nsTArray<nsRefPtr<gfxFontFamily>>* aGenericFamilies);
|
||||
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontFamilyTable;
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> FontEntryTable;
|
||||
|
||||
@@ -332,9 +378,13 @@ protected:
|
||||
// localized family names missed when face name loading takes a long time
|
||||
nsAutoPtr<nsTHashtable<nsStringHashKey> > mOtherNamesMissed;
|
||||
|
||||
// cached pref font lists
|
||||
// maps list of family names ==> array of family entries, one per lang group
|
||||
nsDataHashtable<nsUint32HashKey, nsTArray<nsRefPtr<gfxFontFamily> > > mPrefFonts;
|
||||
typedef nsTArray<nsRefPtr<gfxFontFamily>> PrefFontList;
|
||||
typedef mozilla::RangedArray<nsAutoPtr<PrefFontList>,
|
||||
mozilla::eFamily_generic_first,
|
||||
mozilla::eFamily_generic_count> PrefFontsForLangGroup;
|
||||
mozilla::RangedArray<PrefFontsForLangGroup,
|
||||
eFontPrefLang_First,
|
||||
eFontPrefLang_Count> mLangGroupPrefFonts;
|
||||
|
||||
// when system-wide font lookup fails for a character, cache it to skip future searches
|
||||
gfxSparseBitSet mCodepointsWithNoFonts;
|
||||
@@ -360,6 +410,10 @@ protected:
|
||||
uint32_t mFontlistInitCount; // num times InitFontList called
|
||||
|
||||
nsTHashtable<nsPtrHashKey<gfxUserFontSet> > mUserFontSetList;
|
||||
|
||||
nsCOMPtr<nsILanguageAtomService> mLangService;
|
||||
nsTArray<uint32_t> mCJKPrefLangs;
|
||||
nsTArray<mozilla::FontFamilyType> mDefaultGenericsLangGroup;
|
||||
};
|
||||
|
||||
#endif /* GFXPLATFORMFONTLIST_H_ */
|
||||
|
||||
+145
-230
@@ -222,7 +222,6 @@ gfxTextRun::SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength,
|
||||
if (canBreak && !charGlyphs[i].IsClusterStart()) {
|
||||
// This can happen ... there is no guarantee that our linebreaking rules
|
||||
// align with the platform's idea of what constitutes a cluster.
|
||||
NS_WARNING("Break suggested inside cluster!");
|
||||
canBreak = CompressedGlyph::FLAG_BREAK_TYPE_NONE;
|
||||
}
|
||||
changed |= charGlyphs[i].SetCanBreakBefore(canBreak);
|
||||
@@ -515,13 +514,13 @@ HasSyntheticBold(gfxTextRun *aRun, uint32_t aStart, uint32_t aLength)
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns true if color is non-opaque (i.e. alpha != 1.0) or completely transparent, false otherwise
|
||||
// if true, color is set on output
|
||||
// Returns true if color is neither opaque nor transparent (i.e. alpha is not 0
|
||||
// or 1), and false otherwise. If true, aCurrentColorOut is set on output.
|
||||
static bool
|
||||
HasNonOpaqueColor(gfxContext *aContext, Color& aCurrentColorOut)
|
||||
HasNonOpaqueNonTransparentColor(gfxContext *aContext, Color& aCurrentColorOut)
|
||||
{
|
||||
if (aContext->GetDeviceColor(aCurrentColorOut)) {
|
||||
if (0.0 < aCurrentColorOut.a && aCurrentColorOut.a < 1.0) {
|
||||
if (0.f < aCurrentColorOut.a && aCurrentColorOut.a < 1.f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -532,6 +531,7 @@ HasNonOpaqueColor(gfxContext *aContext, Color& aCurrentColorOut)
|
||||
struct BufferAlphaColor {
|
||||
explicit BufferAlphaColor(gfxContext *aContext)
|
||||
: mContext(aContext)
|
||||
, mAlpha(0.0)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -603,6 +603,25 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
|
||||
return;
|
||||
}
|
||||
|
||||
// synthetic bolding draws glyphs twice ==> colors with opacity won't draw
|
||||
// correctly unless first drawn without alpha
|
||||
BufferAlphaColor syntheticBoldBuffer(aContext);
|
||||
Color currentColor;
|
||||
bool needToRestore = false;
|
||||
|
||||
if (aDrawMode == DrawMode::GLYPH_FILL &&
|
||||
HasNonOpaqueNonTransparentColor(aContext, currentColor) &&
|
||||
HasSyntheticBold(this, aStart, aLength)) {
|
||||
needToRestore = true;
|
||||
// measure text, use the bounding box
|
||||
gfxTextRun::Metrics metrics = MeasureText(aStart, aLength,
|
||||
gfxFont::LOOSE_INK_EXTENTS,
|
||||
aContext, aProvider);
|
||||
metrics.mBoundingBox.MoveBy(aPt);
|
||||
syntheticBoldBuffer.PushSolidColor(metrics.mBoundingBox, currentColor,
|
||||
GetAppUnitsPerDevUnit());
|
||||
}
|
||||
|
||||
// Set up parameters that will be constant across all glyph runs we need
|
||||
// to draw, regardless of the font used.
|
||||
TextRunDrawParams params;
|
||||
@@ -618,25 +637,6 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
|
||||
params.dt = aContext->GetDrawTarget();
|
||||
params.fontSmoothingBGColor = aContext->GetFontSmoothingBackgroundColor();
|
||||
|
||||
// synthetic bolding draws glyphs twice ==> colors with opacity won't draw
|
||||
// correctly unless first drawn without alpha
|
||||
BufferAlphaColor syntheticBoldBuffer(aContext);
|
||||
Color currentColor;
|
||||
bool needToRestore = false;
|
||||
|
||||
if (aDrawMode == DrawMode::GLYPH_FILL &&
|
||||
HasNonOpaqueColor(aContext, currentColor) &&
|
||||
HasSyntheticBold(this, aStart, aLength)) {
|
||||
needToRestore = true;
|
||||
// measure text, use the bounding box
|
||||
gfxTextRun::Metrics metrics = MeasureText(aStart, aLength,
|
||||
gfxFont::LOOSE_INK_EXTENTS,
|
||||
aContext, aProvider);
|
||||
metrics.mBoundingBox.MoveBy(aPt);
|
||||
syntheticBoldBuffer.PushSolidColor(metrics.mBoundingBox, currentColor,
|
||||
GetAppUnitsPerDevUnit());
|
||||
}
|
||||
|
||||
GlyphRunIterator iter(this, aStart, aLength);
|
||||
gfxFloat advance = 0.0;
|
||||
|
||||
@@ -1247,13 +1247,16 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
|
||||
// Copy glyph runs
|
||||
GlyphRunIterator iter(aSource, aStart, aLength);
|
||||
#ifdef DEBUG
|
||||
gfxFont *lastFont = nullptr;
|
||||
GlyphRun *prevRun = nullptr;
|
||||
#endif
|
||||
while (iter.NextRun()) {
|
||||
gfxFont *font = iter.GetGlyphRun()->mFont;
|
||||
NS_ASSERTION(font != lastFont, "Glyphruns not coalesced?");
|
||||
NS_ASSERTION(!prevRun || prevRun->mFont != iter.GetGlyphRun()->mFont ||
|
||||
prevRun->mMatchType != iter.GetGlyphRun()->mMatchType ||
|
||||
prevRun->mOrientation != iter.GetGlyphRun()->mOrientation,
|
||||
"Glyphruns not coalesced?");
|
||||
#ifdef DEBUG
|
||||
lastFont = font;
|
||||
prevRun = iter.GetGlyphRun();
|
||||
uint32_t end = iter.GetStringEnd();
|
||||
#endif
|
||||
uint32_t start = iter.GetStringStart();
|
||||
@@ -1540,7 +1543,7 @@ gfxFontGroup::gfxFontGroup(const FontFamilyList& aFontFamilyList,
|
||||
, mHyphenWidth(-1)
|
||||
, mUserFontSet(aUserFontSet)
|
||||
, mTextPerf(aTextPerf)
|
||||
, mPageLang(gfxPlatform::GetFontPrefLangFor(aStyle->language))
|
||||
, mPageLang(gfxPlatformFontList::GetFontPrefLangFor(aStyle->language))
|
||||
, mSkipDrawing(false)
|
||||
, mSkipUpdateUserFonts(false)
|
||||
{
|
||||
@@ -1554,138 +1557,6 @@ gfxFontGroup::~gfxFontGroup()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontGroup::FindGenericFonts(FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
void *aClosure)
|
||||
{
|
||||
nsAutoTArray<nsString, 5> resolvedGenerics;
|
||||
ResolveGenericFontNames(aGenericType, aLanguage, resolvedGenerics);
|
||||
uint32_t g = 0, numGenerics = resolvedGenerics.Length();
|
||||
for (g = 0; g < numGenerics; g++) {
|
||||
FindPlatformFont(resolvedGenerics[g], false, aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxFontGroup::ResolveGenericFontNames(FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
nsTArray<nsString>& aGenericFamilies)
|
||||
{
|
||||
static const char kGeneric_serif[] = "serif";
|
||||
static const char kGeneric_sans_serif[] = "sans-serif";
|
||||
static const char kGeneric_monospace[] = "monospace";
|
||||
static const char kGeneric_cursive[] = "cursive";
|
||||
static const char kGeneric_fantasy[] = "fantasy";
|
||||
|
||||
// treat -moz-fixed as monospace
|
||||
if (aGenericType == eFamily_moz_fixed) {
|
||||
aGenericType = eFamily_monospace;
|
||||
}
|
||||
|
||||
// type should be standard generic type at this point
|
||||
NS_ASSERTION(aGenericType >= eFamily_serif &&
|
||||
aGenericType <= eFamily_fantasy,
|
||||
"standard generic font family type required");
|
||||
|
||||
// create the lang string
|
||||
nsIAtom *langGroupAtom = nullptr;
|
||||
nsAutoCString langGroupString;
|
||||
if (aLanguage) {
|
||||
if (!gLangService) {
|
||||
CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
|
||||
}
|
||||
if (gLangService) {
|
||||
nsresult rv;
|
||||
langGroupAtom = gLangService->GetLanguageGroup(aLanguage, &rv);
|
||||
}
|
||||
}
|
||||
if (!langGroupAtom) {
|
||||
langGroupAtom = nsGkAtoms::Unicode;
|
||||
}
|
||||
langGroupAtom->ToUTF8String(langGroupString);
|
||||
|
||||
// map generic type to string
|
||||
const char *generic = nullptr;
|
||||
switch (aGenericType) {
|
||||
case eFamily_serif:
|
||||
generic = kGeneric_serif;
|
||||
break;
|
||||
case eFamily_sans_serif:
|
||||
generic = kGeneric_sans_serif;
|
||||
break;
|
||||
case eFamily_monospace:
|
||||
generic = kGeneric_monospace;
|
||||
break;
|
||||
case eFamily_cursive:
|
||||
generic = kGeneric_cursive;
|
||||
break;
|
||||
case eFamily_fantasy:
|
||||
generic = kGeneric_fantasy;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!generic) {
|
||||
return;
|
||||
}
|
||||
|
||||
aGenericFamilies.Clear();
|
||||
|
||||
// load family for "font.name.generic.lang"
|
||||
nsAutoCString prefFontName("font.name.");
|
||||
prefFontName.Append(generic);
|
||||
prefFontName.Append('.');
|
||||
prefFontName.Append(langGroupString);
|
||||
gfxFontUtils::AppendPrefsFontList(prefFontName.get(),
|
||||
aGenericFamilies);
|
||||
|
||||
// if lang has pref fonts, also load fonts for "font.name-list.generic.lang"
|
||||
if (!aGenericFamilies.IsEmpty()) {
|
||||
nsAutoCString prefFontListName("font.name-list.");
|
||||
prefFontListName.Append(generic);
|
||||
prefFontListName.Append('.');
|
||||
prefFontListName.Append(langGroupString);
|
||||
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(),
|
||||
aGenericFamilies);
|
||||
}
|
||||
|
||||
#if 0 // dump out generic mappings
|
||||
printf("%s ===> ", prefFontName.get());
|
||||
for (uint32_t k = 0; k < aGenericFamilies.Length(); k++) {
|
||||
if (k > 0) printf(", ");
|
||||
printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]).get());
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void gfxFontGroup::EnumerateFontList(nsIAtom *aLanguage, void *aClosure)
|
||||
{
|
||||
// initialize fonts in the font family list
|
||||
const nsTArray<FontFamilyName>& fontlist = mFamilyList.GetFontlist();
|
||||
|
||||
// lookup fonts in the fontlist
|
||||
uint32_t i, numFonts = fontlist.Length();
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
const FontFamilyName& name = fontlist[i];
|
||||
if (name.IsNamed()) {
|
||||
FindPlatformFont(name.mName, true, aClosure);
|
||||
} else {
|
||||
FindGenericFonts(name.mType, aLanguage, aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
// if necessary, append default generic onto the end
|
||||
if (mFamilyList.GetDefaultFontType() != eFamily_none &&
|
||||
!mFamilyList.HasDefaultGeneric()) {
|
||||
FindGenericFonts(mFamilyList.GetDefaultFontType(),
|
||||
aLanguage,
|
||||
aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontGroup::BuildFontList()
|
||||
{
|
||||
@@ -1697,56 +1568,85 @@ gfxFontGroup::BuildFontList()
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
enumerateFonts = false;
|
||||
#endif
|
||||
if (enumerateFonts) {
|
||||
EnumerateFontList(mStyle.language);
|
||||
if (!enumerateFonts) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontGroup::FindPlatformFont(const nsAString& aName,
|
||||
bool aUseFontSet,
|
||||
void *aClosure)
|
||||
{
|
||||
bool needsBold;
|
||||
gfxFontFamily *family = nullptr;
|
||||
gfxFontEntry *fe = nullptr;
|
||||
// initialize fonts in the font family list
|
||||
nsAutoTArray<gfxFontFamily*,4> fonts;
|
||||
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||
|
||||
if (aUseFontSet) {
|
||||
// First, look up in the user font set...
|
||||
// If the fontSet matches the family, we must not look for a platform
|
||||
// font of the same name, even if we fail to actually get a fontEntry
|
||||
// here; we'll fall back to the next name in the CSS font-family list.
|
||||
if (mUserFontSet) {
|
||||
// Add userfonts to the fontlist whether already loaded
|
||||
// or not. Loading is initiated during font matching.
|
||||
family = mUserFontSet->LookupFamily(aName);
|
||||
if (family) {
|
||||
nsAutoTArray<gfxFontEntry*,4> userfonts;
|
||||
family->FindAllFontsForStyle(mStyle, userfonts, needsBold);
|
||||
// add these to the fontlist
|
||||
uint32_t count = userfonts.Length();
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
fe = userfonts[i];
|
||||
FamilyFace ff(family, fe, needsBold);
|
||||
ff.CheckState(mSkipDrawing);
|
||||
mFonts.AppendElement(ff);
|
||||
}
|
||||
// lookup fonts in the fontlist
|
||||
for (const FontFamilyName& name : mFamilyList.GetFontlist()) {
|
||||
if (name.IsNamed()) {
|
||||
AddPlatformFont(name.mName, fonts);
|
||||
} else {
|
||||
pfl->AddGenericFonts(name.mType, mStyle.language, fonts);
|
||||
if (mTextPerf) {
|
||||
mTextPerf->current.genericLookups++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not known in the user font set ==> check system fonts
|
||||
if (!family) {
|
||||
gfxPlatformFontList *fontList = gfxPlatformFontList::PlatformFontList();
|
||||
family = fontList->FindFamily(aName, mStyle.language, mStyle.systemFont);
|
||||
if (family) {
|
||||
fe = family->FindFontForStyle(mStyle, needsBold);
|
||||
// if necessary, append default generic onto the end
|
||||
if (mFamilyList.GetDefaultFontType() != eFamily_none &&
|
||||
!mFamilyList.HasDefaultGeneric()) {
|
||||
pfl->AddGenericFonts(mFamilyList.GetDefaultFontType(),
|
||||
mStyle.language, fonts);
|
||||
if (mTextPerf) {
|
||||
mTextPerf->current.genericLookups++;
|
||||
}
|
||||
}
|
||||
|
||||
// add to the font group, unless it's already there
|
||||
if (fe && !HasFont(fe)) {
|
||||
mFonts.AppendElement(FamilyFace(family, fe, needsBold));
|
||||
// build the fontlist from the specified families
|
||||
for (gfxFontFamily* fontFamily : fonts) {
|
||||
AddFamilyToFontList(fontFamily);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontGroup::AddPlatformFont(const nsAString& aName,
|
||||
nsTArray<gfxFontFamily*>& aFamilyList)
|
||||
{
|
||||
gfxFontFamily* family = nullptr;
|
||||
|
||||
// First, look up in the user font set...
|
||||
// If the fontSet matches the family, we must not look for a platform
|
||||
// font of the same name, even if we fail to actually get a fontEntry
|
||||
// here; we'll fall back to the next name in the CSS font-family list.
|
||||
if (mUserFontSet) {
|
||||
// Add userfonts to the fontlist whether already loaded
|
||||
// or not. Loading is initiated during font matching.
|
||||
family = mUserFontSet->LookupFamily(aName);
|
||||
}
|
||||
|
||||
// Not known in the user font set ==> check system fonts
|
||||
if (!family) {
|
||||
gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
family = fontList->FindFamily(aName, mStyle.language, mStyle.systemFont);
|
||||
}
|
||||
|
||||
if (family) {
|
||||
aFamilyList.AppendElement(family);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontGroup::AddFamilyToFontList(gfxFontFamily* aFamily)
|
||||
{
|
||||
NS_ASSERTION(aFamily, "trying to add a null font family to fontlist");
|
||||
nsAutoTArray<gfxFontEntry*,4> fontEntryList;
|
||||
bool needsBold;
|
||||
aFamily->FindAllFontsForStyle(mStyle, fontEntryList, needsBold);
|
||||
// add these to the fontlist
|
||||
for (gfxFontEntry* fe : fontEntryList) {
|
||||
if (!HasFont(fe)) {
|
||||
FamilyFace ff(aFamily, fe, needsBold);
|
||||
if (fe->mIsUserFontContainer) {
|
||||
ff.CheckState(mSkipDrawing);
|
||||
}
|
||||
mFonts.AppendElement(ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2651,9 +2551,6 @@ gfxFontGroup::FindNonItalicFaceForChar(gfxFontFamily* aFamily, uint32_t aCh)
|
||||
}
|
||||
|
||||
nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, needsBold);
|
||||
if (!font->Valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
return font.forget();
|
||||
}
|
||||
|
||||
@@ -3008,16 +2905,40 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
|
||||
|
||||
aRanges[lastRangeIndex].end = aLength;
|
||||
|
||||
#if 0
|
||||
// dump out font matching info
|
||||
if (mStyle.systemFont) return;
|
||||
for (size_t i = 0, i_end = aRanges.Length(); i < i_end; i++) {
|
||||
const gfxTextRange& r = aRanges[i];
|
||||
printf("fontmatch %zd:%zd font: %s (%d)\n",
|
||||
r.start, r.end,
|
||||
(r.font.get() ?
|
||||
NS_ConvertUTF16toUTF8(r.font->GetName()).get() : "<null>"),
|
||||
r.matchType);
|
||||
#ifndef RELEASE_BUILD
|
||||
PRLogModuleInfo *log = (mStyle.systemFont ?
|
||||
gfxPlatform::GetLog(eGfxLog_textrunui) :
|
||||
gfxPlatform::GetLog(eGfxLog_textrun));
|
||||
|
||||
if (MOZ_UNLIKELY(MOZ_LOG_TEST(log, LogLevel::Debug))) {
|
||||
nsAutoCString lang;
|
||||
mStyle.language->ToUTF8String(lang);
|
||||
nsAutoString families;
|
||||
mFamilyList.ToString(families);
|
||||
|
||||
// collect the font matched for each range
|
||||
nsAutoCString fontMatches;
|
||||
for (size_t i = 0, i_end = aRanges.Length(); i < i_end; i++) {
|
||||
const gfxTextRange& r = aRanges[i];
|
||||
fontMatches.AppendPrintf(" [%u:%u] %.200s (%s)", r.start, r.end,
|
||||
(r.font.get() ?
|
||||
NS_ConvertUTF16toUTF8(r.font->GetName()).get() : "<null>"),
|
||||
(r.matchType == gfxTextRange::kFontGroup ?
|
||||
"list" :
|
||||
(r.matchType == gfxTextRange::kPrefsFallback) ?
|
||||
"prefs" : "sys"));
|
||||
}
|
||||
MOZ_LOG(log, LogLevel::Debug,\
|
||||
("(%s-fontmatching) fontgroup: [%s] default: %s lang: %s script: %d"
|
||||
"%s\n",
|
||||
(mStyle.systemFont ? "textrunui" : "textrun"),
|
||||
NS_ConvertUTF16toUTF8(families).get(),
|
||||
(mFamilyList.GetDefaultFontType() == eFamily_serif ?
|
||||
"serif" :
|
||||
(mFamilyList.GetDefaultFontType() == eFamily_sans_serif ?
|
||||
"sans-serif" : "none")),
|
||||
lang.get(), aRunScript,
|
||||
fontMatches.get()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -3114,7 +3035,7 @@ struct PrefFontCallbackData {
|
||||
PrefFontCallbackData *prefFontData = static_cast<PrefFontCallbackData*>(aClosure);
|
||||
|
||||
// map pref lang to langGroup for language-sensitive lookups
|
||||
nsIAtom* lang = gfxPlatform::GetLangGroupForPrefLang(aLang);
|
||||
nsIAtom* lang = gfxPlatformFontList::GetLangGroupForPrefLang(aLang);
|
||||
gfxFontFamily *family =
|
||||
gfxPlatformFontList::PlatformFontList()->FindFamily(aName, lang);
|
||||
if (family) {
|
||||
@@ -3131,7 +3052,8 @@ gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh)
|
||||
|
||||
// get the pref font list if it hasn't been set up already
|
||||
uint32_t unicodeRange = FindCharUnicodeRange(aCh);
|
||||
eFontPrefLang charLang = gfxPlatform::GetPlatform()->GetFontPrefLangFor(unicodeRange);
|
||||
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
|
||||
eFontPrefLang charLang = pfl->GetFontPrefLangFor(unicodeRange);
|
||||
|
||||
// if the last pref font was the first family in the pref list, no need to recheck through a list of families
|
||||
if (mLastPrefFont && charLang == mLastPrefLang &&
|
||||
@@ -3144,29 +3066,22 @@ gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh)
|
||||
eFontPrefLang prefLangs[kMaxLenPrefLangList];
|
||||
uint32_t i, numLangs = 0;
|
||||
|
||||
gfxPlatform::GetPlatform()->GetLangPrefs(prefLangs, numLangs, charLang, mPageLang);
|
||||
pfl->GetLangPrefs(prefLangs, numLangs, charLang, mPageLang);
|
||||
|
||||
for (i = 0; i < numLangs; i++) {
|
||||
nsAutoTArray<nsRefPtr<gfxFontFamily>, 5> families;
|
||||
eFontPrefLang currentLang = prefLangs[i];
|
||||
|
||||
gfxPlatformFontList *fontList = gfxPlatformFontList::PlatformFontList();
|
||||
|
||||
// get the pref families for a single pref lang
|
||||
if (!fontList->GetPrefFontFamilyEntries(currentLang, &families)) {
|
||||
eFontPrefLang prefLangsToSearch[1] = { currentLang };
|
||||
PrefFontCallbackData prefFontData(families);
|
||||
gfxPlatform::ForEachPrefFont(prefLangsToSearch, 1, PrefFontCallbackData::AddFontFamilyEntry,
|
||||
&prefFontData);
|
||||
fontList->SetPrefFontFamilyEntries(currentLang, families);
|
||||
}
|
||||
mozilla::FontFamilyType defaultGeneric =
|
||||
pfl->GetDefaultGeneric(currentLang);
|
||||
nsTArray<nsRefPtr<gfxFontFamily>>* families =
|
||||
pfl->GetPrefFontsLangGroup(defaultGeneric, currentLang);
|
||||
NS_ASSERTION(families, "no pref font families found");
|
||||
|
||||
// find the first pref font that includes the character
|
||||
uint32_t j, numPrefs;
|
||||
numPrefs = families.Length();
|
||||
numPrefs = families->Length();
|
||||
for (j = 0; j < numPrefs; j++) {
|
||||
// look up the appropriate face
|
||||
gfxFontFamily *family = families[j];
|
||||
gfxFontFamily *family = (*families)[j];
|
||||
if (!family) continue;
|
||||
|
||||
// if a pref font is used, it's likely to be used again in the same text run.
|
||||
|
||||
+18
-29
@@ -10,6 +10,7 @@
|
||||
#include "nsString.h"
|
||||
#include "gfxPoint.h"
|
||||
#include "gfxFont.h"
|
||||
#include "gfxFontConstants.h"
|
||||
#include "nsTArray.h"
|
||||
#include "gfxSkipChars.h"
|
||||
#include "gfxPlatform.h"
|
||||
@@ -832,18 +833,6 @@ public:
|
||||
int32_t aRunScript, gfxFont *aPrevMatchedFont,
|
||||
uint8_t *aMatchType);
|
||||
|
||||
// search through pref fonts for a character, return nullptr if no matching pref font
|
||||
virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
|
||||
int32_t aRunScript);
|
||||
|
||||
template<typename T>
|
||||
void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
|
||||
const T *aString, uint32_t aLength,
|
||||
int32_t aRunScript, uint16_t aOrientation);
|
||||
|
||||
gfxUserFontSet* GetUserFontSet();
|
||||
|
||||
// With downloadable fonts, the composition of the font group can change as fonts are downloaded
|
||||
@@ -884,13 +873,19 @@ public:
|
||||
gfxTextRun* GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags,
|
||||
LazyReferenceContextGetter& aRefContextGetter);
|
||||
|
||||
// helper method for resolving generic font families
|
||||
static void
|
||||
ResolveGenericFontNames(mozilla::FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
nsTArray<nsString>& aGenericFamilies);
|
||||
|
||||
protected:
|
||||
// search through pref fonts for a character, return nullptr if no matching pref font
|
||||
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
|
||||
int32_t aRunScript);
|
||||
|
||||
template<typename T>
|
||||
void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
|
||||
const T *aString, uint32_t aLength,
|
||||
int32_t aRunScript, uint16_t aOrientation);
|
||||
|
||||
class FamilyFace {
|
||||
public:
|
||||
FamilyFace() : mFamily(nullptr), mFontEntry(nullptr),
|
||||
@@ -1117,18 +1112,12 @@ protected:
|
||||
|
||||
// helper methods for looking up fonts
|
||||
|
||||
// iterate over the fontlist, lookup names and expand generics
|
||||
void EnumerateFontList(nsIAtom *aLanguage, void *aClosure = nullptr);
|
||||
|
||||
// expand a generic to a list of specific names based on prefs
|
||||
void FindGenericFonts(mozilla::FontFamilyType aGenericType,
|
||||
nsIAtom *aLanguage,
|
||||
void *aClosure);
|
||||
|
||||
// lookup and add a font with a given name (i.e. *not* a generic!)
|
||||
virtual void FindPlatformFont(const nsAString& aName,
|
||||
bool aUseFontSet,
|
||||
void *aClosure);
|
||||
void AddPlatformFont(const nsAString& aName,
|
||||
nsTArray<gfxFontFamily*>& aFamilyList);
|
||||
|
||||
// do style selection and add entries to list
|
||||
void AddFamilyToFontList(gfxFontFamily* aFamily);
|
||||
|
||||
static nsILanguageAtomService* gLangService;
|
||||
};
|
||||
|
||||
@@ -140,7 +140,9 @@ public:
|
||||
nsRefPtr<gfxFontEntry> fe = aFontEntry;
|
||||
// remove existing entry, if already present
|
||||
mAvailableFonts.RemoveElement(aFontEntry);
|
||||
mAvailableFonts.AppendElement(aFontEntry);
|
||||
// insert at the beginning so that the last-defined font is the first
|
||||
// one in the fontlist used for matching, as per CSS Fonts spec
|
||||
mAvailableFonts.InsertElementAt(0, aFontEntry);
|
||||
|
||||
if (aFontEntry->mFamilyName.IsEmpty()) {
|
||||
aFontEntry->mFamilyName = Name();
|
||||
@@ -338,7 +340,9 @@ public:
|
||||
struct Key {
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal; // use nullptr with data: URLs
|
||||
gfxFontEntry* mFontEntry;
|
||||
// The font entry MUST notify the cache when it is destroyed
|
||||
// (by calling ForgetFont()).
|
||||
gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
|
||||
uint32_t mCRC32;
|
||||
uint32_t mLength;
|
||||
bool mPrivate;
|
||||
@@ -444,8 +448,8 @@ public:
|
||||
|
||||
// The "real" font entry corresponding to this downloaded font.
|
||||
// The font entry MUST notify the cache when it is destroyed
|
||||
// (by calling Forget()).
|
||||
gfxFontEntry* mFontEntry;
|
||||
// (by calling ForgetFont()).
|
||||
gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
|
||||
|
||||
// Whether this font was loaded from a private window.
|
||||
bool mPrivate;
|
||||
@@ -647,7 +651,9 @@ protected:
|
||||
nsRefPtr<gfxFontEntry> mPlatformFontEntry;
|
||||
nsTArray<gfxFontFaceSrc> mSrcList;
|
||||
uint32_t mSrcIndex; // index of loading src item
|
||||
nsFontFaceLoader* mLoader; // current loader for this entry, if any
|
||||
// This field is managed by the nsFontFaceLoader. In the destructor and Cancel()
|
||||
// methods of nsFontFaceLoader this reference is nulled out.
|
||||
nsFontFaceLoader* MOZ_NON_OWNING_REF mLoader; // current loader for this entry, if any
|
||||
gfxUserFontSet* mFontSet; // font-set to which the userfont entry belongs
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
};
|
||||
|
||||
+12
-6
@@ -421,6 +421,12 @@ CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable,
|
||||
PROFILER_LABEL("gfxUtils", "CreateSamplingRestricedDrawable",
|
||||
js::ProfileEntry::Category::GRAPHICS);
|
||||
|
||||
DrawTarget* destDrawTarget = aContext->GetDrawTarget();
|
||||
if ((destDrawTarget->GetBackendType() == BackendType::DIRECT2D1_1) ||
|
||||
(destDrawTarget->GetBackendType() == BackendType::DIRECT2D)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfxRect clipExtents = aContext->GetClipExtents();
|
||||
|
||||
// Inflate by one pixel because bilinear filtering will sample at most
|
||||
@@ -757,13 +763,13 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
|
||||
CreateSamplingRestrictedDrawable(aDrawable, aContext,
|
||||
aRegion, aFormat);
|
||||
if (restrictedDrawable) {
|
||||
drawable.swap(restrictedDrawable);
|
||||
}
|
||||
drawable.swap(restrictedDrawable);
|
||||
|
||||
// We no longer need to tile: Either we never needed to, or we already
|
||||
// filled a surface with the tiled pattern; this surface can now be
|
||||
// drawn without tiling.
|
||||
doTile = false;
|
||||
// We no longer need to tile: Either we never needed to, or we already
|
||||
// filled a surface with the tiled pattern; this surface can now be
|
||||
// drawn without tiling.
|
||||
doTile = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1047,6 +1047,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
|
||||
"word-cache-space: %d word-cache-long: %d "
|
||||
"pref-fallbacks: %d system-fallbacks: %d "
|
||||
"textruns-const: %d textruns-destr: %d "
|
||||
"generic-lookups: %d "
|
||||
"cumulative-textruns-destr: %d\n",
|
||||
prefix, aTextPerf->reflowCount, aCounts.numChars,
|
||||
(aURL ? aURL : ""),
|
||||
@@ -1056,6 +1057,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
|
||||
aCounts.wordCacheSpaceRules, aCounts.wordCacheLong,
|
||||
aCounts.fallbackPrefs, aCounts.fallbackSystem,
|
||||
aCounts.textrunConst, aCounts.textrunDestr,
|
||||
aCounts.genericLookups,
|
||||
aTextPerf->cumulative.textrunDestr));
|
||||
} else {
|
||||
MOZ_LOG(tpLog, logLevel,
|
||||
@@ -1066,6 +1068,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
|
||||
"word-cache-space: %d word-cache-long: %d "
|
||||
"pref-fallbacks: %d system-fallbacks: %d "
|
||||
"textruns-const: %d textruns-destr: %d "
|
||||
"generic-lookups: %d "
|
||||
"cumulative-textruns-destr: %d\n",
|
||||
prefix, aTextPerf->reflowCount, aCounts.numChars,
|
||||
aCounts.numContentTextRuns, aCounts.numChromeTextRuns,
|
||||
@@ -1074,6 +1077,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
|
||||
aCounts.wordCacheSpaceRules, aCounts.wordCacheLong,
|
||||
aCounts.fallbackPrefs, aCounts.fallbackSystem,
|
||||
aCounts.textrunConst, aCounts.textrunDestr,
|
||||
aCounts.genericLookups,
|
||||
aTextPerf->cumulative.textrunDestr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -958,7 +958,10 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
|
||||
int32_t intValue = aValue.GetIntValue();
|
||||
if (0 <= intValue) {
|
||||
LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue;
|
||||
if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID, &aResult))) {
|
||||
bool useStandinsForNativeColors = aPresContext &&
|
||||
!aPresContext->IsChrome();
|
||||
if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID,
|
||||
useStandinsForNativeColors, &aResult))) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4424,6 +4424,9 @@ pref("webgl.enable-privileged-extensions", false);
|
||||
pref("webgl.bypass-shader-validation", false);
|
||||
pref("webgl.enable-prototype-webgl2", false);
|
||||
pref("webgl.disable-fail-if-major-performance-caveat", false);
|
||||
pref("webgl.disable-debug-renderer-info", false);
|
||||
pref("webgl.renderer-string-override", "");
|
||||
pref("webgl.vendor-string-override", "");
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
// Keep this disabled on Release and Beta for now. (see bug 1171228)
|
||||
|
||||
@@ -533,6 +533,15 @@ public:
|
||||
*/
|
||||
static nsresult GetColor(ColorID aID, nscolor* aResult);
|
||||
|
||||
/**
|
||||
* This variant of GetColor() takes an extra Boolean parameter that allows
|
||||
* the caller to ask that hard-coded color values be substituted for
|
||||
* native colors (used when it is desireable to hide system colors to
|
||||
* avoid system fingerprinting).
|
||||
*/
|
||||
static nsresult GetColor(ColorID aID, bool aUseStandinsForNativeColors,
|
||||
nscolor* aResult);
|
||||
|
||||
/**
|
||||
* GetInt() and GetFloat() return a int or float value for aID. The result
|
||||
* might be distance, time, some flags or a int value which has particular
|
||||
|
||||
+176
-7
@@ -241,6 +241,7 @@ int32_t nsXPLookAndFeel::sCachedColorBits[COLOR_CACHE_SIZE] = {0};
|
||||
|
||||
bool nsXPLookAndFeel::sInitialized = false;
|
||||
bool nsXPLookAndFeel::sUseNativeColors = true;
|
||||
bool nsXPLookAndFeel::sUseStandinsForNativeColors = false;
|
||||
|
||||
nsLookAndFeel* nsXPLookAndFeel::sInstance = nullptr;
|
||||
bool nsXPLookAndFeel::sShutdown = false;
|
||||
@@ -452,10 +453,12 @@ nsXPLookAndFeel::Init()
|
||||
InitColorFromPref(i);
|
||||
}
|
||||
|
||||
bool val;
|
||||
if (NS_SUCCEEDED(Preferences::GetBool("ui.use_native_colors", &val))) {
|
||||
sUseNativeColors = val;
|
||||
}
|
||||
Preferences::AddBoolVarCache(&sUseNativeColors,
|
||||
"ui.use_native_colors",
|
||||
sUseNativeColors);
|
||||
Preferences::AddBoolVarCache(&sUseStandinsForNativeColors,
|
||||
"ui.use_standins_for_native_colors",
|
||||
sUseStandinsForNativeColors);
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
mozilla::dom::ContentChild* cc =
|
||||
@@ -504,6 +507,153 @@ nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor &aColor)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch (aID) {
|
||||
case eColorID_WindowBackground:
|
||||
case eColorID_WindowForeground:
|
||||
case eColorID_WidgetBackground:
|
||||
case eColorID_WidgetForeground:
|
||||
case eColorID_WidgetSelectBackground:
|
||||
case eColorID_WidgetSelectForeground:
|
||||
case eColorID_Widget3DHighlight:
|
||||
case eColorID_Widget3DShadow:
|
||||
case eColorID_TextBackground:
|
||||
case eColorID_TextForeground:
|
||||
case eColorID_TextSelectBackground:
|
||||
case eColorID_TextSelectForeground:
|
||||
case eColorID_TextSelectBackgroundDisabled:
|
||||
case eColorID_TextSelectBackgroundAttention:
|
||||
case eColorID_TextHighlightBackground:
|
||||
case eColorID_TextHighlightForeground:
|
||||
case eColorID_IMERawInputBackground:
|
||||
case eColorID_IMERawInputForeground:
|
||||
case eColorID_IMERawInputUnderline:
|
||||
case eColorID_IMESelectedRawTextBackground:
|
||||
case eColorID_IMESelectedRawTextForeground:
|
||||
case eColorID_IMESelectedRawTextUnderline:
|
||||
case eColorID_IMEConvertedTextBackground:
|
||||
case eColorID_IMEConvertedTextForeground:
|
||||
case eColorID_IMEConvertedTextUnderline:
|
||||
case eColorID_IMESelectedConvertedTextBackground:
|
||||
case eColorID_IMESelectedConvertedTextForeground:
|
||||
case eColorID_IMESelectedConvertedTextUnderline:
|
||||
case eColorID_SpellCheckerUnderline:
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nscolor
|
||||
nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID)
|
||||
{
|
||||
nscolor result = NS_RGB(0xFF, 0xFF, 0xFF);
|
||||
|
||||
// The stand-in colors are taken from the Windows 7 Aero theme
|
||||
// except Mac-specific colors which are taken from Mac OS 10.7.
|
||||
switch (aID) {
|
||||
// CSS 2 colors:
|
||||
case eColorID_activeborder: result = NS_RGB(0xB4, 0xB4, 0xB4); break;
|
||||
case eColorID_activecaption: result = NS_RGB(0x99, 0xB4, 0xD1); break;
|
||||
case eColorID_appworkspace: result = NS_RGB(0xAB, 0xAB, 0xAB); break;
|
||||
case eColorID_background: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID_buttonface: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
|
||||
case eColorID_buttonhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID_buttonshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break;
|
||||
case eColorID_buttontext: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID_captiontext: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID_graytext: result = NS_RGB(0x6D, 0x6D, 0x6D); break;
|
||||
case eColorID_highlight: result = NS_RGB(0x33, 0x99, 0xFF); break;
|
||||
case eColorID_highlighttext: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID_inactiveborder: result = NS_RGB(0xF4, 0xF7, 0xFC); break;
|
||||
case eColorID_inactivecaption: result = NS_RGB(0xBF, 0xCD, 0xDB); break;
|
||||
case eColorID_inactivecaptiontext:
|
||||
result = NS_RGB(0x43, 0x4E, 0x54); break;
|
||||
case eColorID_infobackground: result = NS_RGB(0xFF, 0xFF, 0xE1); break;
|
||||
case eColorID_infotext: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID_menu: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
|
||||
case eColorID_menutext: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID_scrollbar: result = NS_RGB(0xC8, 0xC8, 0xC8); break;
|
||||
case eColorID_threeddarkshadow: result = NS_RGB(0x69, 0x69, 0x69); break;
|
||||
case eColorID_threedface: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
|
||||
case eColorID_threedhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID_threedlightshadow: result = NS_RGB(0xE3, 0xE3, 0xE3); break;
|
||||
case eColorID_threedshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break;
|
||||
case eColorID_window: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID_windowframe: result = NS_RGB(0x64, 0x64, 0x64); break;
|
||||
case eColorID_windowtext: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_buttondefault:
|
||||
result = NS_RGB(0x69, 0x69, 0x69); break;
|
||||
case eColorID__moz_field: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID__moz_fieldtext: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_dialog: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
|
||||
case eColorID__moz_dialogtext: result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_dragtargetzone:
|
||||
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID__moz_cellhighlight:
|
||||
result = NS_RGB(0xF0, 0xF0, 0xF0); break;
|
||||
case eColorID__moz_cellhighlighttext:
|
||||
result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_html_cellhighlight:
|
||||
result = NS_RGB(0x33, 0x99, 0xFF); break;
|
||||
case eColorID__moz_html_cellhighlighttext:
|
||||
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID__moz_buttonhoverface:
|
||||
result = NS_RGB(0xF0, 0xF0, 0xF0); break;
|
||||
case eColorID__moz_buttonhovertext:
|
||||
result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_menuhover:
|
||||
result = NS_RGB(0x33, 0x99, 0xFF); break;
|
||||
case eColorID__moz_menuhovertext:
|
||||
result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_menubartext:
|
||||
result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_menubarhovertext:
|
||||
result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_oddtreerow:
|
||||
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID__moz_mac_chrome_active:
|
||||
result = NS_RGB(0xB2, 0xB2, 0xB2); break;
|
||||
case eColorID__moz_mac_chrome_inactive:
|
||||
result = NS_RGB(0xE1, 0xE1, 0xE1); break;
|
||||
case eColorID__moz_mac_focusring:
|
||||
result = NS_RGB(0x60, 0x9D, 0xD7); break;
|
||||
case eColorID__moz_mac_menuselect:
|
||||
result = NS_RGB(0x38, 0x75, 0xD7); break;
|
||||
case eColorID__moz_mac_menushadow:
|
||||
result = NS_RGB(0xA3, 0xA3, 0xA3); break;
|
||||
case eColorID__moz_mac_menutextdisable:
|
||||
result = NS_RGB(0x88, 0x88, 0x88); break;
|
||||
case eColorID__moz_mac_menutextselect:
|
||||
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID__moz_mac_disabledtoolbartext:
|
||||
result = NS_RGB(0x3F, 0x3F, 0x3F); break;
|
||||
case eColorID__moz_mac_secondaryhighlight:
|
||||
result = NS_RGB(0xD4, 0xD4, 0xD4); break;
|
||||
case eColorID__moz_win_mediatext:
|
||||
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID__moz_win_communicationstext:
|
||||
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
case eColorID__moz_nativehyperlinktext:
|
||||
result = NS_RGB(0x00, 0x66, 0xCC); break;
|
||||
case eColorID__moz_comboboxtext:
|
||||
result = NS_RGB(0x00, 0x00, 0x00); break;
|
||||
case eColorID__moz_combobox:
|
||||
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// All these routines will return NS_OK if they have a value,
|
||||
// in which case the nsLookAndFeel should use that value;
|
||||
@@ -511,7 +661,8 @@ nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor &aColor)
|
||||
// platform-specific nsLookAndFeel should use its own values instead.
|
||||
//
|
||||
nsresult
|
||||
nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult)
|
||||
nsXPLookAndFeel::GetColorImpl(ColorID aID, bool aUseStandinsForNativeColors,
|
||||
nscolor &aResult)
|
||||
{
|
||||
if (!sInitialized)
|
||||
Init();
|
||||
@@ -597,7 +748,12 @@ nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult)
|
||||
}
|
||||
#endif // DEBUG_SYSTEM_COLOR_USE
|
||||
|
||||
if (IS_COLOR_CACHED(aID)) {
|
||||
if (aUseStandinsForNativeColors &&
|
||||
(ColorIsNotCSSAccessible(aID) || !sUseStandinsForNativeColors)) {
|
||||
aUseStandinsForNativeColors = false;
|
||||
}
|
||||
|
||||
if (!aUseStandinsForNativeColors && IS_COLOR_CACHED(aID)) {
|
||||
aResult = sCachedColors[aID];
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -631,6 +787,11 @@ nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (sUseNativeColors && aUseStandinsForNativeColors) {
|
||||
aResult = GetStandinForNativeColor(aID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (sUseNativeColors && NS_SUCCEEDED(NativeGetColor(aID, aResult))) {
|
||||
if ((gfxPlatform::GetCMSMode() == eCMSMode_All) &&
|
||||
!IsSpecialColor(aID, aResult)) {
|
||||
@@ -727,7 +888,15 @@ namespace mozilla {
|
||||
nsresult
|
||||
LookAndFeel::GetColor(ColorID aID, nscolor* aResult)
|
||||
{
|
||||
return nsLookAndFeel::GetInstance()->GetColorImpl(aID, *aResult);
|
||||
return nsLookAndFeel::GetInstance()->GetColorImpl(aID, false, *aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors,
|
||||
nscolor* aResult)
|
||||
{
|
||||
return nsLookAndFeel::GetInstance()->GetColorImpl(aID,
|
||||
aUseStandinsForNativeColors, *aResult);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -53,7 +53,8 @@ public:
|
||||
// otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
|
||||
// platform-specific nsLookAndFeel should use its own values instead.
|
||||
//
|
||||
nsresult GetColorImpl(ColorID aID, nscolor &aResult);
|
||||
nsresult GetColorImpl(ColorID aID, bool aUseStandinsForNativeColors,
|
||||
nscolor &aResult);
|
||||
virtual nsresult GetIntImpl(IntID aID, int32_t &aResult);
|
||||
virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
|
||||
|
||||
@@ -94,6 +95,8 @@ protected:
|
||||
void InitColorFromPref(int32_t aIndex);
|
||||
virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult) = 0;
|
||||
bool IsSpecialColor(ColorID aID, nscolor &aColor);
|
||||
bool ColorIsNotCSSAccessible(ColorID aID);
|
||||
nscolor GetStandinForNativeColor(ColorID aID);
|
||||
|
||||
static void OnPrefChanged(const char* aPref, void* aClosure);
|
||||
|
||||
@@ -107,6 +110,7 @@ protected:
|
||||
static int32_t sCachedColors[LookAndFeel::eColorID_LAST_COLOR];
|
||||
static int32_t sCachedColorBits[COLOR_CACHE_SIZE];
|
||||
static bool sUseNativeColors;
|
||||
static bool sUseStandinsForNativeColors;
|
||||
|
||||
static nsLookAndFeel* sInstance;
|
||||
static bool sShutdown;
|
||||
|
||||
Reference in New Issue
Block a user