Merge inbound to m-c.

This commit is contained in:
Ryan VanderMeulen 2014-01-02 15:50:28 -05:00
commit 0512939292
67 changed files with 1219 additions and 1331 deletions

View File

@ -84,7 +84,6 @@
<menuitem value="x-cans" label="&font.langGroup.canadian;"/>
<menuitem value="x-western" label="&font.langGroup.latin1;"/>
<menuitem value="x-unicode" label="&font.langGroup.unicode;"/>
<menuitem value="x-user-def" label="&font.langGroup.user-def;"/>
</menupopup>
</menulist>
</caption>

View File

@ -13,6 +13,6 @@
<!ENTITY charsetMenuAutodet.ja.accesskey "J">
<!ENTITY charsetMenuAutodet.ru.label "Russian">
<!ENTITY charsetMenuAutodet.ru.accesskey "R">
<!ENTITY charsetMenuAutodet.uk.label "Ukranian">
<!ENTITY charsetMenuAutodet.uk.label "Ukrainian">
<!ENTITY charsetMenuAutodet.uk.accesskey "U">

View File

@ -36,7 +36,6 @@
<!ENTITY font.langGroup.el "Greek">
<!ENTITY font.langGroup.turkish "Turkish">
<!ENTITY font.langGroup.unicode "Other Languages">
<!ENTITY font.langGroup.user-def "User Defined">
<!ENTITY font.langGroup.thai "Thai">
<!ENTITY font.langGroup.hebrew "Hebrew">
<!ENTITY font.langGroup.arabic "Arabic">

View File

@ -1996,9 +1996,6 @@ GK_ATOM(ko_xxx, "ko-xxx")
GK_ATOM(x_central_euro, "x-central-euro")
GK_ATOM(x_symbol, "x-symbol")
// referenced in all.js
GK_ATOM(x_user_def, "x-user-def")
// additional languages that have special case transformations
GK_ATOM(az, "az")
GK_ATOM(ba, "ba")

View File

@ -39,6 +39,7 @@
#include "GLContextProvider.h"
#include "GLContext.h"
#include "ScopedGLHelpers.h"
#include "GLReadTexImageHelper.h"
#include "gfxCrashReporterUtils.h"
@ -623,7 +624,7 @@ WebGLContext::Render(gfxContext *ctx, GraphicsFilter f, uint32_t aFlags)
return NS_ERROR_FAILURE;
gl->MakeCurrent();
gl->ReadScreenIntoImageSurface(surf);
ReadScreenIntoImageSurface(gl, surf);
bool srcPremultAlpha = mOptions.premultipliedAlpha;
bool dstPremultAlpha = aFlags & RenderFlagPremultAlpha;

View File

@ -9,7 +9,7 @@
#include "Latency.h"
#include "nsThreadUtils.h"
#include <prlog.h>
#include "prlog.h"
#include <cmath>
#include <algorithm>

View File

@ -8,7 +8,7 @@
#define MOZILLA_LATENCY_H
#include "mozilla/TimeStamp.h"
#include "nspr/prlog.h"
#include "prlog.h"
#include "nsCOMPtr.h"
#include "nsIThread.h"
#include "mozilla/Monitor.h"

View File

@ -14,6 +14,7 @@ EncMetaUnsupported=An unsupported character encoding was declared for the HTML d
EncProtocolUnsupported=An unsupported character encoding was declared on the transfer protocol level. The declaration was ignored.
EncBomlessUtf16=Detected UTF-16-encoded Basic Latin-only text without a byte order mark and without a transfer protocol-level declaration. Encoding this content in UTF-16 is inefficient and the character encoding should have been declared in any case.
EncMetaUtf16=A meta tag was used to declare the character encoding as UTF-16. This was interpreted as an UTF-8 declaration instead.
EncMetaUserDefined=A meta tag was used to declare the character encoding as x-user-defined. This was interpreted as a windows-1252 declaration instead for compatibility with intentionally mis-encoded legacy fonts. This site should migrate to Unicode.
# The bulk of the messages below are derived from
# http://hg.mozilla.org/projects/htmlparser/file/1f633cef7de7/src/nu/validator/htmlparser/impl/ErrorReportingTokenizer.java

View File

