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:
Dan Glastonbury 2013-10-16 08:27:59 -04:00
Родитель 969c3412a7
Коммит 93f44b676a
16 изменённых файлов: 544 добавлений и 17 удалений

Просмотреть файл

@ -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