mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c.
This commit is contained in:
commit
0512939292
@ -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>
|
||||
|
@ -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">
|
||||
|
||||
|
@ -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">
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "Latency.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include <prlog.h>
|
||||
#include "prlog.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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*)¤tPackAlignment);
|
||||
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, ¤tPackAlignment);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -300,8 +300,6 @@ GLContextProviderCGL::GetGlobalContext(const ContextFlags)
|
||||
gGlobalContext = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gGlobalContext->SetIsGlobalSharedContext(true);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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];
|
||||
|
@ -730,8 +730,6 @@ GLContextProviderWGL::GetGlobalContext(const ContextFlags flags)
|
||||
gGlobalContext[libToUse] = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gGlobalContext[libToUse]->SetIsGlobalSharedContext(true);
|
||||
}
|
||||
|
||||
return static_cast<GLContext*>(gGlobalContext[libToUse]);
|
||||
|
@ -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 */
|
@ -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_ */
|
645
gfx/gl/GLReadTexImageHelper.cpp
Normal file
645
gfx/gl/GLReadTexImageHelper.cpp
Normal 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, ¤tPackAlignment);
|
||||
|
||||
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*)¤tPackAlignment);
|
||||
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
|
||||
|
||||
|
||||
}
|
||||
}
|
78
gfx/gl/GLReadTexImageHelper.h
Normal file
78
gfx/gl/GLReadTexImageHelper.h
Normal 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
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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',
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -158,6 +158,8 @@ SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
||||
serializer.InitializeBufferInfo(yOffset,
|
||||
cbOffset,
|
||||
crOffset,
|
||||
aData.mYStride,
|
||||
aData.mCbCrStride,
|
||||
aData.mYSize,
|
||||
aData.mCbCrSize,
|
||||
aData.mStereoMode);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -272,7 +272,6 @@ static const char *gPrefLangNames[] = {
|
||||
"x-sinh",
|
||||
"x-tibt",
|
||||
"x-unicode",
|
||||
"x-user-def"
|
||||
};
|
||||
|
||||
gfxPlatform::gfxPlatform()
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -2192,6 +2192,8 @@ jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
|
||||
return true;
|
||||
}
|
||||
|
||||
types::FinishDefinitePropertiesAnalysis(cx, constraints);
|
||||
|
||||
if (!SplitCriticalEdges(graph))
|
||||
return false;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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(); });
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -0,0 +1 @@
|
||||
<meta charset="x-user-defined">
|
@ -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]
|
||||
|
30
parser/htmlparser/tests/mochitest/test_bug213517.html
Normal file
30
parser/htmlparser/tests/mochitest/test_bug213517.html
Normal 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>
|
@ -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();
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user