Bug 738866 - Implement WEBGL_depth_texture extension - r=jgilbert

This commit is contained in:
Alexander Boldyrev 2012-08-13 18:17:55 -07:00
parent 6f53c1980f
commit 45a38ebb0b
19 changed files with 589 additions and 2 deletions

View File

@ -52,6 +52,7 @@ CPPSRCS += \
WebGLExtensionLoseContext.cpp \
WebGLTexelConversions.cpp \
WebGLExtensionCompressedTextureS3TC.cpp \
WebGLExtensionDepthTexture.cpp \
$(NULL)
DEFINES += -DUSE_ANGLE

View File

@ -1007,6 +1007,18 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext)
isSupported = true;
}
break;
case WEBGL_depth_texture:
if (gl->IsGLES2() &&
gl->IsExtensionSupported(GLContext::OES_packed_depth_stencil) &&
gl->IsExtensionSupported(GLContext::OES_depth_texture))
{
isSupported = true;
} else if (!gl->IsGLES2() &&
gl->IsExtensionSupported(GLContext::EXT_packed_depth_stencil))
{
isSupported = true;
}
break;
default:
MOZ_ASSERT(false, "should not get there.");
}
@ -1072,6 +1084,12 @@ WebGLContext::GetExtension(const nsAString& aName)
if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
ext = WEBGL_compressed_texture_s3tc;
}
else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"),
nsCaseInsensitiveStringComparator()))
{
if (IsExtensionSupported(WEBGL_depth_texture))
ext = WEBGL_depth_texture;
}
if (ext == WebGLExtensionID_unknown_extension) {
return nullptr;
@ -1091,6 +1109,9 @@ WebGLContext::GetExtension(const nsAString& aName)
case WEBGL_compressed_texture_s3tc:
mExtensions[ext] = new WebGLExtensionCompressedTextureS3TC(this);
break;
case WEBGL_depth_texture:
mExtensions[ext] = new WebGLExtensionDepthTexture(this);
break;
default:
// create a generic WebGLExtension object for any extensions that don't
// have any additional tokens or methods. We still need these to be separate
@ -1667,6 +1688,8 @@ WebGLContext::GetSupportedExtensions(Nullable< nsTArray<nsString> > &retval)
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
if (IsExtensionSupported(WEBGL_depth_texture))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
}
NS_IMETHODIMP

View File

