b=965848; implement EXT_shader_texture_lod for WebGL; r=jgilbert, r=bz

This commit is contained in:
Vladimir Vukicevic 2014-07-24 11:58:43 -04:00
parent 2a569678d6
commit 40313e5a6d
13 changed files with 336 additions and 0 deletions

View File

@ -1461,6 +1461,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionShaderTextureLod': {
'nativeType': 'mozilla::WebGLExtensionShaderTextureLod',
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionTextureFilterAnisotropic': {
'nativeType': 'mozilla::WebGLExtensionTextureFilterAnisotropic',
'headerFile': 'WebGLExtensions.h'

View File

@ -35,6 +35,7 @@ WebGLContext::GetExtensionString(WebGLExtensionID ext)
WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float)
WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth)
WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
@ -155,6 +156,8 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
return WebGLExtensionDrawBuffers::IsSupported(this);
case WebGLExtensionID::EXT_frag_depth:
return WebGLExtensionFragDepth::IsSupported(this);
case WebGLExtensionID::EXT_shader_texture_lod:
return gl->IsExtensionSupported(GLContext::EXT_shader_texture_lod);
default:
// For warnings-as-errors.
break;
@ -334,6 +337,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
case WebGLExtensionID::EXT_blend_minmax:
obj = new WebGLExtensionBlendMinMax(this);
break;
case WebGLExtensionID::EXT_shader_texture_lod:
obj = new WebGLExtensionShaderTextureLod(this);
break;
default:
MOZ_ASSERT(false, "should not get there.");
}

View File