@ -12,6 +12,7 @@
#include "GLContext.h"
#include "GLBlitHelper.h"
#include "GLBlitTextureImageHelper.h"
#include "GLReadTexImageHelper.h"
#include "gfxCrashReporterUtils.h"
#include "gfxPlatform.h"
@ -253,7 +254,6 @@ GLContext::GLContext(const SurfaceCaps& caps,
bool isOffscreen)
: mInitialized(false),
mIsOffscreen(isOffscreen),
mIsGlobalSharedContext(false),
mContextLost(false),
mVersion(0),
mProfile(ContextProfile::Unknown),
@ -276,11 +276,6 @@ GLContext::GLContext(const SurfaceCaps& caps,
mWorkAroundDriverBugs(true)
{
mOwningThread = NS_GetCurrentThread();
mReadTextureImagePrograms[0] = 0;
mReadTextureImagePrograms[1] = 0;
mReadTextureImagePrograms[2] = 0;
mReadTextureImagePrograms[3] = 0;
}
GLContext::~GLContext() {
@ -1606,11 +1601,7 @@ GLContext::MarkDestroyed()
mBlitHelper = nullptr;
mBlitTextureImageHelper = nullptr;
fDeleteProgram(mReadTextureImagePrograms[0]);
fDeleteProgram(mReadTextureImagePrograms[1]);
fDeleteProgram(mReadTextureImagePrograms[2]);
fDeleteProgram(mReadTextureImagePrograms[3]);
mReadTexImageHelper = nullptr;
mTexGarbageBin->GLContextTeardown();
} else {
@ -1620,660 +1611,6 @@ GLContext::MarkDestroyed()
mSymbols.Zero();
}
static void SwapRAndBComponents(gfxImageSurface* surf)
{
uint8_t *row = surf->Data();
size_t rowBytes = surf->Width()*4;
size_t rowHole = surf->Stride() - rowBytes;
size_t rows = surf->Height();
while (rows) {
const uint8_t *rowEnd = row + rowBytes;
while (row != rowEnd) {
row[0] ^= row[2];
row[2] ^= row[0];
row[0] ^= row[2];
row += 4;
}
row += rowHole;
--rows;
}
}
static already_AddRefed<gfxImageSurface> YInvertImageSurface(gfxImageSurface* aSurf)
{
gfxIntSize size = aSurf->GetSize();
nsRefPtr<gfxImageSurface> temp = new gfxImageSurface(size, aSurf->Format());
nsRefPtr<gfxContext> ctx = new gfxContext(temp);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Scale(1.0, -1.0);
ctx->Translate(-gfxPoint(0.0, size.height));
ctx->SetSource(aSurf);
ctx->Paint();
return temp.forget();
}
already_AddRefed<gfxImageSurface>
GLContext::GetTexImage(GLuint aTexture, bool aYInvert, SurfaceFormat aFormat)
{
MakeCurrent();
GuaranteeResolve();
fActiveTexture(LOCAL_GL_TEXTURE0);
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
gfxIntSize size;
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(size, gfxImageFormatARGB32);
if (!surf || surf->CairoStatus()) {
return nullptr;
}
uint32_t currentPackAlignment = 0;
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
if (currentPackAlignment != 4) {
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
}
fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->Data());
if (currentPackAlignment != 4) {
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
}
if (aFormat == FORMAT_R8G8B8A8 || aFormat == FORMAT_R8G8B8X8) {
SwapRAndBComponents(surf);
}
if (aYInvert) {
surf = YInvertImageSurface(surf);
}
return surf.forget();
}
static float
gReadTextureImageVerts[4*4] = {
-1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f
};
static float*
ReadTextureVertexArray()
{
return gReadTextureImageVerts;
}
static float
gReadTextureImageTexcoords[2*4] = {
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
};
static float*
ReadTextureTexCoordArray(float aWidth, float aHeight, bool aFlip)
{
const float u0 = 0.0f;
const float u1 = aWidth;
const float v0 = (aFlip) ? aHeight : 0.0f;
const float v1 = (aFlip) ? 0.0f : aHeight;
float* uvs = gReadTextureImageTexcoords;
uvs[0] = u0;
uvs[1] = v0;
uvs[2] = u1;
uvs[3] = v0;
uvs[4] = u0;
uvs[5] = v1;
uvs[6] = u1;
uvs[7] = v1;
return uvs;
}
static const char*
gReadTextureImageVS =
"attribute vec4 aVertex;\n"
"attribute vec2 aTexCoord;\n"
"varying vec2 vTexCoord;\n"
"void main() { gl_Position = aVertex; vTexCoord = aTexCoord; }";
static const char*
gReadTextureImageFS[] = {
/* TEXTURE_2D */
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform sampler2D uTexture;\n"
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }"
,
/* TEXTURE_2D with R/B swizzling */
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform sampler2D uTexture;\n"
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord).bgra; }"
,
/* TEXTURE_EXTERNAL */
"#extension GL_OES_EGL_image_external : require\n"
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform samplerExternalOES uTexture;\n"
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }"
,
/* TEXTURE_RECTANGLE */
"#extension GL_ARB_texture_rectangle\n"
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform sampler2DRect uTexture;\n"
"void main() { gl_FragColor = texture2DRect(uTexture, vTexCoord).bgra; }"
};
GLuint
GLContext::TextureImageProgramFor(GLenum aTextureTarget, int aShader) {
int variant = 0;
if (aTextureTarget == LOCAL_GL_TEXTURE_2D &&
(aShader == layers::BGRALayerProgramType ||
aShader == layers::BGRXLayerProgramType))
{ // Need to swizzle R/B.
variant = 1;
} else if (aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
variant = 2;
} else if (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
variant = 3;
}
/* This might be overkill, but assure that we don't access out-of-bounds */
MOZ_ASSERT((size_t) variant < ArrayLength(mReadTextureImagePrograms));
if (!mReadTextureImagePrograms[variant]) {
GLuint vs = fCreateShader(LOCAL_GL_VERTEX_SHADER);
fShaderSource(vs, 1, (const GLchar**) &gReadTextureImageVS, NULL);
fCompileShader(vs);
GLuint fs = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
fShaderSource(fs, 1, (const GLchar**) &gReadTextureImageFS[variant], NULL);
fCompileShader(fs);
GLuint program = fCreateProgram();
fAttachShader(program, vs);
fAttachShader(program, fs);
fBindAttribLocation(program, 0, "aVertex");
fBindAttribLocation(program, 1, "aTexCoord");
fLinkProgram(program);
GLint success;
fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &success);
if (!success) {
fDeleteProgram(program);
program = 0;
}
fDeleteShader(vs);
fDeleteShader(fs);
mReadTextureImagePrograms[variant] = program;
}
return mReadTextureImagePrograms[variant];
}
static bool
DidGLErrorOccur(GLContext* aGL, const char* str)
{
GLenum error = aGL->fGetError();
if (error != LOCAL_GL_NO_ERROR) {
printf_stderr("GL ERROR: %s (0x%04x) %s\n",
aGL->GLErrorToString(error), error, str);
return true;
}
return false;
}
bool
GLContext::ReadBackPixelsIntoSurface(gfxImageSurface* aSurface, const gfxIntSize& aSize) {
GLint oldPackAlignment;
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &oldPackAlignment);
if (oldPackAlignment != 4)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
fReadPixels(0, 0, aSize.width, aSize.height,
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
aSurface->Data());
bool result = DidGLErrorOccur(this, "when reading pixels into surface");
if (oldPackAlignment != 4)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, oldPackAlignment);
return result;
}
#define CLEANUP_IF_GLERROR_OCCURRED(x) \
if (DidGLErrorOccur(this, (x))) { \
isurf = nullptr; \
break; \
}
already_AddRefed<gfxImageSurface>
GLContext::ReadTextureImage(GLuint aTextureId,
GLenum aTextureTarget,
const gfxIntSize& aSize,
/* ShaderProgramType */ int aShaderProgram,
bool aYInvert)
{
// Check aShaderProgram is in bounds for a layers::ShaderProgramType
MOZ_ASSERT(0 <= aShaderProgram && aShaderProgram < NumProgramTypes);
if (aTextureTarget != LOCAL_GL_TEXTURE_2D &&
aTextureTarget != LOCAL_GL_TEXTURE_EXTERNAL &&
aTextureTarget != LOCAL_GL_TEXTURE_RECTANGLE_ARB)
{
printf_stderr("ReadTextureImage target is not TEXTURE_2D || "
"TEXTURE_EXTERNAL || TEXTURE_RECTANGLE\n");
return nullptr;
}
MakeCurrent();
/* Allocate resulting image surface */
nsRefPtr<gfxImageSurface> isurf;
isurf = new gfxImageSurface(aSize, gfxImageFormatARGB32);
if (!isurf || isurf->CairoStatus()) {
isurf = nullptr;
return isurf.forget();
}
realGLboolean oldBlend, oldScissor;
GLint oldrb, oldfb, oldprog, oldTexUnit, oldTex;
GLuint rb, fb;
do {
/* Save current GL state */
oldBlend = fIsEnabled(LOCAL_GL_BLEND);
oldScissor = fIsEnabled(LOCAL_GL_SCISSOR_TEST);
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
fGetIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &oldTexUnit);
fActiveTexture(LOCAL_GL_TEXTURE0);
switch (aTextureTarget) {
case LOCAL_GL_TEXTURE_2D:
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex);
break;
case LOCAL_GL_TEXTURE_EXTERNAL:
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldTex);
break;
case LOCAL_GL_TEXTURE_RECTANGLE:
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &oldTex);
break;
default: /* Already checked above */
break;
}
/* Set required GL state */
fDisable(LOCAL_GL_BLEND);
fDisable(LOCAL_GL_SCISSOR_TEST);
PushViewportRect(nsIntRect(0, 0, aSize.width, aSize.height));
/* Setup renderbuffer */
fGenRenderbuffers(1, &rb);
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
GLenum rbInternalFormat =
IsGLES2()
? (IsExtensionSupported(OES_rgb8_rgba8) ? LOCAL_GL_RGBA8 : LOCAL_GL_RGBA4)
: LOCAL_GL_RGBA;
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, rbInternalFormat, aSize.width, aSize.height);
CLEANUP_IF_GLERROR_OCCURRED("when binding and creating renderbuffer");
/* Setup framebuffer */
fGenFramebuffers(1, &fb);
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
LOCAL_GL_RENDERBUFFER, rb);
CLEANUP_IF_GLERROR_OCCURRED("when binding and creating framebuffer");
if (fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
printf_stderr("framebuffer is incomplete\n");
break; //goto cleanup;
}
/* Setup vertex and fragment shader */
layers::ShaderProgramType shaderProgram = (ShaderProgramType) aShaderProgram;
GLuint program = TextureImageProgramFor(aTextureTarget, shaderProgram);
if (!program) {
printf_stderr("failed to compile program for texture target %u and"
" shader program type %d\n",
aTextureTarget, aShaderProgram);
break; // goto cleanup;
}
fUseProgram(program);
CLEANUP_IF_GLERROR_OCCURRED("when using program");
fUniform1i(fGetUniformLocation(program, "uTexture"), 0);
CLEANUP_IF_GLERROR_OCCURRED("when setting uniform location");
/* Setup quad geometry */
fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
fEnableVertexAttribArray(0);
fEnableVertexAttribArray(1);
float w = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) ? (float) aSize.width : 1.0f;
float h = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) ? (float) aSize.height : 1.0f;
fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, ReadTextureVertexArray());
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, ReadTextureTexCoordArray(w, h, aYInvert));
/* Bind the texture */
if (aTextureId) {
fBindTexture(aTextureTarget, aTextureId);
CLEANUP_IF_GLERROR_OCCURRED("when binding texture");
}
/* Draw quad */
fClearColor(1.0f, 0.0f, 1.0f, 1.0f);
fClear(LOCAL_GL_COLOR_BUFFER_BIT);
CLEANUP_IF_GLERROR_OCCURRED("when clearing color buffer");
fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
CLEANUP_IF_GLERROR_OCCURRED("when drawing texture");
fDisableVertexAttribArray(1);
fDisableVertexAttribArray(0);
/* Read-back draw results */
ReadBackPixelsIntoSurface(isurf, aSize);
CLEANUP_IF_GLERROR_OCCURRED("when reading pixels into surface");
} while (false);
/* Restore GL state */
//cleanup:
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
fUseProgram(oldprog);
// note that deleting 0 has no effect in any of these calls
fDeleteRenderbuffers(1, &rb);
fDeleteFramebuffers(1, &fb);
if (oldBlend)
fEnable(LOCAL_GL_BLEND);
if (oldScissor)
fEnable(LOCAL_GL_SCISSOR_TEST);
if (aTextureId)
fBindTexture(aTextureTarget, oldTex);
if (oldTexUnit != LOCAL_GL_TEXTURE0)
fActiveTexture(oldTexUnit);
PopViewportRect();
return isurf.forget();
}
#undef CLEANUP_IF_GLERROR_OCCURRED
static bool
GetActualReadFormats(GLContext* gl, GLenum destFormat, GLenum destType,
GLenum& readFormat, GLenum& readType)
{
if (destFormat == LOCAL_GL_RGBA &&
destType == LOCAL_GL_UNSIGNED_BYTE)
{
readFormat = destFormat;
readType = destType;
return true;
}
bool fallback = true;
if (gl->IsGLES2()) {
GLenum auxFormat = 0;
GLenum auxType = 0;
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, (GLint*)&auxFormat);
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, (GLint*)&auxType);
if (destFormat == auxFormat &&
destType == auxType)
{
fallback = false;
}
} else {
switch (destFormat) {
case LOCAL_GL_RGB: {
if (destType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV)
fallback = false;
break;
}
case LOCAL_GL_BGRA: {
if (destType == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV)
fallback = false;
break;
}
}
}
if (fallback) {
readFormat = LOCAL_GL_RGBA;
readType = LOCAL_GL_UNSIGNED_BYTE;
return false;
} else {
readFormat = destFormat;
readType = destType;
return true;
}
}
void
GLContext::ReadScreenIntoImageSurface(gfxImageSurface* dest)
{
ScopedBindFramebuffer autoFB(this, 0);
ReadPixelsIntoImageSurface(dest);
}
TemporaryRef<SourceSurface>
GLContext::ReadPixelsToSourceSurface(const gfx::IntSize &aSize)
{
// XXX we should do this properly one day without using the gfxImageSurface
RefPtr<DataSourceSurface> dataSourceSurface =
Factory::CreateDataSourceSurface(aSize, gfx::FORMAT_B8G8R8A8);
nsRefPtr<gfxImageSurface> surf =
new gfxImageSurface(dataSourceSurface->GetData(),
gfxIntSize(aSize.width, aSize.height),
dataSourceSurface->Stride(),
gfxImageFormatARGB32);
ReadPixelsIntoImageSurface(surf);
dataSourceSurface->MarkDirty();
return dataSourceSurface;
}
void
GLContext::ReadPixelsIntoImageSurface(gfxImageSurface* dest)
{
MakeCurrent();
MOZ_ASSERT(dest->GetSize() != gfxIntSize(0, 0));
/* gfxImageFormatARGB32:
* RGBA+UByte: be[RGBA], le[ABGR]
* RGBA+UInt: le[RGBA]
* BGRA+UInt: le[BGRA]
* BGRA+UIntRev: le[ARGB]
*
* gfxImageFormatRGB16_565:
* RGB+UShort: le[rrrrrggg,gggbbbbb]
*/
bool hasAlpha = dest->Format() == gfxImageFormatARGB32;
int destPixelSize;
GLenum destFormat;
GLenum destType;
switch (dest->Format()) {
case gfxImageFormatRGB24: // XRGB
case gfxImageFormatARGB32:
destPixelSize = 4;
// Needs host (little) endian ARGB.
destFormat = LOCAL_GL_BGRA;
destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
break;
case gfxImageFormatRGB16_565:
destPixelSize = 2;
destFormat = LOCAL_GL_RGB;
destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
break;
default:
MOZ_CRASH("Bad format.");
}
MOZ_ASSERT(dest->Stride() == dest->Width() * destPixelSize);
GLenum readFormat = destFormat;
GLenum readType = destType;
bool needsTempSurf = !GetActualReadFormats(this,
destFormat, destType,
readFormat, readType);
nsAutoPtr<gfxImageSurface> tempSurf;
gfxImageSurface* readSurf = nullptr;
int readPixelSize = 0;
if (needsTempSurf) {
if (DebugMode()) {
NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
}
SurfaceFormat readFormatGFX;
switch (readFormat) {
case LOCAL_GL_RGBA:
case LOCAL_GL_BGRA: {
readFormatGFX = hasAlpha ? FORMAT_B8G8R8A8
: FORMAT_B8G8R8X8;
break;
}
case LOCAL_GL_RGB: {
MOZ_ASSERT(readPixelSize == 2);
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
readFormatGFX = FORMAT_R5G6B5;
break;
}
default: {
MOZ_CRASH("Bad read format.");
}
}
switch (readType) {
case LOCAL_GL_UNSIGNED_BYTE: {
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
readPixelSize = 4;
break;
}
case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: {
MOZ_ASSERT(readFormat == LOCAL_GL_BGRA);
readPixelSize = 4;
break;
}
case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: {
MOZ_ASSERT(readFormat == LOCAL_GL_RGB);
readPixelSize = 2;
break;
}
default: {
MOZ_CRASH("Bad read type.");
}
}
tempSurf = new gfxImageSurface(dest->GetSize(),
SurfaceFormatToImageFormat(readFormatGFX),
false);
readSurf = tempSurf;
} else {
readPixelSize = destPixelSize;
readSurf = dest;
}
MOZ_ASSERT(readPixelSize);
GLint currentPackAlignment = 0;
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &currentPackAlignment);
if (currentPackAlignment != readPixelSize)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readPixelSize);
GLsizei width = dest->Width();
GLsizei height = dest->Height();
readSurf->Flush();
fReadPixels(0, 0,
width, height,
readFormat, readType,
readSurf->Data());
readSurf->MarkDirty();
if (currentPackAlignment != readPixelSize)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
if (readSurf != dest) {
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
// So we just copied in RGBA in big endian, or le: 0xAABBGGRR.
// We want 0xAARRGGBB, so swap R and B:
dest->Flush();
SwapRAndBComponents(readSurf);
dest->MarkDirty();
gfxContext ctx(dest);
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
ctx.SetSource(readSurf);
ctx.Paint();
}
// Check if GL is giving back 1.0 alpha for
// RGBA reads to RGBA images from no-alpha buffers.
#ifdef XP_MACOSX
if (WorkAroundDriverBugs() &&
mVendor == VendorNVIDIA &&
dest->Format() == gfxImageFormatARGB32 &&
width && height)
{
GLint alphaBits = 0;
fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
if (!alphaBits) {
const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0);
dest->Flush();
uint32_t* itr = (uint32_t*)dest->Data();
uint32_t testPixel = *itr;
if ((testPixel & alphaMask) != alphaMask) {
// We need to set the alpha channel to 1.0 manually.
uint32_t* itrEnd = itr + width*height; // Stride is guaranteed to be width*4.
for (; itr != itrEnd; itr++) {
*itr |= alphaMask;
}
}
dest->MarkDirty();
}
}
#endif
}
#ifdef MOZ_ENABLE_GL_TRACKING
void
GLContext::CreatedProgram(GLContext *aOrigin, GLuint aName)
@ -2580,6 +1917,16 @@ GLContext::BlitTextureImageHelper()
return mBlitTextureImageHelper;
}
GLReadTexImageHelper*
GLContext::ReadTexImageHelper()
{
if (!mReadTexImageHelper) {
mReadTexImageHelper = new GLReadTexImageHelper(this);
}
return mReadTexImageHelper;
}
bool
DoesStringMatch(const char* aString, const char *aWantedString)
{

View File

@ -70,6 +70,7 @@ namespace mozilla {
class TextureGarbageBin;
class GLBlitHelper;
class GLBlitTextureImageHelper;
class GLReadTexImageHelper;
}
namespace layers {
@ -2435,9 +2436,6 @@ public:
virtual void *GetNativeData(NativeDataType aType) { return nullptr; }
GLContext *GetSharedContext() { return mSharedContext; }
bool IsGlobalSharedContext() { return mIsGlobalSharedContext; }
void SetIsGlobalSharedContext(bool aIsOne) { mIsGlobalSharedContext = aIsOne; }
/**
* Returns true if the thread on which this context was created is the currently
* executing thread.
@ -2445,24 +2443,6 @@ public:
bool IsOwningThreadCurrent();
void DispatchToOwningThread(nsIRunnable *event);
virtual EGLContext GetEGLContext() { return nullptr; }
virtual GLLibraryEGL* GetLibraryEGL() { return nullptr; }
/**
* Only on EGL.
*
* If surf is non-null, this sets it to temporarily override this context's
* primary surface. This makes this context current against this surface,
* and subsequent MakeCurrent calls will continue using this surface as long
* as this override is set.
*
* If surf is null, this removes any previously set override, and makes the
* context current again against its primary surface.
*/
virtual void SetEGLSurfaceOverride(EGLSurface surf) {
MOZ_CRASH("Must be called against a GLContextEGL.");
}
static void PlatformStartup();
public:
@ -2584,54 +2564,6 @@ public:
virtual bool RenewSurface() { return false; }
private:
/**
* Helpers for ReadTextureImage
*/
GLuint TextureImageProgramFor(GLenum aTextureTarget, int aShader);
bool ReadBackPixelsIntoSurface(gfxImageSurface* aSurface, const gfxIntSize& aSize);
public:
/**
* Read the image data contained in aTexture, and return it as an ImageSurface.
* If GL_RGBA is given as the format, a gfxImageFormatARGB32 surface is returned.
* Not implemented yet:
* If GL_RGB is given as the format, a gfxImageFormatRGB24 surface is returned.
* If GL_LUMINANCE is given as the format, a gfxImageFormatA8 surface is returned.
*
* THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
* if you absolutely positively must, and never in any performance
* critical path.
*
* NOTE: aShaderProgram is really mozilla::layers::ShaderProgramType. It is
* passed as int to eliminate including LayerManagerOGLProgram.h in this
* hub header.
*/
already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTextureId,
GLenum aTextureTarget,
const gfxIntSize& aSize,
/* ShaderProgramType */ int aShaderProgram,
bool aYInvert = false);
already_AddRefed<gfxImageSurface> GetTexImage(GLuint aTexture,
bool aYInvert,
SurfaceFormat aFormat);
/**
* Call ReadPixels into an existing gfxImageSurface.
* The image surface must be using image format RGBA32 or RGB24,
* and must have stride == width*4.
* Note that neither ReadPixelsIntoImageSurface nor
* ReadScreenIntoImageSurface call dest->Flush/MarkDirty.
*/
void ReadPixelsIntoImageSurface(gfxImageSurface* dest);
// Similar to ReadPixelsIntoImageSurface, but pulls from the screen
// instead of the currently bound framebuffer.
void ReadScreenIntoImageSurface(gfxImageSurface* dest);
TemporaryRef<gfx::SourceSurface> ReadPixelsToSourceSurface(const gfx::IntSize &aSize);
// Shared code for GL extensions and GLX extensions.
static bool ListHasExtension(const GLubyte *extensions,
const char *extension);
@ -2692,11 +2624,13 @@ protected:
ScopedDeletePtr<GLBlitHelper> mBlitHelper;
ScopedDeletePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
ScopedDeletePtr<GLReadTexImageHelper> mReadTexImageHelper;
public:
GLBlitHelper* BlitHelper();
GLBlitTextureImageHelper* BlitTextureImageHelper();
GLReadTexImageHelper* ReadTexImageHelper();
// Assumes shares are created by all sharing with the same global context.
bool SharesWith(const GLContext* other) const {
@ -2864,8 +2798,6 @@ public:
bool IsOffscreenSizeAllowed(const gfx::IntSize& aSize) const;
protected:
GLuint mReadTextureImagePrograms[4];
bool InitWithPrefix(const char *prefix, bool trygl);
void InitExtensions();

View File

@ -300,8 +300,6 @@ GLContextProviderCGL::GetGlobalContext(const ContextFlags)
gGlobalContext = nullptr;
return nullptr;
}
gGlobalContext->SetIsGlobalSharedContext(true);
}
return gGlobalContext;