@ -111,11 +111,14 @@ enum WebGLTexelFormat
// 1-channel formats
R8,
A8,
D16, // used for WEBGL_depth_texture extension
D32, // used for WEBGL_depth_texture extension
R32F, // used for OES_texture_float extension
A32F, // used for OES_texture_float extension
// 2-channel formats
RA8,
RA32F,
D24S8, // used for WEBGL_depth_texture extension
// 3-channel formats
RGB8,
BGRX8, // used for DOM elements. Source format only.
@ -461,6 +464,7 @@ class WebGLContext :
friend class WebGLExtensionCompressedTextureS3TC;
friend class WebGLContextUserData;
friend class WebGLMemoryPressureObserver;
friend class WebGLExtensionDepthTexture;
public:
WebGLContext();
@ -1147,6 +1151,7 @@ protected:
EXT_texture_filter_anisotropic,
WEBGL_lose_context,
WEBGL_compressed_texture_s3tc,
WEBGL_depth_texture,
WebGLExtensionID_number_of_extensions,
WebGLExtensionID_unknown_extension
};
@ -2697,8 +2702,28 @@ public:
!thisRect->Height())
return false;
if (mTexturePtr)
return mAttachmentPoint == LOCAL_GL_COLOR_ATTACHMENT0;
if (mTexturePtr) {
if (!mTexturePtr->HasImageInfoAt(0, 0))
return false;
WebGLenum format = mTexturePtr->ImageInfoAt(0).Format();
switch (mAttachmentPoint)
{
case LOCAL_GL_COLOR_ATTACHMENT0:
return format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_LUMINANCE ||
format == LOCAL_GL_LUMINANCE_ALPHA ||
format == LOCAL_GL_RGB ||
format == LOCAL_GL_RGBA;
case LOCAL_GL_DEPTH_ATTACHMENT:
return format == LOCAL_GL_DEPTH_COMPONENT;
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
return format == LOCAL_GL_DEPTH_STENCIL;
default:
MOZ_NOT_REACHED("Invalid WebGL texture format?");
}
}
if (mRenderbufferPtr) {
WebGLenum format = mRenderbufferPtr->InternalFormat();
@ -2944,6 +2969,9 @@ public:
// generate the INVALID_FRAMEBUFFER_OPERATION that we need here
if (HasDepthStencilConflict())
return false;
if (HasIncompleteAttachment())
return false;
if (!mColorAttachment.HasUninitializedRenderbuffer() &&
!mDepthAttachment.HasUninitializedRenderbuffer() &&

View File

@ -1037,6 +1037,10 @@ WebGLContext::CopyTexImage2D(WebGLenum target,
return ErrorInvalidOperation("copyTexImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
if (internalformat == LOCAL_GL_DEPTH_COMPONENT ||
internalformat == LOCAL_GL_DEPTH_STENCIL)
return ErrorInvalidOperation("copyTexImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
if (mBoundFramebuffer)
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
@ -1158,6 +1162,10 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target,
return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
if (format == LOCAL_GL_DEPTH_COMPONENT ||
format == LOCAL_GL_DEPTH_STENCIL)
return ErrorInvalidOperation("copyTexSubImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
if (mBoundFramebuffer)
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
@ -2130,6 +2138,12 @@ WebGLContext::GenerateMipmap(WebGLenum target)
if (IsTextureFormatCompressed(format))
return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
if (IsExtensionEnabled(WEBGL_depth_texture) &&
(format == LOCAL_GL_DEPTH_COMPONENT || format == LOCAL_GL_DEPTH_STENCIL))
return ErrorInvalidOperation("generateMipmap: "
"A texture that has a base internal format of "
"DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
if (!tex->AreAllLevel0ImageInfosEqual())
return ErrorInvalidOperation("generateMipmap: The six faces of this cube map have different dimensions, format, or type.");
@ -5616,6 +5630,8 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_DEPTH_COMPONENT:
case LOCAL_GL_DEPTH_STENCIL:
break;
default:
return ErrorInvalidEnumInfo("texImage2D: internal format", internalformat);
@ -5637,6 +5653,20 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
if (border != 0)
return ErrorInvalidValue("texImage2D: border must be 0");
if (format == LOCAL_GL_DEPTH_COMPONENT || format == LOCAL_GL_DEPTH_STENCIL) {
if (IsExtensionEnabled(WEBGL_depth_texture)) {
if (target != LOCAL_GL_TEXTURE_2D || data != NULL || level != 0)
return ErrorInvalidOperation("texImage2D: "
"with format of DEPTH_COMPONENT or DEPTH_STENCIL "
"target must be TEXTURE_2D, "
"data must be NULL, "
"level must be zero");
}
else
return ErrorInvalidEnumInfo("texImage2D: internal format", internalformat);
}
uint32_t dstTexelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texImage2D"))
return;
@ -5849,6 +5879,11 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
return ErrorInvalidValue("texSubImage2D: with level > 0, width and height must be powers of two");
}
if (IsExtensionEnabled(WEBGL_depth_texture) &&
(format == LOCAL_GL_DEPTH_COMPONENT || format == LOCAL_GL_DEPTH_STENCIL)) {
return ErrorInvalidOperation("texSubImage2D: format");
}
uint32_t dstTexelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texSubImage2D"))
return;
@ -6117,6 +6152,30 @@ BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *u
WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
{
//
// WEBGL_depth_texture
if (format == LOCAL_GL_DEPTH_COMPONENT) {
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT:
return WebGLTexelConversions::D16;
case LOCAL_GL_UNSIGNED_INT:
return WebGLTexelConversions::D32;
default:
MOZ_NOT_REACHED("Invalid WebGL texture format/type?");
return WebGLTexelConversions::BadFormat;
}
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
switch (type) {
case LOCAL_GL_UNSIGNED_INT_24_8_EXT:
return WebGLTexelConversions::D24S8;
default:
MOZ_NOT_REACHED("Invalid WebGL texture format/type?");
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelConversions::BadFormat;
}
}
if (type == LOCAL_GL_UNSIGNED_BYTE) {
switch (format) {
case LOCAL_GL_RGBA:
@ -6174,6 +6233,18 @@ InternalFormatForFormatAndType(WebGLenum format, WebGLenum type, bool isGLES2)
if (isGLES2)
return format;
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (type == LOCAL_GL_UNSIGNED_SHORT)
return LOCAL_GL_DEPTH_COMPONENT16;
else if (type == LOCAL_GL_UNSIGNED_INT)
return LOCAL_GL_DEPTH_COMPONENT32;
}
if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
return LOCAL_GL_DEPTH24_STENCIL8;
}
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:

View File

@ -25,3 +25,4 @@ DOMCI_DATA(WebGLExtensionStandardDerivatives, void)
DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, void)
DOMCI_DATA(WebGLExtensionLoseContext, void)
DOMCI_DATA(WebGLExtensionCompressedTextureS3TC, void)
DOMCI_DATA(WebGLExtensionDepthTexture, void)

View File

@ -190,6 +190,8 @@ WebGLContext::IsTextureFormatCompressed(GLenum format)
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_DEPTH_COMPONENT:
case LOCAL_GL_DEPTH_STENCIL:
return false;
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

View File

@ -456,6 +456,16 @@ uint32_t WebGLContext::GetBitsPerTexel(WebGLenum format, WebGLenum type)
return 0;
}
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (type == LOCAL_GL_UNSIGNED_SHORT)
return 2;
else if (type == LOCAL_GL_UNSIGNED_INT)
return 4;
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
return 4;
}
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
switch (format) {
@ -491,6 +501,48 @@ uint32_t WebGLContext::GetBitsPerTexel(WebGLenum format, WebGLenum type)
bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
uint32_t *texelSize, const char *info)
{
if (IsExtensionEnabled(WEBGL_depth_texture)) {
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (jsArrayType != -1) {
if ((type == LOCAL_GL_UNSIGNED_SHORT && jsArrayType != js::ArrayBufferView::TYPE_UINT16) ||
(type == LOCAL_GL_UNSIGNED_INT && jsArrayType != js::ArrayBufferView::TYPE_UINT32)) {
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}
}
switch(type) {
case LOCAL_GL_UNSIGNED_SHORT:
*texelSize = 2;
break;
case LOCAL_GL_UNSIGNED_INT:
*texelSize = 4;
break;
default:
ErrorInvalidOperation("%s: invalid type 0x%x", info, type);
return false;
}
return true;
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type != LOCAL_GL_UNSIGNED_INT_24_8_EXT) {
ErrorInvalidOperation("%s: invalid format 0x%x", info, format);
return false;
}
if (jsArrayType != -1) {
if (jsArrayType != js::ArrayBufferView::TYPE_UINT32) {
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}
}
*texelSize = 4;
return true;
}
}
if (type == LOCAL_GL_UNSIGNED_BYTE ||
(IsExtensionEnabled(OES_texture_float) && type == LOCAL_GL_FLOAT))
{

View File

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLExtensions.h"
using namespace mozilla;
WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(WebGLContext* context) :
WebGLExtension(context)
{
}
WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()
{
}
NS_IMPL_ADDREF_INHERITED(WebGLExtensionDepthTexture, WebGLExtension)
NS_IMPL_RELEASE_INHERITED(WebGLExtensionDepthTexture, WebGLExtension)
DOMCI_DATA(WebGLExtensionDepthTexture, WebGLExtensionDepthTexture)
NS_INTERFACE_MAP_BEGIN(WebGLExtensionDepthTexture)
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionDepthTexture)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionDepthTexture)
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)

