mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ class ErrorResult;
|
||||
|
||||
namespace gfx {
|
||||
class DataSourceSurface;
|
||||
class DrawTarget;
|
||||
class SourceSurface;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
+699
-448
File diff suppressed because it is too large
Load Diff
+26
-18
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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_ */
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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) );
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ public:
|
||||
|
||||
GLsizei Samples() const {
|
||||
if (!mDraw)
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
return mDraw->mSamples;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ struct DeviceInitData
|
||||
bool useD3D11WARP;
|
||||
bool useD3D11ImageBridge;
|
||||
bool d3d11TextureSharingWorks;
|
||||
bool useD2D;
|
||||
bool useD2D1;
|
||||
DxgiAdapterDesc adapter;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user