View File

@ -363,15 +363,6 @@ public:
mIsDoubleBuffered = aIsDB;
}
virtual EGLContext GetEGLContext() {
return mContext;
}
virtual GLLibraryEGL* GetLibraryEGL() {
return &sEGLLibrary;
}
bool SupportsRobustness()
{
return sEGLLibrary.HasRobustness();
@ -418,7 +409,7 @@ public:
return true;
}
virtual void SetEGLSurfaceOverride(EGLSurface surf) MOZ_OVERRIDE {
void SetEGLSurfaceOverride(EGLSurface surf) {
if (Screen()) {
/* Blit `draw` to `read` if we need to, before we potentially juggle
* `read` around. If we don't, we might attach a different `read`,
@ -903,6 +894,16 @@ GLContextProviderEGL::Shutdown()
{
}
GLContextEGL* DowncastGLContextEGL(GLContext* context)
{
return static_cast<GLContextEGL*>(context);
}
void SetEGLSurfaceOverride(GLContextEGL* context, EGLSurface surf)
{
context->SetEGLSurfaceOverride(surf);
}
} /* namespace gl */
} /* namespace mozilla */

View File

@ -1258,8 +1258,6 @@ GLContextProviderGLX::GetGlobalContext(const ContextFlags aFlag)
gfxIntSize dummySize = gfxIntSize(16, 16);
gGlobalContext[libType] = CreateOffscreenPixmapContext(dummySize, libType);
if (gGlobalContext[libType])
gGlobalContext[libType]->SetIsGlobalSharedContext(true);
}
return gGlobalContext[libType];

View File

@ -730,8 +730,6 @@ GLContextProviderWGL::GetGlobalContext(const ContextFlags flags)
gGlobalContext[libToUse] = nullptr;
return nullptr;
}
gGlobalContext[libToUse]->SetIsGlobalSharedContext(true);
}
return static_cast<GLContext*>(gGlobalContext[libToUse]);

View File

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 "GLContext.h"
#include "GLContextUtils.h"
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
TemporaryRef<gfx::DataSourceSurface>
ReadBackSurface(GLContext* aContext, GLuint aTexture, bool aYInvert, SurfaceFormat aFormat)
{
nsRefPtr<gfxImageSurface> image = aContext->GetTexImage(aTexture, aYInvert, aFormat);
RefPtr<gfx::DataSourceSurface> surf =
Factory::CreateDataSourceSurface(gfx::ToIntSize(image->GetSize()), aFormat);
if (!image->CopyTo(surf)) {
return nullptr;
}
return surf.forget();
}
} /* namespace gl */
} /* namespace mozilla */

View File

@ -1,28 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef GLCONTEXTUTILS_H_
#define GLCONTEXTUTILS_H_
#include "GLContextTypes.h"
#include "mozilla/gfx/Types.h"
namespace mozilla {
namespace gfx {
class DataSourceSurface;
}
}
namespace mozilla {
namespace gl {
TemporaryRef<gfx::DataSourceSurface>
ReadBackSurface(GLContext* aContext, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
} // namespace gl
} // namespace mozilla
#endif /* GLCONTEXTUTILS_H_ */

View File

@ -0,0 +1,645 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 "GLReadTexImageHelper.h"
#include "GLContext.h"
#include "OGLShaderProgram.h"
#include "gfxTypes.h"
#include "gfxContext.h"
#include "ScopedGLHelpers.h"
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
namespace mozilla {
namespace gl {
GLReadTexImageHelper::GLReadTexImageHelper(GLContext* gl)
: mGL(gl)
{
mPrograms[0] = 0;
mPrograms[1] = 0;
mPrograms[2] = 0;
mPrograms[3] = 0;
}
GLReadTexImageHelper::~GLReadTexImageHelper()
{
mGL->fDeleteProgram(mPrograms[0]);
mGL->fDeleteProgram(mPrograms[1]);
mGL->fDeleteProgram(mPrograms[2]);
mGL->fDeleteProgram(mPrograms[3]);
}
static const GLchar
readTextureImageVS[] =
"attribute vec2 aVertex;\n"
"attribute vec2 aTexCoord;\n"
"varying vec2 vTexCoord;\n"
"void main() { gl_Position = vec4(aVertex, 0, 1); vTexCoord = aTexCoord; }";
static const GLchar
readTextureImageFS_TEXTURE_2D[] =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform sampler2D uTexture;\n"
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
static const GLchar
readTextureImageFS_TEXTURE_2D_BGRA[] =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform sampler2D uTexture;\n"
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord).bgra; }";
static const GLchar
readTextureImageFS_TEXTURE_EXTERNAL[] =
"#extension GL_OES_EGL_image_external : require\n"
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform samplerExternalOES uTexture;\n"
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
static const GLchar
readTextureImageFS_TEXTURE_RECTANGLE[] =
"#extension GL_ARB_texture_rectangle\n"
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform sampler2DRect uTexture;\n"
"void main() { gl_FragColor = texture2DRect(uTexture, vTexCoord).bgra; }";
GLuint
GLReadTexImageHelper::TextureImageProgramFor(GLenum aTextureTarget, int aShader) {
int variant = 0;
const GLchar* readTextureImageFS = nullptr;
if (aTextureTarget == LOCAL_GL_TEXTURE_2D)
{
if (aShader == layers::BGRALayerProgramType ||
aShader == layers::BGRXLayerProgramType)
{ // Need to swizzle R/B.
readTextureImageFS = readTextureImageFS_TEXTURE_2D_BGRA;
variant = 1;
}
else
{
readTextureImageFS = readTextureImageFS_TEXTURE_2D;
variant = 0;
}
} else if (aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
readTextureImageFS = readTextureImageFS_TEXTURE_EXTERNAL;
variant = 2;
} else if (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
readTextureImageFS = readTextureImageFS_TEXTURE_RECTANGLE;
variant = 3;
}
/* This might be overkill, but assure that we don't access out-of-bounds */
MOZ_ASSERT((size_t) variant < ArrayLength(mPrograms));
if (!mPrograms[variant]) {
GLuint vs = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER);
const GLchar* vsSourcePtr = &readTextureImageVS[0];
mGL->fShaderSource(vs, 1, &vsSourcePtr, nullptr);
mGL->fCompileShader(vs);
GLuint fs = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
mGL->fShaderSource(fs, 1, &readTextureImageFS, nullptr);
mGL->fCompileShader(fs);
GLuint program = mGL->fCreateProgram();
mGL->fAttachShader(program, vs);
mGL->fAttachShader(program, fs);
mGL->fBindAttribLocation(program, 0, "aVertex");
mGL->fBindAttribLocation(program, 1, "aTexCoord");
mGL->fLinkProgram(program);
GLint success;
mGL->fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &success);
if (!success) {
mGL->fDeleteProgram(program);
program = 0;
}
mGL->fDeleteShader(vs);
mGL->fDeleteShader(fs);
mPrograms[variant] = program;
}
return mPrograms[variant];
}
bool
GLReadTexImageHelper::DidGLErrorOccur(const char* str)
{
GLenum error = mGL->fGetError();
if (error != LOCAL_GL_NO_ERROR) {
printf_stderr("GL ERROR: %s (0x%04x) %s\n",
mGL->GLErrorToString(error), error, str);
return true;
}
return false;
}
static bool
GetActualReadFormats(GLContext* gl, GLenum destFormat, GLenum destType,
GLenum& readFormat, GLenum& readType)
{
if (destFormat == LOCAL_GL_RGBA &&
destType == LOCAL_GL_UNSIGNED_BYTE)
{
readFormat = destFormat;
readType = destType;
return true;
}
bool fallback = true;
if (gl->IsGLES2()) {
GLenum auxFormat = 0;
GLenum auxType = 0;
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, (GLint*)&auxFormat);
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, (GLint*)&auxType);
if (destFormat == auxFormat &&
destType == auxType)
{
fallback = false;
}
} else {
switch (destFormat) {
case LOCAL_GL_RGB: {
if (destType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV)
fallback = false;
break;
}
case LOCAL_GL_BGRA: {
if (destType == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV)
fallback = false;
break;
}
}
}
if (fallback) {
readFormat = LOCAL_GL_RGBA;
readType = LOCAL_GL_UNSIGNED_BYTE;
return false;
} else {
readFormat = destFormat;
readType = destType;
return true;
}
}
static void SwapRAndBComponents(gfxImageSurface* surf)
{
uint8_t *row = surf->Data();
size_t rowBytes = surf->Width()*4;
size_t rowHole = surf->Stride() - rowBytes;
size_t rows = surf->Height();
while (rows) {
const uint8_t *rowEnd = row + rowBytes;
while (row != rowEnd) {
row[0] ^= row[2];
row[2] ^= row[0];
row[0] ^= row[2];
row += 4;
}
row += rowHole;
--rows;
}
}
void
ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
gl->MakeCurrent();
MOZ_ASSERT(dest->GetSize() != gfxIntSize(0, 0));
/* gfxImageFormatARGB32:
* RGBA+UByte: be[RGBA], le[ABGR]
* RGBA+UInt: le[RGBA]
* BGRA+UInt: le[BGRA]
* BGRA+UIntRev: le[ARGB]
*
* gfxImageFormatRGB16_565:
* RGB+UShort: le[rrrrrggg,gggbbbbb]
*/
bool hasAlpha = dest->Format() == gfxImageFormatARGB32;
int destPixelSize;
GLenum destFormat;
GLenum destType;
switch (dest->Format()) {
case gfxImageFormatRGB24: // XRGB
case gfxImageFormatARGB32:
destPixelSize = 4;
// Needs host (little) endian ARGB.
destFormat = LOCAL_GL_BGRA;
destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
break;
case gfxImageFormatRGB16_565:
destPixelSize = 2;
destFormat = LOCAL_GL_RGB;
destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
break;
default:
MOZ_CRASH("Bad format.");
}
MOZ_ASSERT(dest->Stride() == dest->Width() * destPixelSize);
GLenum readFormat = destFormat;
GLenum readType = destType;
bool needsTempSurf = !GetActualReadFormats(gl,
destFormat, destType,
readFormat, readType);
nsAutoPtr<gfxImageSurface> tempSurf;
gfxImageSurface* readSurf = nullptr;
int readPixelSize = 0;
if (needsTempSurf) {
if (gl->DebugMode()) {
NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
}
gfx::SurfaceFormat readFormatGFX;
switch (readFormat) {
case LOCAL_GL_RGBA:
case LOCAL_GL_BGRA: {
readFormatGFX = hasAlpha ? gfx::FORMAT_B8G8R8A8
: gfx::FORMAT_B8G8R8X8;
break;
}
case LOCAL_GL_RGB: {
MOZ_ASSERT(readPixelSize == 2);
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
readFormatGFX = gfx::FORMAT_R5G6B5;
break;
}
default: {
MOZ_CRASH("Bad read format.");
}
}
switch (readType) {
case LOCAL_GL_UNSIGNED_BYTE: {
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
readPixelSize = 4;
break;
}
case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: {
MOZ_ASSERT(readFormat == LOCAL_GL_BGRA);
readPixelSize = 4;
break;
}
case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: {
MOZ_ASSERT(readFormat == LOCAL_GL_RGB);
readPixelSize = 2;
break;
}
default: {
MOZ_CRASH("Bad read type.");
}
}
tempSurf = new gfxImageSurface(dest->GetSize(),
SurfaceFormatToImageFormat(readFormatGFX),
false);
readSurf = tempSurf;
} else {
readPixelSize = destPixelSize;
readSurf = dest;
}
MOZ_ASSERT(readPixelSize);
GLint currentPackAlignment = 0;
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &currentPackAlignment);
if (currentPackAlignment != readPixelSize)
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readPixelSize);
GLsizei width = dest->Width();
GLsizei height = dest->Height();
readSurf->Flush();
gl->fReadPixels(0, 0,
width, height,
readFormat, readType,
readSurf->Data());
readSurf->MarkDirty();
if (currentPackAlignment != readPixelSize)
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
if (readSurf != dest) {
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
// So we just copied in RGBA in big endian, or le: 0xAABBGGRR.
// We want 0xAARRGGBB, so swap R and B:
dest->Flush();
SwapRAndBComponents(readSurf);
dest->MarkDirty();
gfxContext ctx(dest);
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
ctx.SetSource(readSurf);
ctx.Paint();
}
// Check if GL is giving back 1.0 alpha for
// RGBA reads to RGBA images from no-alpha buffers.
#ifdef XP_MACOSX
if (gl->WorkAroundDriverBugs() &&
gl->Vendor() == gl::GLContext::VendorNVIDIA &&
dest->Format() == gfxImageFormatARGB32 &&
width && height)
{
GLint alphaBits = 0;
gl->fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
if (!alphaBits) {
const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0);
dest->Flush();
uint32_t* itr = (uint32_t*)dest->Data();
uint32_t testPixel = *itr;
if ((testPixel & alphaMask) != alphaMask) {
// We need to set the alpha channel to 1.0 manually.
uint32_t* itrEnd = itr + width*height; // Stride is guaranteed to be width*4.
for (; itr != itrEnd; itr++) {
*itr |= alphaMask;
}
}
dest->MarkDirty();
}
}
#endif
}
static already_AddRefed<gfxImageSurface> YInvertImageSurface(gfxImageSurface* aSurf)
{
gfxIntSize size = aSurf->GetSize();
nsRefPtr<gfxImageSurface> temp = new gfxImageSurface(size, aSurf->Format());
nsRefPtr<gfxContext> ctx = new gfxContext(temp);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Scale(1.0, -1.0);
ctx->Translate(-gfxPoint(0.0, size.height));
ctx->SetSource(aSurf);
ctx->Paint();
return temp.forget();
}
already_AddRefed<gfxImageSurface>
GetTexImage(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat)
{
gl->MakeCurrent();
gl->GuaranteeResolve();
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
gfxIntSize size;
gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(size, gfxImageFormatARGB32);
if (!surf || surf->CairoStatus()) {
return nullptr;
}
uint32_t currentPackAlignment = 0;
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
if (currentPackAlignment != 4) {
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
}
gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->Data());
if (currentPackAlignment != 4) {
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
}
if (aFormat == gfx::FORMAT_R8G8B8A8 || aFormat == gfx::FORMAT_R8G8B8X8) {
SwapRAndBComponents(surf);
}
if (aYInvert) {
surf = YInvertImageSurface(surf);
}
return surf.forget();
}
TemporaryRef<gfx::DataSourceSurface>
ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat)
{
nsRefPtr<gfxImageSurface> image = GetTexImage(gl, aTexture, aYInvert, aFormat);
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateDataSourceSurface(gfx::ToIntSize(image->GetSize()), aFormat);
if (!image->CopyTo(surf)) {
return nullptr;
}
return surf.forget();
}
void
ReadScreenIntoImageSurface(GLContext* gl, gfxImageSurface* dest)
{
ScopedBindFramebuffer autoFB(gl, 0);
ReadPixelsIntoImageSurface(gl, dest);
}
#define CLEANUP_IF_GLERROR_OCCURRED(x) \
if (DidGLErrorOccur(x)) { \
isurf = nullptr; \
break; \
}
already_AddRefed<gfxImageSurface>
GLReadTexImageHelper::ReadTexImage(GLuint aTextureId,
GLenum aTextureTarget,
const gfxIntSize& aSize,
/* ShaderProgramType */ int aShaderProgram,
bool aYInvert)
{
// Check aShaderProgram is in bounds for a layers::ShaderProgramType
MOZ_ASSERT(0 <= aShaderProgram && aShaderProgram < layers::NumProgramTypes);
MOZ_ASSERT(aTextureTarget == LOCAL_GL_TEXTURE_2D ||
aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL ||
aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
mGL->MakeCurrent();
/* Allocate resulting image surface */
nsRefPtr<gfxImageSurface> isurf = new gfxImageSurface(aSize, gfxImageFormatARGB32);
if (!isurf || isurf->CairoStatus()) {
return nullptr;
}
realGLboolean oldBlend, oldScissor;
GLint oldrb, oldfb, oldprog, oldTexUnit, oldTex;
GLuint rb, fb;
do {
/* Save current GL state */
oldBlend = mGL->fIsEnabled(LOCAL_GL_BLEND);
oldScissor = mGL->fIsEnabled(LOCAL_GL_SCISSOR_TEST);
mGL->fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
mGL->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
mGL->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
mGL->fGetIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &oldTexUnit);
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
switch (aTextureTarget) {
case LOCAL_GL_TEXTURE_2D:
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex);
break;
case LOCAL_GL_TEXTURE_EXTERNAL:
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldTex);
break;
case LOCAL_GL_TEXTURE_RECTANGLE:
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &oldTex);
break;
default: /* Already checked above */
break;
}
/* Set required GL state */
mGL->fDisable(LOCAL_GL_BLEND);
mGL->fDisable(LOCAL_GL_SCISSOR_TEST);
mGL->PushViewportRect(nsIntRect(0, 0, aSize.width, aSize.height));
/* Setup renderbuffer */
mGL->fGenRenderbuffers(1, &rb);
mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
GLenum rbInternalFormat =
mGL->IsGLES2()
? (mGL->IsExtensionSupported(GLContext::OES_rgb8_rgba8) ? LOCAL_GL_RGBA8 : LOCAL_GL_RGBA4)
: LOCAL_GL_RGBA;
mGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, rbInternalFormat, aSize.width, aSize.height);
CLEANUP_IF_GLERROR_OCCURRED("when binding and creating renderbuffer");
/* Setup framebuffer */
mGL->fGenFramebuffers(1, &fb);
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
LOCAL_GL_RENDERBUFFER, rb);
CLEANUP_IF_GLERROR_OCCURRED("when binding and creating framebuffer");
MOZ_ASSERT(mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) == LOCAL_GL_FRAMEBUFFER_COMPLETE);
/* Setup vertex and fragment shader */
layers::ShaderProgramType shaderProgram = (layers::ShaderProgramType) aShaderProgram;
GLuint program = TextureImageProgramFor(aTextureTarget, shaderProgram);
MOZ_ASSERT(program);
mGL->fUseProgram(program);
CLEANUP_IF_GLERROR_OCCURRED("when using program");
mGL->fUniform1i(mGL->fGetUniformLocation(program, "uTexture"), 0);
CLEANUP_IF_GLERROR_OCCURRED("when setting uniform location");
/* Setup quad geometry */
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
mGL->fEnableVertexAttribArray(0);
mGL->fEnableVertexAttribArray(1);
float w = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) ? (float) aSize.width : 1.0f;
float h = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) ? (float) aSize.height : 1.0f;
const float
vertexArray[4*2] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, vertexArray);
const float u0 = 0.0f;
const float u1 = w;
const float v0 = aYInvert ? h : 0.0f;
const float v1 = aYInvert ? 0.0f : h;
const float texCoordArray[8] = { u0, v0,
u1, v0,
u0, v1,
u1, v1 };
mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, texCoordArray);
/* Bind the texture */
if (aTextureId) {
mGL->fBindTexture(aTextureTarget, aTextureId);
CLEANUP_IF_GLERROR_OCCURRED("when binding texture");
}
/* Draw quad */
mGL->fClearColor(1.0f, 0.0f, 1.0f, 1.0f);
mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
CLEANUP_IF_GLERROR_OCCURRED("when clearing color buffer");
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
CLEANUP_IF_GLERROR_OCCURRED("when drawing texture");
mGL->fDisableVertexAttribArray(1);
mGL->fDisableVertexAttribArray(0);
/* Read-back draw results */
ReadPixelsIntoImageSurface(mGL, isurf);
CLEANUP_IF_GLERROR_OCCURRED("when reading pixels into surface");
} while (false);
/* Restore GL state */
//cleanup:
mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
mGL->fUseProgram(oldprog);
// note that deleting 0 has no effect in any of these calls
mGL->fDeleteRenderbuffers(1, &rb);
mGL->fDeleteFramebuffers(1, &fb);
if (oldBlend)
mGL->fEnable(LOCAL_GL_BLEND);
if (oldScissor)
mGL->fEnable(LOCAL_GL_SCISSOR_TEST);
if (aTextureId)
mGL->fBindTexture(aTextureTarget, oldTex);
if (oldTexUnit != LOCAL_GL_TEXTURE0)
mGL->fActiveTexture(oldTexUnit);
mGL->PopViewportRect();
return isurf.forget();
}
#undef CLEANUP_IF_GLERROR_OCCURRED
}
}