View File

@ -56,6 +56,18 @@ public:
NS_DECL_NSIWEBGLEXTENSION
};
class WebGLExtensionDepthTexture :
public nsIWebGLExtensionDepthTexture,
public WebGLExtension
{
public:
WebGLExtensionDepthTexture(WebGLContext* context);
virtual ~WebGLExtensionDepthTexture();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIWEBGLEXTENSION
};
}
#endif // WEBGLEXTENSIONS_H_

View File

@ -109,6 +109,7 @@ inline size_t TexelBytesForFormat(int format) {
case WebGLTexelConversions::RGBA5551:
case WebGLTexelConversions::RGBA4444:
case WebGLTexelConversions::RGB565:
case WebGLTexelConversions::D16:
return 2;
case WebGLTexelConversions::RGB8:
return 3;
@ -117,6 +118,8 @@ inline size_t TexelBytesForFormat(int format) {
case WebGLTexelConversions::BGRX8:
case WebGLTexelConversions::R32F:
case WebGLTexelConversions::A32F:
case WebGLTexelConversions::D32:
case WebGLTexelConversions::D24S8:
return 4;
case WebGLTexelConversions::RA32F:
return 8;

View File

@ -5,4 +5,5 @@ oes-vertex-array-object.html
webgl-debug-renderer-info.html
webgl-debug-shaders.html
--min-version 1.0.2 webgl-compressed-texture-s3tc.html
--min-version 1.0.2 webgl-depth-texture.html

View File

@ -0,0 +1,343 @@
<!--
/*
** Copyright (c) 2012 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"></script>
<script src="../resources/webgl-test-utils.js"></script>
<title>WebGL WEBGL_depth_texture Conformance Tests</title>
</head>
<body>
<script id="vshader" type="x-shader/x-vertex">
attribute vec4 a_position;
void main()
{
gl_Position = a_position;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D u_texture;
uniform vec2 u_resolution;
void main()
{
vec2 texcoord = gl_FragCoord.xy / u_resolution;
gl_FragColor = texture2D(u_texture, texcoord);
}
</script>
<div id="description"></div>
<div id="console"></div>
<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
<script>
if (window.initNonKhronosFramework) {
window.initNonKhronosFramework(false);
}
description("This test verifies the functionality of the WEBGL_depth_texture extension, if it is available.");
debug("");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});
var program = wtu.setupTexturedQuad(gl);
var ext = null;
var vao = null;
var tex;
var name;
var supportedFormats;
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
// Run tests with extension disabled
runTestDisabled();
// Query the extension and store globally so shouldBe can access it
ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture");
if (!ext) {
testPassed("No WEBGL_depth_texture support -- this is legal");
runSupportedTest(false);
} else {
testPassed("Successfully enabled WEBGL_depth_texture extension");
runSupportedTest(true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture");
if (name !== undefined) {
if (extensionEnabled) {
testPassed("WEBGL_depth_texture listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_depth_texture listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_depth_texture not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_depth_texture not listed as supported and getExtension failed -- this is legal");
}
}
}
function runTestDisabled() {
debug("Testing binding enum with extension disabled");
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null)');
shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null)');
}
function dumpIt(gl, res, msg) {
return; // comment out to debug
debug(msg);
var actualPixels = new Uint8Array(res * res * 4);
gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
for (var yy = 0; yy < res; ++yy) {
var strs = [];
for (var xx = 0; xx < res; ++xx) {
var actual = (yy * res + xx) * 4;
strs.push("(" + actualPixels[actual] + "," + actualPixels[actual+1] + "," + actualPixels[actual + 2] + "," + actualPixels[actual + 3] + ")");
}
debug(strs.join(" "));
}
}
function runTestExtension() {
debug("Testing WEBGL_depth_texture");
var res = 8;
// make canvas for testing.
canvas2 = document.createElement("canvas");
canvas2.width = res;
canvas2.height = res;
var ctx = canvas2.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas2.width, canvas2.height);
var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_position']);
gl.useProgram(program);
gl.uniform2f(gl.getUniformLocation(program, "u_resolution"), res, res);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array(
[ 1, 1, 1,
-1, 1, 0,
-1, -1, -1,
1, 1, 1,
-1, -1, -1,
1, -1, 0,
]),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
var types = [
{obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_SHORT', data: 'new Uint16Array(1)' },
{obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_INT', data: 'new Uint32Array(1)' },
{obj: 'ext', attachment: 'DEPTH_STENCIL_ATTACHMENT', format: 'DEPTH_STENCIL', type: 'UNSIGNED_INT_24_8_WEBGL', data: 'new Uint32Array(1)' }
];
for (var ii = 0; ii < types.length; ++ii) {
var typeInfo = types[ii];
var type = typeInfo.type;
var typeStr = typeInfo.obj + '.' + type;
debug("");
debug("testing: " + type);
// check that cubemaps are not allowed.
var cubeTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_CUBE_MAP, cubeTex);
var targets = [
'TEXTURE_CUBE_MAP_POSITIVE_X',
'TEXTURE_CUBE_MAP_NEGATIVE_X',
'TEXTURE_CUBE_MAP_POSITIVE_Y',
'TEXTURE_CUBE_MAP_NEGATIVE_Y',
'TEXTURE_CUBE_MAP_POSITIVE_Z',
'TEXTURE_CUBE_MAP_NEGATIVE_Z'
];
for (var tt = 0; tt < targets.length; ++tt) {
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.' + targets[ii] + ', 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
}
// check 2d textures.
tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// test level > 0
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
// test with data
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')');
// test with canvas
shouldGenerateGLError(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', gl.' + typeInfo.format + ', ' + typeStr + ', canvas2)');
// test copyTexImage2D
shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 0, 0, 1, 1, 0)');
// test real thing
shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', ' + res + ', ' + res + ', 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
// test texSubImage2D
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')');
// test copyTexSubImage2D
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)');
// test generateMipmap
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.generateMipmap(gl.TEXTURE_2D)');
var fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, tex, 0);
// TODO: remove this check if the spec is updated to require these combinations to work.
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
{
// try adding a color buffer.
var colorTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, res, res, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
}
// use the default texture to render with while we return to the depth texture.
gl.bindTexture(gl.TEXTURE_2D, null);
// render the z-quad
gl.enable(gl.DEPTH_TEST);
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
dumpIt(gl, res, "--first--");
// render the depth texture.
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.clearColor(0, 0, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
var actualPixels = new Uint8Array(res * res * 4);
gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
dumpIt(gl, res, "--depth--");
// Check that each pixel's RGB are the same and that it's value is less
// than the previous pixel in either direction. Basically verify we have a
// gradient.
var success = true;
for (var yy = 0; yy < res; ++yy) {
for (var xx = 0; xx < res; ++xx) {
var actual = (yy * res + xx) * 4;
var left = actual - 4;
var down = actual - res * 4;
if (actualPixels[actual + 0] != actualPixels[actual + 1]) {
testFailed('R != G');
success = false;
}
if (actualPixels[actual + 0] != actualPixels[actual + 2]) {
testFailed('R != B');
success = false;
}
// ALPHA is implementation dependent
if (actualPixels[actual + 3] != 0xFF && actualPixels[actual + 3] != actualPixels[actual + 0]) {
testFailed('A != 255 && A != R');
success = false;
}
if (xx > 0) {
if (actualPixels[actual] <= actualPixels[left]) {
testFailed("actual(" + actualPixels[actual] + ") < left(" + actualPixels[left] + ")");
success = false;
}
}
if (yy > 0) {
if (actualPixels[actual] <= actualPixels[down]) {
testFailed("actual(" + actualPixels[actual] + ") < down(" + actualPixels[down] + ")");
success = false;
}
}
}
}
// Check that bottom left corner is vastly different thatn top right.
if (actualPixels[(res * res - 1) * 4] - actualPixels[0] < 0xC0) {
testFailed("corners are not different enough");
success = false;
}
if (success) {
testPassed("depth texture rendered correctly.");
}
// check limitations
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, null, 0);
var badAttachment = typeInfo.attachment == 'DEPTH_ATTACHMENT' ? 'DEPTH_STENCIL_ATTACHMENT' : 'DEPTH_ATTACHMENT';
shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.' + badAttachment + ', gl.TEXTURE_2D, tex, 0)');
shouldNotBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, 'gl.clear(gl.DEPTH_BUFFER_BIT)');
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
shouldBe('gl.getError()', 'gl.NO_ERROR');
}
}
debug("");
successfullyParsed = true;
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>

View File

@ -1581,6 +1581,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTextureS3TC, WebGLExtensionSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ADDPROPERTY)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionDepthTexture, WebGLExtensionSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ADDPROPERTY)
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -4279,6 +4282,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTextureS3TC)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionDepthTexture, nsIWebGLExtensionDepthTexture)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionDepthTexture)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_END

View File

@ -463,6 +463,7 @@ DOMCI_CLASS(WebGLExtensionStandardDerivatives)
DOMCI_CLASS(WebGLExtensionTextureFilterAnisotropic)
DOMCI_CLASS(WebGLExtensionLoseContext)
DOMCI_CLASS(WebGLExtensionCompressedTextureS3TC)
DOMCI_CLASS(WebGLExtensionDepthTexture)
DOMCI_CLASS(PaintRequest)
DOMCI_CLASS(PaintRequestList)

View File

@ -155,6 +155,12 @@ interface nsIWebGLExtensionCompressedTextureS3TC : nsIWebGLExtension
const WebGLenum COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
};
[scriptable, builtinclass, uuid(ef36f000-c1b2-11e1-afa7-0800200c9a66)]
interface nsIWebGLExtensionDepthTexture : nsIWebGLExtension
{
const WebGLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
};
[scriptable, builtinclass, uuid(a1fdfb76-6a08-4a1a-b0c9-d92ef3357cb9)]
interface nsIDOMWebGLRenderingContext : nsISupports
{

View File

@ -265,6 +265,7 @@ var interfaceNamesInGlobalScope =
"SVGLineElement",
"SVGPathSegArcRel",
"WebGLExtension",
"WebGLExtensionDepthTexture",
"XSLTProcessor",
"SVGPathSegLinetoVerticalAbs",
"SVGPathSegLinetoRel",

View File

@ -80,6 +80,7 @@ static const char *sExtensionNames[] = {
"GL_OES_EGL_image",
"GL_OES_EGL_sync",
"GL_OES_EGL_image_external",
"GL_EXT_packed_depth_stencil",
nullptr
};

View File

@ -1591,6 +1591,7 @@ public:
OES_EGL_image,
OES_EGL_sync,
OES_EGL_image_external,
EXT_packed_depth_stencil,
Extensions_Max
};

View File

@ -501,6 +501,7 @@ irregularFilenames = {
'nsIWebGLExtensionTextureFilterAnisotropic' : 'nsIDOMWebGLRenderingContext',
'nsIWebGLExtensionLoseContext' : 'nsIDOMWebGLRenderingContext',
'nsIWebGLExtensionCompressedTextureS3TC' : 'nsIDOMWebGLRenderingContext',
'nsIWebGLExtensionDepthTexture' : 'nsIDOMWebGLRenderingContext',
'nsIIndexedDatabaseUsageCallback': 'nsIIndexedDatabaseManager',