зеркало из https://github.com/mozilla/gecko-dev.git
Bug 843668 - Implement WebGL -draft- extension EXT_sRGB. r=jgilbert
https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/ See content/canvas/test/webgl/conformance/extensions/ext-sRGB.html for example usage.
This commit is contained in:
Родитель
969c3412a7
Коммит
93f44b676a
|
@ -888,6 +888,7 @@ protected:
|
|||
// -------------------------------------------------------------------------
|
||||
// WebGL extensions (implemented in WebGLContextExtensions.cpp)
|
||||
enum WebGLExtensionID {
|
||||
EXT_sRGB,
|
||||
EXT_texture_filter_anisotropic,
|
||||
OES_element_index_uint,
|
||||
OES_standard_derivatives,
|
||||
|
@ -950,7 +951,7 @@ protected:
|
|||
bool ValidateGLSLVariableName(const nsAString& name, const char *info);
|
||||
bool ValidateGLSLCharacter(PRUnichar c);
|
||||
bool ValidateGLSLString(const nsAString& string, const char *info);
|
||||
|
||||
bool ValidateTexImage2DFormat(GLenum format, const char* info);
|
||||
bool ValidateTexImage2DTarget(GLenum target, GLsizei width, GLsizei height, const char* info);
|
||||
bool ValidateCompressedTextureSize(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, uint32_t byteLength, const char* info);
|
||||
bool ValidateLevelWidthHeightForTarget(GLenum target, GLint level, GLsizei width, GLsizei height, const char* info);
|
||||
|
|
|
@ -17,6 +17,7 @@ using namespace mozilla::gl;
|
|||
|
||||
// must match WebGLContext::WebGLExtensionID
|
||||
static const char *sExtensionNames[] = {
|
||||
"EXT_sRGB",
|
||||
"EXT_texture_filter_anisotropic",
|
||||
"OES_element_index_uint",
|
||||
"OES_standard_derivatives",
|
||||
|
@ -113,6 +114,8 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
|||
gl->IsExtensionSupported(GLContext::ANGLE_depth_texture);
|
||||
case ANGLE_instanced_arrays:
|
||||
return WebGLExtensionInstancedArrays::IsSupported(this);
|
||||
case EXT_sRGB:
|
||||
return WebGLExtensionSRGB::IsSupported(this);
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
|
@ -257,6 +260,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
|
|||
case ANGLE_instanced_arrays:
|
||||
obj = new WebGLExtensionInstancedArrays(this);
|
||||
break;
|
||||
case EXT_sRGB:
|
||||
obj = new WebGLExtensionSRGB(this);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "should not get there.");
|
||||
}
|
||||
|
|
|
@ -1415,6 +1415,15 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
|||
|
||||
if (fba.Renderbuffer()) {
|
||||
switch (pname) {
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
|
||||
if (IsExtensionEnabled(EXT_sRGB)) {
|
||||
const GLenum internalFormat = fba.Renderbuffer()->InternalFormat();
|
||||
return (internalFormat == LOCAL_GL_SRGB_EXT ||
|
||||
internalFormat == LOCAL_GL_SRGB_ALPHA_EXT ||
|
||||
internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT) ?
|
||||
JS::NumberValue(uint32_t(LOCAL_GL_SRGB_EXT)) :
|
||||
JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
|
||||
}
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
|
||||
return JS::NumberValue(uint32_t(LOCAL_GL_RENDERBUFFER));
|
||||
|
||||
|
@ -1429,6 +1438,16 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
|||
}
|
||||
} else if (fba.Texture()) {
|
||||
switch (pname) {
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
|
||||
if (IsExtensionEnabled(EXT_sRGB)) {
|
||||
const GLenum internalFormat =
|
||||
fba.Texture()->ImageInfoAt(LOCAL_GL_TEXTURE_2D, 0).Format();
|
||||
return (internalFormat == LOCAL_GL_SRGB_EXT ||
|
||||
internalFormat == LOCAL_GL_SRGB_ALPHA_EXT) ?
|
||||
JS::NumberValue(uint32_t(LOCAL_GL_SRGB_EXT)) :
|
||||
JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
|
||||
}
|
||||
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
|
||||
return JS::NumberValue(uint32_t(LOCAL_GL_TEXTURE));
|
||||
|
||||
|
@ -2493,6 +2512,8 @@ WebGLContext::RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei
|
|||
// We emulate this in WebGLRenderbuffer if we don't have the requisite extension.
|
||||
internalformatForGL = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
break;
|
||||
case LOCAL_GL_SRGB8_ALPHA8_EXT:
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
|
||||
}
|
||||
|
@ -3708,18 +3729,8 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
return;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGB:
|
||||
case LOCAL_GL_RGBA:
|
||||
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);
|
||||
}
|
||||
if (!ValidateTexImage2DFormat(format, "texImage2D: format"))
|
||||
return;
|
||||
|
||||
if (format != internalformat)
|
||||
return ErrorInvalidOperation("texImage2D: format does not match internalformat");
|
||||
|
@ -3791,6 +3802,23 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
// format == internalformat, as checked above and as required by ES.
|
||||
internalformat = InternalFormatForFormatAndType(format, type, gl->IsGLES2());
|
||||
|
||||
// Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
|
||||
// requires that format == internalformat, but GL will fail in this case.
|
||||
// GL requires:
|
||||
// format -> internalformat
|
||||
// GL_RGB GL_SRGB_EXT
|
||||
// GL_RGBA GL_SRGB_ALPHA_EXT
|
||||
if (!gl->IsGLES2()) {
|
||||
switch (internalformat) {
|
||||
case LOCAL_GL_SRGB_EXT:
|
||||
format = LOCAL_GL_RGB;
|
||||
break;
|
||||
case LOCAL_GL_SRGB_ALPHA_EXT:
|
||||
format = LOCAL_GL_RGBA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum error = LOCAL_GL_NO_ERROR;
|
||||
|
||||
WebGLImageDataStatus imageInfoStatusIfSuccess = WebGLImageDataStatus::NoImageData;
|
||||
|
@ -3839,7 +3867,7 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
// have NoImageData at this point.
|
||||
MOZ_ASSERT(imageInfoStatusIfSuccess != WebGLImageDataStatus::NoImageData);
|
||||
|
||||
tex->SetImageInfo(target, level, width, height, format, type, imageInfoStatusIfSuccess);
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, type, imageInfoStatusIfSuccess);
|
||||
|
||||
ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
|
||||
}
|
||||
|
@ -4157,8 +4185,10 @@ WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
|
|||
if (type == LOCAL_GL_UNSIGNED_BYTE) {
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
case LOCAL_GL_SRGB_ALPHA_EXT:
|
||||
return WebGLTexelFormat::RGBA8;
|
||||
case LOCAL_GL_RGB:
|
||||
case LOCAL_GL_SRGB_EXT:
|
||||
return WebGLTexelFormat::RGB8;
|
||||
case LOCAL_GL_ALPHA:
|
||||
return WebGLTexelFormat::A8;
|
||||
|
|
|
@ -300,6 +300,32 @@ bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WebGLContext::ValidateTexImage2DFormat(GLenum format, const char* info)
|
||||
{
|
||||
if (IsExtensionEnabled(EXT_sRGB)) {
|
||||
switch (format) {
|
||||
case LOCAL_GL_SRGB_EXT:
|
||||
case LOCAL_GL_SRGB_ALPHA_EXT:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGB:
|
||||
case LOCAL_GL_RGBA:
|
||||
case LOCAL_GL_ALPHA:
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
case LOCAL_GL_DEPTH_COMPONENT:
|
||||
case LOCAL_GL_DEPTH_STENCIL:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInvalidEnumInfo(info, format);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebGLContext::ValidateTexImage2DTarget(GLenum target, GLsizei width, GLsizei height,
|
||||
const char* info)
|
||||
{
|
||||
|
@ -464,8 +490,10 @@ uint32_t WebGLContext::GetBitsPerTexel(GLenum format, GLenum type)
|
|||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
return 2 * multiplier;
|
||||
case LOCAL_GL_RGB:
|
||||
case LOCAL_GL_SRGB_EXT:
|
||||
return 3 * multiplier;
|
||||
case LOCAL_GL_RGBA:
|
||||
case LOCAL_GL_SRGB_ALPHA_EXT:
|
||||
return 4 * multiplier;
|
||||
case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
|
||||
|
@ -562,9 +590,11 @@ bool WebGLContext::ValidateTexFormatAndType(GLenum format, GLenum type, int jsAr
|
|||
*texelSize = 2 * texMultiplier;
|
||||
return true;
|
||||
case LOCAL_GL_RGB:
|
||||
case LOCAL_GL_SRGB_EXT:
|
||||
*texelSize = 3 * texMultiplier;
|
||||
return true;
|
||||
case LOCAL_GL_RGBA:
|
||||
case LOCAL_GL_SRGB_ALPHA_EXT:
|
||||
*texelSize = 4 * texMultiplier;
|
||||
return true;
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- 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"
|
||||
#include "GLContext.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* context)
|
||||
: WebGLExtensionBase(context)
|
||||
{
|
||||
MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionSRGB: "
|
||||
"sRGB is unsupported.");
|
||||
gl::GLContext* gl = context->GL();
|
||||
if (!gl->IsGLES()) {
|
||||
// Desktop OpenGL requires the following to be enabled to support
|
||||
// sRGB operations on framebuffers
|
||||
gl->MakeCurrent();
|
||||
gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
|
||||
}
|
||||
}
|
||||
|
||||
WebGLExtensionSRGB::~WebGLExtensionSRGB()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLExtensionSRGB::IsSupported(const WebGLContext* context)
|
||||
{
|
||||
gl::GLContext* gl = context->GL();
|
||||
|
||||
return gl->IsSupported(gl::GLFeature::sRGB);
|
||||
}
|
||||
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB)
|
|
@ -109,6 +109,18 @@ public:
|
|||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
class WebGLExtensionSRGB
|
||||
: public WebGLExtensionBase
|
||||
{
|
||||
public:
|
||||
WebGLExtensionSRGB(WebGLContext*);
|
||||
virtual ~WebGLExtensionSRGB();
|
||||
|
||||
static bool IsSupported(const WebGLContext* context);
|
||||
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
class WebGLExtensionStandardDerivatives
|
||||
: public WebGLExtensionBase
|
||||
{
|
||||
|
|
|
@ -132,7 +132,9 @@ WebGLFramebuffer::Attachment::IsComplete() const {
|
|||
format == LOCAL_GL_LUMINANCE ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_RGB ||
|
||||
format == LOCAL_GL_RGBA);
|
||||
format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_SRGB_EXT ||
|
||||
format == LOCAL_GL_SRGB_ALPHA_EXT);
|
||||
}
|
||||
MOZ_CRASH("Invalid WebGL attachment poin?");
|
||||
}
|
||||
|
@ -153,7 +155,8 @@ WebGLFramebuffer::Attachment::IsComplete() const {
|
|||
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
|
||||
return (format == LOCAL_GL_RGB565 ||
|
||||
format == LOCAL_GL_RGB5_A1 ||
|
||||
format == LOCAL_GL_RGBA4);
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_SRGB8_ALPHA8_EXT);
|
||||
}
|
||||
MOZ_CRASH("Invalid WebGL attachment poin?");
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ WebGLRenderbuffer::MemoryUsage() const {
|
|||
primarySize = 3*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGBA8:
|
||||
case LOCAL_GL_SRGB8_ALPHA8_EXT:
|
||||
case LOCAL_GL_DEPTH24_STENCIL8:
|
||||
case LOCAL_GL_DEPTH_COMPONENT32:
|
||||
primarySize = 4*pixels;
|
||||
|
|
|
@ -54,6 +54,7 @@ if CONFIG['MOZ_WEBGL']:
|
|||
'WebGLExtensionElementIndexUint.cpp',
|
||||
'WebGLExtensionInstancedArrays.cpp',
|
||||
'WebGLExtensionLoseContext.cpp',
|
||||
'WebGLExtensionSRGB.cpp',
|
||||
'WebGLExtensionStandardDerivatives.cpp',
|
||||
'WebGLExtensionTextureFilterAnisotropic.cpp',
|
||||
'WebGLExtensionTextureFloat.cpp',
|
||||
|
|
|
@ -6,4 +6,4 @@ 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
|
||||
|
||||
ext-sRGB.html
|
||||
|
|
|
@ -0,0 +1,363 @@
|
|||
<!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>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas" width="16" height="16" style="width: 50px; height: 50px; border: 1px solid black;"></canvas>
|
||||
|
||||
<!-- Shaders to test output -->
|
||||
<script id="vertexShader" type="x-shader/x-vertex">
|
||||
attribute vec4 aPosition;
|
||||
void main() {
|
||||
gl_Position = aPosition;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="fragmentShader" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
uniform float uColor;
|
||||
void main() {
|
||||
gl_FragColor = vec4(uColor, uColor, uColor, 1);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas;
|
||||
var gl;
|
||||
var ext = null;
|
||||
|
||||
function getExtension() {
|
||||
ext = gl.getExtension("EXT_sRGB");
|
||||
}
|
||||
|
||||
function listsExtension() {
|
||||
var supported = gl.getSupportedExtensions();
|
||||
return (supported.indexOf("EXT_sRGB") >= 0);
|
||||
}
|
||||
|
||||
function readLocation(x, y) {
|
||||
var pixel = new Uint8Array(1 * 1 * 4);
|
||||
var px = Math.floor(x * canvas.drawingBufferWidth);
|
||||
var py = Math.floor(y * canvas.drawingBufferHeight);
|
||||
gl.readPixels(px, py, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
|
||||
return pixel;
|
||||
}
|
||||
|
||||
function toVec3String(val) {
|
||||
if (typeof(val) == 'number') {
|
||||
return toVec3String([val, val, val]);
|
||||
}
|
||||
return '[' + val[0] + ', ' + val[1] + ', ' + val[2] + ']';
|
||||
}
|
||||
|
||||
var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher
|
||||
|
||||
function expectResult(target, successMessage, failureMessage) {
|
||||
var anyDiffer = false;
|
||||
var source = readLocation(0.5, 0.5);
|
||||
for (var m = 0; m < 3; m++) {
|
||||
if (Math.abs(source[m] - target) > e) {
|
||||
anyDiffer = true;
|
||||
testFailed(failureMessage + "; should be " + toVec3String(target) + ", was " + toVec3String(source));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!anyDiffer) {
|
||||
testPassed(successMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function createGreysRGBTexture(gl, color) {
|
||||
var numPixels = gl.drawingBufferWidth * gl.drawingBufferHeight;
|
||||
var size = numPixels * 3;
|
||||
var buf = new Uint8Array(size);
|
||||
for (var ii = 0; ii < numPixels; ++ii) {
|
||||
var off = ii * 3;
|
||||
buf[off + 0] = color;
|
||||
buf[off + 1] = color;
|
||||
buf[off + 2] = color;
|
||||
}
|
||||
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D,
|
||||
0,
|
||||
ext.SRGB_EXT,
|
||||
gl.drawingBufferWidth,
|
||||
gl.drawingBufferHeight,
|
||||
0,
|
||||
ext.SRGB_EXT,
|
||||
gl.UNSIGNED_BYTE,
|
||||
buf);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
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);
|
||||
return tex;
|
||||
}
|
||||
|
||||
function testValidFormat(fn, internalFormat, formatName) {
|
||||
fn(internalFormat);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "was able to create type " + formatName);
|
||||
}
|
||||
|
||||
function testInvalidFormat(fn, internalFormat, formatName) {
|
||||
fn(internalFormat);
|
||||
var err = gl.getError();
|
||||
if (err == gl.NO_ERROR) {
|
||||
testFailed("should NOT be able to create type " + formatName);
|
||||
} else if (err == gl.INVALID_OPERATION) {
|
||||
testFailed("should return gl.INVALID_ENUM for type " + formatName);
|
||||
} else if (err == gl.INVALID_ENUM) {
|
||||
testPassed("not able to create invalid format: " + formatName);
|
||||
}
|
||||
}
|
||||
|
||||
var textureFormatFixture = {
|
||||
desc: "Checking texture formats",
|
||||
create: function(format) {
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D,
|
||||
0, // level
|
||||
format, // internalFormat
|
||||
gl.drawingBufferWidth, // width
|
||||
gl.drawingBufferHeight, // height
|
||||
0, // border
|
||||
format, // format
|
||||
gl.UNSIGNED_BYTE, // type
|
||||
null); // data
|
||||
},
|
||||
tests: [
|
||||
{
|
||||
desc: "Checking valid formats",
|
||||
fn: testValidFormat,
|
||||
formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ]
|
||||
},
|
||||
{
|
||||
desc: "Checking invalid formats",
|
||||
fn: testInvalidFormat,
|
||||
formats: [ 'SRGB8_ALPHA8_EXT' ]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var renderbufferFormatFixture = {
|
||||
desc: "Checking renderbuffer formats",
|
||||
create: function(format) {
|
||||
var rbo = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER,
|
||||
format,
|
||||
gl.drawingBufferWidth,
|
||||
gl.drawingBufferHeight);
|
||||
},
|
||||
tests: [
|
||||
{
|
||||
desc: "Checking valid formats",
|
||||
fn: testValidFormat,
|
||||
formats: [ 'SRGB8_ALPHA8_EXT' ]
|
||||
},
|
||||
{
|
||||
desc: "Checking invalid formats",
|
||||
fn: testInvalidFormat,
|
||||
formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
description("Test sRGB texture support");
|
||||
|
||||
debug("");
|
||||
debug("Canvas.getContext");
|
||||
|
||||
canvas = document.getElementById("canvas");
|
||||
gl = wtu.create3DContext(canvas);
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
} else {
|
||||
testPassed("context exists");
|
||||
|
||||
debug("");
|
||||
debug("Checking sRGB texture support");
|
||||
|
||||
// Query the extension and store globally so shouldBe can access it
|
||||
ext = gl.getExtension("EXT_sRGB");
|
||||
|
||||
if (!ext) {
|
||||
testPassed("No EXT_sRGB support -- this is legal");
|
||||
|
||||
runSupportedTest(false);
|
||||
} else {
|
||||
testPassed("Successfully enabled EXT_sRGB extension");
|
||||
|
||||
runSupportedTest(true);
|
||||
|
||||
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
||||
|
||||
runFormatTest(textureFormatFixture);
|
||||
runFormatTest(renderbufferFormatFixture);
|
||||
runTextureReadConversionTest();
|
||||
runFramebufferTextureConversionTest();
|
||||
runFramebufferRenderbufferConversionTest();
|
||||
}
|
||||
}
|
||||
|
||||
function runSupportedTest(extensionEnabled) {
|
||||
if (listsExtension()) {
|
||||
if (extensionEnabled) {
|
||||
testPassed("EXT_sRGB listed as supported and getExtension succeeded");
|
||||
} else {
|
||||
testFailed("EXT_sRGB listed as supported but getExtension failed");
|
||||
}
|
||||
} else {
|
||||
if (extensionEnabled) {
|
||||
testFailed("EXT_sRGB not listed as supported but getExtension succeeded");
|
||||
} else {
|
||||
testPassed("EXT_sRGB not listed as supported and getExtension failed -- this is legal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function runFormatTest(fixture) {
|
||||
debug("");
|
||||
debug(fixture.desc);
|
||||
|
||||
for (var tt = 0; tt < fixture.tests.length; ++tt) {
|
||||
var test = fixture.tests[tt];
|
||||
debug(test.desc);
|
||||
|
||||
for (var ii = 0; ii < test.formats.length; ++ii) {
|
||||
var formatName = test.formats[ii];
|
||||
test.fn(fixture.create, ext[formatName], "ext." + formatName);
|
||||
}
|
||||
|
||||
if (tt != fixture.tests.length - 1)
|
||||
debug("");
|
||||
}
|
||||
}
|
||||
|
||||
function runTextureReadConversionTest() {
|
||||
debug("");
|
||||
debug("Test the conversion of colors from sRGB to linear on texture read");
|
||||
|
||||
// Draw
|
||||
var conversions = [
|
||||
[ 0, 0 ],
|
||||
[ 63, 13 ],
|
||||
[ 127, 54 ],
|
||||
[ 191, 133 ],
|
||||
[ 255, 255 ]
|
||||
];
|
||||
|
||||
var program = wtu.setupTexturedQuad(gl);
|
||||
gl.uniform1i(gl.getUniformLocation(program, "tex2d"), 0);
|
||||
|
||||
for (var ii = 0; ii < conversions.length; ii++) {
|
||||
var tex = createGreysRGBTexture(gl, conversions[ii][0]);
|
||||
wtu.drawQuad(gl);
|
||||
expectResult(conversions[ii][1],
|
||||
"sRGB texture read returned correct data",
|
||||
"sRGB texture read returned incorrect data");
|
||||
}
|
||||
}
|
||||
|
||||
function runFramebufferTextureConversionTest() {
|
||||
debug("");
|
||||
debug("Test the conversion of colors from linear to sRGB on framebuffer (texture) write");
|
||||
|
||||
var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]);
|
||||
var tex = createGreysRGBTexture(gl, 0);
|
||||
var fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
|
||||
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
|
||||
// Draw
|
||||
var conversions = [
|
||||
[ 0, 0 ],
|
||||
[ 13, 63 ],
|
||||
[ 54, 127 ],
|
||||
[ 133, 191 ],
|
||||
[ 255, 255 ]
|
||||
];
|
||||
|
||||
wtu.setupUnitQuad(gl, 0);
|
||||
|
||||
for (var ii = 0; ii < conversions.length; ii++) {
|
||||
gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0);
|
||||
wtu.drawQuad(gl, [0, 0, 0, 0]);
|
||||
expectResult(conversions[ii][1],
|
||||
"framebuffer (texture) read returned correct data",
|
||||
"framebuffer (texture) read returned incorrect data");
|
||||
}
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
}
|
||||
|
||||
function runFramebufferRenderbufferConversionTest() {
|
||||
debug("");
|
||||
debug("Test the conversion of colors from linear to sRGB on framebuffer (renderbuffer) write");
|
||||
|
||||
function createsRGBFramebuffer(gl, width, height) {
|
||||
var rbo = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, ext.SRGB8_ALPHA8_EXT, width, height);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
var fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
|
||||
gl.RENDERBUFFER, rbo);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
|
||||
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
|
||||
return fbo;
|
||||
}
|
||||
|
||||
// Draw
|
||||
var conversions = [
|
||||
[ 0, 0 ],
|
||||
[ 13, 63 ],
|
||||
[ 54, 127 ],
|
||||
[ 133, 191 ],
|
||||
[ 255, 255 ]
|
||||
];
|
||||
|
||||
var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]);
|
||||
wtu.setupUnitQuad(gl, 0);
|
||||
var fbo = createsRGBFramebuffer(gl, 4, 4);
|
||||
|
||||
for (var ii = 0; ii < conversions.length; ii++) {
|
||||
gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0);
|
||||
wtu.drawQuad(gl, [0, 0, 0, 0]);
|
||||
expectResult(conversions[ii][1],
|
||||
"framebuffer (renderbuffer) read returned the correct data",
|
||||
"framebuffer (renderbuffer) read returned incorrect data");
|
||||
}
|
||||
}
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script>finishTest();</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1313,6 +1313,11 @@ DOMInterfaces = {
|
|||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionSRGB': {
|
||||
'nativeType': 'mozilla::WebGLExtensionSRGB',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionStandardDerivatives': {
|
||||
'nativeType': 'mozilla::WebGLExtensionStandardDerivatives',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
|
|
|
@ -830,6 +830,15 @@ interface WebGLExtensionTextureFilterAnisotropic
|
|||
const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionSRGB
|
||||
{
|
||||
const GLenum SRGB_EXT = 0x8C40;
|
||||
const GLenum SRGB_ALPHA_EXT = 0x8C42;
|
||||
const GLenum SRGB8_ALPHA8_EXT = 0x8C43;
|
||||
const GLenum FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT = 0x8210;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionStandardDerivatives {
|
||||
const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
|
||||
|
|
|
@ -116,6 +116,10 @@ static const char *sExtensionNames[] = {
|
|||
"GL_EXT_transform_feedback",
|
||||
"GL_NV_transform_feedback",
|
||||
"GL_ANGLE_depth_texture",
|
||||
"GL_EXT_sRGB",
|
||||
"GL_EXT_texture_sRGB",
|
||||
"GL_ARB_framebuffer_sRGB",
|
||||
"GL_EXT_framebuffer_sRGB",
|
||||
"GL_KHR_debug",
|
||||
nullptr
|
||||
};
|
||||
|
|
|
@ -99,6 +99,7 @@ namespace GLFeature {
|
|||
packed_depth_stencil,
|
||||
query_objects,
|
||||
robustness,
|
||||
sRGB,
|
||||
standard_derivatives,
|
||||
texture_float,
|
||||
texture_float_linear,
|
||||
|
@ -395,6 +396,10 @@ public:
|
|||
EXT_transform_feedback,
|
||||
NV_transform_feedback,
|
||||
ANGLE_depth_texture,
|
||||
EXT_sRGB,
|
||||
EXT_texture_sRGB,
|
||||
ARB_framebuffer_sRGB,
|
||||
EXT_framebuffer_sRGB,
|
||||
KHR_debug,
|
||||
Extensions_Max,
|
||||
Extensions_End
|
||||
|
|
|
@ -249,6 +249,15 @@ static const FeatureInfo sFeatureInfoArr[] = {
|
|||
GLContext::Extensions_End
|
||||
}
|
||||
},
|
||||
{
|
||||
"sRGB",
|
||||
300, // OpenGL version
|
||||
300, // OpenGL ES version
|
||||
{
|
||||
GLContext::EXT_sRGB,
|
||||
GLContext::Extensions_End
|
||||
}
|
||||
},
|
||||
{
|
||||
"standard_derivatives",
|
||||
200, // OpenGL version
|
||||
|
@ -387,6 +396,14 @@ GLContext::InitFeatures()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bug 843668: Work around limitation of the feature system.
|
||||
// For sRGB support under OpenGL to match OpenGL ES spec, check for both
|
||||
// EXT_texture_sRGB and EXT_framebuffer_sRGB is required.
|
||||
if (IsExtensionSupported(EXT_texture_sRGB) &&
|
||||
(IsExtensionSupported(ARB_framebuffer_sRGB) || IsExtensionSupported(EXT_framebuffer_sRGB))) {
|
||||
mAvailableFeatures[GLFeature::sRGB] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Загрузка…
Ссылка в новой задаче