View File

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef GLREADTEXIMAGEHELPER_H_
#define GLREADTEXIMAGEHELPER_H_
#include "GLContextTypes.h"
#include "mozilla/Attributes.h"
#include "nsSize.h"
#include "nsAutoPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/Types.h"
class gfxImageSurface;
namespace mozilla {
namespace gfx {
class DataSourceSurface;
}
namespace gl {
void ReadPixelsIntoImageSurface(GLContext* aGL, gfxImageSurface* aSurface);
void ReadScreenIntoImageSurface(GLContext* aGL, gfxImageSurface* aSurface);
already_AddRefed<gfxImageSurface>
GetTexImage(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
TemporaryRef<gfx::DataSourceSurface>
ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
class GLReadTexImageHelper MOZ_FINAL
{
// The GLContext is the sole owner of the GLBlitHelper.
GLContext* mGL;
GLuint mPrograms[4];
GLuint TextureImageProgramFor(GLenum aTextureTarget, int aShader);
bool DidGLErrorOccur(const char* str);
public:
GLReadTexImageHelper(GLContext* gl);
~GLReadTexImageHelper();
/**
* Read the image data contained in aTexture, and return it as an ImageSurface.
* If GL_RGBA is given as the format, a gfxImageFormatARGB32 surface is returned.
* Not implemented yet:
* If GL_RGB is given as the format, a gfxImageFormatRGB24 surface is returned.
* If GL_LUMINANCE is given as the format, a gfxImageFormatA8 surface is returned.
*
* THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
* if you absolutely positively must, and never in any performance
* critical path.
*
* NOTE: aShaderProgram is really mozilla::layers::ShaderProgramType. It is
* passed as int to eliminate including LayerManagerOGLProgram.h here.
*/
already_AddRefed<gfxImageSurface> ReadTexImage(GLuint aTextureId,
GLenum aTextureTarget,
const gfxIntSize& aSize,
/* ShaderProgramType */ int aShaderProgram,
bool aYInvert = false);
};
}
}
#endif

View File

@ -9,6 +9,7 @@
#include "gfxImageSurface.h"
#include "GLContext.h"
#include "GLBlitHelper.h"
#include "GLReadTexImageHelper.h"
#include "SharedSurfaceGL.h"
#include "SurfaceStream.h"
#ifdef MOZ_WIDGET_GONK
@ -498,7 +499,7 @@ GLScreenBuffer::Readback(SharedSurface_GL* src, gfxImageSurface* dest)
MOZ_ASSERT(buffer);
ScopedBindFramebuffer autoFB(mGL, buffer->FB());
mGL->ReadPixelsIntoImageSurface(dest);
ReadPixelsIntoImageSurface(mGL, dest);
delete buffer;

View File

@ -12,12 +12,16 @@ using namespace mozilla::gfx;
namespace mozilla {
namespace gl {
class GLContextEGL;
void SetEGLSurfaceOverride(GLContextEGL* context, EGLSurface surf);
GLContextEGL* DowncastGLContextEGL(GLContext* context);
SurfaceFactory_ANGLEShareHandle*
SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl,
ID3D10Device1* d3d,
const SurfaceCaps& caps)
{
GLLibraryEGL* egl = gl->GetLibraryEGL();
GLLibraryEGL* egl = &sEGLLibrary;
if (!egl)
return nullptr;
@ -45,7 +49,7 @@ SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle()
void
SharedSurface_ANGLEShareHandle::LockProdImpl()
{
mGL->SetEGLSurfaceOverride(mPBuffer);
SetEGLSurfaceOverride(DowncastGLContextEGL(mGL), mPBuffer);
}
void
@ -194,7 +198,7 @@ SharedSurface_ANGLEShareHandle::Create(GLContext* gl, ID3D10Device1* d3d,
EGLContext context, EGLConfig config,
const gfx::IntSize& size, bool hasAlpha)
{
GLLibraryEGL* egl = gl->GetLibraryEGL();
GLLibraryEGL* egl = &sEGLLibrary;
MOZ_ASSERT(egl);
MOZ_ASSERT(egl->IsExtensionSupported(
GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle));
@ -271,7 +275,7 @@ SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
, mConsD3D(d3d)
{
mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps);
mContext = mProdGL->GetEGLContext();
mContext = mProdGL->GetNativeData(GLContext::NativeGLContext);
MOZ_ASSERT(mConfig && mContext);
}

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SharedSurfaceEGL.h"
#include "GLContext.h"
#include "GLBlitHelper.h"
#include "ScopedGLHelpers.h"
@ -12,6 +11,7 @@
#include "SurfaceFactory.h"
#include "GLLibraryEGL.h"
#include "TextureGarbageBin.h"
#include "GLReadTexImageHelper.h"
using namespace mozilla::gfx;
@ -25,7 +25,7 @@ SharedSurface_EGLImage::Create(GLContext* prodGL,
bool hasAlpha,
EGLContext context)
{
GLLibraryEGL* egl = prodGL->GetLibraryEGL();
GLLibraryEGL* egl = &sEGLLibrary;
MOZ_ASSERT(egl);
if (!HasExtensions(egl, prodGL))
@ -134,7 +134,7 @@ CreateTexturePipe(GLLibraryEGL* const egl, GLContext* const gl,
if (!tex)
return false;
EGLContext context = gl->GetEGLContext();
EGLContext context = (EGLContext) gl->GetNativeData(GLContext::NativeGLContext);
MOZ_ASSERT(context);
EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(tex);
EGLImage image = egl->fCreateImage(egl->Display(), context,
@ -181,7 +181,7 @@ SharedSurface_EGLImage::Fence()
ThebesIntSize(mPixels->GetSize()),
mPixels->Stride(),
SurfaceFormatToImageFormat(mPixels->GetFormat()));
mGL->ReadScreenIntoImageSurface(wrappedData);
ReadScreenIntoImageSurface(mGL, wrappedData);
mPixels->MarkDirty();
return;
}
@ -287,7 +287,7 @@ SurfaceFactory_EGLImage*
SurfaceFactory_EGLImage::Create(GLContext* prodGL,
const SurfaceCaps& caps)
{
EGLContext context = prodGL->GetEGLContext();
EGLContext context = prodGL->GetNativeData(GLContext::NativeGLContext);
return new SurfaceFactory_EGLImage(prodGL, context, caps);
}

View File

@ -9,6 +9,7 @@
#include "ScopedGLHelpers.h"
#include "gfxImageSurface.h"
#include "mozilla/gfx/2D.h"
#include "GLReadTexImageHelper.h"
using namespace mozilla::gfx;
@ -308,7 +309,7 @@ SharedSurface_Basic::Fence()
ThebesIntSize(mData->GetSize()),
mData->Stride(),
SurfaceFormatToImageFormat(mData->GetFormat()));
mGL->ReadScreenIntoImageSurface(wrappedData);
ReadScreenIntoImageSurface(mGL, wrappedData);
mData->MarkDirty();
}

View File

@ -64,7 +64,7 @@ SharedSurface_Gralloc::Create(GLContext* prodGL,
runOnce = false;
}
GLLibraryEGL* egl = prodGL->GetLibraryEGL();
GLLibraryEGL* egl = &sEGLLibrary;
MOZ_ASSERT(egl);
DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");

View File

@ -36,10 +36,10 @@ EXPORTS += [
'GLContextProviderImpl.h',
'GLContextSymbols.h',
'GLContextTypes.h',
'GLContextUtils.h',
'GLDefs.h',
'GLLibraryEGL.h',
'GLLibraryLoader.h',
'GLReadTexImageHelper.h',
'GLScreenBuffer.h',
'GLSharedHandleHelpers.h',
'GLTextureImage.h',
@ -115,9 +115,9 @@ UNIFIED_SOURCES += [
'GLContext.cpp',
'GLContextFeatures.cpp',
'GLContextTypes.cpp',
'GLContextUtils.cpp',
'GLLibraryEGL.cpp',
'GLLibraryLoader.cpp',
'GLReadTexImageHelper.cpp',
'GLScreenBuffer.cpp',
'GLSharedHandleHelpers.cpp',
'GLTextureImage.cpp',

View File

@ -21,6 +21,7 @@
#include "GLContext.h"
#include "GLContextProvider.h"
#include "GLReadTexImageHelper.h"
#include "nsIServiceManager.h"
#include "nsIConsoleService.h"
@ -495,9 +496,9 @@ SendTextureSource(GLContext* aGLContext,
// By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
// texture correctly. textureId is used for tracking in DebugGLTextureData.
nsRefPtr<gfxImageSurface> img =
aGLContext->ReadTextureImage(0, textureTarget,
gfxIntSize(size.width, size.height),
shaderProgram, aFlipY);
aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
gfxIntSize(size.width, size.height),
shaderProgram, aFlipY);
gCurrentSender->Append(
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,

View File

@ -39,8 +39,10 @@ struct YCbCrBufferInfo
uint32_t mYOffset;
uint32_t mCbOffset;
uint32_t mCrOffset;
uint32_t mYStride;
uint32_t mYWidth;
uint32_t mYHeight;
uint32_t mCbCrStride;
uint32_t mCbCrWidth;
uint32_t mCbCrHeight;
StereoMode mStereoMode;
@ -86,13 +88,13 @@ uint8_t* YCbCrImageDataDeserializerBase::GetData()
uint32_t YCbCrImageDataDeserializerBase::GetYStride()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
return info->mYWidth;
return info->mYStride;
}
uint32_t YCbCrImageDataDeserializerBase::GetCbCrStride()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
return info->mCbCrWidth;
return info->mCbCrStride;
}
gfx::IntSize YCbCrImageDataDeserializerBase::GetYSize()
@ -149,6 +151,8 @@ void
YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYOffset,
uint32_t aCbOffset,
uint32_t aCrOffset,
uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode)
@ -158,22 +162,35 @@ YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYOffset,
info->mYOffset = info_size + aYOffset;
info->mCbOffset = info_size + aCbOffset;
info->mCrOffset = info_size + aCrOffset;
info->mYStride = aYStride;
info->mYWidth = aYSize.width;
info->mYHeight = aYSize.height;
info->mCbCrStride = aCbCrStride;
info->mCbCrWidth = aCbCrSize.width;
info->mCbCrHeight = aCbCrSize.height;
info->mStereoMode = aStereoMode;
}
void
YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode)
{
uint32_t yOffset = 0;
uint32_t cbOffset = yOffset + MOZ_ALIGN_WORD(aYStride * aYSize.height);
uint32_t crOffset = cbOffset + MOZ_ALIGN_WORD(aCbCrStride * aCbCrSize.height);
return InitializeBufferInfo(yOffset, cbOffset, crOffset,
aYStride, aCbCrStride, aYSize, aCbCrSize, aStereoMode);
}
void
YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode)
{
uint32_t yOffset = 0;
uint32_t cbOffset = yOffset + MOZ_ALIGN_WORD(aYSize.width * aYSize.height);
uint32_t crOffset = cbOffset + MOZ_ALIGN_WORD(aCbCrSize.width * aCbCrSize.height);
return InitializeBufferInfo(yOffset, cbOffset, crOffset, aYSize, aCbCrSize, aStereoMode);
return InitializeBufferInfo(aYSize.width, aCbCrSize.width, aYSize, aCbCrSize, aStereoMode);
}
static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) {

View File

@ -114,6 +114,13 @@ public:
void InitializeBufferInfo(uint32_t aYOffset,
uint32_t aCbOffset,
uint32_t aCrOffset,
uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode);
void InitializeBufferInfo(uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode);

View File

@ -47,7 +47,7 @@ ClientCanvasLayer::Initialize(const Data& aData)
SurfaceFactory_GL* factory = nullptr;
if (!mForceReadback) {
if (ClientManager()->AsShadowForwarder()->GetCompositorBackendType() == mozilla::layers::LAYERS_OPENGL) {
if (mGLContext->GetEGLContext()) {
if (mGLContext->GetContextType() == ContextTypeEGL) {
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
if (!isCrossProcess) {

View File

@ -158,6 +158,8 @@ SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
serializer.InitializeBufferInfo(yOffset,
cbOffset,
crOffset,
aData.mYStride,
aData.mCbCrStride,
aData.mYSize,
aData.mCbCrSize,
aData.mStereoMode);

View File

@ -5,6 +5,7 @@
#include "CompositingRenderTargetOGL.h"
#include "GLContext.h"
#include "GLReadTexImageHelper.h"
using namespace mozilla;
using namespace mozilla::layers;
@ -61,7 +62,7 @@ CompositingRenderTargetOGL::Dump(Compositor* aCompositor)
{
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(aCompositor);
return mGL->GetTexImage(mTextureHandle, true, compositorOGL->GetFBOFormat());
return GetTexImage(mGL, mTextureHandle, true, compositorOGL->GetFBOFormat());
}
#endif

View File

@ -42,6 +42,7 @@
#include "nsString.h" // for nsString, nsAutoCString, etc
#include "DecomposeIntoNoRepeatTriangles.h"
#include "ScopedGLHelpers.h"
#include "GLReadTexImageHelper.h"
#if MOZ_ANDROID_OMTC
#include "TexturePoolOGL.h"
@ -1485,8 +1486,16 @@ CompositorOGL::CopyToTarget(DrawTarget *aTarget, const gfxMatrix& aTransform)
mGLContext->fReadBuffer(LOCAL_GL_BACK);
}
RefPtr<SourceSurface> source =
mGLContext->ReadPixelsToSourceSurface(IntSize(width, height));
RefPtr<DataSourceSurface> source =
Factory::CreateDataSourceSurface(rect.Size(), gfx::FORMAT_B8G8R8A8);
// XXX we should do this properly one day without using the gfxImageSurface
nsRefPtr<gfxImageSurface> surf =
new gfxImageSurface(source->GetData(),
gfxIntSize(width, height),
source->Stride(),
gfxImageFormatARGB32);
ReadPixelsIntoImageSurface(mGLContext, surf);
source->MarkDirty();
// Map from GL space to Cairo space and reverse the world transform.
Matrix glToCairoTransform = ToMatrix(aTransform);

View File

@ -22,28 +22,16 @@ EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer)
LOCAL_EGL_NONE, LOCAL_EGL_NONE
};
GLLibraryEGL* egl = aGL->GetLibraryEGL();
if (!egl) {
NS_WARNING("Failed to obtain pointer to EGL. Returning EGL_NO_IMAGE.");
return EGL_NO_IMAGE;
}
return egl->fCreateImage(egl->Display(),
EGL_NO_CONTEXT,
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
aBuffer, attrs);
return sEGLLibrary.fCreateImage(sEGLLibrary.Display(),
EGL_NO_CONTEXT,
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
aBuffer, attrs);
}
void
EGLImageDestroy(GLContext* aGL, EGLImage aImage)
{
GLLibraryEGL* egl = aGL->GetLibraryEGL();
if (!egl) {
NS_WARNING("Failed to obtain pointer to EGL. Image not destroyed.");
return;
}
egl->fDestroyImage(egl->Display(), aImage);
sEGLLibrary.fDestroyImage(sEGLLibrary.Display(), aImage);
}
} // namespace layers

View File

@ -11,7 +11,7 @@
#include "mozilla/layers/GrallocTextureHost.h"
#include "mozilla/layers/CompositorOGL.h"
#include "EGLImageHelpers.h"
#include "GLContextUtils.h"
#include "GLReadTexImageHelper.h"
namespace mozilla {
namespace layers {

View File

@ -7,7 +7,7 @@
#include "GLContext.h" // for GLContext, etc
#include "GLSharedHandleHelpers.h"
#include "GLUploadHelpers.h"
#include "GLContextUtils.h" // for GLContextUtils
#include "GLReadTexImageHelper.h"
#include "SharedSurface.h" // for SharedSurface
#include "SharedSurfaceEGL.h" // for SharedSurface_EGLImage
#include "SharedSurfaceGL.h" // for SharedSurface_GLTexture, etc

View File

@ -394,7 +394,6 @@ const MozLangGroupData MozLangGroups[] = {
{ nsGkAtoms::x_telu, "te" },
{ nsGkAtoms::x_tibt, "bo" },
{ nsGkAtoms::Unicode, 0 },
{ nsGkAtoms::x_user_def, 0 }
};
static bool

View File

@ -507,15 +507,11 @@ gfxOS2FontGroup::gfxOS2FontGroup(const nsAString& aFamilies,
nsTArray<nsString> familyArray;
ForEachFont(FontCallback, &familyArray);
// To be able to easily search for glyphs in other fonts, append a few good
// replacement candidates to the list. The best ones are the Unicode fonts that
// are set up, and if the user was so clever to set up the User Defined fonts,
// then these are probable candidates, too.
// To be able to easily search for glyphs in other fonts, append the
// Unicode fonts as replacement candidates to the list.
nsString fontString;
gfxPlatform::GetPlatform()->GetPrefFonts(nsGkAtoms::Unicode, fontString, false);
ForEachFont(fontString, nsGkAtoms::Unicode, FontCallback, &familyArray);
gfxPlatform::GetPlatform()->GetPrefFonts(nsGkAtoms::x_user_def, fontString, false);
ForEachFont(fontString, nsGkAtoms::x_user_def, FontCallback, &familyArray);
// Should append some default font if there are no available fonts.
// Let's use Helv which should be available on any OS/2 system; if

View File

@ -272,7 +272,6 @@ static const char *gPrefLangNames[] = {
"x-sinh",
"x-tibt",
"x-unicode",
"x-user-def"
};
gfxPlatform::gfxPlatform()

View File

@ -91,13 +91,12 @@ enum eFontPrefLang {
eFontPrefLang_Sinhala = 28,
eFontPrefLang_Tibetan = 29,
eFontPrefLang_LangCount = 30, // except Others and UserDefined.
eFontPrefLang_LangCount = 30, // except Others.
eFontPrefLang_Others = 30, // x-unicode
eFontPrefLang_UserDefined = 31,
eFontPrefLang_CJKSet = 32, // special code for CJK set
eFontPrefLang_AllCount = 33
eFontPrefLang_CJKSet = 31, // special code for CJK set
eFontPrefLang_AllCount = 32
};
enum eCMSMode {

View File

@ -223,7 +223,6 @@ x-baltic=x-baltic
x-tamil=x-tamil
x-devanagari=x-devanagari
x-unicode=x-unicode
x-user-def=x-user-def
x-armn=x-armn
x-geor=x-geor
# These self-mappings are not necessary unless somebody use them to specify

View File

@ -156,7 +156,7 @@ macintosh.LangGroup = x-western
x-mac-turkish.LangGroup = tr
x-mac-ukrainian.LangGroup = x-cyrillic
x-mac-romanian.LangGroup = x-central-euro
x-user-defined.LangGroup = x-user-def
x-user-defined.LangGroup = x-unicode
ks_c_5601-1987.LangGroup = ko
x-johab.LangGroup = ko
x-mac-hebrew.LangGroup = he

View File

@ -2192,6 +2192,8 @@ jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
return true;
}
types::FinishDefinitePropertiesAnalysis(cx, constraints);
if (!SplitCriticalEdges(graph))
return false;

View File

@ -24,6 +24,8 @@ enum OptimizationLevel
Optimization_Count
};
#ifdef JS_ION
#ifdef DEBUG
inline const char *
OptimizationLevelString(OptimizationLevel level)
@ -214,6 +216,8 @@ class OptimizationInfos
extern OptimizationInfos js_IonOptimizations;
#endif // JS_ION
} // namespace jit
} // namespace js

View File

@ -910,10 +910,8 @@ CheckFrozenTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTypeSet *actual
TypeSet::TypeList list;
frozen->enumerateTypes(&list);
for (size_t i = 0; i < list.length(); i++) {
// Note: On OOM this will preserve the type set's contents.
for (size_t i = 0; i < list.length(); i++)
actual->addType(cx, list[i]);
}
}
return true;
@ -1032,6 +1030,41 @@ types::FinishCompilation(JSContext *cx, HandleScript script, ExecutionMode execu
return true;
}
static void
CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTypeSet *actual)
{
// The definite properties analysis happens on the main thread, so no new
// types can have been added to actual. The analysis may have updated the
// contents of |frozen| though with new speculative types, and these need
// to be reflected in |actual| for AddClearDefiniteFunctionUsesInScript
// to work.
JS_ASSERT(actual->isSubset(frozen));
if (!frozen->isSubset(actual)) {
TypeSet::TypeList list;
frozen->enumerateTypes(&list);
for (size_t i = 0; i < list.length(); i++)
actual->addType(cx, list[i]);
}
}
void
types::FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints)
{
for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
const CompilerConstraintList::FrozenScript &entry = constraints->frozenScript(i);
JS_ASSERT(entry.script->types);
CheckDefinitePropertiesTypeSet(cx, entry.thisTypes, types::TypeScript::ThisTypes(entry.script));
unsigned nargs = entry.script->function() ? entry.script->function()->nargs() : 0;
for (size_t i = 0; i < nargs; i++)
CheckDefinitePropertiesTypeSet(cx, &entry.argTypes[i], types::TypeScript::ArgTypes(entry.script, i));
for (size_t i = 0; i < entry.script->nTypeSets(); i++)
CheckDefinitePropertiesTypeSet(cx, &entry.bytecodeTypes[i], &entry.script->types->typeArray()[i]);
}
}
namespace {
// Constraint which triggers recompilation of a script if any type is added to a type set. */

View File

@ -1312,6 +1312,11 @@ bool
FinishCompilation(JSContext *cx, HandleScript script, ExecutionMode executionMode,
CompilerConstraintList *constraints, RecompileInfo *precompileInfo);
// Update the actual types in any scripts queried by constraints with any
// speculative types added during the definite properties analysis.
void
FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints);
struct ArrayTableKey;
typedef HashMap<ArrayTableKey,ReadBarriered<TypeObject>,ArrayTableKey,SystemAllocPolicy> ArrayTypeTable;

