import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1173260 - stub out tests that fail when 'cursive' is looked up via fontconfig. r=m_kato (0bb3f03cb8)
- bug 1215657 - make AccessibleWrap::get_accDefaultAction work with proxied accessibles r=davidb (5732eb38eb)
- Bug 1210549 - Allow IServiceProvider::QueryService to work for proxied accessibles r=tbsaunde (7dcd9c2271)
- bug 1215657 - make AccessibleWrap::accSelect work with proxies r=davidb (d52e3d4873)
- Bug 1225682 - Don't use nsAuto{,C}String as class member variables in rdf/. r=Pike (f681938445)
- Bug 1232454 - use UniquePtr<T[]> instead of nsAutoArrayPtr<T> in security/apps/; r=keeler (e416936ed6)
- Bug 1235796 - Allow allocating YCbCr textures with Cb/Cr planes bigger than the Y plane. r=jrmuizel (8f1dbe137c)
- Bug 1241816 - In CreateSourceSurfaceFromMacIOSurface, unlock the IOSurface even in failure cases. r=mattwoodrow (218e6da6c1)
- Bug 1240190 - Add D3D9 texture upload profiler labels. r=jrmuizel (1e55b77bdf)
- Bug 1213429 - Recycle e10s D3D9 textures and add partial upload support. r=Bas (97aeeefdd2)
- Bug 1213429 - Check the result of LockRect. r=Bas (1c3c981d80)
- Bug 1213429 - GCC compilation fixup. (5449005c99)
- Lazily initialize D3D11 mix-blend shaders. (bug 1246388, r=mattwoodrow) (6fd3226030)
- Bug 1237375: Add some more extensive debugging information. r=milan (aed95e4774)
- Bug 1239861. Part 2 Properly resize DXGI swap chain buffer size. r=bas (e9bf410de4)
- Bug 1247775 - Part 1: Remove D3D10/D2D 1.0 texture integration from layers. r=dvander (74d7e93792)
- Bug 1247775 - Part 2: Remove Direct2D 1.0 code from Thebes. r=dvander (f0a1f53917)
- Bug 1247775 - Part 3: Remove Moz2D code to support Direct2D 1.0. r=dvander (10d27128eb)
- Bug 1221656 - Copy mp4parse.h in update-rust.sh. r=kinetik (96ebce3eb8)
- Bug 868333 - Match more MP4 family file types in media sniffer. r=rillian (cd29bd2a74)
- Bug 1211802 - Recognize 'avc?' as mp4 video. r=jya (b68726705b)
- Bug 1244523: [mp4] P2. Have sniffer recognise ftyp qt subtype. r=cpearce (1770f0862b)
- Bug 1087488: Remove some SPROP macro usages in Omnijar.cpp, to avoid triggering -Wtautological-compare clang warning. r=glandium (697dfa9895)
- Bug 1228437 - Add BHR stats from e10s child process. B2G fix by Ting-Yu Chou. r=nchen (213fbb9f37)
- Bug 1198196 - rework EVENTLOOP_UI_LAG_EXP_MS to record all lag. r=vladan (2807460ce0)
- Bug 1240484 - fixed control flow patch issue by adding brackets. r=mccr8 (d2aac14ee1)
- Bug 1242119 - Remove early exit in WinXP debug content processes. r=froydnj (2c2626a1ea)
- Bug 1245513 - Use _exit(0) to exit in B2G debug content processes. r=froydnj (c37efd34d9)
- some crash and profiler stuff (87547f6d8f)
- bug 1234417 - fix a leak in CreateECPublicKey r=rbarnes (99848f0fae)
- Bug 1204784: Handle cases in nsThreadPool where Gecko doesn't own the thread that we're running on. r=froydnj (3f523fc544)
- Bug 1204784: Do not shut the main thread down before all outstanding asynchronous thread shutdowns complete. r=froydnj (6abfb2562f)
- Bug 1234126 - Add Chaos Mode support for setting thread affinity on OS X and Windows. r=froydnj (8811430596)
- Bug 1245586 - add debugging aids for thread shutdown; r=khuey (28b7ae88c3)
- Bug 1191936 - Implement SPKI/PKCS#8/JWK import/export for RSA-PSS r=rbarnes (212ab7fec5)
- Bug 1241757 - Permit export of JWK with empty key_ops field, r=rbarnes (b19f177a13)
- Bug 1205168 - Part 0: Remove copy-ctor from strong type. r=jgilbert (a6070322a1)
- Bug 1205168 - Part 1 - Sort all the WebGLTexelFormats. r=jgilbert (857cd58641)
- Bug 1205168 - Part 2: Texel Conversion - RG8 format. r=jgilbert (6c241194ed)
- Bug 1205168 - Part 3: Texel Conversion - RG16F format. r=jgilbert (7573635218)
- Bug 1205168 - Part 4: Texel Conversion - RG32F format. r=jgilbert (f54343317e)
- Bug 1205168 - Part 5: Texel Conversion - RGB11F11F10F format. r=jgilbert (500514e025)
- Bug 1205168 - Part 6: Fix TexImage2D and TexSubImage2D with texture conversion. r=jgilbert (b5e2e75276)
- Bug 1205168 - Part 7: Remove unneeded functions. r=jgilbert (9bd24cd813)
- Bug 1234744 - Fix build errors in ImageBitmap.h. r=roc (b4b67e5905)
- missing telemetry bits (28161fd3f9)
- Bug 1237193 - Fix WebGL getActiveUniforms return type. r=jgilbert, r=smaug (f9a37a360e)
- Bug 1233353 - Initialize rb correctly if rb bind to READ_FRAMEBUFFER. r=jgilbert (bbc77437a4)
- Bug 1237637 - Disallow negative levels for framebuffer attachments. -r=jrmuizel (fa65b6ad24)
- Bug 1236395 - [WebGL2] pass getFramebufferAttachmentParameter in gl-object-get-calls.html, r=jgilbert (6f9fde1cd2)
- Bug 1236784 - [WebGL2] pass getRenderbufferParameter in gl-object-get-calls.html, r=jgilbert (e4f20f54ad)
- Bug 1238865 - Part 1: Validate attachments before clearBuffer. r=jgilbert (a6e6e05a0c)
- Bug 1229210. Handle the new formats required by WebGL2 in ReadPixels. r=jgilbert (66e305f97d)
- Bug 1238865 - Part 2: Add more format/type checks for WebGL2. r=jgilbert (af629782b3)
- Bug 1238865 - Part 3: Prevent IMPLEMENTATION_COLOR_READ_FORMAT return SRGB_ALPHA. r=jgilbert (81da93d791)
- Bug 1240673 - Fix WebGL2 framebuffer parameter problem. r=jgilbert (2c957a8294)
- Bug 1240438 - Fix WebGL2 framebuffer attachment related implementation. r=jgilbert (b4339241c8)
- Bug 1239187 - Use the GLFeature instead. - r=jrmuizel (c5f2c57646)
- Bug 1094458 - Implement RenderbufferStorageMultisample. - r=jrmuizel (f20f776597)
- Bug 1246007 - Ignore RENDERBUFFER_SAMPLES outside of webgl2. - r=jrmuizel (6b8f59ae49)
- Bug 1243907 - Don't query _BITS enums on Core profiles. - r=jrmuizel (e722abe45b)
- partial Bug 1242120 - Remove switch fallthrough (0f47fb7a71)
- Bug 1236080. Null check format in GetParameter. r=jgilbert (09fedc2ea8)
- Bug 1240662 - Add max level check for framebufferTextureLayer. r=jgilbert (f6d5eda15c)
- Bug 1236091. Move validate checks inside of null checks. r=jgilbert (4c67e04e87)
- Bug 1237191 - Add check for getQueryParameter to return correct error. r=jgilbert (93345aab7e)
- Bug 1230089 - If sampler is bound, use parameter of sampler. r=jgilbert (e4139a5174)
- Bug 1242336 - Fix WebGL2 return type of GL_UNPACK_SKIP. r=jgilbert (4a2ef1956e)
- Bug 1240262 - Annotate intentional switch fallthrough and suppress -Wimplicit-fallthrough warnings in dom/canvas/. r=jgilbert (eaee57ba8f)
- Bug 1237194 - Fix getSyncParameter return error. r=jgilbert (13119be06e)
- Bug 1239541 - Fix WebGL2 texImage related checking. r=jgilbert (6777244db0)
- Bug 1225291 - IsTransformFeedback doesn't report error when input is null. r=jgilbert (8c67d072b5)
- Bug 1233094. Handle null buffers in GetIndexedParameter. r=jgilbert (ae5d75bd47)
- Bug 1228676 - WebGL2 VertexAttrib funcs should match WebGL 1 patterns. - r=jgilbert (bf96c0e17b)
- Bug 1237420 - "Fix length-checking when setting WebGL 2 vertex attributes with an array". r=jgilbert (d8e9ca7111)
- Bug 1233819 - Fix WebGL on WinXP. - r=jrmuizel (39b15ba9ee)
- Bug 1233046 - Mark non-try platforms. Align some tests. (9d16ce70a4)
- Bug 1201885,1247752,1247753 - Re-mark passing/failing tests. (381c71c0f8)
- Bug 1247764 - Disable STENCIL_TEST on mac+intel when not needed. - r=jrmuizel (0b544d0c36)
- Bug 1243908 - Use DrawBuffers through GLScreenBuffer when operating on fb0. - r=jrmuizel (0ac0fc6047)
- Bug 1229944 - Add glClear for zeroing texture data. - r=kamidphish (51df8cbb50)
- Bug 1220450 - Clear length on cache OOM. r=kamidphish (44431a0d3e)
- Bug 1232346 - Clarify ResolveForDraw's failure checking. - r=kamidphish (542917bb85)
This commit is contained in:
2024-01-11 09:39:33 +08:00
parent ee05861206
commit 5a3b3d60eb
129 changed files with 3770 additions and 5918 deletions
@@ -478,14 +478,17 @@
attrs = { "font-family": kAbsentFontFamily };
testTextAttrs(ID, 18, attrs, defAttrs, 18, 22);
attrs = { };
testTextAttrs(ID, 22, attrs, defAttrs, 22, 27);
// bug 1224498 - this fails with 'cursive' fontconfig lookup
if (!LINUX) {
attrs = { };
testTextAttrs(ID, 22, attrs, defAttrs, 22, 27);
attrs = { "font-family": kCursiveFontFamily };
testTextAttrs(ID, 27, attrs, defAttrs, 27, 31);
attrs = { "font-family": kCursiveFontFamily };
testTextAttrs(ID, 27, attrs, defAttrs, 27, 31);
attrs = { };
testTextAttrs(ID, 31, attrs, defAttrs, 31, 45);
attrs = { };
testTextAttrs(ID, 31, attrs, defAttrs, 31, 45);
}
//////////////////////////////////////////////////////////////////////////
// area17, "text-decoration" tests
+36 -16
View File
@@ -128,7 +128,7 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
return E_NOINTERFACE;
*ppv = static_cast<IEnumVARIANT*>(new ChildrenEnumVariant(this));
} else if (IID_IServiceProvider == iid && !IsProxy())
} else if (IID_IServiceProvider == iid)
*ppv = new ServiceProvider(this);
else if (IID_ISimpleDOMNode == iid && !IsProxy()) {
if (IsDefunct() || (!HasOwnContent() && !IsDoc()))
@@ -882,12 +882,13 @@ AccessibleWrap::get_accDefaultAction(
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
// TODO make this work with proxies.
if (xpAccessible->IsProxy())
return E_NOTIMPL;
nsAutoString defaultAction;
xpAccessible->ActionNameAt(0, defaultAction);
if (xpAccessible->IsProxy()) {
xpAccessible->Proxy()->ActionNameAt(0, defaultAction);
} else {
xpAccessible->ActionNameAt(0, defaultAction);
}
*pszDefaultAction = ::SysAllocStringLen(defaultAction.get(),
defaultAction.Length());
return *pszDefaultAction ? S_OK : E_OUTOFMEMORY;
@@ -913,23 +914,42 @@ AccessibleWrap::accSelect(
if (xpAccessible->IsDefunct())
return CO_E_OBJNOTCONNECTED;
// TODO make this work with proxies.
if (xpAccessible->IsProxy())
return E_NOTIMPL;
if (flagsSelect & (SELFLAG_TAKEFOCUS|SELFLAG_TAKESELECTION|SELFLAG_REMOVESELECTION))
{
if (flagsSelect & SELFLAG_TAKEFOCUS)
if (flagsSelect & SELFLAG_TAKEFOCUS) {
if (xpAccessible->IsProxy()) {
xpAccessible->Proxy()->TakeFocus();
} else {
xpAccessible->TakeFocus();
}
if (flagsSelect & SELFLAG_TAKESELECTION)
return S_OK;
}
if (flagsSelect & SELFLAG_TAKESELECTION) {
if (xpAccessible->IsProxy()) {
xpAccessible->Proxy()->TakeSelection();
} else {
xpAccessible->TakeSelection();
}
if (flagsSelect & SELFLAG_ADDSELECTION)
return S_OK;
}
if (flagsSelect & SELFLAG_ADDSELECTION) {
if (xpAccessible->IsProxy()) {
xpAccessible->Proxy()->SetSelected(true);
} else {
xpAccessible->SetSelected(true);
}
if (flagsSelect & SELFLAG_REMOVESELECTION)
return S_OK;
}
if (flagsSelect & SELFLAG_REMOVESELECTION) {
if (xpAccessible->IsProxy()) {
xpAccessible->Proxy()->SetSelected(false);
} else {
xpAccessible->SetSelected(false);
}
return S_OK;
}
+8 -2
View File
@@ -139,8 +139,11 @@ CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL1Context::Create();
if (!ret)
if (!ret) {
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 0);
return nullptr;
}
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 1);
break;
@@ -148,8 +151,11 @@ CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL2Context::Create();
if (!ret)
if (!ret) {
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 0);
return nullptr;
}
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 1);
break;
+1
View File
@@ -26,6 +26,7 @@ class ErrorResult;
namespace gfx {
class DataSourceSurface;
class DrawTarget;
class SourceSurface;
}
+26
View File
@@ -503,6 +503,7 @@ GetFormatForPackingTuple(GLenum packingFormat, GLenum packingType,
switch (packingFormat) {
case LOCAL_GL_RED:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_RED_INTEGER:
*out_texelFormat = WebGLTexelFormat::R8;
return true;
@@ -515,13 +516,20 @@ GetFormatForPackingTuple(GLenum packingFormat, GLenum packingType,
return true;
case LOCAL_GL_RGB:
case LOCAL_GL_RGB_INTEGER:
*out_texelFormat = WebGLTexelFormat::RGB8;
return true;
case LOCAL_GL_RGBA:
case LOCAL_GL_RGBA_INTEGER:
*out_texelFormat = WebGLTexelFormat::RGBA8;
return true;
case LOCAL_GL_RG:
case LOCAL_GL_RG_INTEGER:
*out_texelFormat = WebGLTexelFormat::RG8;
return true;
default:
break;
}
@@ -584,6 +592,10 @@ GetFormatForPackingTuple(GLenum packingFormat, GLenum packingType,
*out_texelFormat = WebGLTexelFormat::RGBA16F;
return true;
case LOCAL_GL_RG:
*out_texelFormat = WebGLTexelFormat::RG16F;
return true;
default:
break;
}
@@ -612,11 +624,25 @@ GetFormatForPackingTuple(GLenum packingFormat, GLenum packingType,
*out_texelFormat = WebGLTexelFormat::RGBA32F;
return true;
case LOCAL_GL_RG:
*out_texelFormat = WebGLTexelFormat::RG32F;
return true;
default:
break;
}
break;
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
switch (packingFormat) {
case LOCAL_GL_RGB:
*out_texelFormat = WebGLTexelFormat::RGB11F11F10F;
return true;
default:
break;
}
break;
default:
break;
}
+6 -3
View File
@@ -360,9 +360,12 @@ public:
void GetUniformIndices(WebGLProgram* program,
const dom::Sequence<nsString>& uniformNames,
dom::Nullable< nsTArray<GLuint> >& retval);
void GetActiveUniforms(WebGLProgram* program,
const dom::Sequence<GLuint>& uniformIndices, GLenum pname,
dom::Nullable< nsTArray<GLint> >& retval);
void GetActiveUniforms(JSContext* cx,
WebGLProgram* program,
const dom::Sequence<GLuint>& uniformIndices,
GLenum pname,
JS::MutableHandleValue retval);
GLuint GetUniformBlockIndex(WebGLProgram* program, const nsAString& uniformBlockName);
void GetActiveUniformBlockParameter(JSContext*, WebGLProgram* program,
GLuint uniformBlockIndex, GLenum pname,
+30 -12
View File
@@ -20,28 +20,33 @@ GetFBInfoForBlit(const WebGLFramebuffer* fb, const char* const fbInfo,
const webgl::FormatInfo** const out_depthFormat,
const webgl::FormatInfo** const out_stencilFormat)
{
*out_samples = 1; // TODO
*out_samples = 0;
*out_colorFormat = nullptr;
*out_depthFormat = nullptr;
*out_stencilFormat = nullptr;
if (fb->ColorAttachment(0).IsDefined()) {
const auto& attachment = fb->ColorAttachment(0);
*out_samples = attachment.Samples();
*out_colorFormat = attachment.Format()->format;
}
if (fb->DepthStencilAttachment().IsDefined()) {
const auto& attachment = fb->DepthStencilAttachment();
*out_samples = attachment.Samples();
*out_depthFormat = attachment.Format()->format;
*out_stencilFormat = *out_depthFormat;
} else {
if (fb->DepthAttachment().IsDefined()) {
const auto& attachment = fb->DepthAttachment();
*out_samples = attachment.Samples();
*out_depthFormat = attachment.Format()->format;
}
if (fb->StencilAttachment().IsDefined()) {
const auto& attachment = fb->StencilAttachment();
*out_samples = attachment.Samples();
*out_stencilFormat = attachment.Format()->format;
}
}
@@ -118,25 +123,22 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
return;
}
if (!mBoundReadFramebuffer->ValidateAndInitAttachments("blitFramebuffer's READ_FRAMEBUFFER") ||
!mBoundDrawFramebuffer->ValidateAndInitAttachments("blitFramebuffer's DRAW_FRAMEBUFFER"))
{
return;
}
GLsizei srcSamples;
const webgl::FormatInfo* srcColorFormat = nullptr;
const webgl::FormatInfo* srcDepthFormat = nullptr;
const webgl::FormatInfo* srcStencilFormat = nullptr;
if (mBoundReadFramebuffer) {
if (!mBoundReadFramebuffer->ValidateAndInitAttachments("blitFramebuffer's READ_FRAMEBUFFER"))
return;
if (!GetFBInfoForBlit(mBoundReadFramebuffer, "READ_FRAMEBUFFER", &srcSamples,
&srcColorFormat, &srcDepthFormat, &srcStencilFormat))
{
return;
}
} else {
srcSamples = 1; // Always 1.
srcSamples = 0; // Always 0.
GetBackbufferFormats(mOptions, &srcColorFormat, &srcDepthFormat,
&srcStencilFormat);
@@ -148,6 +150,9 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
const webgl::FormatInfo* dstStencilFormat = nullptr;
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments("blitFramebuffer's DRAW_FRAMEBUFFER"))
return;
if (!GetFBInfoForBlit(mBoundDrawFramebuffer, "DRAW_FRAMEBUFFER", &dstSamples,
&dstColorFormat, &dstDepthFormat, &dstStencilFormat))
{
@@ -221,13 +226,13 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
return;
}
if (dstSamples != 1) {
if (dstSamples != 0) {
ErrorInvalidOperation("blitFramebuffer: DRAW_FRAMEBUFFER may not have"
" multiple samples.");
return;
}
if (srcSamples != 1) {
if (srcSamples != 0) {
if (mask & LOCAL_GL_COLOR_BUFFER_BIT &&
dstColorFormat != srcColorFormat)
{
@@ -258,7 +263,7 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
static bool
ValidateTextureLayerAttachment(GLenum attachment)
{
if (LOCAL_GL_COLOR_ATTACHMENT0 < attachment &&
if (LOCAL_GL_COLOR_ATTACHMENT0 <= attachment &&
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
{
return true;
@@ -293,15 +298,23 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
"texture object.");
}
if (level < 0)
if (layer < 0)
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
if (level < 0)
return ErrorInvalidValue("framebufferTextureLayer: level must be >= 0.");
switch (texture->Target().get()) {
case LOCAL_GL_TEXTURE_3D:
if (uint32_t(layer) >= mImplMax3DTextureSize) {
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_3D_TEXTURE_SIZE");
}
if (uint32_t(level) > FloorLog2(mImplMax3DTextureSize)) {
return ErrorInvalidValue("framebufferTextureLayer: layer mube be <= "
"log2(MAX_3D_TEXTURE_SIZE");
}
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
@@ -309,6 +322,11 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_ARRAY_TEXTURE_LAYERS");
}
if (uint32_t(level) > FloorLog2(mImplMaxTextureSize)) {
return ErrorInvalidValue("framebufferTextureLayer: layer mube be <= "
"log2(MAX_TEXTURE_SIZE");
}
break;
default:
+21
View File
@@ -52,21 +52,42 @@ bool WebGL2Context::ValidateClearBuffer(const char* info, GLenum buffer, GLint d
void
WebGL2Context::ClearBufferiv_base(GLenum buffer, GLint drawbuffer, const GLint* value)
{
const char funcName[] = "clearBufferiv";
MakeContextCurrent();
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
return;
}
gl->fClearBufferiv(buffer, drawbuffer, value);
}
void
WebGL2Context::ClearBufferuiv_base(GLenum buffer, GLint drawbuffer, const GLuint* value)
{
const char funcName[] = "clearBufferuiv";
MakeContextCurrent();
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
return;
}
gl->fClearBufferuiv(buffer, drawbuffer, value);
}
void
WebGL2Context::ClearBufferfv_base(GLenum buffer, GLint drawbuffer, const GLfloat* value)
{
const char funcName[] = "clearBufferfv";
MakeContextCurrent();
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
return;
}
gl->fClearBufferfv(buffer, drawbuffer, value);
}
+20
View File
@@ -287,6 +287,20 @@ WebGL2Context::GetQuery(GLenum target, GLenum pname)
return tmp.forget();
}
static bool
ValidateQueryEnum(WebGLContext* webgl, GLenum pname, const char* info)
{
switch (pname) {
case LOCAL_GL_QUERY_RESULT_AVAILABLE:
case LOCAL_GL_QUERY_RESULT:
return true;
default:
webgl->ErrorInvalidEnum("%s: invalid pname: %s", info, webgl->EnumName(pname));
return false;
}
}
void
WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
JS::MutableHandleValue retval)
@@ -296,6 +310,9 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
if (IsContextLost())
return;
if (!ValidateQueryEnum(this, pname, "getQueryParameter"))
return;
if (!query) {
/* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1):
* If id is not the name of a query object, or if the query object
@@ -330,6 +347,9 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
// We must wait for an event loop before the query can be available
if (!query->mCanBeAvailable && !gfxPrefs::WebGLImmediateQueries()) {
if (pname == LOCAL_GL_QUERY_RESULT_AVAILABLE) {
retval.set(JS::BooleanValue(false));
}
return;
}
+35 -36
View File
@@ -15,43 +15,45 @@ void
WebGL2Context::GetInternalformatParameter(JSContext* cx, GLenum target,
GLenum internalformat, GLenum pname,
JS::MutableHandleValue retval,
ErrorResult& rv)
ErrorResult& out_rv)
{
if (IsContextLost())
return;
const char funcName[] = "getInternalfomratParameter";
if (IsContextLost())
return;
if (target != LOCAL_GL_RENDERBUFFER) {
return ErrorInvalidEnumInfo("getInternalfomratParameter: target must be "
"RENDERBUFFER. Was:", target);
}
if (target != LOCAL_GL_RENDERBUFFER) {
ErrorInvalidEnum("%s: `target` must be RENDERBUFFER, was: 0x%04x.", funcName,
target);
return;
}
// GL_INVALID_ENUM is generated if internalformat is not color-,
// depth-, or stencil-renderable.
// TODO: When format table queries lands.
// GL_INVALID_ENUM is generated if internalformat is not color-, depth-, or
// stencil-renderable.
// TODO: When format table queries lands.
if (pname != LOCAL_GL_SAMPLES) {
return ErrorInvalidEnumInfo("getInternalformatParameter: pname must be SAMPLES. "
"Was:", pname);
}
if (pname != LOCAL_GL_SAMPLES) {
ErrorInvalidEnumInfo("%s: `pname` must be SAMPLES, was 0x%04x.", funcName, pname);
return;
}
GLint* samples = nullptr;
GLint sampleCount = 0;
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat,
LOCAL_GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
if (sampleCount > 0) {
samples = new GLint[sampleCount];
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat, LOCAL_GL_SAMPLES,
sampleCount, samples);
}
GLint* samples = nullptr;
GLint sampleCount = 0;
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat,
LOCAL_GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
if (sampleCount > 0) {
samples = new GLint[sampleCount];
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat, LOCAL_GL_SAMPLES,
sampleCount, samples);
}
JSObject* obj = dom::Int32Array::Create(cx, this, sampleCount, samples);
if (!obj) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
JSObject* obj = dom::Int32Array::Create(cx, this, sampleCount, samples);
if (!obj) {
out_rv = NS_ERROR_OUT_OF_MEMORY;
}
delete[] samples;
delete[] samples;
retval.setObjectOrNull(obj);
retval.setObjectOrNull(obj);
}
void
@@ -59,14 +61,11 @@ WebGL2Context::RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
const char funcName[] = "renderbufferStorageMultisample";
if (IsContextLost())
return;
const char funcName[] = "renderbufferStorageMultisample";
if (IsContextLost())
return;
//RenderbufferStorage_base(funcName, target, samples, internalFormat, width, height);
ErrorInvalidOperation("%s: Multisampling is still under development, and is currently"
" disabled.", funcName);
RenderbufferStorage_base(funcName, target, samples, internalFormat, width, height);
}
} // namespace mozilla
+9
View File
@@ -47,6 +47,8 @@ WebGL2Context::DeleteSampler(WebGLSampler* sampler)
for (int n = 0; n < mGLMaxTextureUnits; n++) {
if (mBoundSamplers[n] == sampler) {
mBoundSamplers[n] = nullptr;
InvalidateResolveCacheForTextureWithTexUnit(n);
}
}
@@ -88,6 +90,7 @@ WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
return ErrorInvalidOperation("bindSampler: binding deleted sampler");
WebGLContextUnchecked::BindSampler(unit, sampler);
InvalidateResolveCacheForTextureWithTexUnit(unit);
mBoundSamplers[unit] = sampler;
}
@@ -104,6 +107,7 @@ WebGL2Context::SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint para
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameteri"))
return;
sampler->SamplerParameter1i(pname, param);
WebGLContextUnchecked::SamplerParameteri(sampler, pname, param);
}
@@ -124,6 +128,7 @@ WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameteriv"))
return;
sampler->SamplerParameter1i(pname, param.Data()[0]);
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Data());
}
@@ -143,6 +148,7 @@ WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameteriv"))
return;
sampler->SamplerParameter1i(pname, param[0]);
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Elements());
}
@@ -158,6 +164,7 @@ WebGL2Context::SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat pa
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameterf"))
return;
sampler->SamplerParameter1f(pname, param);
WebGLContextUnchecked::SamplerParameterf(sampler, pname, param);
}
@@ -178,6 +185,7 @@ WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameterfv"))
return;
sampler->SamplerParameter1f(pname, param.Data()[0]);
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Data());
}
@@ -197,6 +205,7 @@ WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameterfv"))
return;
sampler->SamplerParameter1f(pname, param[0]);
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Elements());
}
+11 -4
View File
@@ -35,10 +35,7 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
case LOCAL_GL_SAMPLE_COVERAGE:
case LOCAL_GL_TRANSFORM_FEEDBACK_PAUSED:
case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE:
case LOCAL_GL_UNPACK_SKIP_IMAGES:
case LOCAL_GL_UNPACK_SKIP_PIXELS:
case LOCAL_GL_UNPACK_SKIP_ROWS: {
case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE: {
realGLboolean b = 0;
gl->fGetBooleanv(pname, &b);
return JS::BooleanValue(bool(b));
@@ -87,6 +84,15 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::Int32Value(val);
}
case LOCAL_GL_UNPACK_SKIP_IMAGES:
return JS::Int32Value(mPixelStore_UnpackSkipImages);
case LOCAL_GL_UNPACK_SKIP_PIXELS:
return JS::Int32Value(mPixelStore_UnpackSkipPixels);
case LOCAL_GL_UNPACK_SKIP_ROWS:
return JS::Int32Value(mPixelStore_UnpackSkipRows);
case LOCAL_GL_MAX_3D_TEXTURE_SIZE:
return JS::Int32Value(mImplMax3DTextureSize);
@@ -112,6 +118,7 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::NumberValue(0);
/*** fall through to fGetInteger64v ***/
MOZ_FALLTHROUGH;
case LOCAL_GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
case LOCAL_GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+1 -1
View File
@@ -125,7 +125,7 @@ WebGL2Context::GetSyncParameter(JSContext*, WebGLSync* sync, GLenum pname, JS::M
MakeContextCurrent();
gl->fGetSynciv(sync->mGLName, pname, 1, nullptr, &result);
retval.set(JS::Int32Value(result));
break;
return;
}
ErrorInvalidEnum("getSyncParameter: Invalid pname 0x%04x", pname);
-4
View File
@@ -212,10 +212,6 @@ WebGL2Context::IsTexParamValid(GLenum pname) const
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
case LOCAL_GL_TEXTURE_MAX_LEVEL:
case LOCAL_GL_TEXTURE_SWIZZLE_A:
case LOCAL_GL_TEXTURE_SWIZZLE_B:
case LOCAL_GL_TEXTURE_SWIZZLE_G:
case LOCAL_GL_TEXTURE_SWIZZLE_R:
case LOCAL_GL_TEXTURE_WRAP_R:
case LOCAL_GL_TEXTURE_MAX_LOD:
case LOCAL_GL_TEXTURE_MIN_LOD:
@@ -52,10 +52,10 @@ WebGL2Context::IsTransformFeedback(WebGLTransformFeedback* tf)
if (IsContextLost())
return false;
if (!ValidateObjectAllowDeleted("isTransformFeedback", tf))
if (!ValidateObjectAllowDeletedOrNull("isTransformFeedback", tf))
return false;
if (tf->IsDeleted())
if (!tf || tf->IsDeleted())
return false;
MakeContextCurrent();
+71 -12
View File
@@ -273,8 +273,10 @@ WebGL2Context::GetIndexedParameter(GLenum target, GLuint index,
return ErrorInvalidValue("getIndexedParameter: index should be less than "
"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
retval.SetValue().SetAsWebGLBuffer() =
mBoundTransformFeedbackBuffers[index].get();
if (mBoundTransformFeedbackBuffers[index].get()) {
retval.SetValue().SetAsWebGLBuffer() =
mBoundTransformFeedbackBuffers[index].get();
}
return;
case LOCAL_GL_UNIFORM_BUFFER_BINDING:
@@ -282,7 +284,8 @@ WebGL2Context::GetIndexedParameter(GLenum target, GLuint index,
return ErrorInvalidValue("getIndexedParameter: index should be than "
"MAX_UNIFORM_BUFFER_BINDINGS");
retval.SetValue().SetAsWebGLBuffer() = mBoundUniformBuffers[index].get();
if (mBoundUniformBuffers[index].get())
retval.SetValue().SetAsWebGLBuffer() = mBoundUniformBuffers[index].get();
return;
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START:
@@ -315,20 +318,38 @@ WebGL2Context::GetUniformIndices(WebGLProgram* program,
program->GetUniformIndices(uniformNames, retval);
}
static bool
ValidateUniformEnum(WebGLContext* webgl, GLenum pname, const char* info)
{
switch (pname) {
case LOCAL_GL_UNIFORM_TYPE:
case LOCAL_GL_UNIFORM_SIZE:
case LOCAL_GL_UNIFORM_BLOCK_INDEX:
case LOCAL_GL_UNIFORM_OFFSET:
case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
return true;
default:
webgl->ErrorInvalidEnum("%s: invalid pname: %s", info, webgl->EnumName(pname));
return false;
}
}
void
WebGL2Context::GetActiveUniforms(WebGLProgram* program,
WebGL2Context::GetActiveUniforms(JSContext* cx,
WebGLProgram* program,
const dom::Sequence<GLuint>& uniformIndices,
GLenum pname,
dom::Nullable< nsTArray<GLint> >& retval)
JS::MutableHandleValue retval)
{
retval.SetNull();
retval.set(JS::NullValue());
if (IsContextLost())
return;
if (pname == LOCAL_GL_UNIFORM_NAME_LENGTH) {
ErrorInvalidEnumInfo("getActiveUniforms: pname", pname);
if (!ValidateUniformEnum(this, pname, "getActiveUniforms"))
return;
}
if (!ValidateObject("getActiveUniforms: program", program))
return;
@@ -338,12 +359,50 @@ WebGL2Context::GetActiveUniforms(WebGLProgram* program,
return;
GLuint progname = program->mGLName;
nsTArray<GLint>& arr = retval.SetValue();
arr.SetLength(count);
Vector<GLint> samples;
if (!samples.resize(count)) {
return;
}
MakeContextCurrent();
gl->fGetActiveUniformsiv(progname, count, uniformIndices.Elements(), pname,
arr.Elements());
samples.begin());
JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
if (!array) {
return;
}
switch (pname) {
case LOCAL_GL_UNIFORM_TYPE:
case LOCAL_GL_UNIFORM_SIZE:
case LOCAL_GL_UNIFORM_BLOCK_INDEX:
case LOCAL_GL_UNIFORM_OFFSET:
case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
for (uint32_t i = 0; i < count; ++i) {
JS::RootedValue value(cx);
value = JS::Int32Value(samples[i]);
if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) {
return;
}
}
break;
case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
for (uint32_t i = 0; i < count; ++i) {
JS::RootedValue value(cx);
value = JS::BooleanValue(samples[i]);
if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) {
return;
}
}
break;
default:
return;
}
retval.setObjectOrNull(array);
}
GLuint
+27 -11
View File
@@ -104,36 +104,44 @@ WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
mVertexAttribType[index] = LOCAL_GL_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
MakeContextCurrent();
if (index) {
gl->fVertexAttribI4i(index, x, y, z, w);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(x);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(y);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(z);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(w);
if (gl->IsGLES()) {
gl->fVertexAttribI4i(index, x, y, z, w);
}
}
}
void
WebGL2Context::VertexAttribI4iv(GLuint index, size_t length, const GLint* v)
{
if (!ValidateAttribIndex(index, "vertexAttribI4iv"))
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
return;
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
if (!ValidateAttribIndex(index, "vertexAttribI4iv"))
return;
mVertexAttribType[index] = LOCAL_GL_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
MakeContextCurrent();
if (index) {
gl->fVertexAttribI4iv(index, v);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(v[0]);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(v[1]);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(v[2]);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(v[3]);
if (gl->IsGLES()) {
gl->fVertexAttribI4iv(index, v);
}
}
}
@@ -154,14 +162,18 @@ WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLui
mVertexAttribType[index] = LOCAL_GL_UNSIGNED_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
MakeContextCurrent();
if (index) {
gl->fVertexAttribI4ui(index, x, y, z, w);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(x);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(y);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(z);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(w);
if (gl->IsGLES()) {
gl->fVertexAttribI4ui(index, x, y, z, w);
}
}
}
@@ -171,7 +183,7 @@ WebGL2Context::VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v)
if (IsContextLost())
return;
if (!ValidateAttribIndex(index, "vertexAttribI4uiv"))
if (!ValidateAttribArraySetter("vertexAttribI4uiv", 4, length))
return;
if (!ValidateAttribIndex(index, "vertexAttribI4uiv"))
@@ -179,14 +191,18 @@ WebGL2Context::VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v)
mVertexAttribType[index] = LOCAL_GL_UNSIGNED_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
MakeContextCurrent();
if (index) {
gl->fVertexAttribI4uiv(index, v);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(v[0]);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(v[1]);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(v[2]);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(v[3]);
if (gl->IsGLES()) {
gl->fVertexAttribI4uiv(index, v);
}
}
}
+117 -8
View File
@@ -70,6 +70,10 @@
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
#ifdef MOZ_WIDGET_COCOA
#include "nsCocoaFeatures.h"
#endif
// Generated
#include "mozilla/dom/WebGLRenderingContextBinding.h"
@@ -106,9 +110,9 @@ WebGLContext::WebGLContext()
, mMaxFetchedVertices(0)
, mMaxFetchedInstances(0)
, mBypassShaderValidation(false)
, mGLMaxSamples(1)
, mNeedsFakeNoAlpha(false)
, mNeedsFakeNoStencil(false)
, mNeedsEmulatedLoneDepthStencil(false)
{
mGeneration = 0;
mInvalidated = false;
@@ -888,6 +892,17 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
// ANGLE doesn't quite handle this properly.
if (gl->Caps().depth && !gl->Caps().stencil && gl->IsANGLE())
mNeedsFakeNoStencil = true;
if (!mOptions.stencil && gl->Caps().stencil)
mNeedsFakeNoStencil = true;
#ifdef MOZ_WIDGET_COCOA
if (!nsCocoaFeatures::IsAtLeastVersion(10, 12) &&
gl->Vendor() == GLVendor::Intel)
{
mNeedsEmulatedLoneDepthStencil = true;
}
#endif
}
// Update mOptions.
@@ -1290,8 +1305,7 @@ WebGLContext::ClearScreen()
const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK);
if (changeDrawBuffers) {
const GLenum back = LOCAL_GL_BACK;
gl->fDrawBuffers(1, &back);
gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK);
}
GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT;
@@ -1303,7 +1317,7 @@ WebGLContext::ClearScreen()
ForceClearFramebufferWithDefaultValues(bufferBits, mNeedsFakeNoAlpha);
if (changeDrawBuffers) {
gl->fDrawBuffers(1, &mDefaultFB_DrawBuffer0);
gl->Screen()->SetDrawBuffer(mDefaultFB_DrawBuffer0);
}
}
@@ -1815,10 +1829,19 @@ WebGLContext::ScopedMaskWorkaround::ScopedMaskWorkaround(WebGLContext& webgl)
false);
}
if (mFakeNoStencil) {
MOZ_ASSERT(mWebGL.mStencilTestEnabled);
mWebGL.gl->fDisable(LOCAL_GL_STENCIL_TEST);
}
}
/*static*/ bool
WebGLContext::ScopedMaskWorkaround::HasDepthButNoStencil(const WebGLFramebuffer* fb)
{
const auto& depth = fb->DepthAttachment();
const auto& stencil = fb->StencilAttachment();
return depth.IsDefined() && !stencil.IsDefined();
}
WebGLContext::ScopedMaskWorkaround::~ScopedMaskWorkaround()
{
if (mFakeNoAlpha) {
@@ -1895,9 +1918,70 @@ Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
*out_intSize = std::max<int32_t>(0, intEndInSrc - *out_intStartInSrc);
}
static bool
ZeroTexImageWithClear(WebGLContext* webgl, GLContext* gl, TexImageTarget target,
GLuint tex, uint32_t level, const webgl::FormatUsageInfo* usage,
uint32_t width, uint32_t height)
{
MOZ_ASSERT(gl->IsCurrent());
ScopedFramebuffer scopedFB(gl);
ScopedBindFramebuffer scopedBindFB(gl, scopedFB.FB());
const auto format = usage->format;
GLenum attachPoint = 0;
GLbitfield clearBits = 0;
if (format->isColorFormat) {
attachPoint = LOCAL_GL_COLOR_ATTACHMENT0;
clearBits = LOCAL_GL_COLOR_BUFFER_BIT;
}
if (format->hasDepth) {
attachPoint = LOCAL_GL_DEPTH_ATTACHMENT;
clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
}
if (format->hasStencil) {
attachPoint = (format->hasDepth ? LOCAL_GL_DEPTH_STENCIL_ATTACHMENT
: LOCAL_GL_STENCIL_ATTACHMENT);
clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
}
MOZ_RELEASE_ASSERT(attachPoint && clearBits);
{
gl::GLContext::LocalErrorScope errorScope(*gl);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachPoint, target.get(), tex,
level);
if (errorScope.GetError()) {
MOZ_ASSERT(false);
return false;
}
}
auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
return false;
{
gl::GLContext::LocalErrorScope errorScope(*gl);
const bool fakeNoAlpha = false;
webgl->ForceClearFramebufferWithDefaultValues(clearBits, fakeNoAlpha);
if (errorScope.GetError()) {
MOZ_ASSERT(false);
return false;
}
}
return true;
}
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture,
TexImageTarget target, uint32_t level,
GLuint tex, TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
uint32_t zOffset, uint32_t width, uint32_t height, uint32_t depth)
{
@@ -1917,9 +2001,6 @@ ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture
gl::GLContext* gl = webgl->GL();
gl->MakeCurrent();
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
auto compression = usage->format->compression;
if (compression) {
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset);
@@ -1949,6 +2030,10 @@ ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture
if (!zeros)
return false;
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it
// well.
GLenum error = DoCompressedTexSubImage(gl, target.get(), level, xOffset, yOffset,
zOffset, width, height, depth, sizedFormat,
byteCount, zeros.get());
@@ -1961,6 +2046,27 @@ ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture
const auto driverUnpackInfo = usage->idealUnpack;
MOZ_RELEASE_ASSERT(driverUnpackInfo);
if (usage->isRenderable && depth == 1 &&
!xOffset && !yOffset && !zOffset)
{
// While we would like to skip the extra complexity of trying to zero with an FB
// clear, ANGLE_depth_texture requires this.
do {
if (respecifyTexture) {
const auto error = DoTexImage(gl, target, level, driverUnpackInfo, width,
height, depth, nullptr);
if (error)
break;
}
if (ZeroTexImageWithClear(webgl, gl, target, tex, level, usage, width,
height))
{
return true;
}
} while (false);
}
const webgl::PackingInfo packing = driverUnpackInfo->ToPacking();
const auto bytesPerPixel = webgl::BytesPerPixel(packing);
@@ -1979,6 +2085,9 @@ ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture
if (!zeros)
return false;
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
GLenum error;
if (respecifyTexture) {
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset);
+31 -7
View File
@@ -331,6 +331,8 @@ public:
return ActiveBoundTextureForTarget(texTarget);
}
void InvalidateResolveCacheForTextureWithTexUnit(const GLuint);
already_AddRefed<Layer>
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
LayerManager* manager) override;
@@ -824,7 +826,8 @@ protected:
public:
void Disable(GLenum cap);
void Enable(GLenum cap);
bool GetStencilBits(GLint* out_stencilBits);
bool GetStencilBits(GLint* const out_stencilBits);
bool GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val);
virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
void GetParameter(JSContext* cx, GLenum pname,
@@ -1109,7 +1112,6 @@ protected:
int32_t mGLMaxVertexUniformVectors;
uint32_t mGLMaxTransformFeedbackSeparateAttribs;
GLuint mGLMaxUniformBufferBindings;
GLsizei mGLMaxSamples;
// What is supported:
uint32_t mGLMaxColorAttachments;
@@ -1492,6 +1494,7 @@ protected:
bool mNeedsFakeNoAlpha;
bool mNeedsFakeNoStencil;
bool mNeedsEmulatedLoneDepthStencil;
struct ScopedMaskWorkaround {
WebGLContext& mWebGL;
@@ -1506,11 +1509,32 @@ protected:
webgl.mColorWriteMask[3] != false;
}
static bool HasDepthButNoStencil(const WebGLFramebuffer* fb);
static bool ShouldFakeNoStencil(WebGLContext& webgl) {
// We should only be doing this if we're about to draw to the backbuffer.
return !webgl.mBoundDrawFramebuffer &&
webgl.mNeedsFakeNoStencil &&
webgl.mStencilTestEnabled;
if (!webgl.mStencilTestEnabled)
return false;
if (!webgl.mBoundDrawFramebuffer) {
if (webgl.mNeedsFakeNoStencil)
return true;
if (webgl.mNeedsEmulatedLoneDepthStencil &&
webgl.mOptions.depth && !webgl.mOptions.stencil)
{
return true;
}
return false;
}
if (webgl.mNeedsEmulatedLoneDepthStencil &&
HasDepthButNoStencil(webgl.mBoundDrawFramebuffer))
{
return true;
}
return false;
}
explicit ScopedMaskWorkaround(WebGLContext& webgl);
@@ -1739,7 +1763,7 @@ Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture,
TexImageTarget target, uint32_t level,
GLuint tex, TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
uint32_t zOffset, uint32_t width, uint32_t height, uint32_t depth);
+5 -1
View File
@@ -180,6 +180,7 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
}
boundBuffer->SetByteLength(size);
if (!boundBuffer->ElementArrayCacheBufferData(nullptr, size)) {
boundBuffer->SetByteLength(0);
return ErrorOutOfMemory("bufferData: out of memory");
@@ -234,9 +235,12 @@ WebGLContext::BufferDataT(GLenum target,
}
boundBuffer->SetByteLength(data.LengthAllowShared());
// Warning: Possibly shared memory. See bug 1225033.
if (!boundBuffer->ElementArrayCacheBufferData(data.DataAllowShared(), data.LengthAllowShared()))
if (!boundBuffer->ElementArrayCacheBufferData(data.DataAllowShared(), data.LengthAllowShared())) {
boundBuffer->SetByteLength(0);
return ErrorOutOfMemory("bufferData: out of memory");
}
}
void
+13 -10
View File
@@ -47,10 +47,9 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
bool* const out_error)
: mWebGL(webgl)
{
//typedef nsTArray<WebGLRefPtr<WebGLTexture>> TexturesT;
typedef decltype(WebGLContext::mBound2DTextures) TexturesT;
const auto fnResolveAll = [this, funcName, out_error](const TexturesT& textures)
const auto fnResolveAll = [this, funcName](const TexturesT& textures)
{
const auto len = textures.Length();
for (uint32_t texUnit = 0; texUnit < len; ++texUnit) {
@@ -59,7 +58,8 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
continue;
FakeBlackType fakeBlack;
*out_error |= !tex->ResolveForDraw(funcName, texUnit, &fakeBlack);
if (!tex->ResolveForDraw(funcName, texUnit, &fakeBlack))
return false;
if (fakeBlack == FakeBlackType::None)
continue;
@@ -67,18 +67,21 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
mWebGL->BindFakeBlack(texUnit, tex->Target(), fakeBlack);
mRebindRequests.push_back({texUnit, tex});
}
return true;
};
*out_error = false;
bool ok = true;
ok &= fnResolveAll(mWebGL->mBound2DTextures);
ok &= fnResolveAll(mWebGL->mBoundCubeMapTextures);
ok &= fnResolveAll(mWebGL->mBound3DTextures);
ok &= fnResolveAll(mWebGL->mBound2DArrayTextures);
fnResolveAll(mWebGL->mBound2DTextures);
fnResolveAll(mWebGL->mBoundCubeMapTextures);
fnResolveAll(mWebGL->mBound3DTextures);
fnResolveAll(mWebGL->mBound2DArrayTextures);
if (*out_error) {
if (!ok) {
mWebGL->ErrorOutOfMemory("%s: Failed to resolve textures for draw.", funcName);
}
*out_error = !ok;
}
ScopedResolveTexturesForDraw::~ScopedResolveTexturesForDraw()
+236 -126
View File
@@ -173,17 +173,13 @@ WebGLContext::BindRenderbuffer(GLenum target, WebGLRenderbuffer* wrb)
if (wrb && wrb->IsDeleted())
return;
MakeContextCurrent();
// Usually, we would now call into glBindRenderbuffer. However, since we have to
// potentially emulate packed-depth-stencil, there's not a specific renderbuffer that
// we know we should bind here.
// Instead, we do all renderbuffer binding lazily.
// Sometimes we emulate renderbuffers (depth-stencil emu), so there's not
// always a 1-1 mapping from `wrb` to GL name. Just have `wrb` handle it.
if (wrb) {
wrb->BindRenderbuffer();
#ifdef ANDROID
wrb->mIsRB = true;
#endif
} else {
gl->fBindRenderbuffer(target, 0);
wrb->mHasBeenBound = true;
}
mBoundRenderbuffer = wrb;
@@ -537,7 +533,47 @@ WebGLContext::FramebufferTexture2D(GLenum target,
if (!ValidateFramebufferTarget(target, "framebufferTexture2D"))
return;
if (!IsWebGL2() && level != 0) {
if (level < 0) {
ErrorInvalidValue("framebufferTexture2D: level must not be negative.");
return;
}
if (textarget != LOCAL_GL_TEXTURE_2D &&
(textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
{
return ErrorInvalidEnumInfo("framebufferTexture2D: textarget:",
textarget);
}
if (IsWebGL2()) {
/* GLES 3.0.4 p208:
* If textarget is one of TEXTURE_CUBE_MAP_POSITIVE_X,
* TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z,
* TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_Y,
* or TEXTURE_CUBE_MAP_NEGATIVE_Z, then level must be greater
* than or equal to zero and less than or equal to log2 of the
* value of MAX_CUBE_MAP_TEXTURE_SIZE. If textarget is TEXTURE_2D,
* level must be greater than or equal to zero and no larger than
* log2 of the value of MAX_TEXTURE_SIZE. Otherwise, an
* INVALID_VALUE error is generated.
*/
if (textarget == LOCAL_GL_TEXTURE_2D) {
if (uint32_t(level) > FloorLog2(mImplMaxTextureSize)) {
ErrorInvalidValue("framebufferTexture2D: level is too large.");
return;
}
} else {
MOZ_ASSERT(textarget >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
textarget <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
if (uint32_t(level) > FloorLog2(mImplMaxCubeMapTextureSize)) {
ErrorInvalidValue("framebufferTexture2D: level is too large.");
return;
}
}
} else if (level != 0) {
ErrorInvalidValue("framebufferTexture2D: level must be 0.");
return;
}
@@ -562,14 +598,6 @@ WebGLContext::FramebufferTexture2D(GLenum target,
" framebuffer 0.");
}
if (textarget != LOCAL_GL_TEXTURE_2D &&
(textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
{
return ErrorInvalidEnumInfo("framebufferTexture2D: textarget:",
textarget);
}
if (!ValidateFramebufferAttachment(fb, attachment, "framebufferTexture2D"))
return;
@@ -731,7 +759,7 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
}
switch (attachment) {
case LOCAL_GL_COLOR:
case LOCAL_GL_BACK:
case LOCAL_GL_DEPTH:
case LOCAL_GL_STENCIL:
break;
@@ -755,12 +783,12 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
if (attachment == LOCAL_GL_COLOR)
if (attachment == LOCAL_GL_BACK)
return JS::NumberValue(8);
return JS::NumberValue(0);
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
if (attachment == LOCAL_GL_COLOR)
if (attachment == LOCAL_GL_BACK)
return JS::NumberValue(mOptions.alpha ? 8 : 0);
return JS::NumberValue(0);
@@ -807,24 +835,31 @@ WebGLContext::GetRenderbufferParameter(GLenum target, GLenum pname)
MakeContextCurrent();
switch (pname) {
case LOCAL_GL_RENDERBUFFER_WIDTH:
case LOCAL_GL_RENDERBUFFER_HEIGHT:
case LOCAL_GL_RENDERBUFFER_RED_SIZE:
case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
{
// RB emulation means we have to ask the RB itself.
GLint i = mBoundRenderbuffer->GetRenderbufferParameter(target, pname);
return JS::Int32Value(i);
}
default:
ErrorInvalidEnumInfo("getRenderbufferParameter: parameter", pname);
case LOCAL_GL_RENDERBUFFER_SAMPLES:
if (!IsWebGL2())
break;
// fallthrough
case LOCAL_GL_RENDERBUFFER_WIDTH:
case LOCAL_GL_RENDERBUFFER_HEIGHT:
case LOCAL_GL_RENDERBUFFER_RED_SIZE:
case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
{
// RB emulation means we have to ask the RB itself.
GLint i = mBoundRenderbuffer->GetRenderbufferParameter(target, pname);
return JS::Int32Value(i);
}
default:
break;
}
ErrorInvalidEnumInfo("getRenderbufferParameter: parameter", pname);
return JS::NullValue();
}
@@ -961,6 +996,10 @@ WebGLContext::Hint(GLenum target, GLenum mode)
switch (target) {
case LOCAL_GL_GENERATE_MIPMAP_HINT:
// Deprecated and removed in desktop GL Core profiles.
if (gl->IsCoreProfile())
return;
isValid = true;
break;
@@ -1025,16 +1064,7 @@ WebGLContext::IsRenderbuffer(WebGLRenderbuffer* rb)
if (rb->IsDeleted())
return false;
#ifdef ANDROID
if (gl->WorkAroundDriverBugs() &&
gl->Renderer() == GLRenderer::AndroidEmulator)
{
return rb->mIsRB;
}
#endif
MakeContextCurrent();
return gl->fIsRenderbuffer(rb->PrimaryGLName());
return rb->mHasBeenBound;
}
bool
@@ -1311,15 +1341,49 @@ WebGLContext::DoReadPixelsAndConvert(GLint x, GLint y, GLsizei width, GLsizei he
}
static bool
IsFormatAndTypeUnpackable(GLenum format, GLenum type)
IsFormatAndTypeUnpackable(GLenum format, GLenum type, bool isWebGL2)
{
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
switch (format) {
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_LUMINANCE_ALPHA:
return isWebGL2;
case LOCAL_GL_ALPHA:
case LOCAL_GL_RED:
case LOCAL_GL_RED_INTEGER:
case LOCAL_GL_RG:
case LOCAL_GL_RG_INTEGER:
case LOCAL_GL_RGB:
case LOCAL_GL_RGB_INTEGER:
case LOCAL_GL_RGBA:
case LOCAL_GL_RGBA_INTEGER:
return true;
default:
return false;
}
case LOCAL_GL_BYTE:
switch (format) {
case LOCAL_GL_RED:
case LOCAL_GL_RED_INTEGER:
case LOCAL_GL_RG:
case LOCAL_GL_RG_INTEGER:
case LOCAL_GL_RGB:
case LOCAL_GL_RGB_INTEGER:
case LOCAL_GL_RGBA:
case LOCAL_GL_RGBA_INTEGER:
return true;
default:
return false;
}
case LOCAL_GL_FLOAT:
case LOCAL_GL_HALF_FLOAT:
case LOCAL_GL_HALF_FLOAT_OES:
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_RED:
case LOCAL_GL_RG:
case LOCAL_GL_RGB:
case LOCAL_GL_RGBA:
return true;
@@ -1339,6 +1403,38 @@ IsFormatAndTypeUnpackable(GLenum format, GLenum type)
}
}
static bool
IsIntegerFormatAndTypeUnpackable(GLenum format, GLenum type)
{
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT:
case LOCAL_GL_SHORT:
case LOCAL_GL_UNSIGNED_INT:
case LOCAL_GL_INT:
switch (format) {
case LOCAL_GL_RED_INTEGER:
case LOCAL_GL_RG_INTEGER:
case LOCAL_GL_RGB_INTEGER:
case LOCAL_GL_RGBA_INTEGER:
return true;
default:
return false;
}
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
return format == LOCAL_GL_RGBA ||
format == LOCAL_GL_RGBA_INTEGER;
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
return format == LOCAL_GL_RGB;
default:
return false;
}
}
CheckedUint32
WebGLContext::GetPackSize(uint32_t width, uint32_t height, uint8_t bytesPerPixel,
CheckedUint32* const out_startOffset,
@@ -1394,20 +1490,32 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
if (pixels.IsNull())
return ErrorInvalidValue("readPixels: null destination buffer");
if (!IsFormatAndTypeUnpackable(format, type))
if (!(IsWebGL2() && IsIntegerFormatAndTypeUnpackable(format, type)) &&
!IsFormatAndTypeUnpackable(format, type, IsWebGL2())) {
return ErrorInvalidEnum("readPixels: Bad format or type.");
}
int channels = 0;
// Check the format param
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_RED:
case LOCAL_GL_RED_INTEGER:
channels = 1;
break;
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_RG:
case LOCAL_GL_RG_INTEGER:
channels = 2;
break;
case LOCAL_GL_RGB:
case LOCAL_GL_RGB_INTEGER:
channels = 3;
break;
case LOCAL_GL_RGBA:
case LOCAL_GL_RGBA_INTEGER:
channels = 4;
break;
default:
@@ -1419,11 +1527,22 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
int bytesPerPixel;
int requiredDataType;
switch (type) {
case LOCAL_GL_BYTE:
bytesPerPixel = 1*channels;
requiredDataType = js::Scalar::Int8;
break;
case LOCAL_GL_UNSIGNED_BYTE:
bytesPerPixel = 1*channels;
requiredDataType = js::Scalar::Uint8;
break;
case LOCAL_GL_SHORT:
bytesPerPixel = 2*channels;
requiredDataType = js::Scalar::Int16;
break;
case LOCAL_GL_UNSIGNED_SHORT:
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
@@ -1431,6 +1550,24 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
requiredDataType = js::Scalar::Uint16;
break;
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
case LOCAL_GL_UNSIGNED_INT_24_8:
bytesPerPixel = 4;
requiredDataType = js::Scalar::Uint32;
break;
case LOCAL_GL_UNSIGNED_INT:
bytesPerPixel = 4*channels;
requiredDataType = js::Scalar::Uint32;
break;
case LOCAL_GL_INT:
bytesPerPixel = 4*channels;
requiredDataType = js::Scalar::Int32;
break;
case LOCAL_GL_FLOAT:
bytesPerPixel = 4*channels;
requiredDataType = js::Scalar::Float32;
@@ -1488,14 +1625,28 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
if (!ValidateCurFBForRead("readPixels", &srcFormat, &srcWidth, &srcHeight))
return;
auto srcType = srcFormat->format->componentType;
const bool isSrcTypeFloat = (srcType == webgl::ComponentType::Float);
// Check the format and type params to assure they are an acceptable pair (as per spec)
const GLenum mainReadFormat = LOCAL_GL_RGBA;
const GLenum mainReadType = isSrcTypeFloat ? LOCAL_GL_FLOAT
: LOCAL_GL_UNSIGNED_BYTE;
auto srcType = srcFormat->format->componentType;
GLenum mainReadFormat;
GLenum mainReadType;
switch (srcType) {
case webgl::ComponentType::Float:
mainReadFormat = LOCAL_GL_RGBA;
mainReadType = LOCAL_GL_FLOAT;
break;
case webgl::ComponentType::UInt:
mainReadFormat = LOCAL_GL_RGBA_INTEGER;
mainReadType = LOCAL_GL_UNSIGNED_INT;
break;
case webgl::ComponentType::Int:
mainReadFormat = LOCAL_GL_RGBA_INTEGER;
mainReadType = LOCAL_GL_INT;
break;
default:
mainReadFormat = LOCAL_GL_RGBA;
mainReadType = LOCAL_GL_UNSIGNED_BYTE;
break;
}
GLenum auxReadFormat = mainReadFormat;
GLenum auxReadType = mainReadType;
@@ -1511,7 +1662,18 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
const bool mainMatches = (format == mainReadFormat && type == mainReadType);
const bool auxMatches = (format == auxReadFormat && type == auxReadType);
const bool isValid = mainMatches || auxMatches;
bool isValid = mainMatches || auxMatches;
// OpenGL ES 3.0.4 p194 - When the internal format of the rendering surface is
// RGB10_A2, a third combination of format RGBA and type UNSIGNED_INT_2_10_10_10_REV
// is accepted.
if (srcFormat->format->effectiveFormat == webgl::EffectiveFormat::RGB10_A2 &&
format == LOCAL_GL_RGBA &&
type == LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV)
{
isValid = true;
}
if (!isValid)
return ErrorInvalidOperation("readPixels: Invalid format/type pair");
@@ -1624,66 +1786,41 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
void
WebGLContext::RenderbufferStorage_base(const char* funcName, GLenum target,
GLsizei samples,
GLenum internalFormat, GLsizei width,
GLsizei height)
GLsizei samples, GLenum internalFormat,
GLsizei width, GLsizei height)
{
if (IsContextLost())
return;
if (!mBoundRenderbuffer) {
ErrorInvalidOperation("%s: Called on renderbuffer 0.", funcName);
return;
}
if (target != LOCAL_GL_RENDERBUFFER) {
ErrorInvalidEnumInfo("`target`", funcName, target);
return;
}
if (samples < 0 || samples > mGLMaxSamples) {
ErrorInvalidValue("%s: `samples` is out of the valid range.", funcName);
if (!mBoundRenderbuffer) {
ErrorInvalidOperation("%s: Called on renderbuffer 0.", funcName);
return;
}
if (samples < 0) {
ErrorInvalidValue("%s: `samples` must be >= 0.", funcName);
return;
}
if (width < 0 || height < 0) {
ErrorInvalidValue("%s: Width and height must be >= 0.", funcName);
ErrorInvalidValue("%s: `width` and `height` must be >= 0.", funcName);
return;
}
if (uint32_t(width) > mImplMaxRenderbufferSize ||
uint32_t(height) > mImplMaxRenderbufferSize)
{
ErrorInvalidValue("%s: Width or height exceeds maximum renderbuffer"
" size.", funcName);
return;
}
const auto usage = mFormatUsage->GetRBUsage(internalFormat);
if (!usage) {
ErrorInvalidEnumInfo("`internalFormat`", funcName, internalFormat);
return;
}
// Validation complete.
MakeContextCurrent();
GetAndFlushUnderlyingGLErrors();
mBoundRenderbuffer->RenderbufferStorage(samples, usage, width, height);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
GenerateWarning("%s generated error %s", funcName,
ErrorName(error));
return;
}
mBoundRenderbuffer->RenderbufferStorage(funcName, uint32_t(samples), internalFormat,
uint32_t(width), uint32_t(height));
}
void
WebGLContext::RenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height)
{
RenderbufferStorage_base("renderbufferStorage", target, 0,
internalFormat, width, height);
RenderbufferStorage_base("renderbufferStorage", target, 0, internalFormat, width,
height);
}
void
@@ -2148,6 +2285,8 @@ WebGLContext::CreateRenderbuffer()
{
if (IsContextLost())
return nullptr;
MakeContextCurrent();
RefPtr<WebGLRenderbuffer> globj = new WebGLRenderbuffer(this);
return globj.forget();
}
@@ -2327,35 +2466,6 @@ WebGLContext::RestoreContext()
ForceRestoreContext();
}
WebGLTexelFormat
GetWebGLTexelFormat(TexInternalFormat effectiveInternalFormat)
{
switch (effectiveInternalFormat.get()) {
case LOCAL_GL_RGBA8: return WebGLTexelFormat::RGBA8;
case LOCAL_GL_SRGB8_ALPHA8: return WebGLTexelFormat::RGBA8;
case LOCAL_GL_RGB8: return WebGLTexelFormat::RGB8;
case LOCAL_GL_SRGB8: return WebGLTexelFormat::RGB8;
case LOCAL_GL_ALPHA8: return WebGLTexelFormat::A8;
case LOCAL_GL_LUMINANCE8: return WebGLTexelFormat::R8;
case LOCAL_GL_LUMINANCE8_ALPHA8: return WebGLTexelFormat::RA8;
case LOCAL_GL_RGBA32F: return WebGLTexelFormat::RGBA32F;
case LOCAL_GL_RGB32F: return WebGLTexelFormat::RGB32F;
case LOCAL_GL_ALPHA32F_EXT: return WebGLTexelFormat::A32F;
case LOCAL_GL_LUMINANCE32F_EXT: return WebGLTexelFormat::R32F;
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT: return WebGLTexelFormat::RA32F;
case LOCAL_GL_RGBA16F: return WebGLTexelFormat::RGBA16F;
case LOCAL_GL_RGB16F: return WebGLTexelFormat::RGB16F;
case LOCAL_GL_ALPHA16F_EXT: return WebGLTexelFormat::A16F;
case LOCAL_GL_LUMINANCE16F_EXT: return WebGLTexelFormat::R16F;
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT: return WebGLTexelFormat::RA16F;
case LOCAL_GL_RGBA4: return WebGLTexelFormat::RGBA4444;
case LOCAL_GL_RGB5_A1: return WebGLTexelFormat::RGBA5551;
case LOCAL_GL_RGB565: return WebGLTexelFormat::RGB565;
default:
return WebGLTexelFormat::FormatNotSupportingAnyConversion;
}
}
void
WebGLContext::BlendColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
if (IsContextLost())
+124 -17
View File
@@ -73,7 +73,7 @@ StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv)
}
bool
WebGLContext::GetStencilBits(GLint* out_stencilBits)
WebGLContext::GetStencilBits(GLint* const out_stencilBits)
{
*out_stencilBits = 0;
if (mBoundDrawFramebuffer) {
@@ -97,9 +97,107 @@ WebGLContext::GetStencilBits(GLint* out_stencilBits)
return true;
}
bool
WebGLContext::GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val)
{
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
return false;
}
if (!mBoundDrawFramebuffer) {
switch (pname) {
case LOCAL_GL_RED_BITS:
case LOCAL_GL_GREEN_BITS:
case LOCAL_GL_BLUE_BITS:
*out_val = 8;
break;
case LOCAL_GL_ALPHA_BITS:
*out_val = (mOptions.alpha ? 8 : 0);
break;
case LOCAL_GL_DEPTH_BITS:
if (mOptions.depth) {
const auto& glFormats = gl->GetGLFormats();
GLenum depthFormat = glFormats.depth;
if (mOptions.stencil && glFormats.depthStencil) {
depthFormat = glFormats.depthStencil;
}
if (depthFormat == LOCAL_GL_DEPTH_COMPONENT16) {
*out_val = 16;
} else {
*out_val = 24;
}
} else {
*out_val = 0;
}
break;
case LOCAL_GL_STENCIL_BITS:
*out_val = (mOptions.stencil ? 8 : 0);
break;
default:
MOZ_CRASH("bad pname");
}
return true;
}
if (!gl->IsCoreProfile()) {
gl->fGetIntegerv(pname, out_val);
return true;
}
GLenum fbAttachment = 0;
GLenum fbPName = 0;
switch (pname) {
case LOCAL_GL_RED_BITS:
fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
break;
case LOCAL_GL_GREEN_BITS:
fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
break;
case LOCAL_GL_BLUE_BITS:
fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
break;
case LOCAL_GL_ALPHA_BITS:
fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
break;
case LOCAL_GL_DEPTH_BITS:
fbAttachment = LOCAL_GL_DEPTH_ATTACHMENT;
fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
break;
case LOCAL_GL_STENCIL_BITS:
fbAttachment = LOCAL_GL_STENCIL_ATTACHMENT;
fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
break;
default:
MOZ_CRASH("bad pname");
}
gl->fGetFramebufferAttachmentParameteriv(LOCAL_GL_DRAW_FRAMEBUFFER, fbAttachment,
fbPName, out_val);
return true;
}
JS::Value
WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
{
const char funcName[] = "getParameter";
if (IsContextLost())
return JS::NullValue();
@@ -310,6 +408,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
} else {
i = LOCAL_GL_UNSIGNED_BYTE;
}
return JS::NumberValue(uint32_t(i));
}
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT: {
@@ -330,6 +429,14 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
} else {
i = LOCAL_GL_RGBA;
}
// OpenGL ES 3.0.4 p112 Table 3.2 shows that read format SRGB_ALPHA is
// not supported. And if internal format of fbo is SRGB8_ALPHA8, then
// IMPLEMENTATION_COLOR_READ_FORMAT is SRGB_ALPHA which is not supported
// by ReadPixels. So, just return RGBA here.
if (i == LOCAL_GL_SRGB_ALPHA)
i = LOCAL_GL_RGBA;
return JS::NumberValue(uint32_t(i));
}
// int
@@ -347,11 +454,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::Int32Value(refValue & stencilMask);
}
case LOCAL_GL_STENCIL_BITS: {
GLint stencilBits = 0;
GetStencilBits(&stencilBits);
return JS::Int32Value(stencilBits);
}
case LOCAL_GL_STENCIL_CLEAR_VALUE:
case LOCAL_GL_UNPACK_ALIGNMENT:
case LOCAL_GL_PACK_ALIGNMENT:
@@ -361,22 +464,26 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
case LOCAL_GL_MAX_VERTEX_ATTRIBS:
case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
case LOCAL_GL_RED_BITS:
case LOCAL_GL_GREEN_BITS:
case LOCAL_GL_BLUE_BITS:
case LOCAL_GL_DEPTH_BITS: {
case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS: {
GLint i = 0;
gl->fGetIntegerv(pname, &i);
return JS::Int32Value(i);
}
case LOCAL_GL_ALPHA_BITS: {
GLint i = 0;
if (!mNeedsFakeNoAlpha) {
gl->fGetIntegerv(pname, &i);
}
return JS::Int32Value(i);
case LOCAL_GL_RED_BITS:
case LOCAL_GL_GREEN_BITS:
case LOCAL_GL_BLUE_BITS:
case LOCAL_GL_ALPHA_BITS:
case LOCAL_GL_DEPTH_BITS:
case LOCAL_GL_STENCIL_BITS: {
// Deprecated and removed in GL Core profiles, so special handling required.
GLint val;
if (!GetChannelBits(funcName, pname, &val))
return JS::NullValue();
return JS::Int32Value(val);
}
case LOCAL_GL_MAX_TEXTURE_SIZE:
return JS::Int32Value(mImplMaxTextureSize);
+13
View File
@@ -187,6 +187,19 @@ WebGLContext::IsTexParamValid(GLenum pname) const
}
}
void
WebGLContext::InvalidateResolveCacheForTextureWithTexUnit(const GLuint texUnit)
{
if (mBound2DTextures[texUnit])
mBound2DTextures[texUnit]->InvalidateResolveCache();
if (mBoundCubeMapTextures[texUnit])
mBoundCubeMapTextures[texUnit]->InvalidateResolveCache();
if (mBound3DTextures[texUnit])
mBound3DTextures[texUnit]->InvalidateResolveCache();
if (mBound2DArrayTextures[texUnit])
mBound2DArrayTextures[texUnit]->InvalidateResolveCache();
}
//////////////////////////////////////////////////////////////////////////////////////////
// GL calls
+2
View File
@@ -727,6 +727,8 @@ WebGLContext::AssertCachedBindings()
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
#endif
// We do not check the renderbuffer binding, because we never rely on it matching.
}
void
+2 -7
View File
@@ -448,8 +448,8 @@ WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t setterElemSiz
return false;
if (arrayLength < setterElemSize) {
ErrorInvalidOperation("%s: Array must have >= %d elements.", name,
setterElemSize);
ErrorInvalidValue("%s: Array must have >= %d elements.", name,
setterElemSize);
return false;
}
@@ -786,8 +786,6 @@ WebGLContext::InitAndValidateGL()
mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
mGLMaxSamples = 1;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*)&mImplMaxTextureSize);
gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&mImplMaxCubeMapTextureSize);
@@ -800,9 +798,6 @@ WebGLContext::InitAndValidateGL()
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
if (!gl->GetPotentialInteger(LOCAL_GL_MAX_SAMPLES, (GLint*)&mGLMaxSamples))
mGLMaxSamples = 1;
}
// If we don't support a target, its max size is 0. We should only floor-to-POT if the
+23 -2
View File
@@ -416,8 +416,6 @@ BytesPerPixel(const PackingInfo& packing)
//////////////////////////////////////////////////////////////////////////////////////////
// FormatUsageAuthority
bool
FormatUsageInfo::IsUnpackValid(const PackingInfo& key,
const DriverUnpackInfo** const out_value) const
@@ -430,6 +428,29 @@ FormatUsageInfo::IsUnpackValid(const PackingInfo& key,
return true;
}
void
FormatUsageInfo::ResolveMaxSamples(gl::GLContext* gl)
{
MOZ_ASSERT(!this->maxSamplesKnown);
MOZ_ASSERT(this->maxSamples == 0);
MOZ_ASSERT(gl->IsCurrent());
this->maxSamplesKnown = true;
const GLenum internalFormat = this->format->sizedFormat;
if (!internalFormat)
return;
if (!gl->IsSupported(gl::GLFeature::internalformat_query))
return; // Leave it at 0.
GLint maxSamplesGL = 0;
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalFormat, LOCAL_GL_SAMPLES, 1,
&maxSamplesGL);
this->maxSamples = maxSamplesGL;
}
////////////////////////////////////////
static void
+9
View File
@@ -248,10 +248,15 @@ struct FormatUsageInfo
const FormatInfo* const format;
bool isRenderable;
bool isFilterable;
std::map<PackingInfo, DriverUnpackInfo> validUnpacks;
const DriverUnpackInfo* idealUnpack;
const GLint* textureSwizzleRGBA;
bool maxSamplesKnown;
uint32_t maxSamples;
static const GLint kLuminanceSwizzleRGBA[4];
static const GLint kAlphaSwizzleRGBA[4];
static const GLint kLumAlphaSwizzleRGBA[4];
@@ -262,10 +267,14 @@ struct FormatUsageInfo
, isFilterable(false)
, idealUnpack(nullptr)
, textureSwizzleRGBA(nullptr)
, maxSamplesKnown(false)
, maxSamples(0)
{ }
bool IsUnpackValid(const PackingInfo& key,
const DriverUnpackInfo** const out_value) const;
void ResolveMaxSamples(gl::GLContext* gl);
};
class FormatUsageAuthority
+104 -38
View File
@@ -69,6 +69,17 @@ WebGLFBAttachPoint::Format() const
return nullptr;
}
uint32_t
WebGLFBAttachPoint::Samples() const
{
MOZ_ASSERT(IsDefined());
if (mRenderbufferPtr)
return mRenderbufferPtr->Samples();
return 0;
}
bool
WebGLFBAttachPoint::HasAlpha() const
{
@@ -394,11 +405,11 @@ WebGLFBAttachPoint::FinalizeAttachment(gl::GLContext* gl, GLenum attachment) con
}
break;
}
return ;
return;
}
if (Renderbuffer()) {
Renderbuffer()->FramebufferRenderbuffer(attachment);
Renderbuffer()->DoFramebufferRenderbuffer(attachment);
return;
}
@@ -478,9 +489,11 @@ WebGLFBAttachPoint::GetParameter(const char* funcName, WebGLContext* webgl, JSCo
if (webgl->IsWebGL2() ||
webgl->IsExtensionEnabled(WebGLExtensionID::EXT_sRGB))
{
const auto format = Format()->format;
return JS::Int32Value(format->isSRGB ? LOCAL_GL_SRGB
: LOCAL_GL_LINEAR);
const auto format = Format();
if (!format)
return JS::NullValue();
return JS::Int32Value(format->format->isSRGB ? LOCAL_GL_SRGB
: LOCAL_GL_LINEAR);
}
break;
@@ -788,28 +801,6 @@ WebGLFramebuffer::HasIncompleteAttachments(nsCString* const out_info) const
return hasIncomplete;
}
static bool
MatchOrReplaceSize(const WebGLFBAttachPoint& cur, uint32_t* const out_width,
uint32_t* const out_height)
{
if (!cur.HasImage())
return true;
uint32_t width;
uint32_t height;
cur.Size(&width, &height);
if (!*out_width) {
MOZ_ASSERT(!*out_height);
*out_width = width;
*out_height = height;
return true;
}
return (width == *out_width &&
height == *out_height);
}
bool
WebGLFramebuffer::AllImageRectsMatch() const
{
@@ -817,20 +808,84 @@ WebGLFramebuffer::AllImageRectsMatch() const
DebugOnly<nsCString> fbStatusInfo;
MOZ_ASSERT(!HasIncompleteAttachments(&fbStatusInfo));
bool needsInit = true;
uint32_t width = 0;
uint32_t height = 0;
bool imageRectsMatch = true;
imageRectsMatch &= MatchOrReplaceSize(mColorAttachment0, &width, &height);
imageRectsMatch &= MatchOrReplaceSize(mDepthAttachment, &width, &height);
imageRectsMatch &= MatchOrReplaceSize(mStencilAttachment, &width, &height);
imageRectsMatch &= MatchOrReplaceSize(mDepthStencilAttachment, &width, &height);
const auto fnInitializeOrMatch = [&needsInit, &width,
&height](const WebGLFBAttachPoint& attach)
{
if (!attach.HasImage())
return true;
uint32_t curWidth;
uint32_t curHeight;
attach.Size(&curWidth, &curHeight);
if (needsInit) {
needsInit = false;
width = curWidth;
height = curHeight;
return true;
}
return (curWidth == width &&
curHeight == height);
};
bool matches = true;
matches &= fnInitializeOrMatch(mColorAttachment0 );
matches &= fnInitializeOrMatch(mDepthAttachment );
matches &= fnInitializeOrMatch(mStencilAttachment );
matches &= fnInitializeOrMatch(mDepthStencilAttachment);
for (const auto& cur : mMoreColorAttachments) {
imageRectsMatch &= MatchOrReplaceSize(cur, &width, &height);
matches &= fnInitializeOrMatch(cur);
}
return imageRectsMatch;
return matches;
}
bool
WebGLFramebuffer::AllImageSamplesMatch() const
{
MOZ_ASSERT(HasDefinedAttachments());
DebugOnly<nsCString> fbStatusInfo;
MOZ_ASSERT(!HasIncompleteAttachments(&fbStatusInfo));
bool needsInit = true;
uint32_t samples = 0;
const auto fnInitializeOrMatch = [&needsInit,
&samples](const WebGLFBAttachPoint& attach)
{
if (!attach.HasImage())
return true;
const uint32_t curSamples = attach.Samples();
if (needsInit) {
needsInit = false;
samples = curSamples;
return true;
}
return (curSamples == samples);
};
bool matches = true;
matches &= fnInitializeOrMatch(mColorAttachment0 );
matches &= fnInitializeOrMatch(mDepthAttachment );
matches &= fnInitializeOrMatch(mStencilAttachment );
matches &= fnInitializeOrMatch(mDepthStencilAttachment);
for (const auto& cur : mMoreColorAttachments) {
matches &= fnInitializeOrMatch(cur);
}
return matches;
}
FBStatus
@@ -845,11 +900,14 @@ WebGLFramebuffer::PrecheckFramebufferStatus(nsCString* const out_info) const
if (HasIncompleteAttachments(out_info))
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
if (!AllImageRectsMatch())
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // Inconsistent sizes
if (!AllImageSamplesMatch())
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE; // Inconsistent samples
if (!mContext->IsWebGL2()) {
// INCOMPLETE_DIMENSIONS doesn't exist in GLES3.
if (!AllImageRectsMatch())
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // Inconsistent sizes
const auto depthOrStencilCount = int(mDepthAttachment.IsDefined()) +
int(mStencilAttachment.IsDefined()) +
int(mDepthStencilAttachment.IsDefined());
@@ -987,7 +1045,13 @@ WebGLFramebuffer::ValidateAndInitAttachments(const char* funcName)
}
// Clear!
mContext->ForceClearFramebufferWithDefaultValues(clearBits, false);
{
// This FB maybe bind to GL_READ_FRAMEBUFFER and glClear only
// clear GL_DRAW_FRAMEBUFFER. So bind FB to GL_DRAW_FRAMEBUFFER
// here.
gl::ScopedBindFramebuffer autoFB(mContext->gl, mGLName);
mContext->ForceClearFramebufferWithDefaultValues(clearBits, false);
}
if (hasDrawBuffers) {
fnDrawBuffers(mDrawBuffers);
@@ -1149,6 +1213,8 @@ WebGLFramebuffer::GetAttachmentParameter(const char* funcName, JSContext* cx,
attachPoint = GetAttachPoint(LOCAL_GL_DEPTH_ATTACHMENT);
}
FinalizeAttachments();
return attachPoint->GetParameter(funcName, mContext, cx, target, attachment, pname,
out_error);
}
+2 -2
View File
@@ -49,7 +49,6 @@ private:
, mAttachmentPoint(0)
{ }
public:
WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint);
~WebGLFBAttachPoint();
@@ -60,6 +59,7 @@ public:
bool IsDeleteRequested() const;
const webgl::FormatUsageInfo* Format() const;
uint32_t Samples() const;
bool HasAlpha() const;
bool IsReadableFloat() const;
@@ -98,7 +98,6 @@ public:
void SetImageDataStatus(WebGLImageDataStatus x);
void Size(uint32_t* const out_width, uint32_t* const out_height) const;
//const WebGLRectangleObject& RectangleObject() const;
bool HasImage() const;
bool IsComplete(WebGLContext* webgl, nsCString* const out_info) const;
@@ -229,6 +228,7 @@ public:
bool HasDefinedAttachments() const;
bool HasIncompleteAttachments(nsCString* const out_info) const;
bool AllImageRectsMatch() const;
bool AllImageSamplesMatch() const;
FBStatus PrecheckFramebufferStatus(nsCString* const out_info) const;
FBStatus CheckFramebufferStatus(nsCString* const out_info) const;
+127 -121
View File
@@ -15,7 +15,7 @@
namespace mozilla {
static GLenum
DepthStencilDepthFormat(gl::GLContext* gl)
DepthFormatForDepthStencilEmu(gl::GLContext* gl)
{
// We might not be able to get 24-bit, so let's pretend!
if (gl->IsGLES() && !gl->IsExtensionSupported(gl::GLContext::OES_depth24))
@@ -24,47 +24,38 @@ DepthStencilDepthFormat(gl::GLContext* gl)
return LOCAL_GL_DEPTH_COMPONENT24;
}
static bool
SupportsDepthStencil(gl::GLContext* gl)
{
return gl->IsExtensionSupported(gl::GLContext::EXT_packed_depth_stencil) ||
gl->IsExtensionSupported(gl::GLContext::OES_packed_depth_stencil);
}
static bool
NeedsDepthStencilEmu(gl::GLContext* gl, GLenum internalFormat)
{
MOZ_ASSERT(internalFormat != LOCAL_GL_DEPTH_STENCIL);
if (internalFormat != LOCAL_GL_DEPTH24_STENCIL8)
return false;
return !SupportsDepthStencil(gl);
}
JSObject*
WebGLRenderbuffer::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
{
return dom::WebGLRenderbufferBinding::Wrap(cx, this, givenProto);
}
static GLuint
DoCreateRenderbuffer(gl::GLContext* gl)
{
MOZ_ASSERT(gl->IsCurrent());
GLuint ret = 0;
gl->fGenRenderbuffers(1, &ret);
return ret;
}
static bool
EmulatePackedDepthStencil(gl::GLContext* gl)
{
return !gl->IsSupported(gl::GLFeature::packed_depth_stencil);
}
WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl)
: WebGLContextBoundObject(webgl)
, mPrimaryRB(0)
, mPrimaryRB( DoCreateRenderbuffer(webgl->gl) )
, mEmulatePackedDepthStencil( EmulatePackedDepthStencil(webgl->gl) )
, mSecondaryRB(0)
, mFormat(nullptr)
, mSamples(0)
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
, mSamples(1)
, mIsUsingSecondary(false)
#ifdef ANDROID
, mIsRB(false)
#endif
, mHasBeenBound(false)
{
mContext->MakeContextCurrent();
mContext->gl->fGenRenderbuffers(1, &mPrimaryRB);
if (!SupportsDepthStencil(mContext->gl))
mContext->gl->fGenRenderbuffers(1, &mSecondaryRB);
mContext->mRenderbuffers.insertBack(this);
}
@@ -78,9 +69,6 @@ WebGLRenderbuffer::Delete()
mContext->gl->fDeleteRenderbuffers(1, &mSecondaryRB);
LinkedListElement<WebGLRenderbuffer>::removeFrom(mContext->mRenderbuffers);
#ifdef ANDROID
mIsRB = false;
#endif
}
int64_t
@@ -90,156 +78,173 @@ WebGLRenderbuffer::MemoryUsage() const
if (!mFormat)
return 0;
auto bytesPerPixel = mFormat->format->estimatedBytesPerPixel;
uint64_t pixels = uint64_t(mWidth) * uint64_t(mHeight);
const auto bytesPerPixel = mFormat->format->estimatedBytesPerPixel;
const int64_t pixels = int64_t(mWidth) * int64_t(mHeight);
uint64_t totalSize = pixels * bytesPerPixel;
// If we have the same bytesPerPixel whether or not we have a secondary RB.
if (mSecondaryRB && !mIsUsingSecondary) {
totalSize += 2; // 1x1xRGBA4
}
return int64_t(totalSize);
const int64_t totalSize = pixels * bytesPerPixel;
return totalSize;
}
void
WebGLRenderbuffer::BindRenderbuffer() const
{
/* Do this explicitly here, since the meaning changes for depth-stencil emu.
* Under normal circumstances, there's only one RB: `mPrimaryRB`.
* `mSecondaryRB` is used when we have to pretend that the renderbuffer is
* DEPTH_STENCIL, when it's actually one DEPTH buffer `mPrimaryRB` and one
* STENCIL buffer `mSecondaryRB`.
*
* In the DEPTH_STENCIL emulation case, we're actually juggling two RBs, but
* we can only bind one of them at a time. We choose to unconditionally bind
* the depth RB. When we need to ask about the stencil buffer (say, how many
* stencil bits we have), we temporarily bind the stencil RB, so that it
* looks like we're just asking the question of a combined DEPTH_STENCIL
* buffer.
*/
mContext->gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
}
static void
RenderbufferStorageMaybeMultisample(gl::GLContext* gl, GLsizei samples,
GLenum internalFormat, GLsizei width,
GLsizei height)
static GLenum
DoRenderbufferStorageMaybeMultisample(gl::GLContext* gl, GLsizei samples,
GLenum internalFormat, GLsizei width,
GLsizei height)
{
MOZ_ASSERT_IF(samples >= 1, gl->IsSupported(gl::GLFeature::framebuffer_multisample));
MOZ_ASSERT(samples >= 0);
MOZ_ASSERT(samples <= gl->MaxSamples());
// certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL
GLenum internalFormatForGL = internalFormat;
// Certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL.
switch (internalFormat) {
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB5_A1:
// 16-bit RGBA formats are not supported on desktop GL
// 16-bit RGBA formats are not supported on desktop GL.
if (!gl->IsGLES())
internalFormatForGL = LOCAL_GL_RGBA8;
internalFormat = LOCAL_GL_RGBA8;
break;
case LOCAL_GL_RGB565:
// the RGB565 format is not supported on desktop GL
// RGB565 is not supported on desktop GL.
if (!gl->IsGLES())
internalFormatForGL = LOCAL_GL_RGB8;
internalFormat = LOCAL_GL_RGB8;
break;
case LOCAL_GL_DEPTH_COMPONENT16:
if (!gl->IsGLES() || gl->IsExtensionSupported(gl::GLContext::OES_depth24))
internalFormatForGL = LOCAL_GL_DEPTH_COMPONENT24;
else if (gl->IsExtensionSupported(gl::GLContext::OES_packed_depth_stencil))
internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
internalFormat = LOCAL_GL_DEPTH_COMPONENT24;
else if (gl->IsSupported(gl::GLFeature::packed_depth_stencil))
internalFormat = LOCAL_GL_DEPTH24_STENCIL8;
break;
case LOCAL_GL_DEPTH_STENCIL:
// We emulate this in WebGLRenderbuffer if we don't have the requisite extension.
internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
MOZ_CRASH("GL_DEPTH_STENCIL is not valid here.");
break;
default:
break;
}
gl::GLContext::LocalErrorScope errorScope(*gl);
if (samples > 0) {
gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples,
internalFormatForGL, width, height);
internalFormat, width, height);
} else {
gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormatForGL, width,
height);
gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormat, width, height);
}
return errorScope.GetError();
}
void
WebGLRenderbuffer::RenderbufferStorage(GLsizei samples,
const webgl::FormatUsageInfo* format,
GLsizei width, GLsizei height)
GLenum
WebGLRenderbuffer::DoRenderbufferStorage(uint32_t samples,
const webgl::FormatUsageInfo* format,
uint32_t width, uint32_t height)
{
MOZ_ASSERT(mContext->mBoundRenderbuffer == this);
gl::GLContext* gl = mContext->gl;
MOZ_ASSERT(samples >= 0 && samples <= 256); // Sanity check.
MOZ_ASSERT(samples <= 256); // Sanity check.
GLenum primaryFormat = format->format->sizedFormat;
GLenum secondaryFormat = 0;
if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
primaryFormat = DepthStencilDepthFormat(gl);
if (mEmulatePackedDepthStencil && primaryFormat == LOCAL_GL_DEPTH24_STENCIL8) {
primaryFormat = DepthFormatForDepthStencilEmu(gl);
secondaryFormat = LOCAL_GL_STENCIL_INDEX8;
}
RenderbufferStorageMaybeMultisample(gl, samples, primaryFormat, width,
height);
gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
GLenum error = DoRenderbufferStorageMaybeMultisample(gl, samples, primaryFormat,
width, height);
if (error)
return error;
if (mSecondaryRB) {
// We can't leave the secondary RB unspecified either, since we should
// handle the case where we attach a non-depth-stencil RB to a
// depth-stencil attachment point, or attach this depth-stencil RB to a
// non-depth-stencil attachment point.
gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
if (secondaryFormat) {
RenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat, width,
height);
} else {
RenderbufferStorageMaybeMultisample(gl, samples, LOCAL_GL_RGBA4, 1, 1);
if (secondaryFormat) {
if (!mSecondaryRB) {
gl->fGenRenderbuffers(1, &mSecondaryRB);
}
gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mSecondaryRB);
error = DoRenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat,
width, height);
if (error)
return error;
} else if (mSecondaryRB) {
gl->fDeleteRenderbuffers(1, &mSecondaryRB);
mSecondaryRB = 0;
}
return 0;
}
void
WebGLRenderbuffer::RenderbufferStorage(const char* funcName, uint32_t samples,
GLenum internalFormat, uint32_t width,
uint32_t height)
{
const auto usage = mContext->mFormatUsage->GetRBUsage(internalFormat);
if (!usage) {
mContext->ErrorInvalidEnum("%s: Invalid `internalFormat`: 0x%04x.", funcName,
internalFormat);
return;
}
if (width > mContext->mImplMaxRenderbufferSize ||
height > mContext->mImplMaxRenderbufferSize)
{
mContext->ErrorInvalidValue("%s: Width or height exceeds maximum renderbuffer"
" size.",
funcName);
return;
}
mContext->MakeContextCurrent();
if (!usage->maxSamplesKnown) {
const_cast<webgl::FormatUsageInfo*>(usage)->ResolveMaxSamples(mContext->gl);
}
MOZ_ASSERT(usage->maxSamplesKnown);
if (samples > usage->maxSamples) {
mContext->ErrorInvalidValue("%s: `samples` is out of the valid range.", funcName);
return;
}
// Validation complete.
const GLenum error = DoRenderbufferStorage(samples, usage, width, height);
if (error) {
const char* errorName = mContext->ErrorName(error);
mContext->GenerateWarning("%s generated error %s", funcName, errorName);
return;
}
mSamples = samples;
mFormat = format;
mFormat = usage;
mWidth = width;
mHeight = height;
mImageDataStatus = WebGLImageDataStatus::UninitializedImageData;
mIsUsingSecondary = bool(secondaryFormat);
InvalidateStatusOfAttachedFBs();
}
void
WebGLRenderbuffer::FramebufferRenderbuffer(GLenum attachment) const
WebGLRenderbuffer::DoFramebufferRenderbuffer(GLenum attachment) const
{
gl::GLContext* gl = mContext->gl;
if (attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment,
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
const GLuint stencilRB = (mSecondaryRB ? mSecondaryRB : mPrimaryRB);
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_DEPTH_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, mPrimaryRB);
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_STENCIL_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, stencilRB);
return;
}
GLuint stencilRB = mPrimaryRB;
if (mIsUsingSecondary) {
MOZ_ASSERT(mSecondaryRB);
stencilRB = mSecondaryRB;
}
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_DEPTH_ATTACHMENT,
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment,
LOCAL_GL_RENDERBUFFER, mPrimaryRB);
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_STENCIL_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, stencilRB);
}
GLint
@@ -258,6 +263,7 @@ WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
return 8;
case LOCAL_GL_RENDERBUFFER_SAMPLES:
case LOCAL_GL_RENDERBUFFER_WIDTH:
case LOCAL_GL_RENDERBUFFER_HEIGHT:
case LOCAL_GL_RENDERBUFFER_RED_SIZE:
@@ -266,6 +272,7 @@ WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
{
gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
GLint i = 0;
gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
return i;
@@ -285,8 +292,7 @@ WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
}
}
MOZ_ASSERT(false,
"This function should only be called with valid `pname`.");
MOZ_ASSERT(false, "This function should only be called with valid `pname`.");
return 0;
}
+24 -27
View File
@@ -26,7 +26,26 @@ class WebGLRenderbuffer final
, public WebGLContextBoundObject
, public WebGLFramebufferAttachable
{
friend class WebGLContext;
friend class WebGLFramebuffer;
friend class WebGLFBAttachPoint;
public:
const GLuint mPrimaryRB;
protected:
const bool mEmulatePackedDepthStencil;
GLuint mSecondaryRB;
const webgl::FormatUsageInfo* mFormat;
GLsizei mSamples;
WebGLImageDataStatus mImageDataStatus;
bool mHasBeenBound;
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbuffer)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbuffer)
explicit WebGLRenderbuffer(WebGLContext* webgl);
void Delete();
@@ -46,8 +65,6 @@ public:
GLsizei Samples() const { return mSamples; }
GLuint PrimaryGLName() const { return mPrimaryRB; }
const webgl::FormatUsageInfo* Format() const { return mFormat; }
int64_t MemoryUsage() const;
@@ -56,41 +73,21 @@ public:
return mContext;
}
void BindRenderbuffer() const;
void RenderbufferStorage(GLsizei samples, const webgl::FormatUsageInfo* format,
GLsizei width, GLsizei height);
void FramebufferRenderbuffer(GLenum attachment) const;
void RenderbufferStorage(const char* funcName, uint32_t samples,
GLenum internalFormat, uint32_t width, uint32_t height);
// Only handles a subset of `pname`s.
GLint GetRenderbufferParameter(RBTarget target, RBParam pname) const;
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbuffer)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbuffer)
protected:
~WebGLRenderbuffer() {
DeleteOnce();
}
GLuint mPrimaryRB;
GLuint mSecondaryRB;
const webgl::FormatUsageInfo* mFormat;
WebGLImageDataStatus mImageDataStatus;
GLsizei mSamples;
bool mIsUsingSecondary;
#ifdef ANDROID
// Bug 1140459: Some drivers (including our test slaves!) don't
// give reasonable answers for IsRenderbuffer, maybe others.
// This shows up on Android 2.3 emulator.
//
// So we track the `is a Renderbuffer` state ourselves.
bool mIsRB;
#endif
friend class WebGLContext;
friend class WebGLFramebuffer;
friend class WebGLFBAttachPoint;
void DoFramebufferRenderbuffer(GLenum attachment) const;
GLenum DoRenderbufferStorage(uint32_t samples, const webgl::FormatUsageInfo* format,
uint32_t width, uint32_t height);
};
} // namespace mozilla
+75
View File
@@ -14,6 +14,15 @@ namespace mozilla {
WebGLSampler::WebGLSampler(WebGLContext* webgl, GLuint sampler)
: WebGLContextBoundObject(webgl)
, mGLName(sampler)
, mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR)
, mMagFilter(LOCAL_GL_LINEAR)
, mWrapS(LOCAL_GL_REPEAT)
, mWrapT(LOCAL_GL_REPEAT)
, mWrapR(LOCAL_GL_REPEAT)
, mMinLod(-1000)
, mMaxLod(1000)
, mCompareMode(LOCAL_GL_NONE)
, mCompareFunc(LOCAL_GL_LEQUAL)
{
mContext->mSamplers.insertBack(this);
}
@@ -44,6 +53,72 @@ WebGLSampler::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
return dom::WebGLSamplerBinding::Wrap(cx, this, givenProto);
}
void
WebGLSampler::SamplerParameter1i(GLenum pname, GLint param)
{
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_FILTER:
mMinFilter = param;
break;
case LOCAL_GL_TEXTURE_MAG_FILTER:
mMagFilter = param;
break;
case LOCAL_GL_TEXTURE_WRAP_S:
mWrapS = param;
break;
case LOCAL_GL_TEXTURE_WRAP_T:
mWrapT = param;
break;
case LOCAL_GL_TEXTURE_WRAP_R:
mWrapR = param;
break;
case LOCAL_GL_TEXTURE_COMPARE_MODE:
mCompareMode = param;
break;
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
mCompareFunc = param;
break;
default:
MOZ_CRASH("Unhandled pname");
break;
}
for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
if (this == mContext->mBoundSamplers[i])
mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
}
}
void
WebGLSampler::SamplerParameter1f(GLenum pname, GLfloat param)
{
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_LOD:
mMinLod = param;
break;
case LOCAL_GL_TEXTURE_MAX_LOD:
mMaxLod = param;
break;
default:
MOZ_CRASH("Unhandled pname");
break;
}
for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
if (this == mContext->mBoundSamplers[i])
mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
}
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef)
+14
View File
@@ -19,6 +19,7 @@ class WebGLSampler final
, public WebGLContextBoundObject
{
friend class WebGLContext2;
friend class WebGLTexture;
public:
explicit WebGLSampler(WebGLContext* webgl, GLuint sampler);
@@ -30,11 +31,24 @@ public:
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
void SamplerParameter1i(GLenum pname, GLint param);
void SamplerParameter1f(GLenum pname, GLfloat param);
private:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
TexMinFilter mMinFilter;
TexMagFilter mMagFilter;
TexWrap mWrapS;
TexWrap mWrapT;
TexWrap mWrapR;
GLint mMinLod;
GLint mMaxLod;
TexCompareMode mCompareMode;
TexCompareFunc mCompareFunc;
private:
~WebGLSampler();
};
+17 -6
View File
@@ -121,12 +121,6 @@ private:
}
public:
StrongGLenum(const StrongGLenum& other)
: mValue(other.mValue)
{
AssertOnceThatEnumValuesAreSorted();
}
StrongGLenum()
#ifdef DEBUG
: mValue(NonexistantGLenum)
@@ -275,6 +269,22 @@ STRONG_GLENUM_BEGIN(TexWrap)
STRONG_GLENUM_VALUE(MIRRORED_REPEAT),
STRONG_GLENUM_END(TexWrap)
STRONG_GLENUM_BEGIN(TexCompareMode)
STRONG_GLENUM_VALUE(NONE),
STRONG_GLENUM_VALUE(COMPARE_REF_TO_TEXTURE),
STRONG_GLENUM_END(TexCompareMode)
STRONG_GLENUM_BEGIN(TexCompareFunc)
STRONG_GLENUM_VALUE(LEQUAL),
STRONG_GLENUM_VALUE(GEQUAL),
STRONG_GLENUM_VALUE(LESS),
STRONG_GLENUM_VALUE(GREATER),
STRONG_GLENUM_VALUE(EQUAL),
STRONG_GLENUM_VALUE(NOTEQUAL),
STRONG_GLENUM_VALUE(ALWAYS),
STRONG_GLENUM_VALUE(NEVER),
STRONG_GLENUM_END(TexCompareFunc)
STRONG_GLENUM_BEGIN(TexFormat)
STRONG_GLENUM_VALUE(NONE), // 0x0000
STRONG_GLENUM_VALUE(DEPTH_COMPONENT), // 0x1902
@@ -411,6 +421,7 @@ STRONG_GLENUM_BEGIN(FBStatus)
STRONG_GLENUM_END(FBStatus)
STRONG_GLENUM_BEGIN(RBParam)
STRONG_GLENUM_VALUE(RENDERBUFFER_SAMPLES),
STRONG_GLENUM_VALUE(RENDERBUFFER_WIDTH),
STRONG_GLENUM_VALUE(RENDERBUFFER_HEIGHT),
STRONG_GLENUM_VALUE(RENDERBUFFER_INTERNAL_FORMAT),
+68 -49
View File
@@ -40,29 +40,33 @@ class WebGLImageConverter
template<WebGLTexelFormat Format>
static size_t NumElementsPerTexelForFormat() {
switch (Format) {
case WebGLTexelFormat::R8:
case WebGLTexelFormat::A8:
case WebGLTexelFormat::R16F:
case WebGLTexelFormat::A16F:
case WebGLTexelFormat::R32F:
case WebGLTexelFormat::A32F:
case WebGLTexelFormat::RGBA5551:
case WebGLTexelFormat::RGBA4444:
case WebGLTexelFormat::R8:
case WebGLTexelFormat::R16F:
case WebGLTexelFormat::R32F:
case WebGLTexelFormat::RGB565:
case WebGLTexelFormat::RGB11F11F10F:
case WebGLTexelFormat::RGBA4444:
case WebGLTexelFormat::RGBA5551:
return 1;
case WebGLTexelFormat::RA8:
case WebGLTexelFormat::RA16F:
case WebGLTexelFormat::RA32F:
case WebGLTexelFormat::RG8:
case WebGLTexelFormat::RG16F:
case WebGLTexelFormat::RG32F:
return 2;
case WebGLTexelFormat::RGB8:
case WebGLTexelFormat::RGB16F:
case WebGLTexelFormat::RGB32F:
return 3;
case WebGLTexelFormat::RGBA8:
case WebGLTexelFormat::BGRA8:
case WebGLTexelFormat::BGRX8:
case WebGLTexelFormat::RGBA16F:
case WebGLTexelFormat::RGBA32F:
case WebGLTexelFormat::BGRX8:
case WebGLTexelFormat::BGRA8:
return 4;
default:
MOZ_ASSERT(false, "Unknown texel format. Coding mistake?");
@@ -246,26 +250,35 @@ class WebGLImageConverter
return run<SrcFormat, DstFormat>(premultiplicationOp);
switch (dstFormat) {
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB565)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA5551)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA4444)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA32F)
default:
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
// 1-channel formats
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R32F)
// 2-channel formats
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RG8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RG16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RG32F)
// 3-channel formats
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB565)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB11F11F10F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB32F)
// 4-channel formats
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA4444)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA5551)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA32F)
default:
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
}
#undef WEBGLIMAGECONVERTER_CASE_DSTFORMAT
@@ -282,28 +295,34 @@ public:
return run<SrcFormat>(dstFormat, premultiplicationOp);
switch (srcFormat) {
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRX8) // source format only
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB565)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA5551)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA4444)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA32F)
default:
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
// 1-channel formats
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R32F)
// 2-channel formats
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA32F)
// 3-channel formats
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB565)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB32F)
// 4-channel formats
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA4444)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA5551)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA32F)
// DOM element source formats
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRX8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRA8)
default:
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
}
#undef WEBGLIMAGECONVERTER_CASE_SRCFORMAT
File diff suppressed because it is too large Load Diff
+26 -18
View File
@@ -188,12 +188,12 @@ WebGLTexture::SetImageInfosAtLevel(uint32_t level, const ImageInfo& newInfo)
}
bool
WebGLTexture::IsMipmapComplete() const
WebGLTexture::IsMipmapComplete(uint32_t texUnit) const
{
MOZ_ASSERT(DoesMinFilterRequireMipmap());
// GLES 3.0.4, p161
const uint32_t maxLevel = MaxEffectiveMipmapLevel();
const uint32_t maxLevel = MaxEffectiveMipmapLevel(texUnit);
// "* `level_base <= level_max`"
if (mBaseMipmapLevel > maxLevel)
@@ -288,7 +288,7 @@ WebGLTexture::IsCubeComplete() const
}
bool
WebGLTexture::IsComplete(const char** const out_reason) const
WebGLTexture::IsComplete(uint32_t texUnit, const char** const out_reason) const
{
// Texture completeness is established at GLES 3.0.4, p160-161.
// "[A] texture is complete unless any of the following conditions hold true:"
@@ -313,19 +313,23 @@ WebGLTexture::IsComplete(const char** const out_reason) const
return false;
}
WebGLSampler* sampler = mContext->mBoundSamplers[texUnit];
TexMinFilter minFilter = sampler ? sampler->mMinFilter : mMinFilter;
TexMagFilter magFilter = sampler ? sampler->mMagFilter : mMagFilter;
// "* The minification filter requires a mipmap (is neither NEAREST nor LINEAR) and
// the texture is not mipmap complete."
const bool requiresMipmap = (mMinFilter != LOCAL_GL_NEAREST &&
mMinFilter != LOCAL_GL_LINEAR);
if (requiresMipmap && !IsMipmapComplete()) {
const bool requiresMipmap = (minFilter != LOCAL_GL_NEAREST &&
minFilter != LOCAL_GL_LINEAR);
if (requiresMipmap && !IsMipmapComplete(texUnit)) {
*out_reason = "Because the minification filter requires mipmapping, the texture"
" must be \"mipmap complete\".";
return false;
}
const bool isMinFilteringNearest = (mMinFilter == LOCAL_GL_NEAREST ||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
const bool isMagFilteringNearest = (mMagFilter == LOCAL_GL_NEAREST);
const bool isMinFilteringNearest = (minFilter == LOCAL_GL_NEAREST ||
minFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
const bool isMagFilteringNearest = (magFilter == LOCAL_GL_NEAREST);
const bool isFilteringNearestOnly = (isMinFilteringNearest && isMagFilteringNearest);
if (!isFilteringNearestOnly) {
auto formatUsage = baseImageInfo.mFormat;
@@ -392,9 +396,11 @@ WebGLTexture::IsComplete(const char** const out_reason) const
// non-power-of-two images, and either the texture wrap mode is not
// CLAMP_TO_EDGE, or the minification filter is neither NEAREST nor LINEAR."
if (!baseImageInfo.IsPowerOfTwo()) {
TexWrap wrapS = sampler ? sampler->mWrapS : mWrapS;
TexWrap wrapT = sampler ? sampler->mWrapT : mWrapT;
// "either the texture wrap mode is not CLAMP_TO_EDGE"
if (mWrapS != LOCAL_GL_CLAMP_TO_EDGE ||
mWrapT != LOCAL_GL_CLAMP_TO_EDGE)
if (wrapS != LOCAL_GL_CLAMP_TO_EDGE ||
wrapT != LOCAL_GL_CLAMP_TO_EDGE)
{
*out_reason = "Non-power-of-two textures must have a wrap mode of"
" CLAMP_TO_EDGE.";
@@ -419,10 +425,12 @@ WebGLTexture::IsComplete(const char** const out_reason) const
uint32_t
WebGLTexture::MaxEffectiveMipmapLevel() const
WebGLTexture::MaxEffectiveMipmapLevel(uint32_t texUnit) const
{
if (mMinFilter == LOCAL_GL_NEAREST ||
mMinFilter == LOCAL_GL_LINEAR)
WebGLSampler* sampler = mContext->mBoundSamplers[texUnit];
TexMinFilter minFilter = sampler ? sampler->mMinFilter : mMinFilter;
if (minFilter == LOCAL_GL_NEAREST ||
minFilter == LOCAL_GL_LINEAR)
{
// No mips used.
return mBaseMipmapLevel;
@@ -440,7 +448,7 @@ WebGLTexture::GetFakeBlackType(const char* funcName, uint32_t texUnit,
FakeBlackType* const out_fakeBlack)
{
const char* incompleteReason;
if (!IsComplete(&incompleteReason)) {
if (!IsComplete(texUnit, &incompleteReason)) {
if (incompleteReason) {
mContext->GenerateWarning("%s: Active texture %u for target 0x%04x is"
" 'incomplete', and will be rendered as"
@@ -456,7 +464,7 @@ WebGLTexture::GetFakeBlackType(const char* funcName, uint32_t texUnit,
bool hasUninitializedData = false;
bool hasInitializedData = false;
const auto maxLevel = MaxEffectiveMipmapLevel();
const auto maxLevel = MaxEffectiveMipmapLevel(texUnit);
MOZ_ASSERT(mBaseMipmapLevel <= maxLevel);
for (uint32_t level = mBaseMipmapLevel; level <= maxLevel; level++) {
for (uint8_t face = 0; face < mFaceCount; face++) {
@@ -588,8 +596,8 @@ WebGLTexture::InitializeImageData(const char* funcName, TexImageTarget target,
const auto& height = imageInfo.mHeight;
const auto& depth = imageInfo.mDepth;
if (!ZeroTextureData(mContext, funcName, respecifyTexture, target, level, usage, 0, 0,
0, width, height, depth))
if (!ZeroTextureData(mContext, funcName, respecifyTexture, mGLName, target, level,
usage, 0, 0, 0, width, height, depth))
{
return false;
}
+3 -3
View File
@@ -284,7 +284,7 @@ protected:
void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel);
uint32_t MaxEffectiveMipmapLevel() const;
uint32_t MaxEffectiveMipmapLevel(uint32_t texUnit) const;
static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
GLenum rawTexImageTarget = texImageTarget.get();
@@ -369,11 +369,11 @@ public:
bool AreAllLevel0ImageInfosEqual() const;
bool IsMipmapComplete() const;
bool IsMipmapComplete(uint32_t texUnit) const;
bool IsCubeComplete() const;
bool IsComplete(const char** const out_reason) const;
bool IsComplete(uint32_t texUnit, const char** const out_reason) const;
bool IsMipmapCubeComplete() const;
+35 -21
View File
@@ -1031,6 +1031,24 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
auto dstUsage = fua->GetSizedTexUsage(internalFormat);
if (!dstUsage) {
if (internalFormat != unpackFormat) {
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
" 0x%04x/0x%04x",
funcName, unpackFormat, unpackType);
return;
}
if (!fua->IsInternalFormatEnumValid(internalFormat)) {
mContext->ErrorInvalidValue("%s: Invalid internalformat: 0x%04x",
funcName, internalFormat);
return;
}
/* GL ES Version 3.0.4 - 3.8.3 Texture Image Specification
* "Specifying a combination of values for format, type, and
* internalformat that is not listed as a valid combination
* in tables 3.2 or 3.3 generates the error INVALID_OPERATION."
*/
mContext->ErrorInvalidOperation("%s: Unsized internalFormat must match"
" unpack format.",
funcName);
@@ -1041,19 +1059,17 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
}
if (!dstUsage) {
if (!mContext->IsWebGL2()) {
if (!fua->IsInternalFormatEnumValid(internalFormat)) {
mContext->ErrorInvalidValue("%s: Invalid internalformat: 0x%04x",
funcName, internalFormat);
return;
}
if (!fua->IsInternalFormatEnumValid(internalFormat)) {
mContext->ErrorInvalidValue("%s: Invalid internalformat: 0x%04x",
funcName, internalFormat);
return;
}
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
" 0x%04x/0x%04x",
funcName, unpackFormat, unpackType);
return;
}
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
" 0x%04x/0x%04x",
funcName, unpackFormat, unpackType);
return;
}
mContext->ErrorInvalidOperation("%s: Invalid internalformat/format/type:"
@@ -1183,14 +1199,12 @@ WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint lev
const webgl::PackingInfo srcPacking = { unpackFormat, unpackType };
const webgl::DriverUnpackInfo* driverUnpackInfo;
if (!dstUsage->IsUnpackValid(srcPacking, &driverUnpackInfo)) {
if (!mContext->IsWebGL2()) {
const auto& fua = mContext->mFormatUsage;
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
" 0x%04x/0x%04x",
funcName, unpackFormat, unpackType);
return;
}
const auto& fua = mContext->mFormatUsage;
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
" 0x%04x/0x%04x",
funcName, unpackFormat, unpackType);
return;
}
mContext->ErrorInvalidOperation("%s: Mismatched internalFormat and format/type:"
@@ -1778,7 +1792,7 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
const bool respecifyTexture = true;
const uint8_t zOffset = 0;
if (!ZeroTextureData(mContext, funcName, respecifyTexture, target, level,
if (!ZeroTextureData(mContext, funcName, respecifyTexture, mGLName, target, level,
dstUsage, 0, 0, zOffset, width, height, depth))
{
mContext->ErrorOutOfMemory("%s: Failed to zero texture data.", funcName);
+12 -7
View File
@@ -90,30 +90,35 @@ enum class WebGLTexelFormat : uint8_t {
// is implicitly treated as being RGB8 itself.
Auto,
// 1-channel formats
R8,
A8,
R16F, // OES_texture_half_float
A16F, // OES_texture_half_float
R32F, // OES_texture_float
A32F, // OES_texture_float
R8,
R16F, // OES_texture_half_float
R32F, // OES_texture_float
// 2-channel formats
RA8,
RA16F, // OES_texture_half_float
RA32F, // OES_texture_float
RG8,
RG16F,
RG32F,
// 3-channel formats
RGB8,
RGBX8, // used for DOM elements. Source format only.
BGRX8, // used for DOM elements. Source format only.
RGB565,
RGB11F11F10F,
RGB16F, // OES_texture_half_float
RGB32F, // OES_texture_float
// 4-channel formats
RGBA8,
BGRA8, // used for DOM elements
RGBA5551,
RGBA4444,
RGBA16F, // OES_texture_half_float
RGBA32F // OES_texture_float
RGBA32F, // OES_texture_float
// DOM element source only formats.
RGBX8,
BGRX8,
BGRA8
};
enum class WebGLTexImageFunc : uint8_t {
+11 -5
View File
@@ -4,11 +4,11 @@
# 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/.
# Number changes to this file to avoid bug 1081323 (clobber after changing a manifest):
# 1
TEST_DIRS += ['compiledtest']
# Number changes to this file to avoid bug 1081323 (clobber after changing a manifest):
# 11
MOCHITEST_MANIFESTS += [
'test/crossorigin/mochitest.ini',
'test/mochitest-subsuite-webgl.ini',
@@ -58,7 +58,6 @@ UNIFIED_SOURCES += [
# WebGL Sources
UNIFIED_SOURCES += [
'MurmurHash3.cpp',
'TexUnpackBlob.cpp',
'WebGL1Context.cpp',
'WebGL1ContextBuffers.cpp',
@@ -149,6 +148,14 @@ UNIFIED_SOURCES += [
'WebGLVertexArrayObject.cpp',
]
SOURCES += [
'MurmurHash3.cpp',
]
# Suppress warnings from third-party code.
if CONFIG['CLANG_CXX']:
SOURCES['MurmurHash3.cpp'].flags += ['-Wno-implicit-fallthrough']
LOCAL_INCLUDES += [
'/js/xpconnect/wrappers',
]
@@ -176,4 +183,3 @@ CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
CXXFLAGS += CONFIG['TK_CFLAGS']
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
@@ -119,7 +119,6 @@ function GetExpectedTestFailSet() {
failSet['conformance/state/gl-get-calls.html'] = true;
failSet['conformance/textures/tex-image-with-format-and-type.html'] = true;
failSet['conformance/textures/tex-sub-image-2d.html'] = true;
failSet['conformance/textures/texture-mips.html'] = true;
failSet['conformance/textures/texture-size-cube-maps.html'] = true;
} else {
// Android 2.3 slaves.
@@ -128,7 +127,6 @@ function GetExpectedTestFailSet() {
failSet['conformance/misc/object-deletion-behaviour.html'] = true;
failSet['conformance/programs/program-test.html'] = true;
failSet['conformance/textures/tex-image-and-sub-image-2d-with-video.html'] = true;
failSet['conformance/textures/texture-mips.html'] = true;
failSet['conformance/textures/texture-npot.html'] = true;
}
break;
@@ -142,7 +140,6 @@ function GetExpectedTestFailSet() {
failSet['conformance/misc/object-deletion-behaviour.html'] = true;
failSet['conformance/programs/get-active-test.html'] = true;
failSet['conformance/textures/tex-input-validation.html'] = true;
failSet['conformance/textures/texture-mips.html'] = true;
failSet['conformance/textures/texture-npot.html'] = true;
failSet['conformance/textures/texture-size-cube-maps.html'] = true;
failSet['conformance/textures/texture-size.html'] = true;
+42 -1
View File
@@ -3,10 +3,49 @@ subsuite = webgl
skip-if = ((os == 'linux') && (buildapp == 'b2g'))
support-files =
webgl-mochitest/ensure-exts/ensure-ext.js
webgl-mochitest/driver-info.js
webgl-mochitest/es3-data.js
webgl-mochitest/webgl-util.js
[webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html]
fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
[webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html]
fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html]
fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html]
fail-if = (os == 'android') || (os == 'mac') || (os == 'win')
[webgl-mochitest/ensure-exts/test_EXT_frag_depth.html]
fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_EXT_sRGB.html]
fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6') || (os == 'win')
[webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html]
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac')
[webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html]
fail-if = (os == 'android') || (os == 'linux')
[webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html]
fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html]
fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html]
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html]
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html]
# Win7 is 6.1
fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html]
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html]
fail-if = (os == 'android') || (os == 'linux')
[webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html]
fail-if = (os == 'mac' && os_version == '10.6')
[webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html]
# Win7 is 6.1
fail-if = (os == 'android') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
[webgl-mochitest/ensure-exts/test_common.html]
[webgl-mochitest/test_backbuffer_channels.html]
fail-if = (os == 'b2g')
[webgl-mochitest/test_depth_readpixels.html]
@@ -18,6 +57,8 @@ support-files = captureStream_common.js
[webgl-mochitest/test_fb_param_crash.html]
[webgl-mochitest/test_hidden_alpha.html]
skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so)
[webgl-mochitest/test_hidden_depth_stencil.html]
fail-if = (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
[webgl-mochitest/test_implicit_color_buffer_float.html]
[webgl-mochitest/test_highp_fs.html]
[webgl-mochitest/test_no_arr_points.html]
@@ -29,13 +70,13 @@ skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.
[webgl-mochitest/test_texsubimage_float.html]
[webgl-mochitest/test_uninit_data.html]
[webgl-mochitest/test_webgl_available.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
#[webgl-mochitest/test_webgl_color_buffer_float.html]
# We haven't cleaned up the Try results yet, but let's get this on the books first.
[webgl-mochitest/test_webgl_conformance.html]
skip-if = buildapp == 'mulet' || toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[webgl-mochitest/test_webgl_compressed_texture_es3.html]
[webgl-mochitest/test_webgl_disjoint_timer_query.html]
[webgl-mochitest/test_webgl_force_enable.html]
[webgl-mochitest/test_webgl_request_context.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[webgl-mochitest/test_webgl_request_mismatch.html]
@@ -0,0 +1,32 @@
'use strict';
function EnsureExt(name, shouldBe = true) {
var c = document.createElement('canvas');
var gl = c.getContext('experimental-webgl');
if (shouldBe) {
ok(gl.getExtension(name), 'Should have extension ' + name + '.');
} else {
ok(!gl.getExtension(name), 'Should not have extension ' + name + '.');
}
}
function EnsureDraftExt(name, shouldBe = true) {
SimpleTest.waitForExplicitFinish();
var fnEnsure = function() {
EnsureExt(name, shouldBe);
SimpleTest.finish();
};
if ('SpecialPowers' in window) {
var prefStateList = [
['webgl.enable-draft-extensions', true],
];
var prefEnv = {'set': prefStateList};
SpecialPowers.pushPrefEnv(prefEnv, fnEnsure);
} else {
console.log('Couldn\'t use SpecialPowers to enable draft extensions.');
fnEnsure();
}
}
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('ANGLE_instanced_arrays');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('EXT_blend_minmax');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('EXT_color_buffer_half_float');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureDraftExt('EXT_disjoint_timer_query');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('EXT_frag_depth');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('EXT_sRGB');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('EXT_shader_texture_lod');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('EXT_texture_filter_anisotropic');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('OES_standard_derivatives');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('WEBGL_color_buffer_float');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('WEBGL_compressed_texture_atc');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureDraftExt('WEBGL_compressed_texture_es3');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('WEBGL_compressed_texture_etc1');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('WEBGL_compressed_texture_pvrtc');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('WEBGL_compressed_texture_s3tc');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('WEBGL_depth_texture');
</script>
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
EnsureExt('WEBGL_draw_buffers');
</script>
</body>
</html>
@@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
</head>
<body>
<script>
'use strict';
var c = document.createElement('canvas');
var gl = c.getContext('experimental-webgl');
function ensureExt(name) {
ok(gl.getExtension(name), 'Should have extension ' + name + '.');
}
function ensureNoExt(name) {
ok(!gl.getExtension(name), 'Should not have extension ' + name + '.');
}
do {
if (!gl)
break;
// These aren't all guaranteed, but they're common to all our test slaves.
// If you're adding a slave config that is missing one of these, comment the line out
// and split it into its own test.
// Implemented. (commented out if not test-slave-universal)
//ensureExt('ANGLE_instanced_arrays');
//ensureExt('EXT_blend_minmax');
//ensureExt('EXT_color_buffer_half_float');
//ensureExt('EXT_frag_depth');
//ensureExt('EXT_shader_texture_lod');
//ensureExt('EXT_sRGB');
//ensureExt('EXT_texture_filter_anisotropic');
ensureExt('OES_element_index_uint');
//ensureExt('OES_standard_derivatives');
ensureExt('OES_texture_float');
ensureExt('OES_texture_float_linear');
ensureExt('OES_texture_half_float');
ensureExt('OES_texture_half_float_linear');
ensureExt('OES_vertex_array_object');
//ensureExt('WEBGL_color_buffer_float');
//ensureExt('WEBGL_compressed_texture_atc');
//ensureExt('WEBGL_compressed_texture_es3');
//ensureExt('WEBGL_compressed_texture_etc1');
//ensureExt('WEBGL_compressed_texture_pvrtc');
//ensureExt('WEBGL_compressed_texture_s3tc');
//ensureExt('WEBGL_depth_texture');
//ensureExt('WEBGL_draw_buffers');
ensureExt('WEBGL_lose_context');
// Draft extensions, which should not be exposed by default.
ensureNoExt('EXT_disjoint_timer_query');
ensureNoExt('WEBGL_compressed_texture_es3');
// Not implemented.
ensureNoExt('EXT_color_buffer_float');
ensureNoExt('OES_fbo_render_mipmap');
ensureNoExt('WEBGL_compressed_texture_astc');
ensureNoExt('WEBGL_security_sensitive_resources');
ensureNoExt('WEBGL_shared_resources');
// Privileged
//ensureExt('WEBGL_debug_renderer_info');
//ensureExt('WEBGL_debug_shaders');
} while (false);
</script>
</body>
</html>
@@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='webgl-util.js'></script>
</head>
<body>
<script id='vs' type='x-shader/x-vertex'>
attribute vec2 aVertCoord;
void main(void) {
gl_Position = vec4(aVertCoord, 0.0, 1.0);
}
</script>
<script id='fs' type='x-shader/x-fragment'>
precision mediump float;
uniform sampler2D uTexUnit;
void main(void) {
vec4 tex = texture2D(uTexUnit, vec2(0));
gl_FragColor = vec4(tex.r, 1.0, 0.0, 1.0);
}
</script>
<script>
'use strict';
var gl = null;
do {
var c = document.createElement('canvas');
gl = c.getContext('webgl');
if (!gl) {
todo(false, 'Get GL working here first.');
break;
}
var ext = gl.getExtension('WEBGL_depth_texture');
if (!ext) {
todo(false, 'WEBGL_depth_texture not supported, which is fine.');
break;
}
var prog = WebGLUtil.createProgramByIds(gl, 'vs', 'fs');
if (!prog) {
ok(false, 'Program linking should succeed.');
break;
}
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT,
gl.UNSIGNED_INT, null);
var uTexUnit = gl.getUniformLocation(prog, 'uTexUnit');
gl.useProgram(prog);
gl.uniform1i(uTexUnit, 0);
gl.drawArrays(gl.POINTS, 0, 1);
ok(!gl.getError(), 'Should have no errors.');
} while (false);
ok(true, 'Test complete.');
</script>
</body>
</html>
@@ -0,0 +1,159 @@
<!DOCTYPE HTML>
<title>WebGL test: Hidden depth/stencil passes without a depth/stencil buffer respectively</title>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='webgl-util.js'></script>
<body>
<script id='vs' type='x-shader/x-vertex'>
void main(void) {
gl_PointSize = 1.0; // Note that this is undefined if we don't write to it!
gl_Position = vec4(vec3(0), 1);
}
</script>
<script id='fs' type='x-shader/x-fragment'>
precision mediump float;
void main(void) {
gl_FragColor = vec4(0, 1, 0, 1);
}
</script>
<script>
function ColorString(arr) {
return '[' + arr[0] + ', ' + arr[1] + ', ' + arr[2] + ', ' + arr[3] + ']';
}
function DrawAndCheck(gl, infoPrefix, refColorStr) {
gl.viewport(0, 0, 1, 1);
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 1);
var pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
var pixelStr = ColorString(pixel);
ok(pixelStr == refColorStr, infoPrefix + pixelStr + ' should be ' + refColorStr);
}
function TestCurrent(gl, attribs, infoPrefix) {
infoPrefix = infoPrefix + JSON.stringify(attribs) + ': ';
var CLEAR_COLOR = ColorString([255, 0, 0, 255]);
var DRAW_COLOR = ColorString([0, 255, 0, 255]);
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.STENCIL_TEST);
DrawAndCheck(gl, infoPrefix + 'initial: ', DRAW_COLOR);
if (!attribs.depth) {
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.NEVER);
gl.disable(gl.STENCIL_TEST);
// Depth test is enabled, and should pass NEVER.
// Since there is no depth buffer, the depth test is not run.
// Stencil test is disabled.
DrawAndCheck(gl, infoPrefix + 'no-depth: ', DRAW_COLOR);
}
if (!attribs.stencil) {
gl.disable(gl.DEPTH_TEST);
gl.enable(gl.STENCIL_TEST);
gl.stencilFunc(gl.NEVER, 0, 0);
// Depth test is disabled.
// Stencil test is enabled, and should pass NEVER.
// Since there is no stencil buffer, the stencil test is not run.
DrawAndCheck(gl, infoPrefix + 'no-stencil: ', DRAW_COLOR);
}
}
function TestBackbuffer(requestedAttribs) {
var canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
var gl = canvas.getContext('experimental-webgl', requestedAttribs);
if (!gl) {
ok(true, 'WebGL doesn\'t work, skipping test.');
return;
}
ok(gl.drawingBufferWidth == 1 && gl.drawingBufferHeight == 1,
'backbuffer should be 1x1');
var prog = WebGLUtil.createProgramByIds(gl, 'vs', 'fs');
gl.useProgram(prog);
var attribs = {
depth: gl.getContextAttributes().depth,
stencil: gl.getContextAttributes().stencil,
};
TestCurrent(gl, attribs, 'Backbuffer: ');
}
function TestUserFB() {
var canvas = document.createElement('canvas');
var gl = canvas.getContext('experimental-webgl');
if (!gl) {
ok(true, 'WebGL doesn\'t work, skipping test.');
return;
}
var prog = WebGLUtil.createProgramByIds(gl, 'vs', 'fs');
gl.useProgram(prog);
var rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 1, 1);
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
var depthRB = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthRB);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
var stencilRB = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, stencilRB);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
do {
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRB);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != gl.FRAMEBUFFER_COMPLETE) {
ok(true, 'Depth-only user FB is incomplete. This is allowed.');
break;
}
TestCurrent(gl, {depth: true, stencil: false}, 'Depth-only user FB');
} while (false);
do {
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilRB);
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != gl.FRAMEBUFFER_COMPLETE) {
ok(true, 'Stencil-only user FB is incomplete. This is allowed.');
break;
}
TestCurrent(gl, {depth: false, stencil: true}, 'Stencil-only user FB');
} while (false);
}
(function(){
TestBackbuffer({depth: true, stencil: false});
TestBackbuffer({depth: false, stencil: true});
TestUserFB();
})();
</script>
</body>
@@ -1,50 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL test: Check that WebGL works (or not) if it should (or should not).</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="webgl-util.js"></script>
<script src="driver-info.js"></script>
</head>
<body>
<canvas id="c"></canvas>
<script>
<head>
<meta charset='utf-8'/>
<title>WebGL test: Check that WebGL works out-of-the-box.</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
function test() {
ok(SpecialPowers.getBoolPref('webgl.force-enabled'), 'WebGL should be force-enabled.');
'use strict';
var c = document.createElement('canvas');
var gl = c.getContext('experimental-webgl');
ok(gl, 'Expected WebGL creation to succeed.');
var shouldSucceed = true;
var shouldFail = false;
if (DriverInfo.getOS() == DriverInfo.OS.ANDROID &&
DriverInfo.getOSVersion() < 15)
{
// Consider 'random'. Actually, ARMv6 fails, and ARMv7 succeeds, but we have
// not been successful at determining this from JS. (see bug 917478)
shouldSucceed = false;
shouldFail = false;
}
var gl = WebGLUtil.getWebGL('c');
if (shouldSucceed) {
ok(gl, 'Expected WebGL creation to succeed.');
}
if (shouldFail) {
ok(!gl, 'Expected WebGL creation to fail.');
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
var prefArrArr = [
['webgl.force-enabled', true]
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, test);
</script>
</body>
</script>
</body>
</html>
@@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL test: Check that WebGL works (or not) if it should (or should not).</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="webgl-util.js"></script>
<script src="driver-info.js"></script>
</head>
<body>
<canvas id="c"></canvas>
<script>
function test() {
ok(SpecialPowers.getBoolPref('webgl.force-enabled'), 'WebGL should be force-enabled.');
var shouldSucceed = true;
var shouldFail = false;
if (DriverInfo.getOS() == DriverInfo.OS.ANDROID &&
DriverInfo.getOSVersion() < 15)
{
// Consider 'random'. Actually, ARMv6 fails, and ARMv7 succeeds, but we have
// not been successful at determining this from JS. (see bug 917478)
shouldSucceed = false;
shouldFail = false;
}
var gl = WebGLUtil.getWebGL('c');
if (shouldSucceed) {
ok(gl, 'Expected WebGL creation to succeed.');
}
if (shouldFail) {
ok(!gl, 'Expected WebGL creation to fail.');
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
var prefArrArr = [
['webgl.force-enabled', true]
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, test);
</script>
</body>
</html>
+6 -1
View File
@@ -974,11 +974,16 @@ CreateECPublicKey(const SECItem* aKeyData, const nsString& aNamedCurve)
return nullptr;
}
SECKEYPublicKey* key = PORT_ArenaZNew(arena, SECKEYPublicKey);
// It's important that this be a ScopedSECKEYPublicKey, as this ensures that
// SECKEY_DestroyPublicKey will be called on it. If this doesn't happen, when
// CryptoKey::PublicKeyValid is called on it and it gets moved to the internal
// PKCS#11 slot, it will leak a reference to the slot.
ScopedSECKEYPublicKey key(PORT_ArenaZNew(arena, SECKEYPublicKey));
if (!key) {
return nullptr;
}
key->arena = nullptr; // key doesn't own the arena; it won't get double-freed
key->keyType = ecKey;
key->pkcs11Slot = nullptr;
key->pkcs11ID = CK_INVALID_HANDLE;
+13
View File
@@ -193,6 +193,19 @@ KeyAlgorithmProxy::JwkAlg() const
}
}
if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
nsString hashName = mRsa.mHash.mName;
if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
return NS_LITERAL_STRING(JWK_ALG_PS1);
} else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
return NS_LITERAL_STRING(JWK_ALG_PS256);
} else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
return NS_LITERAL_STRING(JWK_ALG_PS384);
} else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
return NS_LITERAL_STRING(JWK_ALG_PS512);
}
}
return nsString();
}
+6
View File
@@ -88,6 +88,10 @@
#define JWK_ALG_RSA_OAEP_256 "RSA-OAEP-256"
#define JWK_ALG_RSA_OAEP_384 "RSA-OAEP-384"
#define JWK_ALG_RSA_OAEP_512 "RSA-OAEP-512"
#define JWK_ALG_PS1 "PS1" // RSA-PSS
#define JWK_ALG_PS256 "PS256"
#define JWK_ALG_PS384 "PS384"
#define JWK_ALG_PS512 "PS512"
#define JWK_ALG_ECDSA_P_256 "ES256"
#define JWK_ALG_ECDSA_P_384 "ES384"
#define JWK_ALG_ECDSA_P_521 "ES521"
@@ -206,6 +210,8 @@ MapAlgorithmNameToMechanism(const nsString& aName)
mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
mechanism = CKM_RSA_PKCS_OAEP;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
mechanism = CKM_RSA_PKCS_PSS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
mechanism = CKM_ECDH1_DERIVE;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
+12 -9
View File
@@ -1673,7 +1673,8 @@ public:
// If this is RSA with a hash, cache the hash name
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
RootedDictionary<RsaHashedImportParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv)) {
@@ -1775,7 +1776,8 @@ private:
mKey->HasUsageOtherThan(CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY))) {
return NS_ERROR_DOM_DATA_ERR;
}
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
if ((mKey->GetKeyType() == CryptoKey::PUBLIC &&
mKey->HasUsageOtherThan(CryptoKey::VERIFY)) ||
(mKey->GetKeyType() == CryptoKey::PRIVATE &&
@@ -2173,11 +2175,9 @@ private:
mJwk.mExt.Construct(mExtractable);
if (!mKeyUsages.IsEmpty()) {
mJwk.mKey_ops.Construct();
if (!mJwk.mKey_ops.Value().AppendElements(mKeyUsages, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
mJwk.mKey_ops.Construct();
if (!mJwk.mKey_ops.Value().AppendElements(mKeyUsages, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
@@ -3341,7 +3341,8 @@ WebCryptoTask::CreateImportKeyTask(JSContext* aCx,
return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
return new ImportRsaKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
@@ -3387,6 +3388,7 @@ WebCryptoTask::CreateExportKeyTask(const nsAString& aFormat,
algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
@@ -3609,7 +3611,8 @@ WebCryptoTask::CreateUnwrapKeyTask(JSContext* aCx,
aUnwrappedKeyAlgorithm,
aExtractable, aKeyUsages);
} else if (keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP)) {
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_PSS)) {
importTask = new ImportRsaKeyTask(aCx, aFormat,
aUnwrappedKeyAlgorithm,
aExtractable, aKeyUsages);
+80
View File
@@ -418,6 +418,86 @@ tv = {
),
},
// RSA-PSS test vectors, pss-vect.txt, Example 1: A 1024-bit RSA Key Pair
// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
rsapss: {
pkcs8: util.hex2abv(
"30820275020100300d06092a864886f70d01010105000482025f3082025b0201" +
"0002818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1" +
"e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ce" +
"abfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e" +
"6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb22" +
"49bd9a2137020301000102818033a5042a90b27d4f5451ca9bbbd0b44771a101" +
"af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca" +
"0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574" +
"501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c06" +
"22ad79c6dcee883547c6a3b325024100e7e8942720a877517273a356053ea2a1" +
"bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1" +
"535bd9b3cc34160b3b6dcd3eda8e6443024100b69dca1cf7d4d7ec81e75b90fc" +
"ca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542" +
"cd20dc723e6963364a1f9425452b269a6799fd024028fa13938655be1f8a159c" +
"baca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8d" +
"d3ede2448328f385d81b30e8e43b2fffa02786197902401a8b38f398fa712049" +
"898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455e" +
"aeb6e1678255827580a8e4e8e14151d1510a82a3f2e729024027156aba4126d2" +
"4a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a" +
"2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d"
),
spki: util.hex2abv(
"30819f300d06092a864886f70d010101050003818d0030818902818100a56e4a" +
"0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c510" +
"56ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd95" +
"08096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2" +
"d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137020301" +
"0001"
),
data: util.hex2abv(
"cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b6" +
"2371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb76" +
"9757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb0" +
"61a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d61" +
"93c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c" +
"296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16" +
"be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0"
),
sig: util.hex2abv(
"9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887" +
"e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215" +
"df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65" +
"984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c"
),
salt: util.hex2abv(
"dee959c7e06411361420ff80185ed57f3e6776af"
),
jwk_priv: {
kty: "RSA",
n: "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhK" +
"oijlN_1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm" +
"_4nRnxBazC0_DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc",
e: "AQAB",
d: "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-kuiUpySsPFaMj5eFOtB8A" +
"mbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQGlMmgxCcKr" +
"rKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU",
p: "5-iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh3" +
"1WhU1vZs8w0Fgs7bc0-2o5kQw",
q: "tp3KHPfU1-yB51uQ_MqHSrzeEj_ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCz" +
"SDccj5pYzZKH5QlRSsmmmeZ_Q",
dp: "KPoTk4ZVvh-KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt" +
"4kSDKPOF2Bsw6OQ7L_-gJ4YZeQ",
dq: "Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-RV6utuFn" +
"glWCdYCo5OjhQVHRUQqCo_LnKQ",
qi: "JxVqukEm0kqB86Uoy_sn9WiG-ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo" +
"2FhBlOshkKz4MrhH8To9JKefTQ",
},
jwk_pub: {
kty: "RSA",
n: "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhK" +
"oijlN_1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm" +
"_4nRnxBazC0_DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc",
e: "AQAB",
},
},
key_wrap_known_answer: {
key: util.hex2abv("0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a"),
wrapping_key: util.hex2abv("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+52
View File
@@ -250,6 +250,58 @@ TestArray.addTest(
);
}
);
// --------
TestArray.addTest(
"Check JWK parameters on generated ECDSA key pair",
function() {
crypto.subtle.generateKey({name: 'ECDSA', namedCurve: 'P-256'}, true, ['sign', 'verify'])
.then(pair => Promise.all([
crypto.subtle.exportKey('jwk', pair.privateKey),
crypto.subtle.exportKey('jwk', pair.publicKey)
]))
.then(
complete(this, function(x) {
var priv = x[0];
var pub = x[1];
var pubIsSubsetOfPriv = Object.keys(pub)
.filter(k => k !== 'key_ops') // key_ops is the only complex attr
.reduce((all, k) => all && pub[k] === priv[k], true);
// Can't use hasBaseJwkFields() because EC keys don't get "alg":
// "alg" matches curve to hash, but WebCrypto keys are more flexible.
return hasFields(pub, ['kty', 'crv', 'key_ops', 'ext']) &&
pub.kty === 'EC' &&
pub.crv === 'P-256' &&
pub.ext &&
typeof(pub.x) === 'string' &&
typeof(pub.y) === 'string' &&
shallowArrayEquals(pub.key_ops, ['verify']) &&
pubIsSubsetOfPriv &&
shallowArrayEquals(priv.key_ops, ['sign']) &&
typeof(priv.d) === 'string';
}),
error(this));
}
);
// --------
TestArray.addTest(
"Check key_ops parameter on an unusable RSA public key",
function() {
var parameters = {
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 1024,
publicExponent: new Uint8Array([1, 0, 1]),
hash: 'SHA-256'
};
// The public key generated here will have no usages and will therefore
// have an empty key_ops list.
crypto.subtle.generateKey(parameters, true, ['sign'])
.then(pair => crypto.subtle.exportKey('jwk', pair.publicKey))
.then(complete(this, x => x.key_ops.length === 0),
error(this));
}
);
/*]]>*/</script>
</head>
+198
View File
@@ -73,6 +73,204 @@ TestArray.addTest(
.then(complete(that, x => x), error(that))
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS verify known signature (SHA-1, 1024-bit)",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
function doVerify(x) {
var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
return crypto.subtle.verify(alg, x, tv.rsapss.sig, tv.rsapss.data);
}
crypto.subtle.importKey("spki", tv.rsapss.spki, alg, false, ["verify"])
.then(doVerify, error(that))
.then(complete(that, x => x), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS verify known signature (SHA-1, 1024-bit, JWK)",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
function doVerify(x) {
var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
return crypto.subtle.verify(alg, x, tv.rsapss.sig, tv.rsapss.data);
}
crypto.subtle.importKey("jwk", tv.rsapss.jwk_pub, alg, false, ["verify"])
.then(doVerify, error(that))
.then(complete(that, x => x), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS import SPKI/PKCS#8 keys and sign/verify (SHA-1, 1024-bit)",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
var privKey, pubKey;
function setKeys([pub, priv]) { pubKey = pub; privKey = priv; }
function doSign() {
var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
return crypto.subtle.sign(alg, privKey, tv.rsapss.data);
}
function doVerify(x) {
var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
return crypto.subtle.verify(alg, pubKey, x, tv.rsapss.data);
}
var spki =
crypto.subtle.importKey("spki", tv.rsapss.spki, alg, false, ["verify"]);
var pkcs8 =
crypto.subtle.importKey("pkcs8", tv.rsapss.pkcs8, alg, false, ["sign"]);
Promise.all([spki, pkcs8])
.then(setKeys, error(that))
.then(doSign, error(that))
.then(doVerify, error(that))
.then(complete(that, x => x), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS import JWK keys and sign/verify (SHA-1, 1024-bit)",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
var privKey, pubKey;
function setKeys([pub, priv]) { pubKey = pub; privKey = priv; }
function doSign() {
var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
return crypto.subtle.sign(alg, privKey, tv.rsapss.data);
}
function doVerify(x) {
var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
return crypto.subtle.verify(alg, pubKey, x, tv.rsapss.data);
}
var spki =
crypto.subtle.importKey("jwk", tv.rsapss.jwk_pub, alg, false, ["verify"]);
var pkcs8 =
crypto.subtle.importKey("jwk", tv.rsapss.jwk_priv, alg, false, ["sign"]);
Promise.all([spki, pkcs8])
.then(setKeys, error(that))
.then(doSign, error(that))
.then(doVerify, error(that))
.then(complete(that, x => x), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS SPKI import/export (SHA-1, 1024-bit)",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
function doExport(x) {
return crypto.subtle.exportKey("spki", x);
}
crypto.subtle.importKey("spki", tv.rsapss.spki, alg, true, ["verify"])
.then(doExport, error(that))
.then(memcmp_complete(that, tv.rsapss.spki), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS PKCS#8 import/export (SHA-1, 1024-bit)",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
function doExport(x) {
return crypto.subtle.exportKey("pkcs8", x);
}
crypto.subtle.importKey("pkcs8", tv.rsapss.pkcs8, alg, true, ["sign"])
.then(doExport, error(that))
.then(memcmp_complete(that, tv.rsapss.pkcs8), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS JWK export a public key",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
var jwk = tv.rsapss.jwk_pub;
function doExport(x) {
return crypto.subtle.exportKey("jwk", x);
}
crypto.subtle.importKey("jwk", jwk, alg, true, ["verify"])
.then(doExport)
.then(
complete(that, function(x) {
return hasBaseJwkFields(x) &&
hasFields(x, ["n", "e"]) &&
x.kty == "RSA" &&
x.alg == "PS1" &&
x.ext &&
shallowArrayEquals(x.key_ops, ["verify"]) &&
x.n == jwk.n &&
x.e == jwk.e;
}),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-PSS JWK export a private key",
function () {
var that = this;
var alg = {name: "RSA-PSS", hash: "SHA-1"};
var jwk = tv.rsapss.jwk_priv;
function doExport(x) {
return crypto.subtle.exportKey("jwk", x);
}
crypto.subtle.importKey("jwk", jwk, alg, true, ["sign"])
.then(doExport)
.then(
complete(that, function(x) {
return hasBaseJwkFields(x) &&
hasFields(x, ["n", "e", "d", "p", "q", "dp", "dq", "qi"]) &&
x.kty == "RSA" &&
x.alg == "PS1" &&
x.ext &&
shallowArrayEquals(x.key_ops, ["sign"]) &&
x.n == jwk.n &&
x.e == jwk.e &&
x.d == jwk.d &&
x.p == jwk.p &&
x.q == jwk.q &&
x.dp == jwk.dp &&
x.dq == jwk.dq &&
x.qi == jwk.qi;
}),
error(that)
);
}
);
/*]]>*/</script>
</head>
+1 -1
View File
@@ -480,7 +480,7 @@ interface WebGL2RenderingContext : WebGLRenderingContext
// GLintptr here, otherwise interface generator returns error.
(WebGLBuffer or GLintptr)? getIndexedParameter(GLenum target, GLuint index);
sequence<GLuint>? getUniformIndices(WebGLProgram? program, sequence<DOMString> uniformNames);
sequence<GLint>? getActiveUniforms(WebGLProgram? program, sequence<GLuint> uniformIndices, GLenum pname);
any getActiveUniforms(WebGLProgram? program, sequence<GLuint> uniformIndices, GLenum pname);
GLuint getUniformBlockIndex(WebGLProgram? program, DOMString uniformBlockName);
[Throws]
(GLuint or Uint32Array or GLboolean)? getActiveUniformBlockParameter(WebGLProgram? program, GLuint uniformBlockIndex, GLenum pname);
-11
View File
@@ -36,8 +36,6 @@ typedef _cairo_surface cairo_surface_t;
struct _cairo_scaled_font;
typedef _cairo_scaled_font cairo_scaled_font_t;
struct ID3D10Device1;
struct ID3D10Texture2D;
struct ID3D11Texture2D;
struct ID3D11Device;
struct ID2D1Device;
@@ -1365,14 +1363,6 @@ public:
#endif
#ifdef WIN32
static already_AddRefed<DrawTarget> CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
static already_AddRefed<DrawTarget>
CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
ID3D10Texture2D *aTextureB,
SurfaceFormat aFormat);
static void SetDirect3D10Device(ID3D10Device1 *aDevice);
static ID3D10Device1 *GetDirect3D10Device();
static already_AddRefed<DrawTarget> CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat);
static void SetDirect3D11Device(ID3D11Device *aDevice);
@@ -1395,7 +1385,6 @@ public:
private:
static ID2D1Device *mD2D1Device;
static ID3D10Device1 *mD3D10Device;
static ID3D11Device *mD3D11Device;
#endif
File diff suppressed because it is too large Load Diff
-290
View File
@@ -1,290 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 MOZILLA_GFX_DRAWTARGETD2D_H_
#define MOZILLA_GFX_DRAWTARGETD2D_H_
#include "2D.h"
#include "PathD2D.h"
#include <d3d10_1.h>
#include "HelpersD2D.h"
#include <vector>
#include <sstream>
#include <unordered_set>
struct IDWriteFactory;
namespace mozilla {
namespace gfx {
class SourceSurfaceD2DTarget;
class SourceSurfaceD2D;
class GradientStopsD2D;
class ScaledFontDWrite;
const int32_t kLayerCacheSize = 5;
struct PrivateD3D10DataD2D
{
RefPtr<ID3D10Effect> mEffect;
RefPtr<ID3D10InputLayout> mInputLayout;
RefPtr<ID3D10Buffer> mVB;
RefPtr<ID3D10BlendState> mBlendStates[size_t(CompositionOp::OP_COUNT)];
};
class DrawTargetD2D : public DrawTarget
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D, override)
DrawTargetD2D();
virtual ~DrawTargetD2D();
virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; }
virtual BackendType GetBackendType() const override { return BackendType::DIRECT2D; }
virtual already_AddRefed<SourceSurface> Snapshot() override;
virtual IntSize GetSize() override { return mSize; }
virtual void Flush() override;
virtual void DrawSurface(SourceSurface *aSurface,
const Rect &aDest,
const Rect &aSource,
const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
const DrawOptions &aOptions = DrawOptions()) override;
virtual void DrawFilter(FilterNode *aNode,
const Rect &aSourceRect,
const Point &aDestPoint,
const DrawOptions &aOptions = DrawOptions()) override;
virtual void DrawSurfaceWithShadow(SourceSurface *aSurface,
const Point &aDest,
const Color &aColor,
const Point &aOffset,
Float aSigma,
CompositionOp aOperator) override;
virtual void ClearRect(const Rect &aRect) override;
virtual void MaskSurface(const Pattern &aSource,
SourceSurface *aMask,
Point aOffset,
const DrawOptions &aOptions = DrawOptions()) override;
virtual void CopySurface(SourceSurface *aSurface,
const IntRect &aSourceRect,
const IntPoint &aDestination) override;
virtual void FillRect(const Rect &aRect,
const Pattern &aPattern,
const DrawOptions &aOptions = DrawOptions()) override;
virtual void StrokeRect(const Rect &aRect,
const Pattern &aPattern,
const StrokeOptions &aStrokeOptions = StrokeOptions(),
const DrawOptions &aOptions = DrawOptions()) override;
virtual void StrokeLine(const Point &aStart,
const Point &aEnd,
const Pattern &aPattern,
const StrokeOptions &aStrokeOptions = StrokeOptions(),
const DrawOptions &aOptions = DrawOptions()) override;
virtual void Stroke(const Path *aPath,
const Pattern &aPattern,
const StrokeOptions &aStrokeOptions = StrokeOptions(),
const DrawOptions &aOptions = DrawOptions()) override;
virtual void Fill(const Path *aPath,
const Pattern &aPattern,
const DrawOptions &aOptions = DrawOptions()) override;
virtual void FillGlyphs(ScaledFont *aFont,
const GlyphBuffer &aBuffer,
const Pattern &aPattern,
const DrawOptions &aOptions = DrawOptions(),
const GlyphRenderingOptions *aRenderingOptions = nullptr) override;
virtual void Mask(const Pattern &aSource,
const Pattern &aMask,
const DrawOptions &aOptions = DrawOptions()) override;
virtual void PushClip(const Path *aPath) override;
virtual void PushClipRect(const Rect &aRect) override;
virtual void PopClip() override;
virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat) const override;
virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const override;
virtual already_AddRefed<SourceSurface>
CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override;
virtual already_AddRefed<DrawTarget>
CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override;
virtual already_AddRefed<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override;
virtual already_AddRefed<GradientStops>
CreateGradientStops(GradientStop *aStops,
uint32_t aNumStops,
ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
virtual bool SupportsRegionClipping() const override { return false; }
virtual void *GetNativeSurface(NativeSurfaceType aType) override;
bool Init(const IntSize &aSize, SurfaceFormat aFormat);
bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
bool InitD3D10Data();
uint32_t GetByteSize() const;
already_AddRefed<ID2D1Layer> GetCachedLayer();
void PopCachedLayer(ID2D1RenderTarget *aRT);
already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface *aSurface);
static ID2D1Factory *factory();
static void CleanupD2D();
static IDWriteFactory *GetDWriteFactory();
ID2D1RenderTarget *GetRT() { return mRT; }
static uint32_t GetMaxSurfaceSize() {
return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
}
operator std::string() const {
std::stringstream stream;
stream << "DrawTargetD2D(" << this << ")";
return stream.str();
}
static uint64_t mVRAMUsageDT;
static uint64_t mVRAMUsageSS;
private:
already_AddRefed<ID2D1Bitmap>
GetBitmapForSurface(SourceSurface *aSurface,
Rect &aSource);
friend class AutoSaveRestoreClippedOut;
friend class SourceSurfaceD2DTarget;
typedef std::unordered_set<DrawTargetD2D*> TargetSet;
bool InitD2DRenderTarget();
void PrepareForDrawing(ID2D1RenderTarget *aRT);
// This function will mark the surface as changing, and make sure any
// copy-on-write snapshots are notified.
void MarkChanged();
void FlushTransformToRT() {
if (mTransformDirty) {
mRT->SetTransform(D2DMatrix(mTransform));
mTransformDirty = false;
}
}
void AddDependencyOnSource(SourceSurfaceD2DTarget* aSource);
ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator);
ID2D1RenderTarget *GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern);
void FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds); void EnsureViews();
void PopAllClips();
void PushClipsToRT(ID2D1RenderTarget *aRT);
void PopClipsFromRT(ID2D1RenderTarget *aRT);
// This function ensures mCurrentClipMaskTexture contains a texture containing
// a mask corresponding with the current DrawTarget clip. See
// GetClippedGeometry for a description of aClipBounds.
void EnsureClipMaskTexture(IntRect *aClipBounds);
bool FillGlyphsManual(ScaledFontDWrite *aFont,
const GlyphBuffer &aBuffer,
const Color &aColor,
IDWriteRenderingParams *aParams,
const DrawOptions &aOptions = DrawOptions());
already_AddRefed<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
// This returns the clipped geometry, in addition it returns aClipBounds which
// represents the intersection of all pixel-aligned rectangular clips that
// are currently set. The returned clipped geometry must be clipped by these
// bounds to correctly reflect the total clip. This is in device space.
already_AddRefed<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
already_AddRefed<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
already_AddRefed<ID3D10Texture2D> CreateGradientTexture(const GradientStopsD2D *aStops);
already_AddRefed<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds);
void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern);
void SetupStateForRendering();
// Set the scissor rect to a certain IntRects, resets the scissor rect to
// surface bounds when nullptr is specified.
void SetScissorToRect(IntRect *aRect);
void PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform);
static const uint32_t test = 4;
IntSize mSize;
RefPtr<ID3D10Device1> mDevice;
RefPtr<ID3D10Texture2D> mTexture;
RefPtr<ID3D10Texture2D> mCurrentClipMaskTexture;
RefPtr<ID2D1Geometry> mCurrentClippedGeometry;
// This is only valid if mCurrentClippedGeometry is non-null. And will
// only be the intersection of all pixel-aligned retangular clips. This is in
// device space.
IntRect mCurrentClipBounds;
mutable RefPtr<ID2D1RenderTarget> mRT;
// We store this to prevent excessive SetTextRenderingParams calls.
RefPtr<IDWriteRenderingParams> mTextRenderingParams;
// Temporary texture and render target used for supporting alternative operators.
RefPtr<ID3D10Texture2D> mTempTexture;
RefPtr<ID3D10RenderTargetView> mRTView;
RefPtr<ID3D10ShaderResourceView> mSRView;
RefPtr<ID2D1RenderTarget> mTempRT;
RefPtr<ID3D10RenderTargetView> mTempRTView;
// List of pushed clips.
struct PushedClip
{
RefPtr<ID2D1Layer> mLayer;
D2D1_RECT_F mBounds;
union {
// If mPath is non-nullptr, the mTransform member will be used, otherwise
// the mIsPixelAligned member is valid.
D2D1_MATRIX_3X2_F mTransform;
bool mIsPixelAligned;
};
RefPtr<PathD2D> mPath;
};
std::vector<PushedClip> mPushedClips;
// We cache ID2D1Layer objects as it causes D2D to keep around textures that
// serve as the temporary surfaces for these operations. As texture creation
// is quite expensive this considerably improved performance.
// Careful here, RAII will not ensure destruction of the RefPtrs.
RefPtr<ID2D1Layer> mCachedLayers[kLayerCacheSize];
uint32_t mCurrentCachedLayer;
// The latest snapshot of this surface. This needs to be told when this
// target is modified. We keep it alive as a cache.
RefPtr<SourceSurfaceD2DTarget> mSnapshot;
// A list of targets we need to flush when we're modified.
TargetSet mDependentTargets;
// A list of targets which have this object in their mDependentTargets set
TargetSet mDependingOnTargets;
// True of the current clip stack is pushed to the main RT.
bool mClipsArePushed;
PrivateD3D10DataD2D *mPrivateData;
static ID2D1Factory *mFactory;
static IDWriteFactory *mDWriteFactory;
};
}
}
#endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */
+67 -7
View File
@@ -5,24 +5,32 @@
#include <initguid.h>
#include "DrawTargetD2D1.h"
#include "DrawTargetD2D.h"
#include "FilterNodeSoftware.h"
#include "GradientStopsD2D.h"
#include "SourceSurfaceD2D1.h"
#include "SourceSurfaceD2D.h"
#include "RadialGradientEffectD2D1.h"
#include "HelpersD2D.h"
#include "FilterNodeD2D1.h"
#include "ExtendInputEffectD2D1.h"
#include "Tools.h"
using namespace std;
// decltype is not usable for overloaded functions.
typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
D2D1_FACTORY_TYPE factoryType,
REFIID iid,
CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
void **factory
);
namespace mozilla {
namespace gfx {
uint64_t DrawTargetD2D1::mVRAMUsageDT;
uint64_t DrawTargetD2D1::mVRAMUsageSS;
IDWriteFactory *DrawTargetD2D1::mDWriteFactory;
ID2D1Factory1* DrawTargetD2D1::mFactory = nullptr;
ID2D1Factory1 *D2DFactory1()
@@ -584,7 +592,7 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
DWRITE_MEASURING_MODE_NATURAL, &userRect);
RefPtr<ID2D1PathGeometry> path;
D2DFactory()->CreatePathGeometry(getter_AddRefs(path));
factory()->CreatePathGeometry(getter_AddRefs(path));
RefPtr<ID2D1GeometrySink> sink;
path->Open(getter_AddRefs(sink));
AddRectToSink(sink, userRect);
@@ -1038,27 +1046,79 @@ DrawTargetD2D1::factory()
return mFactory;
}
ID2D1Factory* d2dFactory = D2DFactory();
if (!d2dFactory) {
RefPtr<ID2D1Factory> factory;
D2D1CreateFactoryFunc createD2DFactory;
HMODULE d2dModule = LoadLibraryW(L"d2d1.dll");
createD2DFactory = (D2D1CreateFactoryFunc)
GetProcAddress(d2dModule, "D2D1CreateFactory");
if (!createD2DFactory) {
gfxWarning() << "Failed to locate D2D1CreateFactory function.";
return nullptr;
}
HRESULT hr = d2dFactory->QueryInterface((ID2D1Factory1**)&mFactory);
D2D1_FACTORY_OPTIONS options;
#ifdef _DEBUG
options.debugLevel = D2D1_DEBUG_LEVEL_WARNING;
#else
options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
#endif
//options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
if (FAILED(hr)) {
HRESULT hr = createD2DFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
__uuidof(ID2D1Factory),
&options,
getter_AddRefs(factory));
if (FAILED(hr) || !factory) {
gfxWarning() << "Failed to create Direct2D factory.";
return nullptr;
}
hr = factory->QueryInterface((ID2D1Factory1**)&mFactory);
if (FAILED(hr) || !mFactory) {
return nullptr;
}
ExtendInputEffectD2D1::Register(mFactory);
RadialGradientEffectD2D1::Register(mFactory);
return mFactory;
}
IDWriteFactory*
DrawTargetD2D1::GetDWriteFactory()
{
if (mDWriteFactory) {
return mDWriteFactory;
}
decltype(DWriteCreateFactory)* createDWriteFactory;
HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll");
createDWriteFactory = (decltype(DWriteCreateFactory)*)
GetProcAddress(dwriteModule, "DWriteCreateFactory");
if (!createDWriteFactory) {
gfxWarning() << "Failed to locate DWriteCreateFactory function.";
return nullptr;
}
HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&mDWriteFactory));
if (FAILED(hr)) {
gfxWarning() << "Failed to create DWrite Factory.";
}
return mDWriteFactory;
}
void
DrawTargetD2D1::CleanupD2D()
{
if (mFactory) {
RadialGradientEffectD2D1::Unregister(mFactory);
ExtendInputEffectD2D1::Unregister(mFactory);
mFactory->Release();
mFactory = nullptr;
}
+2 -97
View File
@@ -35,7 +35,6 @@
#endif
#ifdef WIN32
#include "DrawTargetD2D.h"
#include "DrawTargetD2D1.h"
#include "ScaledFontDWrite.h"
#include "NativeFontResourceDWrite.h"
@@ -161,7 +160,6 @@ int32_t LoggingPrefs::sGfxLogLevel =
LOG_DEFAULT);
#ifdef WIN32
ID3D10Device1 *Factory::mD3D10Device;
ID3D11Device *Factory::mD3D11Device;
ID2D1Device *Factory::mD2D1Device;
#endif
@@ -326,15 +324,6 @@ Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFor
RefPtr<DrawTarget> retVal;
switch (aBackend) {
#ifdef WIN32
case BackendType::DIRECT2D:
{
RefPtr<DrawTargetD2D> newTarget;
newTarget = new DrawTargetD2D();
if (newTarget->Init(aSize, aFormat)) {
retVal = newTarget;
}
break;
}
case BackendType::DIRECT2D1_1:
{
RefPtr<DrawTargetD2D1> newTarget;
@@ -512,8 +501,6 @@ Factory::GetMaxSurfaceSize(BackendType aType)
return DrawTargetSkia::GetMaxSurfaceSize();
#endif
#ifdef WIN32
case BackendType::DIRECT2D:
return DrawTargetD2D::GetMaxSurfaceSize();
case BackendType::DIRECT2D1_1:
return DrawTargetD2D1::GetMaxSurfaceSize();
#endif
@@ -624,87 +611,6 @@ Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB)
#ifdef WIN32
already_AddRefed<DrawTarget>
Factory::CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat)
{
MOZ_ASSERT(aTexture);
RefPtr<DrawTargetD2D> newTarget;
newTarget = new DrawTargetD2D();
if (newTarget->Init(aTexture, aFormat)) {
RefPtr<DrawTarget> retVal = newTarget;
if (mRecorder) {
retVal = new DrawTargetRecording(mRecorder, retVal, true);
}
return retVal.forget();
}
gfxWarning() << "Failed to create draw target for D3D10 texture.";
// Failed
return nullptr;
}
already_AddRefed<DrawTarget>
Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
ID3D10Texture2D *aTextureB,
SurfaceFormat aFormat)
{
MOZ_ASSERT(aTextureA && aTextureB);
RefPtr<DrawTargetD2D> newTargetA;
RefPtr<DrawTargetD2D> newTargetB;
newTargetA = new DrawTargetD2D();
if (!newTargetA->Init(aTextureA, aFormat)) {
gfxWarning() << "Failed to create dual draw target for D3D10 texture.";
return nullptr;
}
newTargetB = new DrawTargetD2D();
if (!newTargetB->Init(aTextureB, aFormat)) {
gfxWarning() << "Failed to create new draw target for D3D10 texture.";
return nullptr;
}
RefPtr<DrawTarget> newTarget =
new DrawTargetDual(newTargetA, newTargetB);
RefPtr<DrawTarget> retVal = newTarget;
if (mRecorder) {
retVal = new DrawTargetRecording(mRecorder, retVal);
}
return retVal.forget();
}
void
Factory::SetDirect3D10Device(ID3D10Device1 *aDevice)
{
// do not throw on failure; return error codes and disconnect the device
// On Windows 8 error codes are the default, but on Windows 7 the
// default is to throw (or perhaps only with some drivers?)
if (aDevice) {
aDevice->SetExceptionMode(0);
}
mD3D10Device = aDevice;
}
ID3D10Device1*
Factory::GetDirect3D10Device()
{
#ifdef DEBUG
if (mD3D10Device) {
UINT mode = mD3D10Device->GetExceptionMode();
MOZ_ASSERT(0 == mode);
}
#endif
return mD3D10Device;
}
already_AddRefed<DrawTarget>
Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat)
{
@@ -780,13 +686,13 @@ Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams)
uint64_t
Factory::GetD2DVRAMUsageDrawTarget()
{
return DrawTargetD2D::mVRAMUsageDT;
return DrawTargetD2D1::mVRAMUsageDT;
}
uint64_t
Factory::GetD2DVRAMUsageSourceSurface()
{
return DrawTargetD2D::mVRAMUsageSS;
return DrawTargetD2D1::mVRAMUsageSS;
}
void
@@ -797,7 +703,6 @@ Factory::D2DCleanup()
mD2D1Device = nullptr;
}
DrawTargetD2D1::CleanupD2D();
DrawTargetD2D::CleanupD2D();
}
already_AddRefed<ScaledFont>
-5
View File
@@ -8,9 +8,6 @@
#include "Logging.h"
#include "SourceSurfaceD2D1.h"
#include "SourceSurfaceD2D.h"
#include "SourceSurfaceD2DTarget.h"
#include "DrawTargetD2D.h"
#include "DrawTargetD2D1.h"
#include "ExtendInputEffectD2D1.h"
@@ -159,8 +156,6 @@ already_AddRefed<ID2D1Image> GetImageForSourceSurface(DrawTarget *aDT, SourceSur
switch (aDT->GetBackendType()) {
case BackendType::DIRECT2D1_1:
return static_cast<DrawTargetD2D1*>(aDT)->GetImageForSurface(aSurface, ExtendMode::CLAMP);
case BackendType::DIRECT2D:
return static_cast<DrawTargetD2D*>(aDT)->GetImageForSurface(aSurface);
default:
gfxDevCrash(LogReason::FilterNodeD2D1Backend) << "Unknown draw target type! " << (int)aDT->GetBackendType();
return nullptr;
+1 -2
View File
@@ -25,9 +25,8 @@
namespace mozilla {
namespace gfx {
ID2D1Factory* D2DFactory();
ID2D1Factory1* D2DFactory1();
static ID2D1Factory* D2DFactory() { return D2DFactory1(); }
static inline D2D1_POINT_2F D2DPoint(const Point &aPoint)
{
+3 -3
View File
@@ -8,7 +8,7 @@
#include <unordered_map>
#include "DrawTargetD2D.h"
#include "DrawTargetD2D1.h"
#include "Logging.h"
#include "mozilla/RefPtr.h"
@@ -69,7 +69,7 @@ public:
{
if (!mInstance) {
mInstance = new DWriteFontFileLoader();
DrawTargetD2D::GetDWriteFactory()->
DrawTargetD2D1::GetDWriteFactory()->
RegisterFontFileLoader(mInstance);
}
return mInstance;
@@ -221,7 +221,7 @@ already_AddRefed<NativeFontResourceDWrite>
NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength,
bool aNeedsCairo)
{
IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
if (!factory) {
gfxWarning() << "Failed to get DWrite Factory.";
return nullptr;
+2 -2
View File
@@ -6,7 +6,7 @@
#include "PathD2D.h"
#include "HelpersD2D.h"
#include <math.h>
#include "DrawTargetD2D.h"
#include "DrawTargetD2D1.h"
#include "Logging.h"
namespace mozilla {
@@ -351,7 +351,7 @@ already_AddRefed<PathBuilder>
PathD2D::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
{
RefPtr<ID2D1PathGeometry> path;
HRESULT hr = DrawTargetD2D::factory()->CreatePathGeometry(getter_AddRefs(path));
HRESULT hr = DrawTargetD2D1::factory()->CreatePathGeometry(getter_AddRefs(path));
if (FAILED(hr)) {
gfxWarning() << "Failed to create PathGeometry. Code: " << hexa(hr);
+2 -2
View File
@@ -3,7 +3,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 "DrawTargetD2D.h"
#include "DrawTargetD2D1.h"
#include "ScaledFontDWrite.h"
#include "PathD2D.h"
@@ -120,7 +120,7 @@ ScaledFontDWrite::GetSkTypeface()
{
MOZ_ASSERT(mFont);
if (!mTypeface) {
IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily);
}
return mTypeface;
-317
View File
@@ -1,317 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "SourceSurfaceD2D.h"
#include "DrawTargetD2D.h"
#include "Logging.h"
#include "Tools.h"
namespace mozilla {
namespace gfx {
SourceSurfaceD2D::SourceSurfaceD2D()
{
}
SourceSurfaceD2D::~SourceSurfaceD2D()
{
if (mBitmap) {
DrawTargetD2D::mVRAMUsageSS -= GetByteSize();
}
}
IntSize
SourceSurfaceD2D::GetSize() const
{
return mSize;
}
SurfaceFormat
SourceSurfaceD2D::GetFormat() const
{
return mFormat;
}
bool
SourceSurfaceD2D::IsValid() const
{
return mDevice == Factory::GetDirect3D10Device();
}
already_AddRefed<DataSourceSurface>
SourceSurfaceD2D::GetDataSurface()
{
RefPtr<DataSourceSurfaceD2D> result = new DataSourceSurfaceD2D(this);
if (result->IsValid()) {
return result.forget();
}
return nullptr;
}
bool
SourceSurfaceD2D::InitFromData(unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat,
ID2D1RenderTarget *aRT)
{
HRESULT hr;
mFormat = aFormat;
mSize = aSize;
if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
(uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
gfxDebug() << "Bitmap does not fit in texture.";
return false;
}
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
hr = aRT->CreateBitmap(D2DIntSize(aSize), props, getter_AddRefs(mBitmap));
if (FAILED(hr)) {
gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hexa(hr);
return false;
}
hr = mBitmap->CopyFromMemory(nullptr, aData, aStride);
if (FAILED(hr)) {
gfxWarning() << "Failed to copy data to D2D bitmap. Code: " << hexa(hr);
return false;
}
DrawTargetD2D::mVRAMUsageSS += GetByteSize();
mDevice = Factory::GetDirect3D10Device();
return true;
}
bool
SourceSurfaceD2D::InitFromTexture(ID3D10Texture2D *aTexture,
SurfaceFormat aFormat,
ID2D1RenderTarget *aRT)
{
HRESULT hr;
RefPtr<IDXGISurface> surf;
hr = aTexture->QueryInterface((IDXGISurface**)&surf);
if (FAILED(hr)) {
gfxWarning() << "Failed to QI texture to surface. Code: " << hexa(hr);
return false;
}
D3D10_TEXTURE2D_DESC desc;
aTexture->GetDesc(&desc);
mSize = IntSize(desc.Width, desc.Height);
mFormat = aFormat;
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, getter_AddRefs(mBitmap));
if (FAILED(hr)) {
gfxWarning() << "Failed to create SharedBitmap. Code: " << hexa(hr);
return false;
}
aTexture->GetDevice(getter_AddRefs(mDevice));
DrawTargetD2D::mVRAMUsageSS += GetByteSize();
return true;
}
uint32_t
SourceSurfaceD2D::GetByteSize() const
{
return mSize.width * mSize.height * BytesPerPixel(mFormat);
}
DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
: mTexture(nullptr)
, mFormat(aSourceSurface->mFormat)
, mSize(aSourceSurface->mSize)
, mMapped(false)
{
// We allocate ourselves a regular D3D surface (sourceTexture) and paint the
// D2D bitmap into it via a DXGI render target. Then we need to copy
// sourceTexture into a staging texture (mTexture), which we will lazily map
// to get the data.
CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
desc.MipLevels = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
RefPtr<ID3D10Texture2D> sourceTexture;
HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
getter_AddRefs(sourceTexture));
if (FAILED(hr)) {
gfxWarning() << "Failed to create texture. Code: " << hexa(hr);
return;
}
RefPtr<IDXGISurface> dxgiSurface;
hr = sourceTexture->QueryInterface((IDXGISurface**)getter_AddRefs(dxgiSurface));
if (FAILED(hr)) {
gfxWarning() << "Failed to create DXGI surface. Code: " << hexa(hr);
return;
}
D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
RefPtr<ID2D1RenderTarget> renderTarget;
hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
&rtProps,
getter_AddRefs(renderTarget));
if (FAILED(hr)) {
gfxWarning() << "Failed to create render target. Code: " << hexa(hr);
return;
}
renderTarget->BeginDraw();
renderTarget->Clear(D2D1::ColorF(0, 0.0f));
if (aSourceSurface->GetFormat() != SurfaceFormat::A8) {
renderTarget->DrawBitmap(aSourceSurface->mBitmap,
D2D1::RectF(0, 0,
Float(mSize.width),
Float(mSize.height)));
} else {
RefPtr<ID2D1SolidColorBrush> brush;
renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), getter_AddRefs(brush));
renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
renderTarget->FillOpacityMask(aSourceSurface->mBitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
}
hr = renderTarget->EndDraw();
if (FAILED(hr)) {
gfxWarning() << "Failed to draw bitmap. Code: " << hexa(hr);
return;
}
desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE;
desc.Usage = D3D10_USAGE_STAGING;
desc.BindFlags = 0;
hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
if (FAILED(hr)) {
gfxWarning() << "Failed to create staging texture. Code: " << hexa(hr);
mTexture = nullptr;
return;
}
aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
}
DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
{
if (mMapped) {
mTexture->Unmap(0);
}
}
unsigned char*
DataSourceSurfaceD2D::GetData()
{
EnsureMappedTexture();
if (!mMapped) {
return nullptr;
}
return reinterpret_cast<unsigned char*>(mData.pData);
}
int32_t
DataSourceSurfaceD2D::Stride()
{
EnsureMappedTexture();
if (!mMapped) {
return 0;
}
return mData.RowPitch;
}
IntSize
DataSourceSurfaceD2D::GetSize() const
{
return mSize;
}
SurfaceFormat
DataSourceSurfaceD2D::GetFormat() const
{
return mFormat;
}
bool
DataSourceSurfaceD2D::Map(MapType aMapType, MappedSurface *aMappedSurface)
{
// DataSourceSurfaces used with the new Map API should not be used with GetData!!
MOZ_ASSERT(!mMapped);
MOZ_ASSERT(!mIsMapped);
if (!mTexture) {
return false;
}
D3D10_MAP mapType;
if (aMapType == MapType::READ) {
mapType = D3D10_MAP_READ;
} else if (aMapType == MapType::WRITE) {
mapType = D3D10_MAP_WRITE;
} else {
mapType = D3D10_MAP_READ_WRITE;
}
D3D10_MAPPED_TEXTURE2D map;
HRESULT hr = mTexture->Map(0, mapType, 0, &map);
if (FAILED(hr)) {
gfxWarning() << "Texture map failed with code: " << hexa(hr);
return false;
}
aMappedSurface->mData = (uint8_t*)map.pData;
aMappedSurface->mStride = map.RowPitch;
mIsMapped = !!aMappedSurface->mData;
return mIsMapped;
}
void
DataSourceSurfaceD2D::Unmap()
{
MOZ_ASSERT(mIsMapped);
mIsMapped = false;
mTexture->Unmap(0);
}
void
DataSourceSurfaceD2D::EnsureMappedTexture()
{
// Do not use GetData() after having used Map!
MOZ_ASSERT(!mIsMapped);
if (mMapped ||
!mTexture) {
return;
}
HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
if (FAILED(hr)) {
gfxWarning() << "Failed to map texture. Code: " << hexa(hr);
mTexture = nullptr;
} else {
mMapped = true;
}
}
}
}
-90
View File
@@ -1,90 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 MOZILLA_GFX_SOURCESURFACED2D_H_
#define MOZILLA_GFX_SOURCESURFACED2D_H_
#include "2D.h"
#include "HelpersD2D.h"
#include <vector>
namespace mozilla {
namespace gfx {
class DataSourceSurfaceD2D;
class SourceSurfaceD2D : public SourceSurface
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2D)
SourceSurfaceD2D();
~SourceSurfaceD2D();
virtual SurfaceType GetType() const { return SurfaceType::D2D1_BITMAP; }
virtual IntSize GetSize() const;
virtual SurfaceFormat GetFormat() const;
virtual bool IsValid() const;
virtual already_AddRefed<DataSourceSurface> GetDataSurface();
ID2D1Bitmap *GetBitmap() { return mBitmap; }
bool InitFromData(unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat,
ID2D1RenderTarget *aRT);
bool InitFromTexture(ID3D10Texture2D *aTexture,
SurfaceFormat aFormat,
ID2D1RenderTarget *aRT);
private:
friend class DrawTargetD2D;
friend class DataSourceSurfaceD2D;
uint32_t GetByteSize() const;
RefPtr<ID2D1Bitmap> mBitmap;
// We need to keep this pointer here to check surface validity.
RefPtr<ID3D10Device> mDevice;
SurfaceFormat mFormat;
IntSize mSize;
};
class DataSourceSurfaceD2D : public DataSourceSurface
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2D)
DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface);
virtual ~DataSourceSurfaceD2D();
virtual unsigned char* GetData();
virtual int32_t Stride();
virtual IntSize GetSize() const;
virtual SurfaceFormat GetFormat() const;
virtual bool Map(MapType, MappedSurface *aMappedSurface);
virtual void Unmap();
bool IsValid()
{
return mTexture;
}
private:
void EnsureMappedTexture();
RefPtr<ID3D10Texture2D> mTexture;
D3D10_MAPPED_TEXTURE2D mData;
SurfaceFormat mFormat;
IntSize mSize;
bool mMapped;
};
}
}
#endif /* MOZILLA_GFX_SOURCESURFACED2D_H_ */
-325
View File
@@ -1,325 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "SourceSurfaceD2DTarget.h"
#include "Logging.h"
#include "DrawTargetD2D.h"
#include "Tools.h"
#include <algorithm>
namespace mozilla {
namespace gfx {
SourceSurfaceD2DTarget::SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget,
ID3D10Texture2D* aTexture,
SurfaceFormat aFormat)
: mDrawTarget(aDrawTarget)
, mTexture(aTexture)
, mFormat(aFormat)
, mOwnsCopy(false)
{
}
SourceSurfaceD2DTarget::~SourceSurfaceD2DTarget()
{
// We don't need to do anything special here to notify our mDrawTarget. It must
// already have cleared its mSnapshot field, otherwise this object would
// be kept alive.
if (mOwnsCopy) {
IntSize size = GetSize();
DrawTargetD2D::mVRAMUsageSS -= size.width * size.height * BytesPerPixel(mFormat);
}
}
IntSize
SourceSurfaceD2DTarget::GetSize() const
{
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
return IntSize(desc.Width, desc.Height);
}
SurfaceFormat
SourceSurfaceD2DTarget::GetFormat() const
{
return mFormat;
}
already_AddRefed<DataSourceSurface>
SourceSurfaceD2DTarget::GetDataSurface()
{
RefPtr<DataSourceSurfaceD2DTarget> dataSurf =
new DataSourceSurfaceD2DTarget(mFormat);
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
desc.Usage = D3D10_USAGE_STAGING;
desc.BindFlags = 0;
desc.MiscFlags = 0;
if (!Factory::GetDirect3D10Device()) {
gfxCriticalError() << "Invalid D3D10 device in D2D target surface (GDS)";
return nullptr;
}
HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(dataSurf->mTexture));
if (FAILED(hr)) {
gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hexa(hr);
return nullptr;
}
Factory::GetDirect3D10Device()->CopyResource(dataSurf->mTexture, mTexture);
return dataSurf.forget();
}
void*
SourceSurfaceD2DTarget::GetNativeSurface(NativeSurfaceType aType)
{
if (aType == NativeSurfaceType::D3D10_TEXTURE) {
return static_cast<void*>(mTexture.get());
}
return nullptr;
}
ID3D10ShaderResourceView*
SourceSurfaceD2DTarget::GetSRView()
{
if (mSRView) {
return mSRView;
}
if (!Factory::GetDirect3D10Device()) {
gfxCriticalError() << "Invalid D3D10 device in D2D target surface (SRV)";
return nullptr;
}
HRESULT hr = Factory::GetDirect3D10Device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
if (FAILED(hr)) {
gfxWarning() << "Failed to create ShaderResourceView. Code: " << hexa(hr);
}
return mSRView;
}
void
SourceSurfaceD2DTarget::DrawTargetWillChange()
{
RefPtr<ID3D10Texture2D> oldTexture = mTexture;
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
// Our original texture might implement the keyed mutex flag. We shouldn't
// need that here. We actually specifically don't want it since we don't lock
// our texture for usage!
desc.MiscFlags = 0;
// Get a copy of the surface data so the content at snapshot time was saved.
Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
Factory::GetDirect3D10Device()->CopyResource(mTexture, oldTexture);
mBitmap = nullptr;
DrawTargetD2D::mVRAMUsageSS += desc.Width * desc.Height * BytesPerPixel(mFormat);
mOwnsCopy = true;
// We now no longer depend on the source surface content remaining the same.
MarkIndependent();
}
ID2D1Bitmap*
SourceSurfaceD2DTarget::GetBitmap(ID2D1RenderTarget *aRT)
{
if (mBitmap) {
return mBitmap;
}
HRESULT hr;
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
IntSize size(desc.Width, desc.Height);
RefPtr<IDXGISurface> surf;
hr = mTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surf));
if (FAILED(hr)) {
gfxWarning() << "Failed to query interface texture to DXGISurface. Code: " << hexa(hr);
return nullptr;
}
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(mFormat));
hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, getter_AddRefs(mBitmap));
if (FAILED(hr)) {
// This seems to happen for SurfaceFormat::A8 sometimes...
hr = aRT->CreateBitmap(D2D1::SizeU(desc.Width, desc.Height),
D2D1::BitmapProperties(D2DPixelFormat(mFormat)),
getter_AddRefs(mBitmap));
if (FAILED(hr)) {
gfxWarning() << "Failed in CreateBitmap. Code: " << hexa(hr);
return nullptr;
}
RefPtr<ID2D1RenderTarget> rt;
if (mDrawTarget) {
rt = mDrawTarget->mRT;
}
if (!rt) {
// Okay, we already separated from our drawtarget. And we're an A8
// surface the only way we can get to a bitmap is by creating a
// a rendertarget and from there copying to a bitmap! Terrible!
RefPtr<IDXGISurface> surface;
hr = mTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surface));
if (FAILED(hr)) {
gfxWarning() << "Failed to QI texture to surface.";
return nullptr;
}
D2D1_RENDER_TARGET_PROPERTIES props =
D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2DPixelFormat(mFormat));
hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(surface, props, getter_AddRefs(rt));
if (FAILED(hr)) {
gfxWarning() << "Failed to create D2D render target for texture.";
return nullptr;
}
}
mBitmap->CopyFromRenderTarget(nullptr, rt, nullptr);
return mBitmap;
}
return mBitmap;
}
void
SourceSurfaceD2DTarget::MarkIndependent()
{
if (mDrawTarget) {
MOZ_ASSERT(mDrawTarget->mSnapshot == this);
mDrawTarget->mSnapshot = nullptr;
mDrawTarget = nullptr;
}
}
DataSourceSurfaceD2DTarget::DataSourceSurfaceD2DTarget(SurfaceFormat aFormat)
: mFormat(aFormat)
, mMapped(false)
{
}
DataSourceSurfaceD2DTarget::~DataSourceSurfaceD2DTarget()
{
if (mMapped) {
mTexture->Unmap(0);
}
}
IntSize
DataSourceSurfaceD2DTarget::GetSize() const
{
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
return IntSize(desc.Width, desc.Height);
}
SurfaceFormat
DataSourceSurfaceD2DTarget::GetFormat() const
{
return mFormat;
}
uint8_t*
DataSourceSurfaceD2DTarget::GetData()
{
EnsureMapped();
return (unsigned char*)mMap.pData;
}
int32_t
DataSourceSurfaceD2DTarget::Stride()
{
EnsureMapped();
return mMap.RowPitch;
}
bool
DataSourceSurfaceD2DTarget::Map(MapType aMapType, MappedSurface *aMappedSurface)
{
// DataSourceSurfaces used with the new Map API should not be used with GetData!!
MOZ_ASSERT(!mMapped);
MOZ_ASSERT(!mIsMapped);
if (!mTexture) {
return false;
}
D3D10_MAP mapType;
if (aMapType == MapType::READ) {
mapType = D3D10_MAP_READ;
} else if (aMapType == MapType::WRITE) {
mapType = D3D10_MAP_WRITE;
} else {
mapType = D3D10_MAP_READ_WRITE;
}
D3D10_MAPPED_TEXTURE2D map;
HRESULT hr = mTexture->Map(0, mapType, 0, &map);
if (FAILED(hr)) {
gfxWarning() << "Texture map failed with code: " << hexa(hr);
return false;
}
aMappedSurface->mData = (uint8_t*)map.pData;
aMappedSurface->mStride = map.RowPitch;
mIsMapped = !!aMappedSurface->mData;
return mIsMapped;
}
void
DataSourceSurfaceD2DTarget::Unmap()
{
MOZ_ASSERT(mIsMapped);
mIsMapped = false;
mTexture->Unmap(0);
}
void
DataSourceSurfaceD2DTarget::EnsureMapped()
{
// Do not use GetData() after having used Map!
MOZ_ASSERT(!mIsMapped);
if (!mMapped) {
HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mMap);
if (FAILED(hr)) {
gfxWarning() << "Failed to map texture to memory. Code: " << hexa(hr);
return;
}
mMapped = true;
}
}
}
}
-90
View File
@@ -1,90 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 MOZILLA_GFX_SOURCESURFACED2DTARGET_H_
#define MOZILLA_GFX_SOURCESURFACED2DTARGET_H_
#include "2D.h"
#include "HelpersD2D.h"
#include <vector>
#include <d3d10_1.h>
namespace mozilla {
namespace gfx {
class DrawTargetD2D;
class SourceSurfaceD2DTarget : public SourceSurface
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2DTarget)
SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget, ID3D10Texture2D* aTexture,
SurfaceFormat aFormat);
~SourceSurfaceD2DTarget();
virtual SurfaceType GetType() const { return SurfaceType::D2D1_DRAWTARGET; }
virtual IntSize GetSize() const;
virtual SurfaceFormat GetFormat() const;
virtual already_AddRefed<DataSourceSurface> GetDataSurface();
virtual void *GetNativeSurface(NativeSurfaceType aType);
DrawTargetD2D* GetDT() { return mDrawTarget; }
ID2D1Bitmap *GetBitmap(ID2D1RenderTarget *aRT);
private:
friend class DrawTargetD2D;
ID3D10ShaderResourceView *GetSRView();
// This function is called by the draw target this texture belongs to when
// it is about to be changed. The texture will be required to make a copy
// of itself when this happens.
void DrawTargetWillChange();
// This will mark the surface as no longer depending on its drawtarget,
// this may happen on destruction or copying.
void MarkIndependent();
RefPtr<ID3D10ShaderResourceView> mSRView;
RefPtr<ID2D1Bitmap> mBitmap;
// Non-null if this is a "lazy copy" of the given draw target.
// Null if we've made a copy. The target is not kept alive, otherwise we'd
// have leaks since it might keep us alive. If the target is destroyed, it
// will notify us.
DrawTargetD2D* mDrawTarget;
mutable RefPtr<ID3D10Texture2D> mTexture;
SurfaceFormat mFormat;
bool mOwnsCopy;
};
class DataSourceSurfaceD2DTarget : public DataSourceSurface
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2DTarget)
DataSourceSurfaceD2DTarget(SurfaceFormat aFormat);
~DataSourceSurfaceD2DTarget();
virtual SurfaceType GetType() const { return SurfaceType::DATA; }
virtual IntSize GetSize() const;
virtual SurfaceFormat GetFormat() const;
virtual uint8_t *GetData();
virtual int32_t Stride();
virtual bool Map(MapType, MappedSurface *aMappedSurface);
virtual void Unmap();
private:
friend class SourceSurfaceD2DTarget;
void EnsureMapped();
mutable RefPtr<ID3D10Texture2D> mTexture;
SurfaceFormat mFormat;
D3D10_MAPPED_TEXTURE2D mMap;
bool mMapped;
};
}
}
#endif /* MOZILLA_GFX_SOURCESURFACED2DTARGET_H_ */
+1 -1
View File
@@ -123,7 +123,7 @@ enum class DrawTargetType : int8_t {
enum class BackendType : int8_t {
NONE = 0,
DIRECT2D,
DIRECT2D, // Used for version independent D2D objects.
COREGRAPHICS,
COREGRAPHICS_ACCELERATED,
CAIRO,
-3
View File
@@ -66,7 +66,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
SOURCES += [
'DrawTargetD2D.cpp',
'DrawTargetD2D1.cpp',
'ExtendInputEffectD2D1.cpp',
'FilterNodeD2D1.cpp',
@@ -77,9 +76,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'RadialGradientEffectD2D1.cpp',
'ScaledFontDWrite.cpp',
'ScaledFontWin.cpp',
'SourceSurfaceD2D.cpp',
'SourceSurfaceD2D1.cpp',
'SourceSurfaceD2DTarget.cpp',
]
DEFINES['WIN32'] = True
+1 -1
View File
@@ -2054,7 +2054,7 @@ GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
// Be clear that these are 0 if unavailable.
formats.depthStencil = 0;
if (!IsGLES() || IsExtensionSupported(OES_packed_depth_stencil)) {
if (IsSupported(GLFeature::packed_depth_stencil)) {
formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
}
+30 -18
View File
@@ -153,6 +153,34 @@ GetAndInitDisplay(GLLibraryEGL& egl, void* displayType)
return display;
}
static EGLDisplay
GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl)
{
EGLDisplay ret = 0;
// D3D11 ANGLE only works with OMTC; there's a bug in the non-OMTC layer
// manager, and it's pointless to try to fix it. We also don't try
// D3D11 ANGLE if the layer manager is prefering D3D9 (hrm, do we care?)
if (gfxPrefs::LayersOffMainThreadCompositionEnabled() &&
!gfxPrefs::LayersPreferD3D9())
{
if (gfxPrefs::WebGLANGLEForceD3D11())
return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
if (gfxPrefs::WebGLANGLETryD3D11() &&
gfxPlatform::CanUseDirect3D11ANGLE())
{
ret = GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
}
}
if (!ret) {
ret = GetAndInitDisplay(egl, EGL_DEFAULT_DISPLAY);
}
return ret;
}
bool
GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface)
{
@@ -367,30 +395,14 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel)
if (!chosenDisplay) {
// If falling back to WARP did not work and we don't want to try
// using HW accelerated ANGLE, then fail
// using HW accelerated ANGLE, then fail.
if (!shouldTryAccel) {
NS_ERROR("Fallback WARP ANGLE context failed to initialize.");
return false;
}
// Hardware accelerated ANGLE path
// D3D11 ANGLE only works with OMTC; there's a bug in the non-OMTC layer
// manager, and it's pointless to try to fix it. We also don't try
// D3D11 ANGLE if the layer manager is prefering D3D9 (hrm, do we care?)
if (gfxPrefs::LayersOffMainThreadCompositionEnabled() &&
!gfxPrefs::LayersPreferD3D9())
{
if (gfxPrefs::WebGLANGLEForceD3D11()) {
chosenDisplay = GetAndInitDisplay(*this,
LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
} else if (gfxPrefs::WebGLANGLETryD3D11() &&
gfxPlatform::CanUseDirect3D11ANGLE())
{
chosenDisplay = GetAndInitDisplay(*this,
LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
}
}
chosenDisplay = GetAndInitDisplayForAccelANGLE(*this);
}
} else {
chosenDisplay = GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY);
+2 -5
View File
@@ -532,7 +532,7 @@ GLScreenBuffer::Swap(const gfx::IntSize& size)
if (!newBack)
return false;
// In the case of DXGL interop, the new surface needs to be acquired before
// In the case of DXGL interop, the new surface needs to be acquired before
// it is attached so that the interop surface is locked, which populates
// the GL renderbuffer. This results in the renderbuffer being ready and
// attachment to framebuffer succeeds in Attach() call.
@@ -822,10 +822,7 @@ DrawBuffer::Create(GLContext* const gl,
gl->fGenFramebuffers(1, &fb);
gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb);
GLsizei samples = formats.samples;
if (!samples)
samples = 1;
const GLsizei samples = formats.samples;
UniquePtr<DrawBuffer> ret( new DrawBuffer(gl, size, samples, fb, colorMSRB,
depthRB, stencilRB) );
+1 -1
View File
@@ -206,7 +206,7 @@ public:
GLsizei Samples() const {
if (!mDraw)
return 1;
return 0;
return mDraw->mSamples;
}
-1
View File
@@ -19,7 +19,6 @@ struct DeviceInitData
bool useD3D11WARP;
bool useD3D11ImageBridge;
bool d3d11TextureSharingWorks;
bool useD2D;
bool useD2D1;
DxgiAdapterDesc adapter;
};
+2 -3
View File
@@ -73,9 +73,8 @@ ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride,
MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 ||
aYSize.width > aYStride || aCbCrSize.width > aCbCrStride ||
aCbCrStride > aYStride || aCbCrSize.height > aYSize.height ||
!gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height))) {
!gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height)) ||
!gfx::Factory::AllowedSurfaceSize(IntSize(aCbCrStride, aCbCrSize.height))) {
return 0;
}
// Overflow checks are performed in AllowedSurfaceSize
+24 -14
View File
@@ -13,32 +13,34 @@ using namespace gfx;
namespace layers {
already_AddRefed<SourceSurface>
CreateSourceSurfaceFromMacIOSurface(MacIOSurface* aSurface)
static already_AddRefed<SourceSurface>
CreateSourceSurfaceFromLockedMacIOSurface(MacIOSurface* aSurface)
{
RefPtr<DataSourceSurface> dataSurface;
aSurface->Lock();
size_t bytesPerRow = aSurface->GetBytesPerRow();
size_t ioWidth = aSurface->GetDevicePixelWidth();
size_t ioHeight = aSurface->GetDevicePixelHeight();
SurfaceFormat ioFormat = aSurface->GetFormat();
SurfaceFormat format = aSurface->GetFormat() == SurfaceFormat::NV12 ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
if (ioFormat == SurfaceFormat::NV12 &&
(ioWidth > PlanarYCbCrImage::MAX_DIMENSION ||
ioHeight > PlanarYCbCrImage::MAX_DIMENSION)) {
return nullptr;
}
dataSurface = Factory::CreateDataSourceSurface(IntSize(ioWidth, ioHeight), format);
SurfaceFormat format = ioFormat == SurfaceFormat::NV12 ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
RefPtr<DataSourceSurface> dataSurface =
Factory::CreateDataSourceSurface(IntSize(ioWidth, ioHeight), format);
if (NS_WARN_IF(!dataSurface)) {
return nullptr;
}
DataSourceSurface::MappedSurface mappedSurface;
if (!dataSurface->Map(DataSourceSurface::WRITE, &mappedSurface))
if (!dataSurface->Map(DataSourceSurface::WRITE, &mappedSurface)) {
return nullptr;
}
if (aSurface->GetFormat() == SurfaceFormat::NV12) {
if (aSurface->GetDevicePixelWidth() > PlanarYCbCrImage::MAX_DIMENSION ||
aSurface->GetDevicePixelHeight() > PlanarYCbCrImage::MAX_DIMENSION) {
return nullptr;
}
if (ioFormat == SurfaceFormat::NV12) {
/* Extract and separate the CbCr planes */
size_t cbCrStride = aSurface->GetBytesPerRow(1);
size_t cbCrWidth = aSurface->GetDevicePixelWidth(1);
@@ -86,10 +88,18 @@ CreateSourceSurfaceFromMacIOSurface(MacIOSurface* aSurface)
}
dataSurface->Unmap();
aSurface->Unlock();
return dataSurface.forget();
}
already_AddRefed<SourceSurface>
CreateSourceSurfaceFromMacIOSurface(MacIOSurface* aSurface)
{
aSurface->Lock();
RefPtr<SourceSurface> result = CreateSourceSurfaceFromLockedMacIOSurface(aSurface);
aSurface->Unlock();
return result.forget();
}
} // namespace gfx
} // namespace mozilla
+1 -1
View File
@@ -73,7 +73,7 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
#ifdef XP_WIN
if (backend == LayersBackend::LAYERS_D3D11) {
useDoubleBuffering = !!gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
useDoubleBuffering = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
} else
#endif
#ifdef MOZ_WIDGET_GTK
+33 -11
View File
@@ -67,6 +67,7 @@ struct DeviceAttachmentsD3D11
{}
bool CreateShaders();
bool InitBlendShaders();
bool InitSyncObject();
typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11VertexShader>>
@@ -970,7 +971,9 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
gfx::IntRect rect = ComputeBackdropCopyRect(aRect, aClipRect, aTransform, &backdropTransform);
RefPtr<ID3D11ShaderResourceView> srv;
if (CopyBackdrop(rect, &mixBlendBackdrop, &srv)) {
if (CopyBackdrop(rect, &mixBlendBackdrop, &srv) &&
mAttachments->InitBlendShaders())
{
vertexShader = mAttachments->mVSQuadBlendShader[maskType];
pixelShader = mAttachments->mBlendShader[MaskType::MaskNone];
@@ -1354,6 +1357,7 @@ CompositorD3D11::VerifyBufferSize()
if (mDefaultRT) {
RefPtr<ID3D11RenderTargetView> rtView = mDefaultRT->mRTView;
RefPtr<ID3D11ShaderResourceView> srView = mDefaultRT->mSRV;
// Make sure the texture, which belongs to the swapchain, is destroyed
// before resizing the swapchain.
@@ -1369,20 +1373,28 @@ CompositorD3D11::VerifyBufferSize()
ULONG newRefCnt = rtView.forget().take()->Release();
if (newRefCnt > 0) {
gfxCriticalError() << "mRTView not destroyed on final release!";
gfxCriticalError() << "mRTView not destroyed on final release! RefCnt: " << newRefCnt;
}
if (srView) {
newRefCnt = srView.forget().take()->Release();
if (newRefCnt > 0) {
gfxCriticalError() << "mSRV not destroyed on final release! RefCnt: " << newRefCnt;
}
}
newRefCnt = resource.forget().take()->Release();
if (newRefCnt > 0) {
gfxCriticalError() << "Unexpecting lingering references to backbuffer!";
gfxCriticalError() << "Unexpecting lingering references to backbuffer! RefCnt: " << newRefCnt;
}
hr = mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
DXGI_FORMAT_B8G8R8A8_UNORM,
0);
}
hr = mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
DXGI_FORMAT_B8G8R8A8_UNORM,
0);
mVerifyBuffersFailed = FAILED(hr);
if (mVerifyBuffersFailed) {
gfxCriticalNote << "D3D11 swap resize buffers failed " << hexa(hr) << " on " << mSize;
@@ -1481,15 +1493,26 @@ DeviceAttachmentsD3D11::InitSyncObject()
return true;
}
bool
DeviceAttachmentsD3D11::InitBlendShaders()
{
if (!mVSQuadBlendShader[MaskType::MaskNone]) {
InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone);
InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask2d);
InitVertexShader(sLayerQuadBlendMask3DVS, mVSQuadBlendShader, MaskType::Mask3d);
}
if (!mBlendShader[MaskType::MaskNone]) {
InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone);
}
return mInitOkay;
}
bool
DeviceAttachmentsD3D11::CreateShaders()
{
InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone);
InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask2d);
InitVertexShader(sLayerQuadMask3DVS, mVSQuadShader, MaskType::Mask3d);
InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone);
InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask2d);
InitVertexShader(sLayerQuadBlendMask3DVS, mVSQuadBlendShader, MaskType::Mask3d);
InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone);
InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask2d);
@@ -1500,7 +1523,6 @@ DeviceAttachmentsD3D11::CreateShaders()
InitPixelShader(sRGBAShaderMask3D, mRGBAShader, MaskType::Mask3d);
InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone);
InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask2d);
InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone);
if (gfxPrefs::ComponentAlphaEnabled()) {
InitPixelShader(sComponentAlphaShader, mComponentAlphaShader, MaskType::MaskNone);
InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask2d);

Some files were not shown because too many files have changed in this diff Show More