@ -3041,6 +3041,9 @@ WebGLContext::CompileShader(WebGLShader *shader)
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
resources.EXT_draw_buffers = 1;
if (IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
resources.EXT_shader_texture_lod = 1;
// Tell ANGLE to allow highp in frag shaders. (unless disabled)
// If underlying GLES doesn't have highp in frag shaders, it should complain anyways.
resources.FragmentPrecisionHigh = mDisableFragHighP ? 0 : 1;

View File

@ -0,0 +1,21 @@
/* -*- 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"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
using namespace mozilla;
WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(WebGLContext* context)
: WebGLExtensionBase(context)
{
}
WebGLExtensionShaderTextureLod::~WebGLExtensionShaderTextureLod()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod)

View File

@ -178,6 +178,16 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionShaderTextureLod
: public WebGLExtensionBase
{
public:
WebGLExtensionShaderTextureLod(WebGLContext*);
virtual ~WebGLExtensionShaderTextureLod();
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionTextureFilterAnisotropic
: public WebGLExtensionBase
{

View File

@ -150,6 +150,7 @@ MOZ_BEGIN_ENUM_CLASS(WebGLExtensionID, uint8_t)
EXT_color_buffer_half_float,
EXT_frag_depth,
EXT_sRGB,
EXT_shader_texture_lod,
EXT_texture_filter_anisotropic,
OES_element_index_uint,
OES_standard_derivatives,

View File

@ -73,6 +73,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLExtensionFragDepth.cpp',
'WebGLExtensionInstancedArrays.cpp',
'WebGLExtensionLoseContext.cpp',
'WebGLExtensionShaderTextureLod.cpp',
'WebGLExtensionSRGB.cpp',
'WebGLExtensionStandardDerivatives.cpp',
'WebGLExtensionTextureFilterAnisotropic.cpp',

View File

@ -8,3 +8,4 @@ webgl-compressed-texture-etc1.html
webgl-compressed-texture-s3tc.html
--min-version 1.0.2 webgl-depth-texture.html
ext-sRGB.html
ext-shader-texture-lod.html

View File

@ -0,0 +1,280 @@
<!--
Copyright (c) 2011 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL EXT_shader_texture_lod Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"></script>
<script src="../resources/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" width="256" height="256" style="width: 50px; height: 50px;"> </canvas>
<div id="console"></div>
<!-- Shaders for testing standard derivatives -->
<!-- Shader omitting the required #extension pragma -->
<script id="missingPragmaFragmentShader" type="x-shader/x-fragment">
precision mediump float;
varying vec2 texCoord0v;
void main() {
vec4 color = texture2DLodEXT(tex, texCoord0v, lod);
gl_FragColor = vec4(dx, dy, w, 1.0);
}
</script>
<!-- Shader to test macro definition -->
<script id="macroFragmentShader" type="x-shader/x-fragment">
precision mediump float;
void main() {
#ifdef GL_EXT_shader_texture_lod
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
#else
// Error expected
#error no GL_EXT_shader_texture_lod;
#endif
}
</script>
<!-- Shader with required #extension pragma -->
<script id="testFragmentShader" type="x-shader/x-fragment">
#extension GL_EXT_shader_texture_lod : enable
precision mediump float;
varying vec2 texCoord0v;
uniform float lod;
uniform sampler2D tex;
void main() {
vec4 color = texture2DLodEXT(tex, texCoord0v, lod);
gl_FragColor = color;
}
</script>
<!-- Shaders to link with test fragment shaders -->
<script id="goodVertexShader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec2 texCoord0;
varying vec2 texCoord0v;
void main() {
texCoord0v = texCoord0;
gl_Position = vPosition;
}
</script>
<!-- Shaders to test output -->
<script id="outputVertexShader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec2 texCoord0;
varying vec2 texCoord0v;
void main() {
texCoord0v = texCoord0;
gl_Position = vPosition;
}
</script>
<script id="outputFragmentShader" type="x-shader/x-fragment">
#extension GL_EXT_shader_texture_lod : require
precision mediump float;
varying vec2 texCoord0v;
uniform float lod;
uniform sampler2D tex;
void main() {
vec4 color = texture2DLodEXT(tex, texCoord0v, lod);
gl_FragColor = color;
}
</script>
<script>
description("This test verifies the functionality of the EXT_shader_texture_lod extension, if it is available.");
debug("");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
shouldBe("canvas.width", "256");
shouldBe("canvas.height", "256");
var gl = wtu.create3DContext(canvas);
var ext = null;
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
// Run tests with extension disabled
runShaderTests(false);
// Query the extension and store globally so shouldBe can access it
ext = gl.getExtension("EXT_shader_texture_lod");
if (!ext) {
testPassed("No EXT_shader_texture_lod support -- this is legal");
runSupportedTest(false);
} else {
testPassed("Successfully enabled EXT_shader_texture_lod extension");
runSupportedTest(true);
runShaderTests(true);
runOutputTests();
runUniqueObjectTest();
runReferenceCycleTest();
}
}
function runSupportedTest(extensionEnabled) {
var supported = gl.getSupportedExtensions();
if (supported.indexOf("EXT_shader_texture_lod") >= 0) {
if (extensionEnabled) {
testPassed("EXT_shader_texture_lod listed as supported and getExtension succeeded");
} else {
testFailed("EXT_shader_texture_lod listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("EXT_shader_texture_lod not listed as supported but getExtension succeeded");
} else {
testPassed("EXT_shader_texture_lod not listed as supported and getExtension failed -- this is legal");
}
}
}
function runShaderTests(extensionEnabled) {
debug("");
debug("Testing various shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
// Expect the macro shader to succeed ONLY if enabled
var macroFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "macroFragmentShader");
if (extensionEnabled) {
if (macroFragmentProgram) {
// Expected result
testPassed("GL_EXT_shader_texture_lod defined in shaders when extension is enabled");
} else {
testFailed("GL_EXT_shader_texture_lod not defined in shaders when extension is enabled");
}
} else {
if (macroFragmentProgram) {
testFailed("GL_EXT_shader_texture_lod defined in shaders when extension is disabled");
} else {
testPassed("GL_EXT_shader_texture_lod not defined in shaders when extension disabled");
}
}
// Always expect the shader missing the #pragma to fail (whether enabled or not)
var missingPragmaFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "missingPragmaFragmentShader");
if (missingPragmaFragmentProgram) {
testFailed("Shader built-ins allowed without #extension pragma");
} else {
testPassed("Shader built-ins disallowed without #extension pragma");
}
// Try to compile a shader using the built-ins that should only succeed if enabled
var testFragmentProgram = wtu.loadProgramFromScriptExpectError(gl, "goodVertexShader", "testFragmentShader");
if (extensionEnabled) {
if (testFragmentProgram) {
testPassed("Shader built-ins compiled successfully when extension enabled");
} else {
testFailed("Shader built-ins failed to compile when extension enabled");
}
} else {
if (testFragmentProgram) {
testFailed("Shader built-ins compiled successfully when extension disabled");
} else {
testPassed("Shader built-ins failed to compile when extension disabled");
}
}
}
function runOutputTests() {
debug("Testing various draws for valid built-in function behavior");
canvas.width = 256; canvas.height = 256;
gl.viewport(0, 0, canvas.width, canvas.height);
var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['vPosition', 'texCoord0'], [0, 1]);
var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
var colors = [
{name: 'red', color:[255, 0, 0, 255]},
{name: 'green', color:[0, 255, 0, 255]},
{name: 'blue', color:[0, 0, 255, 255]},
{name: 'yellow', color:[255, 255, 0, 255]},
{name: 'magenta', color:[255, 0, 255, 255]},
{name: 'cyan', color:[0, 255, 255, 255]},
{name: 'pink', color:[255, 128, 128, 255]},
{name: 'gray', color:[128, 128, 128, 255]},
{name: 'light green', color:[128, 255, 128, 255]},
];
if (colors.length != 9) {
testFailed("9 colors are needed (9 mips for 256x256 texture), only have " + colors.length);
} else {
testPassed("9 colors found (9 mips for 256x256 texture)");
}
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(
gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
for (var ii = 0; ii < colors.length; ++ii) {
var color = colors[ii];
var size = Math.pow(2, colors.length - ii - 1);
wtu.fillTexture(gl, tex, size, size, color.color, ii);
}
var loc = gl.getUniformLocation(program, "lod");
for (var ii = 0; ii < colors.length; ++ii) {
gl.uniform1f(loc, ii);
var color = colors[ii];
wtu.drawQuad(gl);
wtu.checkCanvas(
gl, color.color,
"256x256 texture drawn to 256x256 dest with lod = " + ii +
" should be " + color.name);
}
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
}
function runUniqueObjectTest()
{
debug("Testing that getExtension() returns the same object each time");
gl.getExtension("EXT_shader_texture_lod").myProperty = 2;
gc();
shouldBe('gl.getExtension("EXT_shader_texture_lod").myProperty', '2');
}
function runReferenceCycleTest()
{
// create some reference cycles. The goal is to see if they cause leaks. The point is that
// some browser test runners have instrumentation to detect leaked refcounted objects.
debug("Testing reference cycles between context and extension objects");
var ext = gl.getExtension("EXT_shader_texture_lod");
// create cycle between extension and context, since the context has to hold a reference to the extension
ext.context = gl;
// create a self-cycle on the extension object
ext.ext = ext;
}
debug("");
successfullyParsed = true;
</script>
<script>finishTest();</script>
</body>
</html>

View File

@ -39,6 +39,7 @@ support-files =
conformance/extensions/00_test_list.txt
conformance/extensions/ext-sRGB.html
conformance/extensions/ext-texture-filter-anisotropic.html
conformance/extensions/ext-shader-texture-lod.html
conformance/extensions/oes-standard-derivatives.html
conformance/extensions/oes-texture-float.html
conformance/extensions/oes-vertex-array-object.html

View File

@ -916,6 +916,11 @@ interface WebGLExtensionTextureFloatLinear
{
};
[NoInterfaceObject]
interface WebGLExtensionShaderTextureLod
{
};
[NoInterfaceObject]
interface WebGLExtensionTextureHalfFloat
{

View File

@ -142,6 +142,7 @@ static const char *sExtensionNames[] = {
"GL_EXT_frag_depth",
"GL_OES_compressed_ETC1_RGB8_texture",
"GL_EXT_draw_range_elements",
"GL_EXT_shader_texture_lod",
nullptr
};

View File

@ -412,6 +412,7 @@ public:
EXT_frag_depth,
OES_compressed_ETC1_RGB8_texture,
EXT_draw_range_elements,
EXT_shader_texture_lod,
Extensions_Max,
Extensions_End
};