View File

@ -1452,7 +1452,7 @@ js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc
JS_ASSERT(parent);
JS_ASSERT(allocKind <= gc::FINALIZE_OBJECT_LAST);
if (CanBeFinalizedInBackground(allocKind, &JSObject::class_))
if (CanBeFinalizedInBackground(allocKind, type->clasp()))
allocKind = GetBackgroundAllocKind(allocKind);
NewObjectCache &cache = cx->runtime()->newObjectCache;
@ -1462,19 +1462,19 @@ js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc
newKind == GenericObject &&
!cx->compartment()->hasObjectMetadataCallback())
{
if (cache.lookupType(&JSObject::class_, type, allocKind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, &JSObject::class_));
if (cache.lookupType(type->clasp(), type, allocKind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, type->clasp()));
if (obj)
return obj;
}
}
JSObject *obj = NewObject(cx, &JSObject::class_, type, parent, allocKind, newKind);
JSObject *obj = NewObject(cx, type->clasp(), type, parent, allocKind, newKind);
if (!obj)
return nullptr;
if (entry != -1 && !obj->hasDynamicSlots())
cache.fillType(entry, &JSObject::class_, type, allocKind, obj);
cache.fillType(entry, type->clasp(), type, allocKind, obj);
return obj;
}

View File

@ -943,6 +943,14 @@ JSObject *
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
NewObjectKind newKind = GenericObject);
inline JSObject *
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent,
NewObjectKind newKind = GenericObject)
{
gc::AllocKind allocKind = gc::GetGCObjectKind(type->clasp());
return NewObjectWithType(cx, type, parent, allocKind, newKind);
}
JSObject *
NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind allocKind, HandleShape shape,

View File

@ -53,14 +53,16 @@ RegExpObjectBuilder::getOrCreate()
}
bool
RegExpObjectBuilder::getOrCreateClone(RegExpObject *proto)
RegExpObjectBuilder::getOrCreateClone(HandleTypeObject type)
{
JS_ASSERT(!reobj_);
JS_ASSERT(type->clasp() == &RegExpObject::class_);
JSObject *parent = type->proto().toObject()->getParent();
// Note: RegExp objects are always allocated in the tenured heap. This is
// not strictly required, but simplifies embedding them in jitcode.
JSObject *clone = NewObjectWithGivenProto(cx, &RegExpObject::class_, proto, proto->getParent(),
TenuredObject);
JSObject *clone = NewObjectWithType(cx->asJSContext(), type, parent, TenuredObject);
if (!clone)
return false;
clone->initPrivate(nullptr);
@ -94,7 +96,10 @@ RegExpObjectBuilder::build(HandleAtom source, RegExpFlag flags)
RegExpObject *
RegExpObjectBuilder::clone(Handle<RegExpObject *> other, Handle<RegExpObject *> proto)
{
if (!getOrCreateClone(proto))
RootedTypeObject type(cx, other->type());
JS_ASSERT(type->proto().toObject() == proto);
if (!getOrCreateClone(type))
return nullptr;
/*
@ -777,7 +782,9 @@ js::CloneRegExpObject(JSContext *cx, JSObject *obj_, JSObject *proto_)
RegExpObjectBuilder builder(cx);
Rooted<RegExpObject*> regex(cx, &obj_->as<RegExpObject>());
Rooted<RegExpObject*> proto(cx, &proto_->as<RegExpObject>());
return builder.clone(regex, proto);
JSObject *res = builder.clone(regex, proto);
JS_ASSERT(res->type() == regex->type());
return res;
}
bool

View File

@ -73,7 +73,7 @@ class RegExpObjectBuilder
Rooted<RegExpObject*> reobj_;
bool getOrCreate();
bool getOrCreateClone(RegExpObject *proto);
bool getOrCreateClone(HandleTypeObject type);
public:
RegExpObjectBuilder(ExclusiveContext *cx, RegExpObject *reobj = nullptr);

View File

@ -44,7 +44,6 @@ nsMathMLTokenFrame::GetMathMLFrameType()
(StyleFont()->mFont.style == NS_STYLE_FONT_STYLE_ITALIC ||
HasAnyStateBits(TEXT_IS_IN_SINGLE_CHAR_MI))) ||
mathVariant == NS_MATHML_MATHVARIANT_ITALIC ||
mathVariant == NS_MATHML_MATHVARIANT_ITALIC ||
mathVariant == NS_MATHML_MATHVARIANT_BOLD_ITALIC ||
mathVariant == NS_MATHML_MATHVARIANT_SANS_SERIF_ITALIC ||
mathVariant == NS_MATHML_MATHVARIANT_SANS_SERIF_BOLD_ITALIC) {

View File

@ -310,9 +310,10 @@ public:
*/
void GetCustomPropertyNameAt(uint32_t aIndex, nsAString& aResult) const {
MOZ_ASSERT(mOrder[aIndex] >= eCSSProperty_COUNT);
uint32_t variableIndex = mOrder[aIndex] - eCSSProperty_COUNT;
aResult.Truncate();
aResult.AppendLiteral("var-");
aResult.Append(mVariableOrder[aIndex]);
aResult.Append(mVariableOrder[variableIndex]);
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;

View File

@ -12,6 +12,10 @@ p { var-a:123!important; }
p { var-a: a !important; }
</style>
<style id="test3">
p { border-left-style: inset; padding: 1px; var-decoration: line-through; }
</style>
<script>
var tests = [
function() {
@ -27,6 +31,12 @@ var tests = [
var declaration = document.getElementById("test2").sheet.cssRules[0].style;
is(declaration.getPropertyPriority("var-a"), "important");
},
function() {
// https://bugzilla.mozilla.org/show_bug.cgi?id=955913
var declaration = document.getElementById("test3").sheet.cssRules[0].style;
is(declaration[declaration.length - 1], "var-decoration");
},
];
tests.forEach(function(fn) { fn(); });

View File

@ -15,6 +15,142 @@
using namespace mozilla::dom;
/**
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
*/
#ifdef IS_BIG_ENDIAN
#define GFX_ARGB32_OFFSET_A 0
#define GFX_ARGB32_OFFSET_R 1
#define GFX_ARGB32_OFFSET_G 2
#define GFX_ARGB32_OFFSET_B 3
#else
#define GFX_ARGB32_OFFSET_A 3
#define GFX_ARGB32_OFFSET_R 2
#define GFX_ARGB32_OFFSET_G 1
#define GFX_ARGB32_OFFSET_B 0
#endif
// c = n / 255
// c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)) * 255 + 0.5
static const uint8_t gsRGBToLinearRGBMap[256] = {
0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7,
8, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 12, 12, 12, 13,
13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 17, 18, 18, 19, 19, 20,
20, 21, 22, 22, 23, 23, 24, 24,
25, 25, 26, 27, 27, 28, 29, 29,
30, 30, 31, 32, 32, 33, 34, 35,
35, 36, 37, 37, 38, 39, 40, 41,
41, 42, 43, 44, 45, 45, 46, 47,
48, 49, 50, 51, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 76, 77, 78, 79,
80, 81, 82, 84, 85, 86, 87, 88,
90, 91, 92, 93, 95, 96, 97, 99,
100, 101, 103, 104, 105, 107, 108, 109,
111, 112, 114, 115, 116, 118, 119, 121,
122, 124, 125, 127, 128, 130, 131, 133,
134, 136, 138, 139, 141, 142, 144, 146,
147, 149, 151, 152, 154, 156, 157, 159,
161, 163, 164, 166, 168, 170, 171, 173,
175, 177, 179, 181, 183, 184, 186, 188,
190, 192, 194, 196, 198, 200, 202, 204,
206, 208, 210, 212, 214, 216, 218, 220,
222, 224, 226, 229, 231, 233, 235, 237,
239, 242, 244, 246, 248, 250, 253, 255
};
static void
ComputesRGBLuminanceMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity)
{
for (int32_t y = aRect.y; y < aRect.YMost(); y++) {
for (int32_t x = aRect.x; x < aRect.XMost(); x++) {
uint8_t *pixel = aData + aStride * y + 4 * x;
uint8_t a = pixel[GFX_ARGB32_OFFSET_A];
uint8_t luminance;
if (a) {
/* sRGB -> intensity (unpremultiply cancels out the
* (a/255.0) multiplication with aOpacity */
luminance =
static_cast<uint8_t>
((pixel[GFX_ARGB32_OFFSET_R] * 0.2125 +
pixel[GFX_ARGB32_OFFSET_G] * 0.7154 +
pixel[GFX_ARGB32_OFFSET_B] * 0.0721) *
aOpacity);
} else {
luminance = 0;
}
memset(pixel, luminance, 4);
}
}
}
static void
ComputeLinearRGBLuminanceMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity)
{
for (int32_t y = aRect.y; y < aRect.YMost(); y++) {
for (int32_t x = aRect.x; x < aRect.XMost(); x++) {
uint8_t *pixel = aData + aStride * y + 4 * x;
uint8_t a = pixel[GFX_ARGB32_OFFSET_A];
uint8_t luminance;
// unpremultiply
if (a) {
if (a != 255) {
pixel[GFX_ARGB32_OFFSET_B] =
(255 * pixel[GFX_ARGB32_OFFSET_B]) / a;
pixel[GFX_ARGB32_OFFSET_G] =
(255 * pixel[GFX_ARGB32_OFFSET_G]) / a;
pixel[GFX_ARGB32_OFFSET_R] =
(255 * pixel[GFX_ARGB32_OFFSET_R]) / a;
}
/* sRGB -> linearRGB -> intensity */
luminance =
static_cast<uint8_t>
((gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_R]] *
0.2125 +
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_G]] *
0.7154 +
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_B]] *
0.0721) * (a / 255.0) * aOpacity);
} else {
luminance = 0;
}
memset(pixel, luminance, 4);
}
}
}
static void
ComputeAlphaMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity)
{
for (int32_t y = aRect.y; y < aRect.YMost(); y++) {
for (int32_t x = aRect.x; x < aRect.XMost(); x++) {
uint8_t *pixel = aData + aStride * y + 4 * x;
uint8_t luminance = pixel[GFX_ARGB32_OFFSET_A] * aOpacity;
memset(pixel, luminance, 4);
}
}
}
//----------------------------------------------------------------------
// Implementation
@ -118,12 +254,12 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext,
if (StyleSVGReset()->mMaskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
if (StyleSVG()->mColorInterpolation ==
NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
nsSVGUtils::ComputeLinearRGBLuminanceMask(data, stride, rect, aOpacity);
ComputeLinearRGBLuminanceMask(data, stride, rect, aOpacity);
} else {
nsSVGUtils::ComputesRGBLuminanceMask(data, stride, rect, aOpacity);
ComputesRGBLuminanceMask(data, stride, rect, aOpacity);
}
} else {
nsSVGUtils::ComputeAlphaMask(data, stride, rect, aOpacity);
ComputeAlphaMask(data, stride, rect, aOpacity);
}
nsRefPtr<gfxPattern> retval = new gfxPattern(image);

View File

@ -58,80 +58,6 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gfx;
// c = n / 255
// (c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1 / 2.4) - 0.055) * 255 + 0.5
static const uint8_t glinearRGBTosRGBMap[256] = {
0, 13, 22, 28, 34, 38, 42, 46,
50, 53, 56, 59, 61, 64, 66, 69,
71, 73, 75, 77, 79, 81, 83, 85,
86, 88, 90, 92, 93, 95, 96, 98,
99, 101, 102, 104, 105, 106, 108, 109,
110, 112, 113, 114, 115, 117, 118, 119,
120, 121, 122, 124, 125, 126, 127, 128,
129, 130, 131, 132, 133, 134, 135, 136,
137, 138, 139, 140, 141, 142, 143, 144,
145, 146, 147, 148, 148, 149, 150, 151,
152, 153, 154, 155, 155, 156, 157, 158,
159, 159, 160, 161, 162, 163, 163, 164,
165, 166, 167, 167, 168, 169, 170, 170,
171, 172, 173, 173, 174, 175, 175, 176,
177, 178, 178, 179, 180, 180, 181, 182,
182, 183, 184, 185, 185, 186, 187, 187,
188, 189, 189, 190, 190, 191, 192, 192,
193, 194, 194, 195, 196, 196, 197, 197,
198, 199, 199, 200, 200, 201, 202, 202,
203, 203, 204, 205, 205, 206, 206, 207,
208, 208, 209, 209, 210, 210, 211, 212,
212, 213, 213, 214, 214, 215, 215, 216,
216, 217, 218, 218, 219, 219, 220, 220,
221, 221, 222, 222, 223, 223, 224, 224,
225, 226, 226, 227, 227, 228, 228, 229,
229, 230, 230, 231, 231, 232, 232, 233,
233, 234, 234, 235, 235, 236, 236, 237,
237, 238, 238, 238, 239, 239, 240, 240,
241, 241, 242, 242, 243, 243, 244, 244,
245, 245, 246, 246, 246, 247, 247, 248,
248, 249, 249, 250, 250, 251, 251, 251,
252, 252, 253, 253, 254, 254, 255, 255
};
// c = n / 255
// c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)) * 255 + 0.5
static const uint8_t gsRGBToLinearRGBMap[256] = {
0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7,
8, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 12, 12, 12, 13,
13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 17, 18, 18, 19, 19, 20,
20, 21, 22, 22, 23, 23, 24, 24,
25, 25, 26, 27, 27, 28, 29, 29,
30, 30, 31, 32, 32, 33, 34, 35,
35, 36, 37, 37, 38, 39, 40, 41,
41, 42, 43, 44, 45, 45, 46, 47,
48, 49, 50, 51, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 76, 77, 78, 79,
80, 81, 82, 84, 85, 86, 87, 88,
90, 91, 92, 93, 95, 96, 97, 99,
100, 101, 103, 104, 105, 107, 108, 109,
111, 112, 114, 115, 116, 118, 119, 121,
122, 124, 125, 127, 128, 130, 131, 133,
134, 136, 138, 139, 141, 142, 144, 146,
147, 149, 151, 152, 154, 156, 157, 159,
161, 163, 164, 166, 168, 170, 171, 173,
175, 177, 179, 181, 183, 184, 186, 188,
190, 192, 194, 196, 198, 200, 202, 204,
206, 208, 210, 212, 214, 216, 218, 220,
222, 224, 226, 229, 231, 233, 235, 237,
239, 242, 244, 246, 248, 250, 253, 255
};
static bool sSVGDisplayListHitTestingEnabled;
static bool sSVGDisplayListPaintingEnabled;
@ -209,179 +135,6 @@ nsSVGUtils::Init()
"svg.display-lists.painting.enabled");
}
void
nsSVGUtils::UnPremultiplyImageDataAlpha(uint8_t *data,
int32_t stride,
const nsIntRect &rect)
{
for (int32_t y = rect.y; y < rect.YMost(); y++) {
for (int32_t x = rect.x; x < rect.XMost(); x++) {
uint8_t *pixel = data + stride * y + 4 * x;
uint8_t a = pixel[GFX_ARGB32_OFFSET_A];
if (a == 255)
continue;
if (a) {
pixel[GFX_ARGB32_OFFSET_B] = (255 * pixel[GFX_ARGB32_OFFSET_B]) / a;
pixel[GFX_ARGB32_OFFSET_G] = (255 * pixel[GFX_ARGB32_OFFSET_G]) / a;
pixel[GFX_ARGB32_OFFSET_R] = (255 * pixel[GFX_ARGB32_OFFSET_R]) / a;
} else {
pixel[GFX_ARGB32_OFFSET_B] = 0;
pixel[GFX_ARGB32_OFFSET_G] = 0;
pixel[GFX_ARGB32_OFFSET_R] = 0;
}
}
}
}
void
nsSVGUtils::PremultiplyImageDataAlpha(uint8_t *data,
int32_t stride,
const nsIntRect &rect)
{
for (int32_t y = rect.y; y < rect.YMost(); y++) {
for (int32_t x = rect.x; x < rect.XMost(); x++) {
uint8_t *pixel = data + stride * y + 4 * x;
uint8_t a = pixel[GFX_ARGB32_OFFSET_A];
if (a == 255)
continue;
FAST_DIVIDE_BY_255(pixel[GFX_ARGB32_OFFSET_B],
pixel[GFX_ARGB32_OFFSET_B] * a);
FAST_DIVIDE_BY_255(pixel[GFX_ARGB32_OFFSET_G],
pixel[GFX_ARGB32_OFFSET_G] * a);
FAST_DIVIDE_BY_255(pixel[GFX_ARGB32_OFFSET_R],
pixel[GFX_ARGB32_OFFSET_R] * a);
}
}
}
void
nsSVGUtils::ConvertImageDataToLinearRGB(uint8_t *data,
int32_t stride,
const nsIntRect &rect)
{
for (int32_t y = rect.y; y < rect.YMost(); y++) {
for (int32_t x = rect.x; x < rect.XMost(); x++) {
uint8_t *pixel = data + stride * y + 4 * x;
pixel[GFX_ARGB32_OFFSET_B] =
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_B]];
pixel[GFX_ARGB32_OFFSET_G] =
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_G]];
pixel[GFX_ARGB32_OFFSET_R] =
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_R]];
}
}
}
void
nsSVGUtils::ConvertImageDataFromLinearRGB(uint8_t *data,
int32_t stride,
const nsIntRect &rect)
{
for (int32_t y = rect.y; y < rect.YMost(); y++) {
for (int32_t x = rect.x; x < rect.XMost(); x++) {
uint8_t *pixel = data + stride * y + 4 * x;
pixel[GFX_ARGB32_OFFSET_B] =
glinearRGBTosRGBMap[pixel[GFX_ARGB32_OFFSET_B]];
pixel[GFX_ARGB32_OFFSET_G] =
glinearRGBTosRGBMap[pixel[GFX_ARGB32_OFFSET_G]];
pixel[GFX_ARGB32_OFFSET_R] =
glinearRGBTosRGBMap[pixel[GFX_ARGB32_OFFSET_R]];
}
}
}
void
nsSVGUtils::ComputesRGBLuminanceMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity)
{
for (int32_t y = aRect.y; y < aRect.YMost(); y++) {
for (int32_t x = aRect.x; x < aRect.XMost(); x++) {
uint8_t *pixel = aData + aStride * y + 4 * x;
uint8_t a = pixel[GFX_ARGB32_OFFSET_A];
uint8_t luminance;
if (a) {
/* sRGB -> intensity (unpremultiply cancels out the
* (a/255.0) multiplication with aOpacity */
luminance =
static_cast<uint8_t>
((pixel[GFX_ARGB32_OFFSET_R] * 0.2125 +
pixel[GFX_ARGB32_OFFSET_G] * 0.7154 +
pixel[GFX_ARGB32_OFFSET_B] * 0.0721) *
aOpacity);
} else {
luminance = 0;
}
memset(pixel, luminance, 4);
}
}
}
void
nsSVGUtils::ComputeLinearRGBLuminanceMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity)
{
for (int32_t y = aRect.y; y < aRect.YMost(); y++) {
for (int32_t x = aRect.x; x < aRect.XMost(); x++) {
uint8_t *pixel = aData + aStride * y + 4 * x;
uint8_t a = pixel[GFX_ARGB32_OFFSET_A];
uint8_t luminance;
// unpremultiply
if (a) {
if (a != 255) {
pixel[GFX_ARGB32_OFFSET_B] =
(255 * pixel[GFX_ARGB32_OFFSET_B]) / a;
pixel[GFX_ARGB32_OFFSET_G] =
(255 * pixel[GFX_ARGB32_OFFSET_G]) / a;
pixel[GFX_ARGB32_OFFSET_R] =
(255 * pixel[GFX_ARGB32_OFFSET_R]) / a;
}
/* sRGB -> linearRGB -> intensity */
luminance =
static_cast<uint8_t>
((gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_R]] *
0.2125 +
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_G]] *
0.7154 +
gsRGBToLinearRGBMap[pixel[GFX_ARGB32_OFFSET_B]] *
0.0721) * (a / 255.0) * aOpacity);
} else {
luminance = 0;
}
memset(pixel, luminance, 4);
}
}
}
void
nsSVGUtils::ComputeAlphaMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity)
{
for (int32_t y = aRect.y; y < aRect.YMost(); y++) {
for (int32_t x = aRect.x; x < aRect.XMost(); x++) {
uint8_t *pixel = aData + aStride * y + 4 * x;
uint8_t luminance = pixel[GFX_ARGB32_OFFSET_A] * aOpacity;
memset(pixel, luminance, 4);
}
}
}
nsSVGDisplayContainerFrame*
nsSVGUtils::GetNearestSVGViewport(nsIFrame *aFrame)
{
@ -1120,22 +873,6 @@ nsSVGUtils::CompositeSurfaceMatrix(gfxContext *aContext,
}
}
void
nsSVGUtils::CompositePatternMatrix(gfxContext *aContext,
gfxPattern *aPattern,
const gfxMatrix &aCTM, float aWidth, float aHeight, float aOpacity)
{
if (aCTM.IsSingular())
return;
aContext->Save();
SetClipRect(aContext, aCTM, gfxRect(0, 0, aWidth, aHeight));
aContext->Multiply(aCTM);
aContext->SetPattern(aPattern);
aContext->Paint(aOpacity);
aContext->Restore();
}
void
nsSVGUtils::SetClipRect(gfxContext *aContext,
const gfxMatrix &aCTM,
@ -1149,17 +886,6 @@ nsSVGUtils::SetClipRect(gfxContext *aContext,
aContext->Clip(aRect);
}
void
nsSVGUtils::ClipToGfxRect(nsIntRect* aRect, const gfxRect& aGfxRect)
{
gfxRect r = aGfxRect;
r.RoundOut();
gfxRect r2(aRect->x, aRect->y, aRect->width, aRect->height);
r = r.Intersect(r2);
*aRect = nsIntRect(int32_t(r.X()), int32_t(r.Y()),
int32_t(r.Width()), int32_t(r.Height()));
}
gfxRect
nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
{

View File

@ -111,21 +111,6 @@ class SourceSurface;
#define NS_STATE_SVG_TEXT_IN_REFLOW NS_FRAME_STATE_BIT(24)
/**
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
*/
#ifdef IS_BIG_ENDIAN
#define GFX_ARGB32_OFFSET_A 0
#define GFX_ARGB32_OFFSET_R 1
#define GFX_ARGB32_OFFSET_G 2
#define GFX_ARGB32_OFFSET_B 3
#else
#define GFX_ARGB32_OFFSET_A 3
#define GFX_ARGB32_OFFSET_R 2
#define GFX_ARGB32_OFFSET_G 1
#define GFX_ARGB32_OFFSET_B 0
#endif
// maximum dimension of an offscreen surface - choose so that
// the surface size doesn't overflow a 32-bit signed int using
// 4 bytes per pixel; in line with gfxASurface::CheckSurfaceSize
@ -247,55 +232,6 @@ public:
static void Init();
/*
* Converts image data from premultipled to unpremultiplied alpha
*/
static void UnPremultiplyImageDataAlpha(uint8_t *data,
int32_t stride,
const nsIntRect &rect);
/*
* Converts image data from unpremultipled to premultiplied alpha
*/
static void PremultiplyImageDataAlpha(uint8_t *data,
int32_t stride,
const nsIntRect &rect);
/*
* Converts image data from premultiplied sRGB to Linear RGB
*/
static void ConvertImageDataToLinearRGB(uint8_t *data,
int32_t stride,
const nsIntRect &rect);
/*
* Converts image data from LinearRGB to premultiplied sRGB
*/
static void ConvertImageDataFromLinearRGB(uint8_t *data,
int32_t stride,
const nsIntRect &rect);
/*
* Converts image data from sRGB to luminance
*/
static void ComputesRGBLuminanceMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity);
/*
* Converts image data from sRGB to luminance assuming
* Linear RGB Interpolation
*/
static void ComputeLinearRGBLuminanceMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity);
/*
* Converts image data to luminance using the value of alpha as luminance
*/
static void ComputeAlphaMask(uint8_t *aData,
int32_t aStride,
const nsIntRect &aRect,
float aOpacity);
/**
* Gets the nearest nsSVGInnerSVGFrame or nsSVGOuterSVGFrame frame. aFrame
* must be an SVG frame. If aFrame is of type nsGkAtoms::svgOuterSVGFrame,
@ -489,19 +425,10 @@ public:
const gfxPoint &aSurfaceOffset,
const gfxMatrix &aCTM);
static void CompositePatternMatrix(gfxContext *aContext,
gfxPattern *aPattern,
const gfxMatrix &aCTM, float aWidth, float aHeight, float aOpacity);
static void SetClipRect(gfxContext *aContext,
const gfxMatrix &aCTM,
const gfxRect &aRect);
/**
* Restricts aRect to pixels that intersect aGfxRect.
*/
static void ClipToGfxRect(nsIntRect* aRect, const gfxRect& aGfxRect);
/* Using group opacity instead of fill or stroke opacity on a
* geometry object seems to be a common authoring mistake. If we're
* not applying filters and not both stroking and filling, we can

View File

@ -4,6 +4,7 @@
* 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 <iomanip>
#include "logging.h"
#include "nspr.h"
#include "cryptohi.h"
@ -25,6 +26,9 @@ DtlsIdentity::~DtlsIdentity() {
CERT_DestroyCertificate(cert_);
}
const std::string DtlsIdentity::DEFAULT_HASH_ALGORITHM = "sha-256";
const size_t DtlsIdentity::HASH_ALGORITHM_MAX_LENGTH = 64;
TemporaryRef<DtlsIdentity> DtlsIdentity::Generate() {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
@ -86,7 +90,7 @@ TemporaryRef<DtlsIdentity> DtlsIdentity::Generate() {
// now with some slack in case the other side expects
// some before expiry.
//
// Note: explicit casts necessary to avoid
// Note: explicit casts necessary to avoid
// warning C4307: '*' : integral constant overflow
static const PRTime oneDay = PRTime(PR_USEC_PER_SEC)
* PRTime(60) // sec
@ -206,8 +210,29 @@ nsresult DtlsIdentity::ComputeFingerprint(const CERTCertificate *cert,
return NS_OK;
}
// Format the fingerprint in RFC 4572 Section 5 format, colons and
// all.
// Format the fingerprint in RFC 4572 Section 5 attribute format, including both
// the hash name and the fingerprint, colons and all.
// returns an empty string if there is a problem
std::string DtlsIdentity::GetFormattedFingerprint(const std::string &algorithm) {
unsigned char digest[HASH_ALGORITHM_MAX_LENGTH];
size_t digest_length;
nsresult res = this->ComputeFingerprint(algorithm,
digest,
sizeof(digest),
&digest_length);
if (NS_FAILED(res)) {
MOZ_MTLOG(ML_ERROR, "Unable to compute " << algorithm
<< " hash for identity: nsresult = 0x"
<< std::hex << std::uppercase
<< static_cast<uint32_t>(res)
<< std::nouppercase << std::dec);
return "";
}
return algorithm + " " + this->FormatFingerprint(digest, digest_length);
}
std::string DtlsIdentity::FormatFingerprint(const unsigned char *digest,
std::size_t size) {
std::string str("");
@ -215,7 +240,7 @@ std::string DtlsIdentity::FormatFingerprint(const unsigned char *digest,
for (std::size_t i=0; i < size; i++) {
PR_snprintf(group, sizeof(group), "%.2X", digest[i]);
if (i != 0){
if (i != 0) {
str += ":";
}
str += group;

View File

@ -32,6 +32,8 @@ class DtlsIdentity {
CERTCertificate *cert() { return cert_; }
SECKEYPrivateKey *privkey() { return privkey_; }
std::string GetFormattedFingerprint(const std::string &algorithm = DEFAULT_HASH_ALGORITHM);
nsresult ComputeFingerprint(const std::string algorithm,
unsigned char *digest,
std::size_t size,
@ -43,8 +45,6 @@ class DtlsIdentity {
std::size_t size,
std::size_t *digest_length);
static std::string FormatFingerprint(const unsigned char *digest,
std::size_t size);
static nsresult ParseFingerprint(const std::string fp,
unsigned char *digest,
size_t size, size_t *length);
@ -56,6 +56,12 @@ class DtlsIdentity {
: privkey_(privkey), cert_(cert) {}
DISALLOW_COPY_ASSIGN(DtlsIdentity);
static const std::string DEFAULT_HASH_ALGORITHM;
static const size_t HASH_ALGORITHM_MAX_LENGTH;
std::string FormatFingerprint(const unsigned char *digest,
std::size_t size);
ScopedSECKEYPrivateKey privkey_;
CERTCertificate *cert_; // TODO: Using a smart pointer here causes link
// errors.

View File

@ -1178,10 +1178,10 @@ short vcmAddRemoteStreamHint(
* Get DTLS key data
*
* @param[in] peerconnection - the peerconnection in use
* @param[out] digest_algp - the digest algorithm e.g. 'SHA-1'
* @param[in] max_digest_alg_len - length of string
* @param[out] digest_algp - the digest algorithm e.g. 'sha-256'
* @param[in] max_digest_alg_len - available length of string
* @param[out] digestp - the digest string
* @param[in] max_digest_len - length of string
* @param[in] max_digest_len - available length of string
*
* Returns: zero(0) for success; otherwise, ERROR for failure
*/
@ -1197,33 +1197,10 @@ static short vcmGetDtlsIdentity_m(const char *peerconnection,
sipcc::PeerConnectionWrapper pc(peerconnection);
ENSURE_PC(pc, VCM_ERROR);
unsigned char digest[TransportLayerDtls::kMaxDigestLength];
size_t digest_len;
mozilla::RefPtr<DtlsIdentity> id = pc.impl()->GetIdentity();
if (!id) {
return VCM_ERROR;
}
nsresult res = id->ComputeFingerprint("sha-256", digest, sizeof(digest),
&digest_len);
if (!NS_SUCCEEDED(res)) {
CSFLogError( logTag, "%s: Could not compute identity fingerprint", __FUNCTION__);
return VCM_ERROR;
}
// digest_len should be 32 for SHA-256
PR_ASSERT(digest_len == 32);
std::string fingerprint_txt = DtlsIdentity::FormatFingerprint(digest, digest_len);
if (max_digest_len <= fingerprint_txt.size()) {
CSFLogError( logTag, "%s: Formatted digest will not fit in provided buffer",
__FUNCTION__);
return VCM_ERROR;
}
sstrncpy(digest_algp, "sha-256", max_digest_alg_len);
sstrncpy(digestp, fingerprint_txt.c_str(), max_digest_len);
std::string algorithm = pc.impl()->GetFingerprintAlgorithm();
sstrncpy(digest_algp, algorithm.c_str(), max_digest_alg_len);
std::string value = pc.impl()->GetFingerprintHexValue();
sstrncpy(digestp, value.c_str(), max_digest_len);
return 0;
}

View File

@ -789,26 +789,9 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
return NS_ERROR_FAILURE;
}
// Set the fingerprint. Right now assume we only have one
// DTLS identity
unsigned char fingerprint[DTLS_FINGERPRINT_LENGTH];
size_t fingerprint_length;
res = mIdentity->ComputeFingerprint("sha-256",
fingerprint,
sizeof(fingerprint),
&fingerprint_length);
if (NS_FAILED(res)) {
CSFLogError(logTag, "%s: ComputeFingerprint failed: %u",
__FUNCTION__, static_cast<uint32_t>(res));
return res;
}
mFingerprint = "sha-256 " + mIdentity->FormatFingerprint(fingerprint,
fingerprint_length);
if (NS_FAILED(res)) {
CSFLogError(logTag, "%s: do_GetService failed: %u",
__FUNCTION__, static_cast<uint32_t>(res));
mFingerprint = mIdentity->GetFormattedFingerprint();
if (mFingerprint.empty()) {
CSFLogError(logTag, "%s: unable to get fingerprint", __FUNCTION__);
return res;
}
@ -816,11 +799,56 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
}
RefPtr<DtlsIdentity> const
PeerConnectionImpl::GetIdentity() {
PeerConnectionImpl::GetIdentity() const
{
PC_AUTO_ENTER_API_CALL_NO_CHECK();
return mIdentity;
}
std::string
PeerConnectionImpl::GetFingerprint() const
{
PC_AUTO_ENTER_API_CALL_NO_CHECK();
return mFingerprint;
}
NS_IMETHODIMP
PeerConnectionImpl::FingerprintSplitHelper(std::string& fingerprint,
size_t& spaceIdx) const
{
fingerprint = GetFingerprint();
spaceIdx = fingerprint.find_first_of(' ');
if (spaceIdx == std::string::npos) {
CSFLogError(logTag, "%s: fingerprint is messed up: %s",
__FUNCTION__, fingerprint.c_str());
return NS_ERROR_FAILURE;
}
return NS_OK;
}
std::string
PeerConnectionImpl::GetFingerprintAlgorithm() const
{
std::string fp;
size_t spc;
if (NS_SUCCEEDED(FingerprintSplitHelper(fp, spc))) {
return fp.substr(0, spc);
}
return "";
}
std::string
PeerConnectionImpl::GetFingerprintHexValue() const
{
std::string fp;
size_t spc;
if (NS_SUCCEEDED(FingerprintSplitHelper(fp, spc))) {
return fp.substr(spc + 1);
}
return "";
}
nsresult
PeerConnectionImpl::CreateFakeMediaStream(uint32_t aHint, nsIDOMMediaStream** aRetval)
{

View File

@ -246,7 +246,10 @@ public:
}
// Get the DTLS identity
mozilla::RefPtr<DtlsIdentity> const GetIdentity();
mozilla::RefPtr<DtlsIdentity> const GetIdentity() const;
std::string GetFingerprint() const;
std::string GetFingerprintAlgorithm() const;
std::string GetFingerprintHexValue() const;
// Create a fake media stream
nsresult CreateFakeMediaStream(uint32_t hint, nsIDOMMediaStream** retval);
@ -532,6 +535,10 @@ private:
nsresult IceGatheringStateChange_m(
mozilla::dom::PCImplIceGatheringState aState);
NS_IMETHOD FingerprintSplitHelper(
std::string& fingerprint, size_t& spaceIdx) const;
#ifdef MOZILLA_INTERNAL_API
// Fills in an RTCStatsReportInternal. Must be run on STS.
void GetStats_s(

View File

@ -2005,7 +2005,6 @@ pref("font.minimum-size.tr", 0);
pref("font.minimum-size.x-cans", 0);
pref("font.minimum-size.x-western", 0);
pref("font.minimum-size.x-unicode", 0);
pref("font.minimum-size.x-user-def", 0);
/*
* A value greater than zero enables font size inflation for
@ -3332,10 +3331,6 @@ pref("font.name.serif.x-unicode", "Charis SIL Compact");
pref("font.name.sans-serif.x-unicode", "Fira Sans OT");
pref("font.name.monospace.x-unicode", "Fira Mono OT");
pref("font.name.serif.x-user-def", "Charis SIL Compact");
pref("font.name.sans-serif.x-user-def", "Fira Sans OT");
pref("font.name.monospace.x-user-def", "Fira Mono OT");
pref("font.name.serif.x-western", "Charis SIL Compact");
pref("font.name.sans-serif.x-western", "Fira Sans OT");
pref("font.name.monospace.x-western", "Fira Mono OT");
@ -3417,12 +3412,6 @@ pref("font.name.monospace.x-unicode", "Droid Sans Mono");
pref("font.name-list.serif.x-unicode", "Droid Serif");
pref("font.name-list.sans-serif.x-unicode", "Clear Sans, Roboto, Droid Sans");
pref("font.name.serif.x-user-def", "Charis SIL Compact");
pref("font.name.sans-serif.x-user-def", "Clear Sans");
pref("font.name.monospace.x-user-def", "Droid Sans Mono");
pref("font.name-list.serif.x-user-def", "Droid Serif");
pref("font.name-list.sans-serif.x-user-def", "Clear Sans, Roboto, Droid Sans");
pref("font.name.serif.x-western", "Charis SIL Compact");
pref("font.name.sans-serif.x-western", "Clear Sans");
pref("font.name.monospace.x-western", "Droid Sans Mono");
@ -3499,10 +3488,6 @@ pref("font.default.x-unicode", "sans-serif");
pref("font.size.variable.x-unicode", 16);
pref("font.size.fixed.x-unicode", 12);
pref("font.default.x-user-def", "sans-serif");
pref("font.size.variable.x-user-def", 16);
pref("font.size.fixed.x-user-def", 12);
pref("font.default.x-western", "sans-serif");
pref("font.size.variable.x-western", 16);
pref("font.size.fixed.x-western", 12);
@ -3695,10 +3680,6 @@ pref("font.name.serif.x-unicode", "serif");
pref("font.name.sans-serif.x-unicode", "sans-serif");
pref("font.name.monospace.x-unicode", "monospace");
pref("font.name.serif.x-user-def", "serif");
pref("font.name.sans-serif.x-user-def", "sans-serif");
pref("font.name.monospace.x-user-def", "monospace");
pref("font.name.serif.x-western", "serif");
pref("font.name.sans-serif.x-western", "sans-serif");
pref("font.name.monospace.x-western", "monospace");
@ -3760,10 +3741,6 @@ pref("font.default.x-unicode", "serif");
pref("font.size.variable.x-unicode", 16);
pref("font.size.fixed.x-unicode", 12);
pref("font.default.x-user-def", "serif");
pref("font.size.variable.x-user-def", 16);
pref("font.size.fixed.x-user-def", 12);
pref("font.default.x-western", "serif");
pref("font.size.variable.x-western", 16);
pref("font.size.fixed.x-western", 12);

View File

@ -35,6 +35,11 @@ nsHtml5MetaScanner::tryCharset(nsString* charset)
mCharset.Assign("UTF-8");
return true;
}
if (encoding.EqualsLiteral("x-user-defined")) {
// WebKit/Blink hack for Indian and Armenian legacy sites
mCharset.Assign("windows-1252");
return true;
}
mCharset.Assign(encoding);
return true;
}

View File

@ -1203,8 +1203,7 @@ nsHtml5StreamParser::PreferredForInternalEncodingDecl(nsACString& aEncoding)
return false;
}
if (newEncoding.EqualsLiteral("UTF-16") ||
newEncoding.EqualsLiteral("UTF-16BE") ||
if (newEncoding.EqualsLiteral("UTF-16BE") ||
newEncoding.EqualsLiteral("UTF-16LE")) {
mTreeBuilder->MaybeComplainAboutCharset("EncMetaUtf16",
true,
@ -1212,6 +1211,14 @@ nsHtml5StreamParser::PreferredForInternalEncodingDecl(nsACString& aEncoding)
newEncoding.Assign("UTF-8");
}
if (newEncoding.EqualsLiteral("x-user-defined")) {
// WebKit/Blink hack for Indian and Armenian legacy sites
mTreeBuilder->MaybeComplainAboutCharset("EncMetaUserDefined",
true,
mTokenizer->getLineNumber());
newEncoding.Assign("windows-1252");
}
if (newEncoding.Equals(mCharset)) {
if (mCharsetSource < kCharsetFromMetaPrescan) {
if (mInitialEncodingWasFromParentFrame) {

View File

@ -0,0 +1 @@
<meta charset="x-user-defined">

View File

@ -25,6 +25,7 @@ support-files =
file_bug672453_meta_unsupported.html
file_bug672453_meta_utf16.html
file_bug672453_not_declared.html
file_bug672453_meta_userdefined.html
file_bug716579-16.html
file_bug716579-16.html^headers^
file_bug716579-16.xhtml
@ -92,6 +93,7 @@ support-files =
[test_bug102699.html]
[test_bug174351.html]
[test_bug213517.html]
[test_bug339350.xhtml]
[test_bug358797.html]
[test_bug396568.html]

View File

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=213517
-->
<head>
<meta charset="x-user-defined">
<title>Test for Bug 213517</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 213517 **/
is(document.characterSet, "windows-1252", "x-user-defined in <meta> should have gotten mapped to windows-1252");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=213517">Mozilla Bug 213517</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -25,7 +25,8 @@ var tests = [
"file_bug672453_http_unsupported.html",
"file_bug672453_bomless_utf16.html",
"file_bug672453_meta_utf16.html",
"file_bug672453_meta_non_superset.html"
"file_bug672453_meta_non_superset.html",
"file_bug672453_meta_userdefined.html",
];
var expectedErrors = [
@ -68,7 +69,12 @@ var expectedErrors = [
sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html",
lineNumber: 1,
isWarning: false,
isException: false }
isException: false },
{ errorMessage: "A meta tag was used to declare the character encoding as x-user-defined. This was interpreted as a windows-1252 declaration instead for compatibility with intentionally mis-encoded legacy fonts. This site should migrate to Unicode.",
sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_userdefined.html",
lineNumber: 1,
isWarning: false,
isException: false },
];
SimpleTest.waitForExplicitFinish();

View File

@ -42,6 +42,7 @@
#include <errno.h>
#include <stdio.h>
#include "mozilla/NullPtr.h"
gboolean save_to_stdout(const gchar *buf, gsize count,
GError **error, gpointer data)