Merge inbound to mozilla-central. a=merge

This commit is contained in:
shindli 2018-10-09 19:24:28 +03:00
commit 089182bee5
360 changed files with 10465 additions and 3916 deletions

View File

@ -1175,7 +1175,7 @@ BrowserPageActions.addSearchEngine = {
},
_installEngine(uri, image) {
Services.search.addEngine(uri, null, image, false, {
Services.search.addEngine(uri, image, false, {
onSuccess: engine => {
showBrowserPageActionFeedback(this.action);
},

View File

@ -54,7 +54,7 @@ add_task(async function() {
};
Services.obs.addObserver(searchObserver, "browser-search-engine-modified");
Services.search.addEngine("http://test:80/browser/browser/base/content/test/about/POSTSearchEngine.xml",
null, null, false);
null, false);
});
});
});

View File

@ -167,7 +167,7 @@ function promiseNewEngine(basename) {
info("Waiting for engine to be added: " + basename);
return new Promise((resolve, reject) => {
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) {
info("Search engine added: " + basename);
registerCleanupFunction(() => {

View File

@ -22,7 +22,7 @@ add_task(async function setup() {
});
Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
null, null, false);
null, false);
let [subject, data] = await engineAddedPromise;

View File

@ -42,7 +42,7 @@ function addSearchEngine(basename) {
return new Promise((resolve, reject) => {
info("Waiting for engine to be added: " + basename);
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess: (engine) => {
info(`Search engine added: ${basename}`);
registerCleanupFunction(() => Services.search.removeEngine(engine));

View File

@ -28,7 +28,7 @@ var SearchTestUtils = Object.freeze({
*/
promiseNewSearchEngine(url) {
return new Promise((resolve, reject) => {
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) {
gTestGlobals.registerCleanupFunction(() => Services.search.removeEngine(engine));
resolve(engine);

View File

@ -82,7 +82,7 @@ function promiseSetEngine() {
Services.obs.addObserver(observer, "browser-search-engine-modified");
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/426329.xml",
null, "data:image/x-icon,%00", false);
"data:image/x-icon,%00", false);
});
}

View File

@ -24,7 +24,7 @@ function test() {
Services.obs.addObserver(observer, "browser-search-engine-modified");
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-1.xml",
null, "data:image/x-icon;%00", false);
"data:image/x-icon;%00", false);
}
function test2() {
@ -45,5 +45,5 @@ function test2() {
Services.obs.addObserver(observer, "browser-search-engine-modified");
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-2.xml",
null, "data:image/x-icon;%00", false);
"data:image/x-icon;%00", false);
}

View File

@ -50,7 +50,7 @@ var gTests = [
Services.obs.addObserver(observer, "browser-search-engine-modified");
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
null, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
},
added(engine) {

View File

@ -49,7 +49,7 @@ add_task(async function() {
Services.obs.addObserver(observer, "browser-search-engine-modified");
ss.addEngine("resource://search-plugins/testEngine_mozsearch.xml",
null, "data:image/x-icon,%00", false);
"data:image/x-icon,%00", false);
});
contextMenu = document.getElementById("contentAreaContextMenu");

View File

@ -78,7 +78,7 @@ function test() {
Services.obs.addObserver(observer, "browser-search-engine-modified");
gCUITestUtils.addSearchBar().then(function() {
Services.search.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
null, "data:image/x-icon,%00", false);
"data:image/x-icon,%00", false);
});
}

View File

@ -9,7 +9,7 @@ function promiseNewEngine(basename) {
Services.search.init({
onInitComplete() {
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) {
info("Search engine added: " + basename);
resolve(engine);

View File

@ -61,7 +61,7 @@ function promiseNewEngine(basename, options = {}) {
onInitComplete() {
let url = getRootDirectory(options.testPath || gTestPath) + basename;
let current = Services.search.currentEngine;
Services.search.addEngine(url, null, options.iconURL || "", false, {
Services.search.addEngine(url, options.iconURL || "", false, {
onSuccess(engine) {
info("Search engine added: " + basename);
if (setAsCurrent) {

View File

@ -1,5 +1,5 @@
This is the PDF.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 2.0.911
Current extension version is: 2.0.919
Taken from upstream commit: ff2df9c5
Taken from upstream commit: f45e46d7

View File

@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
"use strict";
var pdfjsVersion = '2.0.911';
var pdfjsBuild = 'ff2df9c5';
var pdfjsVersion = '2.0.919';
var pdfjsBuild = 'f45e46d7';
var pdfjsSharedUtil = __w_pdfjs_require__(1);
var pdfjsDisplayAPI = __w_pdfjs_require__(7);
var pdfjsDisplayTextLayer = __w_pdfjs_require__(19);
@ -4082,8 +4082,7 @@ var DEFAULT_RANGE_CHUNK_SIZE = 65536;
let isWorkerDisabled = false;
let workerSrc;
const pdfjsFilePath = null;
var fakeWorkerFilesLoader = null;
var useRequireEnsure = false;
let fakeWorkerFilesLoader = null;
;
var createPDFNetworkStream;
function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
@ -4226,7 +4225,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
}
return worker.messageHandler.sendWithPromise('GetDocRequest', {
docId,
apiVersion: '2.0.911',
apiVersion: '2.0.919',
source: {
data: source.data,
url: source.url,
@ -4742,12 +4741,12 @@ var PDFWorker = function PDFWorkerClosure() {
fakeWorkerFilesLoadedCapability.resolve(mainWorkerMessageHandler);
return fakeWorkerFilesLoadedCapability.promise;
}
let loader = fakeWorkerFilesLoader || function (callback) {
(0, _dom_utils.loadScript)(getWorkerSrc()).then(function () {
callback(window.pdfjsWorker.WorkerMessageHandler);
const loader = fakeWorkerFilesLoader || function () {
return (0, _dom_utils.loadScript)(getWorkerSrc()).then(function () {
return window.pdfjsWorker.WorkerMessageHandler;
});
};
loader(fakeWorkerFilesLoadedCapability.resolve);
loader().then(fakeWorkerFilesLoadedCapability.resolve, fakeWorkerFilesLoadedCapability.reject);
return fakeWorkerFilesLoadedCapability.promise;
}
function createCDNWrapper(url) {
@ -4881,6 +4880,8 @@ var PDFWorker = function PDFWorkerClosure() {
var messageHandler = new _message_handler.MessageHandler(id, id + '_worker', port);
this._messageHandler = messageHandler;
this._readyCapability.resolve();
}).catch(reason => {
this._readyCapability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`));
});
},
destroy: function PDFWorker_destroy() {
@ -5553,8 +5554,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
}();
var version, build;
{
exports.version = version = '2.0.911';
exports.build = build = 'ff2df9c5';
exports.version = version = '2.0.919';
exports.build = build = 'f45e46d7';
}
exports.getDocument = getDocument;
exports.LoopbackPort = LoopbackPort;

View File

@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
"use strict";
var pdfjsVersion = '2.0.911';
var pdfjsBuild = 'ff2df9c5';
var pdfjsVersion = '2.0.919';
var pdfjsBuild = 'f45e46d7';
var pdfjsCoreWorker = __w_pdfjs_require__(1);
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
@ -327,7 +327,7 @@ var WorkerMessageHandler = {
var cancelXHRs = null;
var WorkerTasks = [];
let apiVersion = docParams.apiVersion;
let workerVersion = '2.0.911';
let workerVersion = '2.0.919';
if (apiVersion !== workerVersion) {
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
}

View File

@ -467,7 +467,9 @@ let PDFViewerApplication = {
let enabled = hashParams['pdfbug'].split(',');
waitOn.push(loadAndEnablePDFBug(enabled));
}
return Promise.all(waitOn);
return Promise.all(waitOn).catch(reason => {
console.error(`_parseHashParameters: "${reason.message}".`);
});
},
async _initializeL10n() {
this.l10n = this.externalServices.createL10n({ locale: _app_options.AppOptions.get('locale') });
@ -496,8 +498,8 @@ let PDFViewerApplication = {
eventBus
});
this.findController = findController;
let container = appConfig.mainContainer;
let viewer = appConfig.viewerContainer;
const container = appConfig.mainContainer;
const viewer = appConfig.viewerContainer;
this.pdfViewer = new _pdf_viewer.PDFViewer({
container,
viewer,
@ -538,7 +540,7 @@ let PDFViewerApplication = {
eventBus,
cursorToolOnLoad: _app_options.AppOptions.get('cursorToolOnLoad')
});
this.toolbar = new _toolbar.Toolbar(appConfig.toolbar, container, eventBus, this.l10n);
this.toolbar = new _toolbar.Toolbar(appConfig.toolbar, eventBus, this.l10n);
this.secondaryToolbar = new _secondary_toolbar.SecondaryToolbar(appConfig.secondaryToolbar, container, eventBus);
if (this.supportsFullscreen) {
this.pdfPresentationMode = new _pdf_presentation_mode.PDFPresentationMode({
@ -8636,9 +8638,8 @@ const PAGE_NUMBER_LOADING_INDICATOR = 'visiblePageIsLoading';
const SCALE_SELECT_CONTAINER_PADDING = 8;
const SCALE_SELECT_PADDING = 22;
class Toolbar {
constructor(options, mainContainer, eventBus, l10n = _ui_utils.NullL10n) {
constructor(options, eventBus, l10n = _ui_utils.NullL10n) {
this.toolbar = options.container;
this.mainContainer = mainContainer;
this.eventBus = eventBus;
this.l10n = l10n;
this.items = options;
@ -8657,7 +8658,7 @@ class Toolbar {
this._updateUIState(true);
}
setPageScale(pageScaleValue, pageScale) {
this.pageScaleValue = pageScaleValue;
this.pageScaleValue = (pageScaleValue || pageScale).toString();
this.pageScale = pageScale;
this._updateUIState(false);
}
@ -8729,9 +8730,7 @@ class Toolbar {
if (!this._wasLocalized) {
return;
}
let { pageNumber, pagesCount, items } = this;
let scaleValue = (this.pageScaleValue || this.pageScale).toString();
let scale = this.pageScale;
const { pageNumber, pagesCount, pageScaleValue, pageScale, items } = this;
if (resetNumPages) {
if (this.hasPageLabels) {
items.pageNumber.type = 'text';
@ -8756,15 +8755,15 @@ class Toolbar {
}
items.previous.disabled = pageNumber <= 1;
items.next.disabled = pageNumber >= pagesCount;
items.zoomOut.disabled = scale <= _ui_utils.MIN_SCALE;
items.zoomIn.disabled = scale >= _ui_utils.MAX_SCALE;
let customScale = Math.round(scale * 10000) / 100;
items.zoomOut.disabled = pageScale <= _ui_utils.MIN_SCALE;
items.zoomIn.disabled = pageScale >= _ui_utils.MAX_SCALE;
let customScale = Math.round(pageScale * 10000) / 100;
this.l10n.get('page_scale_percent', { scale: customScale }, '{{scale}}%').then(msg => {
let options = items.scaleSelect.options;
let predefinedValueFound = false;
for (let i = 0, ii = options.length; i < ii; i++) {
let option = options[i];
if (option.value !== scaleValue) {
if (option.value !== pageScaleValue) {
option.selected = false;
continue;
}

View File

@ -20,7 +20,7 @@ origin:
# Human-readable identifier for this version/release
# Generally "version NNN", "tag SSS", "bookmark SSS"
release: version 2.0.911
release: version 2.0.919
# The package's license, where possible using the mnemonic from
# https://spdx.org/licenses/

View File

@ -335,7 +335,7 @@ function waitForNewEngine(mm, basename, numImages) {
// Wait for addEngine().
let addDeferred = PromiseUtils.defer();
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) {
info("Search engine added: " + basename);
addDeferred.resolve(engine);

View File

@ -186,7 +186,7 @@ add_task(async function test_oneOff_enterSelection() {
// for this test.
const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
let suggestionEngine = await new Promise((resolve, reject) => {
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) { resolve(engine); },
onError() { reject(); },
});
@ -254,7 +254,7 @@ add_task(async function test_suggestion_click() {
// for this test.
const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
let suggestionEngine = await new Promise((resolve, reject) => {
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) { resolve(engine); },
onError() { reject(); },
});
@ -311,7 +311,7 @@ add_task(async function test_suggestion_enterSelection() {
// for this test.
const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
let suggestionEngine = await new Promise((resolve, reject) => {
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) { resolve(engine); },
onError() { reject(); },
});

View File

@ -82,7 +82,7 @@ function clickURLBarSuggestion(entryName, button = 1) {
async function withNewSearchEngine(taskFn) {
const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
let suggestionEngine = await new Promise((resolve, reject) => {
Services.search.addEngine(url, null, "", false, {
Services.search.addEngine(url, "", false, {
onSuccess(engine) { resolve(engine); },
onError() { reject(); },
});

View File

@ -220,9 +220,9 @@ networkMenu.sizeCached=cached
# by a service worker.
networkMenu.sizeServiceWorker=service worker
# LOCALIZATION NOTE (networkMenu.totalMS): This is the label displayed
# LOCALIZATION NOTE (networkMenu.totalMS2): This is the label displayed
# in the network menu specifying the time for a request to finish (in milliseconds).
networkMenu.totalMS=%S ms
networkMenu.totalMS2=%S ms
# This string is used to concatenate tooltips (netmonitor.waterfall.tooltip.*)
# in the requests waterfall for total time (in milliseconds). \\u0020 represents

View File

@ -104,7 +104,7 @@ class RequestListColumnWaterfall extends Component {
}
if (typeof totalTime === "number") {
const title = L10N.getFormatStr("networkMenu.totalMS", totalTime);
const title = L10N.getFormatStr("networkMenu.totalMS2", totalTime);
boxes.push(
div({
key: "total",

View File

@ -85,7 +85,7 @@ class TimingsPanel extends Component {
},
}),
span({ className: "requests-list-timings-total" },
L10N.getFormatStr("networkMenu.totalMS", timings[type])
L10N.getFormatStr("networkMenu.totalMS2", timings[type])
)
),
);

View File

@ -24,7 +24,7 @@ add_task(async function() {
function testL10N() {
is(typeof L10N.getStr("netmonitor.security.enabled"), "string",
"The getStr() method didn't return a valid string.");
is(typeof L10N.getFormatStr("networkMenu.totalMS", "foo"), "string",
is(typeof L10N.getFormatStr("networkMenu.totalMS2", "foo"), "string",
"The getFormatStr() method didn't return a valid string.");
}

View File

@ -1150,7 +1150,7 @@ nsGlobalWindowInner::CleanupCachedXBLHandlers()
}
void
nsGlobalWindowInner::FreeInnerObjects()
nsGlobalWindowInner::FreeInnerObjects(bool aForDocumentOpen)
{
if (IsDying()) {
return;
@ -1208,8 +1208,10 @@ nsGlobalWindowInner::FreeInnerObjects()
mDocumentURI = mDoc->GetDocumentURI();
mDocBaseURI = mDoc->GetDocBaseURI();
while (mDoc->EventHandlingSuppressed()) {
mDoc->UnsuppressEventHandlingAndFireEvents(false);
if (!aForDocumentOpen) {
while (mDoc->EventHandlingSuppressed()) {
mDoc->UnsuppressEventHandlingAndFireEvents(false);
}
}
if (mObservingDidRefresh) {

View File

@ -1083,7 +1083,7 @@ protected:
// Object Management
virtual ~nsGlobalWindowInner();
void FreeInnerObjects();
void FreeInnerObjects(bool aForDocumentOpen = false);
// Only to be called on an inner window.
// aDocument must not be null.

View File

@ -1970,7 +1970,7 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
// We no longer need the old inner window. Start its destruction if
// its not being reused and clear our reference.
if (doomCurrentInner) {
currentInner->FreeInnerObjects();
currentInner->FreeInnerObjects(handleDocumentOpen);
}
currentInner = nullptr;

View File

@ -0,0 +1 @@
master

View File

@ -54,24 +54,28 @@ canvas.addEventListener(
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext(canvas, {preserveDrawingBuffer: true});
shouldBeNonNull("gl");
var array = new Float32Array([0]);
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
var attribLocation = 1;
gl.enableVertexAttribArray(attribLocation);
gl.vertexAttribPointer(attribLocation, 1, gl.FLOAT, false, 0, 0);
gl.deleteBuffer(buf);
setTimeout(function() {
// Wait for possible context loss
if (!gl) {
testFailed("context does not exist");
finishTest();
}, 2000);
} else {
var array = new Float32Array([0]);
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
var attribLocation = 1;
gl.enableVertexAttribArray(attribLocation);
gl.vertexAttribPointer(attribLocation, 1, gl.FLOAT, false, 0, 0);
gl.deleteBuffer(buf);
setTimeout(function() {
// Wait for possible context loss
finishTest();
}, 2000);
}
var successfullyParsed = true;
</script>

View File

@ -55,6 +55,7 @@ var ctx2d = canvas2d.getContext("2d");
var gl = wtu.create3DContext(canvas);
if (!gl) {
testFailed("context does not exist");
finishTest();
} else {
testPassed("context exists");

View File

@ -88,8 +88,8 @@ if (!gl) {
err = gl.getError();
debug("");
finishTest();
}
finishTest();
</script>
</body>

View File

@ -91,8 +91,8 @@ if (!gl) {
err = gl.getError();
debug("");
finishTest();
}
finishTest();
</script>
</body>

View File

@ -45,6 +45,11 @@ function test() {
var glCanvas = document.getElementById("example");
var gl = wtu.create3DContext(glCanvas, {preserveDrawingBuffer: true, premultipliedAlpha: true});
if (!gl) {
testFailed("context does not exist");
return;
}
var program = wtu.setupColorQuad(gl);
// Clear backbuffer in red.

View File

@ -91,6 +91,8 @@ function nextTest() {
if (!gl) {
testFailed("context does not exist");
wtu.requestAnimFrame(nextTest);
} else {
testPassed("context exists");

View File

@ -51,6 +51,7 @@ var main = function() {
if (!gl) {
testFailed("can't create 3d context");
finishTest();
return;
}

View File

@ -15,5 +15,4 @@ context-lost.html
incorrect-context-object-behaviour.html
--max-version 1.9.9 methods.html
premultiplyalpha-test.html
resource-sharing-test.html
--min-version 1.0.4 user-defined-properties-on-context.html

View File

@ -82,6 +82,15 @@ function runTest(preserve) {
var ctx1 = c1.getContext('2d');
var ctx2 = c2.getContext('2d');
var gl = wtu.create3DContext(c3, { alpha:false, preserveDrawingBuffer:preserve });
if (!gl) {
testFailed("context does not exist");
if (preserve) {
finishTest()
} else {
runTest(true);
}
return;
}
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
ctx1.drawImage(c3, 0, 0);

View File

@ -44,41 +44,139 @@ description("Tests calling WebGL APIs with objects from other contexts");
var wtu = WebGLTestUtils;
var contextA = wtu.create3DContext();
var contextB = wtu.create3DContext();
var bufferA = contextA.createBuffer();
var bufferB = contextB.createBuffer();
var frameBufferA = contextA.createFramebuffer();
var frameBufferB = contextB.createFramebuffer();
var programA = wtu.loadStandardProgram(contextA);
var programB = wtu.loadStandardProgram(contextB);
var renderBufferA = contextA.createRenderbuffer();
var renderBufferB = contextB.createRenderbuffer();
var shaderA = wtu.loadStandardVertexShader(contextA);
var shaderB = wtu.loadStandardVertexShader(contextB);
var textureA = contextA.createTexture();
var textureB = contextB.createTexture();
var frameBufferA = contextA.createFramebuffer();
var frameBufferB = contextB.createFramebuffer();
var renderBufferA = contextA.createRenderbuffer();
var renderBufferB = contextB.createRenderbuffer();
var locationA = contextA.getUniformLocation(programA, 'u_modelViewProjMatrix');
var locationB = contextB.getUniformLocation(programB, 'u_modelViewProjMatrix');
var uniformData = [];
function generateFloat32Array(length) {
uniformData = new Float32Array(length);
}
function generateFloatArray(length) {
uniformData = new Array(length);
for (var i = 0; i < length; i++) {
uniformData[i] = 0.0;
}
}
function generateInt32Array(length) {
uniformData = new Int32Array(length);
}
function generateIntArray(length) {
uniformData = new Array(length);
for (var i = 0; i < length; i++) {
uniformData[i] = 0;
}
}
// Make the bindable objects valid in both contexts first.
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, bufferA)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, null)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, bufferB)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, null)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferA)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, null)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindFramebuffer(contextB.FRAMEBUFFER, frameBufferB)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindFramebuffer(contextB.FRAMEBUFFER, null)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferA)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindRenderbuffer(contextA.RENDERBUFFER, null)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindRenderbuffer(contextB.RENDERBUFFER, renderBufferB)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindRenderbuffer(contextB.RENDERBUFFER, null)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTexture(contextA.TEXTURE_2D, textureA)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTexture(contextA.TEXTURE_2D, null)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTexture(contextB.TEXTURE_2D, textureB)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTexture(contextB.TEXTURE_2D, null)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.compileShader(shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.linkProgram(programB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programA, shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programB, shaderA)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programB, shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programA, shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderA)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.shaderSource(shaderB, 'foo')");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindAttribLocation(programB, 0, 'foo')");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindBuffer(contextA.ARRAY_BUFFER, bufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindTexture(contextA.TEXTURE_2D, textureB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.compileShader(shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteBuffer(bufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteFramebuffer(frameBufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteProgram(programB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteRenderbuffer(renderBufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteShader(shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteShader(shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteTexture(textureB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programA, shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderA)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferRenderbuffer(contextA.FRAMEBUFFER, contextA.DEPTH_ATTACHMENT, contextA.RENDERBUFFER, renderBufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferTexture2D(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, contextA.TEXTURE_2D, textureB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveAttrib(programB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniform(programB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getAttachedShaders(programB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getAttribLocation(programB, 'a_vertex')");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getProgramParameter(programB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getProgramInfoLog(programB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderParameter(shaderB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderInfoLog(shaderB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderSource(shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programB, locationA)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programA, locationB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformLocation(programB, 'u_modelViewProjMatrix')");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isBuffer(bufferB)");
shouldBeFalse("contextA.isBuffer(bufferB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isFramebuffer(frameBufferB)");
shouldBeFalse("contextA.isFramebuffer(frameBufferB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isProgram(programB)");
shouldBeFalse("contextA.isProgram(programB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isRenderbuffer(renderBufferB)");
shouldBeFalse("contextA.isRenderbuffer(renderBufferB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isShader(shaderB)");
shouldBeFalse("contextA.isShader(shaderB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isTexture(textureB)");
shouldBeFalse("contextA.isTexture(textureB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.linkProgram(programB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.shaderSource(shaderB, 'foo')");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1f(locationB, 0.0)");
generateFloat32Array(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData)");
generateFloatArray(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1i(locationB, 0)");
generateInt32Array(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData)");
generateIntArray(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2f(locationB, 0.0, 0.0)");
generateFloat32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData)");
generateFloatArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2i(locationB, 0, 0)");
generateInt32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData)");
generateIntArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3f(locationB, 0.0, 0.0, 0.0)");
generateFloat32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData)");
generateFloatArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3i(locationB, 0, 0, 0)");
generateInt32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData)");
generateIntArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4f(locationB, 0.0, 0.0, 0.0, 0.0)");
generateFloat32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData)");
generateFloatArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4i(locationB, 0, 0, 0, 0)");
generateInt32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData)");
generateIntArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData)");
generateFloat32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData)");
generateFloatArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData)");
generateFloat32Array(9); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData)");
generateFloatArray(9); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData)");
generateFloat32Array(16); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData)");
generateFloatArray(16); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData)");
var successfullyParsed = true;
</script>

View File

@ -173,6 +173,12 @@ function doNextTest() {
+ ", antialias: " + antialias
+ ", imageFormat: " + test.imageFormat);
if (!gl) {
testFailed("context does not exist");
doNextTest();
return;
}
shouldBe('gl.getContextAttributes().premultipliedAlpha', premultipliedAlpha.toString());
shouldBeTrue('gl.getContextAttributes().preserveDrawingBuffer');

View File

@ -1,6 +1,8 @@
--min-version 1.0.3 --max-version 1.9.9 angle-instanced-arrays.html
--min-version 1.0.3 --max-version 1.9.9 angle-instanced-arrays-out-of-bounds.html
--min-version 1.0.3 --max-version 1.9.9 ext-blend-minmax.html
--min-version 1.0.4 ext-texture-compression-bptc.html
--min-version 1.0.4 ext-texture-compression-rgtc.html
--min-version 1.0.4 ext-disjoint-timer-query.html
--min-version 1.0.3 --max-version 1.9.9 ext-frag-depth.html
--min-version 1.0.3 --max-version 1.9.9 ext-shader-texture-lod.html
@ -26,8 +28,8 @@
webgl-debug-renderer-info.html
webgl-debug-shaders.html
--min-version 1.0.4 webgl-compressed-texture-astc.html
--min-version 1.0.3 webgl-compressed-texture-atc.html
--min-version 1.0.4 webgl-compressed-texture-etc.html
--min-version 1.0.4 webgl-compressed-texture-etc1.html
--min-version 1.0.3 webgl-compressed-texture-pvrtc.html
--min-version 1.0.2 webgl-compressed-texture-s3tc.html
--min-version 1.0.4 webgl-compressed-texture-s3tc-srgb.html
@ -38,5 +40,3 @@ webgl-debug-shaders.html
--min-version 1.0.3 --max-version 1.9.9 webgl-draw-buffers-feedback-loop.html
--min-version 1.0.4 --max-version 1.9.9 webgl-draw-buffers-framebuffer-unsupported.html
--min-version 1.0.4 --max-version 1.9.9 webgl-draw-buffers-max-draw-buffers.html
--min-version 1.0.3 webgl-shared-resources.html

View File

@ -0,0 +1,102 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL EXT_texture_compression_bptc Conformance Tests</title>
<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/compressed-texture-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("This test verifies the functionality of the EXT_texture_compression_bptc extension, if it is available.");
debug("");
var validFormats = {
COMPRESSED_RGBA_BPTC_UNORM_EXT: 0x8E8C,
COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 0x8E8D,
COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 0x8E8E,
COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 0x8E8F
};
function expectedByteLength(width, height, format) {
return Math.ceil(width / 4) * Math.ceil(height / 4) * 16;
}
function getBlockDimensions(format) {
return {width: 4, height: 4};
}
var wtu = WebGLTestUtils;
var ctu = CompressedTextureUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var gl = wtu.create3DContext();
var ext;
var formats = null;
function runTestExtension() {
// Test that enum values are listed correctly in supported formats and in the extension object.
ctu.testCompressedFormatsListed(gl, validFormats);
ctu.testCorrectEnumValuesInExt(ext, validFormats);
// Test that texture upload buffer size is validated correctly.
ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
};
function runTest() {
if (!gl) {
testFailed("context does not exist");
} else {
testPassed("context exists");
ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
ext = gl.getExtension("EXT_texture_compression_bptc");
wtu.runExtensionSupportedTest(gl, "EXT_texture_compression_bptc", ext !== null);
if (ext !== null) {
runTestExtension();
}
}
}
runTest();
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,107 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL EXT_texture_compression_rgtc Conformance Tests</title>
<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/compressed-texture-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("This test verifies the functionality of the EXT_texture_compression_rgtc extension, if it is available.");
debug("");
var validFormats = {
COMPRESSED_RED_RGTC1_EXT: 0x8DBB,
COMPRESSED_SIGNED_RED_RGTC1_EXT: 0x8DBC,
COMPRESSED_RED_GREEN_RGTC2_EXT: 0x8DBD,
COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 0x8DBE
};
function expectedByteLength(width, height, format) {
if (format == validFormats.COMPRESSED_RED_RGTC1_EXT || format == validFormats.COMPRESSED_SIGNED_RED_RGTC1_EXT) {
return Math.ceil(width / 4) * Math.ceil(height / 4) * 8;
}
else {
return Math.ceil(width / 4) * Math.ceil(height / 4) * 16;
}
}
function getBlockDimensions(format) {
return {width: 4, height: 4};
}
var wtu = WebGLTestUtils;
var ctu = CompressedTextureUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var gl = wtu.create3DContext();
var ext;
var formats = null;
function runTestExtension() {
// Test that enum values are listed correctly in supported formats and in the extension object.
ctu.testCompressedFormatsListed(gl, validFormats);
ctu.testCorrectEnumValuesInExt(ext, validFormats);
// Test that texture upload buffer size is validated correctly.
ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
};
function runTest() {
if (!gl) {
testFailed("context does not exist");
} else {
testPassed("context exists");
ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
ext = gl.getExtension("EXT_texture_compression_rgtc");
wtu.runExtensionSupportedTest(gl, "EXT_texture_compression_rgtc", ext !== null);
if (ext !== null) {
runTestExtension();
}
}
}
runTest();
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -30,6 +30,7 @@
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/compressed-texture-utils.js"></script>
<title>WebGL WEBGL_compressed_texture_astc Conformance Tests</title>
<style>
img {
@ -1601,6 +1602,7 @@ var decoded_12x12_argb_hdr = new Uint8Array([
]);
var wtu = WebGLTestUtils;
var ctu = CompressedTextureUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});
@ -1641,127 +1643,44 @@ var validFormats = {
};
var name;
var supportedFormats;
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
// Run tests with extension disabled
runTestDisabled();
debug("");
// The texture size 3 * 5 * 8 below is divisible by all the different block sizes supported by the extension.
ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 3 * 5 * 8);
// Query the extension and store globally so shouldBe can access it
ext = wtu.getExtensionWithKnownPrefixes(gl, extFlag);
if (!ext) {
testPassed("No WEBGL_compressed_texture_astc support -- this is legal");
runSupportedTest(false);
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_astc", false);
} else {
testPassed("Successfully enabled WEBGL_compressed_texture_astc extension");
debug("");
runSupportedTest(true);
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_astc", true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, extFlag);
if (name !== undefined) {
if (extensionEnabled) {
testPassed("WEBGL_compressed_texture_astc listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_compressed_texture_astc listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_compressed_texture_astc not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_compressed_texture_astc not listed as supported and getExtension failed -- this is legal");
}
}
}
function runTestDisabled() {
debug("Testing binding enum with extension disabled");
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
shouldBe("supportedFormats", "[]");
}
function runTestExtension() {
debug("");
debug("Testing " + extFlag);
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
// There should be exactly 28 formats for both WebGL 1.0 and WebGL 2.0.
shouldBe("supportedFormats.length", "28");
// Test that enum values are listed correctly in supported formats and in the extension object.
ctu.testCompressedFormatsListed(gl, validFormats);
ctu.testCorrectEnumValuesInExt(ext, validFormats);
// Test that texture upload buffer size is validated correctly.
ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
console.log(wtu);
// check that all 28 formats exist
testFormatsExist(supportedFormats);
// check that all format enums exist.
testCompressionFormatsValidity();
// check that the specified restrictions fails with
// an INVALID_VALUE error when not respected
testASTCFormatsRestrictions();
// Tests ASTC texture with every format
testLDRTextures();
testHDRTextures();
}
function testFormatsExist(supportedFormats) {
debug("");
debug("Testing every supported formats exist");
var failed;
for (var name in validFormats) {
var format = validFormats[name];
failed = true;
for (var ii = 0; ii < supportedFormats.length; ++ii) {
if (format == supportedFormats[ii]) {
testPassed("supported format " + formatToString(format) + " exists");
failed = false;
break;
}
}
if (failed) {
testFailed("supported format " + formatToString(format) + " does not exist");
}
}
}
function testCompressionFormatsValidity() {
debug("");
debug("Testing every supported formats is valid");
for (name in validFormats) {
var expected = "0x" + validFormats[name].toString(16);
var actual = "ext['" + name + "']";
shouldBe(actual, expected);
}
}
function testASTCFormatsRestrictions() {
debug("");
debug("Testing format restrictions on buffer size");
var data = new Uint8Array(17);
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
for (var formatId in validFormats) {
var format = validFormats[formatId];
var expectedSize = expectedByteLength(16, 16, format, data.length);
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, 16, 16, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
formatToString(format) + " expected size: " + expectedSize);
}
}
function testLDRTextures() {
debug("");
debug("Testing every LDR texture format compression");
@ -1850,7 +1769,7 @@ function testASTCTexture(test, useTexStorage) {
canvas.height = height;
gl.viewport(0, 0, width, height);
debug("");
debug("testing " + formatToString(format) + " " + width + "x" + height + " (" + test.mode + ")" +
debug("testing " + ctu.formatToString(ext, format) + " " + width + "x" + height + " (" + test.mode + ")" +
(useTexStorage ? " via texStorage2D" : " via compressedTexImage2D"));
debug("");
@ -1913,10 +1832,10 @@ function compareRect(
var div = document.createElement("div");
div.className = "testimages";
insertImg(div, "expected", makeImage(
ctu.insertCaptionedImg(div, "expected", ctu.makeScaledImage(
actualWidth, actualHeight, dataWidth, expectedData,
actualChannels == 4));
insertImg(div, "actual", makeImage(
ctu.insertCaptionedImg(div, "actual", ctu.makeScaledImage(
actualWidth, actualHeight, actualWidth, actual,
actualChannels == 4));
div.appendChild(document.createElement('br'));
@ -1975,74 +1894,51 @@ function buildTests(data, formats, raws, mode) {
return tests;
}
function formatToString(format) {
for (var p in ext) {
if (ext[p] == format) {
return p;
}
}
return "0x" + format.toString(16);
}
function expectedByteLength(w, h, format) {
if (format == ext.COMPRESSED_RGBA_ASTC_4x4_KHR)
if (format == validFormats.COMPRESSED_RGBA_ASTC_4x4_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR)
return Math.floor((w + 3) / 4) * Math.floor((h + 3) / 4) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_5x4_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_5x4_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR)
return Math.floor((w + 4) / 5) * Math.floor((h + 3) / 4) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_5x5_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_5x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR)
return Math.floor((w + 4) / 5) * Math.floor((h + 4) / 5) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_6x5_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_6x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR)
return Math.floor((w + 5) / 6) * Math.floor((h + 4) / 5) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_6x6_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_6x6_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR)
return Math.floor((w + 5) / 6) * Math.floor((h + 5) / 6) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_8x5_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_8x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR)
return Math.floor((w + 7) / 8) * Math.floor((h + 4) / 5) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_8x6_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_8x6_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR)
return Math.floor((w + 7) / 8) * Math.floor((h + 5) / 6) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_8x8_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_8x8_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR)
return Math.floor((w + 7) / 8) * Math.floor((h + 7) / 8) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_10x5_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x5_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR)
return Math.floor((w + 9) / 10) * Math.floor((h + 4) / 5) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_10x6_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x6_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR)
return Math.floor((w + 9) / 10) * Math.floor((h + 5) / 6) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_10x8_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x8_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR)
return Math.floor((w + 9) / 10) * Math.floor((h + 7) / 8) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_10x10_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_10x10_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR)
return Math.floor((w + 9) / 10) * Math.floor((h + 9) / 10) * 16;
else if (format == ext.COMPRESSED_RGBA_ASTC_12x10_KHR)
else if (format == validFormats.COMPRESSED_RGBA_ASTC_12x10_KHR || format == validFormats.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR)
return Math.floor((w + 11) / 12) * Math.floor((h + 9) / 10) * 16;
return Math.floor((w + 11) / 12) * Math.floor((h + 11) / 12) * 16;
}
function insertImg(element, caption, img) {
var div = document.createElement("div");
div.appendChild(img);
var label = document.createElement("div");
label.appendChild(document.createTextNode(caption));
div.appendChild(label);
element.appendChild(div);
}
function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
var scale = 8;
var c = document.createElement("canvas");
c.width = imageWidth * scale;
c.height = imageHeight * scale;
var ctx = c.getContext("2d");
for (var yy = 0; yy < imageHeight; ++yy) {
for (var xx = 0; xx < imageWidth; ++xx) {
var offset = (yy * dataWidth + xx) * 4;
ctx.fillStyle = "rgba(" +
data[offset + 0] + "," +
data[offset + 1] + "," +
data[offset + 2] + "," +
(alpha ? data[offset + 3] / 255 : 1) + ")";
ctx.fillRect(xx * scale, yy * scale, scale, scale);
function getBlockDimensions(format) {
var re = /.*_(\d+)x(\d+)_KHR/;
for (name in validFormats) {
if (validFormats[name] === format) {
var match = name.match(re);
return {
width: parseInt(match[1], 10),
height: parseInt(match[2], 10)
};
}
}
return wtu.makeImageFromCanvas(c);
testFailed('Could not find block dimensions for format ' + ctu.formatToString(ext, format));
return {width: 4, height: 4};
}
// Swaps two cells in an arraybuffer.

View File

@ -1,427 +0,0 @@
<!--
/*
** Copyright (c) 2013 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="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<title>WebGL WEBGL_compressed_texture_atc Conformance Tests</title>
<style>
img {
border: 1px solid black;
margin-right: 1em;
}
.testimages {
}
.testimages br {
clear: both;
}
.testimages > div {
float: left;
margin: 1em;
}
</style>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
<div id="console"></div>
<script>
"use strict";
description("This test verifies the functionality of the WEBGL_compressed_texture_atc extension, if it is available.");
debug("");
// Compressed textures generated with AMD's Compressonator tool
// http://developer.amd.com/resources/archive/archived-tools/gpu-tools-archive/the-compressonator/
var img_4x4_rgba_raw = new Uint8Array([
0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,
0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,
0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,
0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,
]);
var img_4x4_rgb_atc = new Uint8Array([
0x00,0x7c,0xe0,0x07,0xcc,0xcf,0xc0,0xff,
]);
var img_4x4_rgba_atc_explicit = new Uint8Array([
0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x7c,0xe0,0x07,0xcc,0xcf,0xc0,0xff,
]);
var img_4x4_rgba_atc_interpolated = new Uint8Array([
0xff,0x6a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xe0,0x07,0xcc,0xcf,0xc0,0xff,
]);
var img_8x8_rgba_raw = new Uint8Array([
0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,
0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,
0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,
0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,
0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,
0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,
0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,
0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,
0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,
0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,
0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,
0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,
0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,
0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,
0xff,0x00,0xff,0x69,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,
0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,
]);
var img_8x8_rgb_atc = new Uint8Array([
0x00,0x7c,0xe0,0x07,0xcc,0xcf,0xc0,0xff,0x1f,0x00,0xe0,0xff,0x33,0x30,0x3f,0x00,
0x1f,0x7c,0xe0,0x07,0x33,0x30,0x3f,0x00,0x1f,0x00,0xff,0x07,0xcc,0xcf,0xc0,0xff,
]);
var img_8x8_rgba_atc_explicit = new Uint8Array([
0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0x7c,0xe0,0x07,0xcc,0xcf,0xc0,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0xe0,0xff,0x33,0x30,0x3f,0x00,
0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x1f,0x7c,0xe0,0x07,0x33,0x30,0x3f,0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0xff,0x07,0xcc,0xcf,0xc0,0xff,
]);
var img_8x8_rgba_atc_interpolated = new Uint8Array([
0xff,0x6a,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x7c,0xe0,0x07,0xcc,0xcf,0xc0,0xff,
0x00,0xff,0x49,0x92,0x24,0x49,0x92,0x24,0x1f,0x00,0xe0,0xff,0x33,0x30,0x3f,0x00,
0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x1f,0x7c,0xe0,0x07,0x33,0x30,0x3f,0x00,
0x00,0xff,0x49,0x92,0x24,0x49,0x92,0x24,0x1f,0x00,0xff,0x07,0xcc,0xcf,0xc0,0xff,
]);
var wtu = WebGLTestUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});
var program = wtu.setupTexturedQuad(gl);
var ext = null;
var vao = null;
var validFormats = {
COMPRESSED_RGB_ATC_WEBGL : 0x8C92,
COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL : 0x8C93,
COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL : 0x87EE,
};
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_compressed_texture_atc");
if (!ext) {
testPassed("No WEBGL_compressed_texture_atc support -- this is legal");
runSupportedTest(false);
} else {
testPassed("Successfully enabled WEBGL_compressed_texture_atc extension");
runSupportedTest(true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_atc");
if (name !== undefined) {
if (extensionEnabled) {
testPassed("WEBGL_compressed_texture_atc listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_compressed_texture_atc listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_compressed_texture_atc not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_compressed_texture_atc not listed as supported and getExtension failed -- this is legal");
}
}
}
function runTestDisabled() {
debug("Testing binding enum with extension disabled");
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
shouldBe("supportedFormats", "[]");
}
function formatExists(format, supportedFormats) {
for (var ii = 0; ii < supportedFormats.length; ++ii) {
if (format == supportedFormats[ii]) {
testPassed("supported format " + formatToString(format) + " is exists");
return;
}
}
testFailed("supported format " + formatToString(format) + " does not exist");
}
function formatToString(format) {
for (var p in ext) {
if (ext[p] == format) {
return p;
}
}
return "0x" + format.toString(16);
}
function runTestExtension() {
debug("Testing WEBGL_compressed_texture_atc");
// check that all format enums exist.
for (name in validFormats) {
var expected = "0x" + validFormats[name].toString(16);
var actual = "ext['" + name + "']";
shouldBe(actual, expected);
}
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
// There should be exactly 3 formats for both WebGL 1.0 and WebGL 2.0.
shouldBe("supportedFormats.length", "3");
// check that all 3 formats exist
for (var name in validFormats.length) {
formatExists(validFormats[name], supportedFormats);
}
// Test each format
testATC_RGB();
testATC_RGBA_Explicit();
testATC_RGBA_Interpolated();
}
function testATC_RGB() {
var tests = [
{ width: 4,
height: 4,
channels: 3,
data: img_4x4_rgb_atc,
raw: img_4x4_rgba_raw,
format: ext.COMPRESSED_RGB_ATC_WEBGL
},
{ width: 8,
height: 8,
channels: 3,
data: img_8x8_rgb_atc,
raw: img_8x8_rgba_raw,
format: ext.COMPRESSED_RGB_ATC_WEBGL
}
];
testACTTextures(tests);
}
function testATC_RGBA_Explicit() {
var tests = [
{ width: 4,
height: 4,
channels: 4,
data: img_4x4_rgba_atc_explicit,
raw: img_4x4_rgba_raw,
format: ext.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL
},
{ width: 8,
height: 8,
channels: 4,
data: img_8x8_rgba_atc_explicit,
raw: img_8x8_rgba_raw,
format: ext.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL
}
];
testACTTextures(tests);
}
function testATC_RGBA_Interpolated() {
var tests = [
{ width: 4,
height: 4,
channels: 4,
data: img_4x4_rgba_atc_interpolated,
raw: img_4x4_rgba_raw,
format: ext.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL
},
{ width: 8,
height: 8,
channels: 4,
data: img_8x8_rgba_atc_interpolated,
raw: img_8x8_rgba_raw,
format: ext.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL
}
];
testACTTextures(tests);
}
function testACTTextures(tests) {
debug("<hr/>");
for (var ii = 0; ii < tests.length; ++ii) {
testACTTexture(tests[ii]);
}
}
function testACTTexture(test) {
var data = new Uint8Array(test.data);
var width = test.width;
var height = test.height;
var format = test.format;
var uncompressedData = test.raw;
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
debug("testing " + formatToString(format) + " " + width + "x" + height);
var 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.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
gl.generateMipmap(gl.TEXTURE_2D);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
wtu.clearAndDrawUnitQuad(gl);
compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "NEAREST");
// Test again with linear filtering.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
wtu.clearAndDrawUnitQuad(gl);
compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "LINEAR");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, -1, format, 1, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "cannot specify negative mip level");
// ATC Does not allow use of CompressedTexSubImage
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed");
}
function insertImg(element, caption, img) {
var div = document.createElement("div");
div.appendChild(img);
var label = document.createElement("div");
label.appendChild(document.createTextNode(caption));
div.appendChild(label);
element.appendChild(div);
}
function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
var scale = 8;
var c = document.createElement("canvas");
c.width = imageWidth * scale;
c.height = imageHeight * scale;
var ctx = c.getContext("2d");
for (var yy = 0; yy < imageHeight; ++yy) {
for (var xx = 0; xx < imageWidth; ++xx) {
var offset = (yy * dataWidth + xx) * 4;
ctx.fillStyle = "rgba(" +
data[offset + 0] + "," +
data[offset + 1] + "," +
data[offset + 2] + "," +
(alpha ? data[offset + 3] / 255 : 1) + ")";
ctx.fillRect(xx * scale, yy * scale, scale, scale);
}
}
return wtu.makeImageFromCanvas(c);
}
function compareRect(
actualWidth, actualHeight, actualChannels,
dataWidth, dataHeight, expectedData,
testData, testFormat, tolerance, filteringMode) {
if(typeof(tolerance) == 'undefined') { tolerance = 5; }
var actual = new Uint8Array(actualWidth * actualHeight * 4);
gl.readPixels(
0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
var div = document.createElement("div");
div.className = "testimages";
insertImg(div, "expected", makeImage(
actualWidth, actualHeight, dataWidth, expectedData,
actualChannels == 4));
insertImg(div, "actual", makeImage(
actualWidth, actualHeight, actualWidth, actual,
actualChannels == 4));
div.appendChild(document.createElement('br'));
document.getElementById("console").appendChild(div);
var failed = false;
for (var yy = 0; yy < actualHeight; ++yy) {
for (var xx = 0; xx < actualWidth; ++xx) {
var actualOffset = (yy * actualWidth + xx) * 4;
var expectedOffset = (yy * dataWidth + xx) * 4;
var expected = [
expectedData[expectedOffset + 0],
expectedData[expectedOffset + 1],
expectedData[expectedOffset + 2],
(actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
];
for (var jj = 0; jj < 4; ++jj) {
if (Math.abs(actual[actualOffset + jj] - expected[jj]) > tolerance) {
failed = true;
var was = actual[actualOffset + 0].toString();
for (j = 1; j < 4; ++j) {
was += "," + actual[actualOffset + j];
}
testFailed('at (' + xx + ', ' + yy +
') expected: ' + expected + ' was ' + was);
}
}
}
}
if (!failed) {
testPassed("texture rendered correctly with " + filteringMode + " filtering");
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -33,6 +33,7 @@
<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/compressed-texture-utils.js"></script>
</head>
<body>
<div id="description"></div>
@ -42,25 +43,42 @@
description("This test verifies the functionality of the WEBGL_compressed_texture_etc extension, if it is available.");
debug("");
var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
var COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
var COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
var COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
var COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
var COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
var ETC1_RGB8_OES = 0x8D64;
var COMPRESSED_R11_EAC = 0x9270;
var COMPRESSED_SIGNED_R11_EAC = 0x9271;
var COMPRESSED_RG11_EAC = 0x9272;
var COMPRESSED_SIGNED_RG11_EAC = 0x9273;
var COMPRESSED_RGB8_ETC2 = 0x9274;
var COMPRESSED_SRGB8_ETC2 = 0x9275;
var COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276;
var COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277;
var COMPRESSED_RGBA8_ETC2_EAC = 0x9278;
var COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279;
var validFormats = {
COMPRESSED_R11_EAC : 0x9270,
COMPRESSED_SIGNED_R11_EAC : 0x9271,
COMPRESSED_RG11_EAC : 0x9272,
COMPRESSED_SIGNED_RG11_EAC : 0x9273,
COMPRESSED_RGB8_ETC2 : 0x9274,
COMPRESSED_SRGB8_ETC2 : 0x9275,
COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9276,
COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9277,
COMPRESSED_RGBA8_ETC2_EAC : 0x9278,
COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : 0x9279
};
function expectedByteLength(width, height, format) {
var blockSizeInBytes = 8;
var largerBlockFormats = [
validFormats.COMPRESSED_RG11_EAC,
validFormats.COMPRESSED_SIGNED_RG11_EAC,
validFormats.COMPRESSED_RGBA8_ETC2_EAC,
validFormats.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC];
if (largerBlockFormats.indexOf(format) >= 0) {
blockSizeInBytes = 16;
}
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * blockSizeInBytes;
}
function getBlockDimensions(format) {
return {width: 4, height: 4};
}
var wtu = WebGLTestUtils;
var ctu = CompressedTextureUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var gl = wtu.create3DContext();
var WEBGL_compressed_texture_etc;
@ -73,84 +91,49 @@ function runTest() {
} else {
testPassed("context exists");
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
var haveExt = gl.getSupportedExtensions().indexOf("WEBGL_compressed_texture_etc") >= 0;
WEBGL_compressed_texture_etc = gl.getExtension("WEBGL_compressed_texture_etc");
var isPositive = true;
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_etc", WEBGL_compressed_texture_etc !== null);
if (haveExt) {
if (WEBGL_compressed_texture_etc !== null) {
testPassed("WEBGL_compressed_texture_etc listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_compressed_texture_etc listed as supported but getExtension failed");
return;
}
} else {
if (WEBGL_compressed_texture_etc !== null) {
testFailed("WEBGL_compressed_texture_etc listed as unsupported but getExtension succeeded");
return;
} else {
testPassed("No WEBGL_compressed_texture_etc support -- this is legal");
isPositive = false;
}
}
var isPositive = WEBGL_compressed_texture_etc !== null;
if (isPositive) {
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_R11_EAC", "0x9270");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_SIGNED_R11_EAC", "0x9271");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_RG11_EAC", "0x9272");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_SIGNED_RG11_EAC", "0x9273");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_RGB8_ETC2", "0x9274");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_ETC2", "0x9275");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", "0x9276");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", "0x9277");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_RGBA8_ETC2_EAC", "0x9278");
shouldBe("WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", "0x9279");
// Test that enum values are listed correctly in supported formats and in the extension object.
ctu.testCompressedFormatsListed(gl, validFormats);
ctu.testCorrectEnumValuesInExt(WEBGL_compressed_texture_etc, validFormats);
// Test that texture upload buffer size is validated correctly.
ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
for (var name in validFormats) {
if (validFormats.hasOwnProperty(name)) {
var format = validFormats[name];
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, " + format + ", 4, 4, 0, new Uint8Array(" + expectedByteLength(4, 4, format) + "))");
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, " + format + ", new Uint8Array(" + expectedByteLength(4, 4, format) + "))");
}
}
}
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 0, new Uint8Array(16))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ETC1_RGB8_OES, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_3D, 0, COMPRESSED_R11_EAC, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexSubImage2D(gl.TEXTURE_3D, 0, 0, 0, 4, 4, COMPRESSED_R11_EAC, new Uint8Array(8))");
var expected = isPositive ? gl.NO_ERROR : gl.INVALID_ENUM;
var expectedSub = isPositive ? gl.NO_ERROR : [gl.INVALID_ENUM, gl.INVALID_OPERATION];
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_R11_EAC, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, expectedSub, "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, COMPRESSED_R11_EAC, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_SIGNED_R11_EAC, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RG11_EAC, 4, 4, 0, new Uint8Array(16))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_SIGNED_RG11_EAC, 4, 4, 0, new Uint8Array(16))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB8_ETC2, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_SRGB8_ETC2, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 0, new Uint8Array(16))");
wtu.shouldGenerateGLError(gl, expected, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 4, 0, new Uint8Array(16))");
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)");
shouldBeNonNull("formats");
shouldBe("formats.length", isPositive ? "10" : "0");
var tex2 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex2);
debug("");
if (contextVersion >= 2) {
var expectedError = isPositive ? gl.INVALID_OPERATION: [gl.INVALID_ENUM, gl.INVALID_OPERATION];
// `null` coerces into `0` for the PBO entrypoint, yielding INVALID_OP due to no PBO bound.
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_R11_EAC, 4, 4, 0, 0, null)");
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, COMPRESSED_R11_EAC, 0, null)");
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, COMPRESSED_R11_EAC, 4, 4, 4, 0, 0, null)");
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, COMPRESSED_R11_EAC, 0, null)");
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 0, 0, null)");
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, 0, null)");
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 4, 0, 0, null)");
wtu.shouldGenerateGLError(gl, expectedError, "gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, 0, null)");
} else {
shouldThrow("gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_R11_EAC, 4, 4, 0, null)");
shouldThrow("gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, COMPRESSED_R11_EAC, null)");
shouldThrow("gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, COMPRESSED_R11_EAC, 4, 4, 4, 0, null)");
shouldThrow("gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, COMPRESSED_R11_EAC, null)");
shouldThrow("gl.compressedTexImage2D(gl.TEXTURE_2D, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 0, null)");
shouldThrow("gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, null)");
shouldThrow("gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, validFormats.COMPRESSED_R11_EAC, 4, 4, 4, 0, null)");
shouldThrow("gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, validFormats.COMPRESSED_R11_EAC, null)");
}
}
}

View File

@ -0,0 +1,95 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_compressed_texture_etc1 Conformance Tests</title>
<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/compressed-texture-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("This test verifies the functionality of the WEBGL_compressed_texture_etc1 extension, if it is available.");
debug("");
var validFormats = {
COMPRESSED_RGB_ETC1_WEBGL: 0x8D64,
};
function expectedByteLength(width, height, format) {
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
}
function getBlockDimensions(format) {
return {width: 4, height: 4};
}
var wtu = WebGLTestUtils;
var ctu = CompressedTextureUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var gl = wtu.create3DContext();
var WEBGL_compressed_texture_etc1;
var formats = null;
function runTest() {
if (!gl) {
testFailed("context does not exist");
} else {
testPassed("context exists");
ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
WEBGL_compressed_texture_etc1 = gl.getExtension("WEBGL_compressed_texture_etc1");
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_etc1", WEBGL_compressed_texture_etc1 !== null);
if (WEBGL_compressed_texture_etc1 !== null) {
// Test that enum values are listed correctly in supported formats and in the extension object.
ctu.testCompressedFormatsListed(gl, validFormats);
ctu.testCorrectEnumValuesInExt(WEBGL_compressed_texture_etc1, validFormats);
// Test that texture upload buffer size is validated correctly.
ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
}
}
}
runTest();
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -32,6 +32,7 @@
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/compressed-texture-utils.js"></script>
<title>WebGL WEBGL_compressed_texture_s3tc_srgb Conformance Tests</title>
<style>
img {
@ -105,6 +106,7 @@ var img_8x8_rgba_dxt5 = new Uint8Array([
]);
var wtu = WebGLTestUtils;
var ctu = CompressedTextureUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});
@ -125,84 +127,40 @@ if (!gl) {
} else {
testPassed("WebGL context exists");
// Run tests with extension disabled
runTestDisabled();
ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
// Query the extension and store globally so shouldBe can access it
ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_s3tc_srgb");
if (!ext) {
testPassed("No WEBGL_compressed_texture_s3tc_srgb support -- this is legal");
runSupportedTest(false);
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc_srgb", false);
} else {
testPassed("Successfully enabled WEBGL_compressed_texture_s3tc_srgb extension");
runSupportedTest(true);
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc_srgb", true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_s3tc_srgb");
if (name !== undefined) {
if (extensionEnabled) {
testPassed("WEBGL_compressed_texture_s3tc_srgb listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_compressed_texture_s3tc_srgb listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_compressed_texture_s3tc_srgb not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_compressed_texture_s3tc_srgb not listed as supported and getExtension failed -- this is legal");
}
function expectedByteLength(width, height, format) {
if (format == validFormats.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || format == validFormats.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
}
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
}
function runTestDisabled() {
debug("Testing binding enum with extension disabled");
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
shouldBe("supportedFormats", "[]");
}
function formatExists(format, supportedFormats) {
for (var ii = 0; ii < supportedFormats.length; ++ii) {
if (format == supportedFormats[ii]) {
testPassed("supported format " + formatToString(format) + " is exists");
return;
}
}
testFailed("supported format " + formatToString(format) + " does not exist");
}
function formatToString(format) {
for (var p in ext) {
if (ext[p] == format) {
return p;
}
}
return "0x" + format.toString(16);
function getBlockDimensions(format) {
return {width: 4, height: 4};
}
function runTestExtension() {
debug("Testing WEBGL_compressed_texture_s3tc_srgb");
// check that all format enums exist.
for (name in validFormats) {
var expected = "0x" + validFormats[name].toString(16);
var actual = "ext['" + name + "']";
shouldBe(actual, expected);
}
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
// There should be exactly 4 formats for both WebGL 1.0 and WebGL 2.0.
shouldBe("supportedFormats.length", "4");
// check that all 4 formats exist
for (var name in validFormats.length) {
formatExists(validFormats[name], supportedFormats);
}
// Test that enum values are listed correctly in supported formats and in the extension object.
ctu.testCompressedFormatsListed(gl, validFormats);
ctu.testCorrectEnumValuesInExt(ext, validFormats);
// Test that texture upload buffer size is validated correctly.
ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
// Test each format
testDXT1_SRGB();
@ -466,7 +424,7 @@ function testDXTTexture(test, useTexStorage) {
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
debug("testing " + formatToString(format) + " " + width + "x" + height +
debug("testing " + ctu.formatToString(ext, format) + " " + width + "x" + height +
(useTexStorage ? " via texStorage2D" : " via compressedTexImage2D"));
var tex = gl.createTexture();
@ -612,35 +570,6 @@ function testDXTTexture(test, useTexStorage) {
}
}
function insertImg(element, caption, img) {
var div = document.createElement("div");
div.appendChild(img);
var label = document.createElement("div");
label.appendChild(document.createTextNode(caption));
div.appendChild(label);
element.appendChild(div);
}
function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
var scale = 8;
var c = document.createElement("canvas");
c.width = imageWidth * scale;
c.height = imageHeight * scale;
var ctx = c.getContext("2d");
for (var yy = 0; yy < imageHeight; ++yy) {
for (var xx = 0; xx < imageWidth; ++xx) {
var offset = (yy * dataWidth + xx) * 4;
ctx.fillStyle = "rgba(" +
data[offset + 0] + "," +
data[offset + 1] + "," +
data[offset + 2] + "," +
(alpha ? data[offset + 3] / 255 : 1) + ")";
ctx.fillRect(xx * scale, yy * scale, scale, scale);
}
}
return wtu.makeImageFromCanvas(c);
}
// See EXT_texture_sRGB, Section 3.8.x, sRGB Texture Color Conversion.
function sRGBChannelToLinear(value) {
value = value / 255;
@ -663,10 +592,10 @@ function compareRect(
var div = document.createElement("div");
div.className = "testimages";
insertImg(div, "expected", makeImage(
ctu.insertCaptionedImg(div, "expected", ctu.makeScaledImage(
actualWidth, actualHeight, dataWidth, expectedData,
actualChannels == 4));
insertImg(div, "actual", makeImage(
ctu.insertCaptionedImg(div, "actual", ctu.makeScaledImage(
actualWidth, actualHeight, actualWidth, actual,
actualChannels == 4));
div.appendChild(document.createElement('br'));

View File

@ -32,6 +32,7 @@
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/compressed-texture-utils.js"></script>
<title>WebGL WEBGL_compressed_texture_s3tc Conformance Tests</title>
<style>
img {
@ -93,6 +94,7 @@ var img_8x8_rgba_dxt5 = new Uint8Array([
]);
var wtu = WebGLTestUtils;
var ctu = CompressedTextureUtils;
var contextVersion = wtu.getDefault3DContextVersion();
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});
@ -114,83 +116,41 @@ if (!gl) {
testPassed("WebGL context exists");
// Run tests with extension disabled
runTestDisabled();
ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4);
// Query the extension and store globally so shouldBe can access it
ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_s3tc");
if (!ext) {
testPassed("No WEBGL_compressed_texture_s3tc support -- this is legal");
runSupportedTest(false);
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc", false);
} else {
testPassed("Successfully enabled WEBGL_compressed_texture_s3tc extension");
runSupportedTest(true);
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc", true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_s3tc");
if (name !== undefined) {
if (extensionEnabled) {
testPassed("WEBGL_compressed_texture_s3tc listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_compressed_texture_s3tc listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_compressed_texture_s3tc not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_compressed_texture_s3tc not listed as supported and getExtension failed -- this is legal");
}
function expectedByteLength(width, height, format) {
if (format == validFormats.COMPRESSED_RGBA_S3TC_DXT3_EXT || format == validFormats.COMPRESSED_RGBA_S3TC_DXT5_EXT) {
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
}
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
}
function runTestDisabled() {
debug("Testing binding enum with extension disabled");
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
shouldBe("supportedFormats", "[]");
}
function formatExists(format, supportedFormats) {
for (var ii = 0; ii < supportedFormats.length; ++ii) {
if (format == supportedFormats[ii]) {
testPassed("supported format " + formatToString(format) + " is exists");
return;
}
}
testFailed("supported format " + formatToString(format) + " does not exist");
}
function formatToString(format) {
for (var p in ext) {
if (ext[p] == format) {
return p;
}
}
return "0x" + format.toString(16);
function getBlockDimensions(format) {
return {width: 4, height: 4};
}
function runTestExtension() {
debug("");
debug("Testing WEBGL_compressed_texture_s3tc");
// check that all format enums exist.
for (name in validFormats) {
var expected = "0x" + validFormats[name].toString(16);
var actual = "ext['" + name + "']";
shouldBe(actual, expected);
}
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
// There should be exactly 4 formats for both WebGL 1.0 and WebGL 2.0.
shouldBe("supportedFormats.length", "4");
// check that all 4 formats exist
for (var name in validFormats.length) {
formatExists(validFormats[name], supportedFormats);
}
// Test that enum values are listed correctly in supported formats and in the extension object.
ctu.testCompressedFormatsListed(gl, validFormats);
ctu.testCorrectEnumValuesInExt(ext, validFormats);
// Test that texture upload buffer size is validated correctly.
ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions);
// Test each format
testDXT1_RGB();
@ -487,7 +447,7 @@ function testDXTTexture(test, useTexStorage) {
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
debug("testing " + formatToString(format) + " " + width + "x" + height +
debug("testing " + ctu.formatToString(ext, format) + " " + width + "x" + height +
(useTexStorage ? " via texStorage2D" : " via compressedTexImage2D"));
var tex = gl.createTexture();
@ -552,15 +512,6 @@ function testDXTTexture(test, useTexStorage) {
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
@ -658,35 +609,6 @@ function testDXTTexture(test, useTexStorage) {
}
}
function insertImg(element, caption, img) {
var div = document.createElement("div");
div.appendChild(img);
var label = document.createElement("div");
label.appendChild(document.createTextNode(caption));
div.appendChild(label);
element.appendChild(div);
}
function makeImage(imageWidth, imageHeight, data, alpha) {
var scale = 8;
var c = document.createElement("canvas");
c.width = imageWidth * scale;
c.height = imageHeight * scale;
var ctx = c.getContext("2d");
for (var yy = 0; yy < imageHeight; ++yy) {
for (var xx = 0; xx < imageWidth; ++xx) {
var offset = (yy * imageWidth + xx) * 4;
ctx.fillStyle = "rgba(" +
data[offset + 0] + "," +
data[offset + 1] + "," +
data[offset + 2] + "," +
(alpha ? data[offset + 3] / 255 : 1) + ")";
ctx.fillRect(xx * scale, yy * scale, scale, scale);
}
}
return wtu.makeImageFromCanvas(c);
}
function compareRect(width, height, channels, expectedData, filteringMode) {
var actual = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, actual);
@ -694,8 +616,8 @@ function compareRect(width, height, channels, expectedData, filteringMode) {
var div = document.createElement("div");
div.className = "testimages";
insertImg(div, "expected", makeImage(width, height, expectedData, channels == 4));
insertImg(div, "actual", makeImage(width, height, actual, channels == 4));
ctu.insertCaptionedImg(div, "expected", ctu.makeScaledImage(width, height, width, expectedData, channels == 4));
ctu.insertCaptionedImg(div, "actual", ctu.makeScaledImage(width, height, width, actual, channels == 4));
div.appendChild(document.createElement('br'));
document.getElementById("console").appendChild(div);

View File

@ -1,861 +0,0 @@
<!--
/*
** Copyright (c) 2013 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">
<title>WebGL WEBGL_Shared_Resources Conformance Test</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</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 vec4 u_color;
void main() {
gl_FragColor = u_color;
}
</script>
<style>
canvas {
border: 1px solid black;
}
</style>
<canvas id="canvas1" width="64" height="64"> </canvas>
<canvas id="canvas2" width="64" height="64"> </canvas>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description();
var wtu = WebGLTestUtils;
var shouldGenerateGLError = wtu.shouldGenerateGLError;
var canvas1 = document.getElementById("canvas1");
var gl = wtu.create3DContext(canvas1);
var gl2;
var ext = null;
var ext2;
var ext3;
var buf;
var elementBuf;
var tex;
var tex3;
var rb;
var fb;
var id;
var resource;
var shader;
var program;
var uniformLocation;
var acquiredFlag;
var shaderProgram; // acquired progam (never released) used for shader testing
var programShader; // acquired shader (never released) used for program testing
if (!gl) {
testFailed("context does not exist");
} else {
testPassed("context exists");
// Run tests with extension disabled
runTestDisabled();
// Query the extension and store globally so shouldBe can access it
ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_shared_resources");
if (!ext) {
testPassed("No WEBGL_shared_resources support -- this is legal");
runSupportedTest(false);
finishTest();
} else {
testPassed("Successfully enabled WEBGL_shared_resources extension");
runSupportedTest(true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_shared_resources");
if (name !== undefined) {
if (extensionEnabled) {
testPassed("WEBGL_shared_resources listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_shared_resources listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_shared_resources not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_shared_resources not listed as supported and getExtension failed -- this is legal");
}
}
}
function runTestDisabled() {
// There is no functionality accessable with this extension disabled.
}
function makeFailCallback(msg) {
return function() {
testFailed(msg);
}
};
function runTestExtension() {
var canvas2 = document.getElementById("canvas2");
gl2 = wtu.create3DContext(canvas2, { group: ext.group });
ext2 = wtu.getExtensionWithKnownPrefixes(gl2, "WEBGL_shared_resources");
// Runs an array of functions. Expects each function takes a callback
// it will call when finished.
var runSequence = function(steps) {
var stepNdx = 0;
var runNextStep = function() {
if (stepNdx < steps.length) {
steps[stepNdx++](runNextStep);
}
};
runNextStep();
};
var bufferTests = {
resourceType: "buffer",
setupFunction: function() {
buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, 16, gl.STATIC_DRAW);
return buf;
},
bindFunction: function(buf) {
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
},
implicitBindFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0)");
},
modificationFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.bufferData(gl.ARRAY_BUFFER, 16, gl.STATIC_DRAW)");
shouldGenerateGLError(gl, expectedError, "gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Uint8Array(4))");
},
queryFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)");
},
};
var programTests = {
resourceType: "program",
setupFunction: function() {
// We need a valid a program with valid shaders to share because the only way to 'bind'
// a program is to call gl.useProgram and you can't call gl.useProgram on an invalid program.
program = wtu.setupProgram(gl, ["vshader", "fshader"]);
programShader = gl.getAttachedShaders(program)[0];
uniformLocation = gl.getUniformLocation(program, "u_color");
return program;
},
bindFunction: function(program) {
gl.useProgram(program);
},
implicitBindFunctions: function(expectedError) {
},
modificationFunctions: function(expectedError) {
if (expectedError == gl.NO_ERROR) {
// Need to get a new location because we may have re-linked.
uniformLocation = gl.getUniformLocation(program, 'u_color');
}
shouldGenerateGLError(gl, expectedError, "gl.uniform4f(uniformLocation, 0, 1, 2, 3)");
shouldGenerateGLError(gl, expectedError, "gl.detachShader(program, programShader)");
shouldGenerateGLError(gl, expectedError, "gl.attachShader(program, programShader)");
shouldGenerateGLError(gl, expectedError, "gl.bindAttribLocation(program, 0, 'foo')");
shouldGenerateGLError(gl, expectedError, "gl.linkProgram(program)");
},
queryFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.getProgramParameter(program, gl.LINK_STATUS)");
shouldGenerateGLError(gl, expectedError, "gl.getProgramInfoLog(program)");
shouldGenerateGLError(gl, expectedError, "gl.getAttachedShaders(program)");
shouldGenerateGLError(gl, expectedError, "gl.getAttribLocation(program, 'foo')");
shouldGenerateGLError(gl, expectedError, "gl.getUniformLocation(program, 'foo')");
shouldGenerateGLError(gl, expectedError, "gl.getActiveAttrib(program, 0)");
shouldGenerateGLError(gl, expectedError, "gl.getActiveUniform(program, 0)");
shouldGenerateGLError(gl, expectedError, "gl.getUniform(program, uniformLocation)");
},
};
var renderbufferTests = {
resourceType: "renderbuffer",
setupFunction: function() {
rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
fb = gl.createFramebuffer();
return rb;
},
bindFunction: function(rb) {
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
},
implicitBindFunctions: function(expectedError) {
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
shouldGenerateGLError(gl, expectedError, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb)");
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
},
modificationFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
},
queryFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)");
},
};
var shaderTests = {
resourceType: "shader",
setupFunction: function() {
var shaderSource = "Hello World";
shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, shaderSource);
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, shader);
return shader;
},
bindFunction: function(shader) {
gl.detachShader(shaderProgram, shader); // you can't attach if a shader is already attached.
gl.attachShader(shaderProgram, shader);
},
implicitBindFunctions: function(expectedError) {
},
modificationFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.shaderSource(shader, 'foo')");
shouldGenerateGLError(gl, expectedError, "gl.compileShader(shader)");
},
queryFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.getShaderParameter(shader, gl.COMPILE_STATUS)");
shouldGenerateGLError(gl, expectedError, "gl.getShaderInfoLog(shader)");
},
};
var textureTests = {
resourceType: "texture",
setupFunction: function() {
tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
return tex;
},
bindFunction: function(tex) {
gl.bindTexture(gl.TEXTURE_2D, tex);
},
implicitBindFunctions: function(expectedError) {
},
modificationFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)");
shouldGenerateGLError(gl, expectedError, "gl.generateMipmap(gl.TEXTURE_2D)");
shouldGenerateGLError(gl, expectedError, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
shouldGenerateGLError(gl, expectedError, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
shouldGenerateGLError(gl, expectedError, "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 16, 16, 0)");
shouldGenerateGLError(gl, expectedError, "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16)");
// TODO: Add compressed texture test if extension exists?
},
queryFunctions: function(expectedError) {
shouldGenerateGLError(gl, expectedError, "gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)");
},
};
var testResourceWithSingleContext = function(info, callback) {
var resourceType = info.resourceType;
debug("")
debug("test " + resourceType);
var resource = info.setupFunction();
ext.releaseSharedResource(resource);
debug("");
debug("test " + resourceType + " functions can not be called on released " + resourceType);
info.modificationFunctions(gl.INVALID_OPERATION);
info.implicitBindFunctions(gl.INVALID_OPERATION);
info.queryFunctions(gl.INVALID_OPERATION);
debug("");
debug("test acquring " + resourceType);
ext.acquireSharedResource(resource, ext.READ_ONLY, function() {
debug("");
debug("test " + resourceType + " functions can not be called on READ_ONLY acquired " + resourceType + " that has not been bound");
info.queryFunctions(gl.INVALID_OPERATION);
info.modificationFunctions(gl.INVALID_OPERATION);
debug("");
debug("test query " + resourceType + " functions can be called on READ_ONLY acquired " + resourceType + " that has been bound but not " + resourceType + " modification functions");
info.bindFunction(resource);
info.queryFunctions(gl.NO_ERROR);
info.modificationFunctions(gl.INVALID_OPERATION);
ext.releaseSharedResource(resource);
ext.acquireSharedResource(resource, ext.EXCLUSIVE, function() {
debug("");
debug("test " + resourceType + " functions can not be called on EXCLUSIVE acquired " + resourceType + " that has not been bound");
info.queryFunctions(gl.INVALID_OPERATION);
info.modificationFunctions(gl.INVALID_OPERATION);
debug("");
debug("test all " + resourceType + " functions can be called on EXCLUSIVE acquired " + resourceType + " that has been bound.");
info.bindFunction(resource)
info.queryFunctions(gl.NO_ERROR);
info.modificationFunctions(gl.NO_ERROR);
callback();
});
});
};
var makeSingleContextResourceTest = function(info) {
return function(callback) {
testResourceWithSingleContext(info, callback);
};
};
var testCommonResourceFeatures = function(info, callback) {
var type = info.resourceType.charAt(0).toUpperCase() + info.resourceType.slice(1);
acquiredFlag = false;
debug("");
debug("test common features of " + type);
resource = info.setupFunction();
info.bindFunction(resource);
debug("Test a deleted resource can still be acquired.");
var checkAcquireAfterDelete = function() {
debug("check Acquire After Delete");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)");
// TODO: fix spec then comment this in shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bind" + type + "(gl." + target + ", resource)"); // You can't bind a deleted resource
shouldGenerateGLError(gl, gl.NO_ERROR, "ext.releaseSharedResource(resource)");
callback();
};
var checkDeleteExclusive = function() {
debug("check delete EXLUSIVE");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)");
info.bindFunction(resource);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error deleting exclusively acquired resource");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.delete" + type + "(resource)");
ext.releaseSharedResource(resource);
ext.acquireSharedResource(resource, ext.EXCLUSIVE, checkAcquireAfterDelete);
};
var checkDeleteReadOnly = function() {
acquiredFlag = true;
debug("check delete READ_ONLY");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)");
info.bindFunction(resource);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error bind read only acquired resource");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)"); // We're READ_ONLY so this should fail
ext.releaseSharedResource(resource);
ext.acquireSharedResource(resource, ext.EXCLUSIVE, checkDeleteExclusive);
};
debug("Test you can't have 2 outstanding requests for the same resource.");
ext.releaseSharedResource(resource);
ext.acquireSharedResource(resource, ext.READ_ONLY, checkDeleteReadOnly);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error from 1st acquire request");
ext.acquireSharedResource(resource, ext.READ_ONLY, checkDeleteReadOnly);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should be INVALID_OPERATION from 2nd acquire request");
debug("Test acquire does not happen immediately on release (must exit current event)");
shouldBeTrue("acquiredFlag === false");
};
var makeCommonResourceFeatureTest = function(info) {
return function(callback) {
testCommonResourceFeatures(info, callback);
};
};
// acquire multiple resources in multiple contexts.
var acquireMultipleResources = function(extensions, resources, mode, callback) {
var numNeeded = resources.length * extensions.length;
var checkAcquire = function() {
--numNeeded;
if (numNeeded == 0) {
callback();
}
};
resources.forEach(function(resource) {
extensions.forEach(function(ext) {
ext.acquireSharedResource(resource, mode, checkAcquire);
});
});
};
// release multiple resources in multiple contexts.
var releaseMultipleResources = function(extensions, resources) {
resources.forEach(function(resource) {
extensions.forEach(function(ext) {
ext.releaseSharedResource(resource);
});
});
};
var testRendering = function(callback) {
debug("");
debug("test rendering");
var positionLocation = 0;
var texcoordLocation = 1;
var program = wtu.setupSimpleTextureProgram(gl, positionLocation, texcoordLocation);
var buffers = wtu.setupUnitQuad(gl, positionLocation, texcoordLocation);
var rb = gl.createRenderbuffer();
var fb = gl.createFramebuffer();
var elementBuf = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 3, 4, 5]), gl.STATIC_DRAW);
var width = 16;
var height = 16;
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height);
var destTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, destTex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
// It's not clear if gl.RGBA4 must be framebuffer complete.
var canCheckRenderbuffer = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, destTex, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE");
var tex = gl.createTexture();
wtu.fillTexture(gl, tex, 1, 1, [0, 255, 0, 255]);
if (!program) {
testFailed("could not link program");
callback();
return;
}
var releaseAndAcquireResources = function(callback) {
var resources = [buffers[0], buffers[1], tex, program, elementBuf];
releaseMultipleResources([ext], resources);
acquireMultipleResources([ext, ext2], resources, ext.READ_ONLY, callback);
};
var doRenderTest = function(callback) {
debug("Test 2 contexts can render with read only resources.");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[1]);
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
gl.bindTexture(gl.TEXTURE_2D, tex);
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
gl.useProgram(program);
// Render to canvas1;
debug("render with context 1");
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 0, 0, 0]);
wtu.drawUnitQuad(gl);
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255]);
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuf);
gl.clear(gl.COLOR_BUFFER_BIT);
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)");
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255]);
// Render to canvas2;
debug("render with context 2");
gl2.useProgram(program);
gl2.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
gl2.enableVertexAttribArray(positionLocation);
gl2.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl2.bindBuffer(gl.ARRAY_BUFFER, buffers[1]);
gl2.enableVertexAttribArray(texcoordLocation);
gl2.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0);
gl2.bindTexture(gl.TEXTURE_2D, tex);
wtu.checkCanvas(gl2, [0, 0, 0, 0]);
wtu.drawUnitQuad(gl2);
wtu.checkCanvas(gl2, [0, 255, 0, 255]);
shouldGenerateGLError(gl2, gl2.INVALID_OPERATION, "gl2.drawElements(gl2.TRIANGLES, 6, gl2.UNSIGNED_SHORT, 0)");
gl2.bindBuffer(gl2.ELEMENT_ARRAY_BUFFER, elementBuf);
gl2.clear(gl2.COLOR_BUFFER_BIT);
shouldGenerateGLError(gl2, gl2.NO_ERROR, "gl2.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)");
wtu.checkCanvas(gl2, [0, 255, 0, 255]);
debug("Test you can't render to a framebuffer with a released texture");
ext.releaseSharedResource(destTex);
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)");
debug("Test you can't read from a framebuffer with a released texture");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
ext.acquireSharedResource(destTex, ext.READ_ONLY, callback);
};
var checkReadOnlyTextureOnFramebuffer = function(callback) {
debug("");
debug("test READ_ONLY texture attachment");
debug("Test we fail of we haven't bound again");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, destTex);
gl.activeTexture(gl.TEXTURE0);
debug("Test we fail to draw because we're read only.");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)");
debug("Test we can read a READ_ONLY texture.");
shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
checkRenderbuffer(callback);
};
var checkRenderbuffer = function(callback) {
if (canCheckRenderbuffer) {
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
wtu.drawUnitQuad(gl);
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255]);
debug("Test you can't render to a framebuffer with a released renderbuffer");
ext.releaseSharedResource(rb);
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)");
debug("Test you can't read from a framebuffer with a released renderbuffer");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
}
ext.acquireSharedResource(rb, ext.READ_ONLY, callback);
};
var checkReadOnlyRenderbufferOnFramebuffer = function(callback) {
if (canCheckRenderbuffer) {
debug("");
debug("test READ_ONLY renderbuffer attachment");
debug("Test we fail of we haven't bound again");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
debug("Test we fail to draw because we're read only.");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
debug("Test we can read a READ_ONLY renderbuffer.");
shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
}
ext.releaseSharedResource(rb);
ext.acquireSharedResource(rb, ext.READ_ONLY, callback);
};
var checkRenderbufferBindsOnAttach = function(callback) {
if (canCheckRenderbuffer) {
debug("");
debug("Test we fail of we haven't bound again");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
debug("Test attaching a renderbuffer marks it as bound");
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
debug("Test we can read a READ_ONLY renderbuffer.");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
}
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, destTex, 0);
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
ext.releaseSharedResource(destTex);
ext.acquireSharedResource(destTex, ext.READ_ONLY, callback);
};
var checkTextureBindsOnAttach = function(callback) {
debug("");
debug("Test we fail of we haven't bound again");
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
debug("Test attaching a texture marks it as bound");
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, destTex, 0);
debug("Test we can read a READ_ONLY texture.");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))");
callback();
};
var checkCanNotRenderWithReleasedProgram = function(callback) {
debug("");
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
ext.releaseSharedResource(program);
debug("Test we can't draw with a released program.");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
ext.acquireSharedResource(program, ext.EXCLUSIVE, callback);
ext2.releaseSharedResource(program);
};
var checkCanNotRenderWithReleasedBuffer = function(callback) {
debug("");
gl.useProgram(program);
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
ext.releaseSharedResource(buffers[0]);
debug("Test we can't draw with a released buffer.");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
ext.acquireSharedResource(buffers[0], ext.READ_ONLY, callback);
};
var checkCanNotRenderWithReleasedTexture = function(callback) {
debug("");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
ext.releaseSharedResource(tex);
debug("Test we can't draw with a released texture.");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
ext.acquireSharedResource(tex, ext.READ_ONLY, callback);
};
var checkCanRenderWithReleasedShader = function(callback) {
gl.bindTexture(gl.TEXTURE_2D, tex);
var shaders = gl.getAttachedShaders(program);
ext.releaseSharedResource(shaders[0]);
debug("");
debug("Test we can draw with a released shader.");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)");
callback();
};
runSequence(
[
releaseAndAcquireResources,
doRenderTest,
checkReadOnlyTextureOnFramebuffer,
checkReadOnlyRenderbufferOnFramebuffer,
checkRenderbufferBindsOnAttach,
checkTextureBindsOnAttach,
checkCanNotRenderWithReleasedProgram,
checkCanNotRenderWithReleasedBuffer,
checkCanNotRenderWithReleasedTexture,
checkCanRenderWithReleasedShader,
callback,
]);
};
var testMisc = function(callback) {
debug("");
debug("Test you can't release a framebuffer");
// TODO: It's not clear what should happen here to me.
//shouldThrow("ext.releaseSharedResource(fb)", "TypeError");
debug("")
debug("Test you can compare sharegroups");
var gl3 = wtu.create3DContext();
ext3 = wtu.getExtensionWithKnownPrefixes(gl3, "WEBGL_shared_resources");
// TODO: comment in once this comparison works.
//shouldBeTrue("ext.group == ext2.group");
shouldBeTrue("ext.group != ext3.group");
debug("Test you can't use resources from another different group.");
tex3 = gl3.createTexture();
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.releaseSharedResource(tex3)");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.acquireSharedResource(tex3, ext.READ_ONLY, makeFailCallback('should not be able to acquire resource from other context'))");
var failTest = function() {
testFailed("cancelled callback was called");
};
var tex = gl.createTexture();
debug("test releasing from the wrong context. Should be a no-op");
shouldGenerateGLError(gl, gl.NO_ERROR, "ext2.releaseSharedResource(tex)");
id = ext2.acquireSharedResource(tex, ext.READ_ONLY, failTest);
debug("test cancelling a request for which an event has not been posted");
ext2.cancelAcquireSharedResource(id);
debug("test cancelling a request for which an event has already been posted");
ext.releaseSharedResource(tex);
id = ext.acquireSharedResource(tex, ext.READ_ONLY, failTest);
ext.cancelAcquireSharedResource(id);
debug("test cancelling on the wrong context's extension is ignored");
id = ext2.acquireSharedResource(tex, ext.READ_ONLY, callback);
shouldGenerateGLError(gl, gl.NO_ERROR, 'ext.cancelAcquireSharedResource(id)');
};
var testLostContext = function(callback) {
var WEBGL_lose_context = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_lose_context");
if (!WEBGL_lose_context) {
callback();
return;
}
var tex = gl.createTexture();
var tex2 = gl.createTexture();
var setupAcquire = function(callback) {
var callbacksNeeded = 3;
var waitForContextLostAndAcquire = function(e) {
if (e && e.preventDefault) {
e.preventDefault(); // allow context restore.
}
--callbacksNeeded;
if (callbacksNeeded == 0) {
callback();
}
return false;
};
debug("");
debug("Test extension still functions during context lost.");
acquireMultipleResources([ext2], [tex, tex2], ext2.READ_ONLY, waitForContextLostAndAcquire);
canvas1.addEventListener("webglcontextlost", waitForContextLostAndAcquire, false);
canvas2.addEventListener("webglcontextlost", waitForContextLostAndAcquire, false);
// Release one before context lost
ext.releaseSharedResource(tex);
WEBGL_lose_context.loseContext();
// Release one after context lost
ext.releaseSharedResource(tex2);
shouldBeTrue('gl.isContextLost()');
shouldBeTrue('gl2.isContextLost()');
};
var checkAcquireExt2 = function(callback) {
testPassed("was able to acquire resources during context lost");
acquireMultipleResources([ext], [tex, tex2], ext.READ_ONLY, callback);
};
var checkAcquireExt = function(callback) {
testPassed("was able to request acquire resources during context lost");
canvas1.addEventListener("webglcontextrestored", callback, false);
WEBGL_lose_context.restoreContext();
};
var passTest = function(callback) {
testPassed("extension works during lost context");
callback();
};
runSequence(
[
setupAcquire,
checkAcquireExt2,
checkAcquireExt,
passTest,
callback,
]);
};
runSequence(
[
makeCommonResourceFeatureTest(bufferTests),
makeCommonResourceFeatureTest(programTests),
makeCommonResourceFeatureTest(shaderTests),
makeCommonResourceFeatureTest(renderbufferTests),
makeCommonResourceFeatureTest(textureTests),
makeSingleContextResourceTest(bufferTests),
makeSingleContextResourceTest(programTests),
makeSingleContextResourceTest(renderbufferTests),
makeSingleContextResourceTest(shaderTests),
makeSingleContextResourceTest(textureTests),
testRendering,
testMisc,
testLostContext,
finishTest,
]);
}
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -40,6 +40,7 @@
--min-version 1.0.4 sequence-operator-evaluation-order.html
--min-version 1.0.4 sketchfab-lighting-shader-crash.html
--min-version 1.0.4 struct-constructor-highp-bug.html
--min-version 1.0.4 struct-with-single-member-constructor.html
--min-version 1.0.3 temp-expressions-should-not-crash.html
--min-version 1.0.4 unary-minus-operator-float-bug.html
--min-version 1.0.4 undefined-index-should-not-crash.html

View File

@ -0,0 +1,73 @@
<!--
/*
** Copyright (c) 2018 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">
<title>GLSL struct with a single member constructor test</title>
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
<script src="../../../js/js-test-pre.js"></script>
<script src="../../../js/webgl-test-utils.js"></script>
<script src="../../../js/glsl-conformance-test.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script id="fshader" type="x-shader/x-fragment">
#version 100
precision mediump float;
struct S {
mat2 rotation;
};
void main(void)
{
float angle = 1.0;
S(mat2(1.0, angle, 1.0, 1.0));
}
</script>
<script>
"use strict";
description();
debug("This is a regression test for <a href='https://bugs.chromium.org/p/swiftshader/issues/detail?id=56'>Swiftshader bug 56</a>.");
debug("");
GLSLConformanceTester.runTests([
{
fShaderId: 'fshader',
fShaderSuccess: true,
linkSuccess: true,
passMsg: "Construct a struct with a single matrix member"
}
]);
</script>
</body>
</html>

View File

@ -5,6 +5,7 @@ embedded-struct-definitions-forbidden.html
--min-version 1.0.4 empty-declaration.html
empty_main.vert.html
--min-version 1.0.3 expression-list-in-declarator-initializer.html
--min-version 1.0.4 fragcolor-fragdata-invariant.html
gl_position_unset.vert.html
--min-version 1.0.4 global-variable-init.html
# this test is intentionally disabled as it is too strict and to hard to simulate
@ -98,6 +99,8 @@ shader-without-precision.frag.html
--min-version 1.0.3 shaders-with-uniform-structs.html
--min-version 1.0.2 shaders-with-varyings.html
shared.html
--min-version 1.0.4 struct-as-inout-parameter.html
--min-version 1.0.4 struct-as-out-parameter.html
struct-nesting-exceeds-maximum.html
struct-nesting-under-maximum.html
--max-version 1.9.9 uniform-location-length-limits.html

View File

@ -0,0 +1,61 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL GLSL Conformance Tests - gl_FragColor and gl_FragData both declared as invariant</title>
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
<script src="../../../js/js-test-pre.js"></script>
<script src="../../../js/webgl-test-utils.js"></script>
<script src="../../../js/glsl-conformance-test.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script id="fragmentShader" type="text/something-not-javascript">
// Declaring both gl_FragColor and gl_FragData invariant should succeed.
precision mediump float;
// Static write of both gl_FragColor and gl_FragData is disallowed. However, simply declaring a variable invariant is not really accessing the variable, so it should be ok.
invariant gl_FragColor;
invariant gl_FragData;
void main()
{
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
</script>
<script>
"use strict";
GLSLConformanceTester.runTest();
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -0,0 +1,138 @@
<!--
/*
** Copyright (c) 2018 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">
<title>GLSL Structure as Inout Parameter Test</title>
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
<script src="../../../js/js-test-pre.js"></script>
<script src="../../../js/webgl-test-utils.js"> </script>
<script src="../../../js/glsl-conformance-test.js"></script>
<script id="simple-vs" type="x-shader/x-vertex">
attribute vec4 a_position;
void main(void) {
gl_Position = a_position;
}
</script>
<script id="struct-inout-parameter-fs" type="x-shader/x-fragment">
struct ColorData {
vec3 red;
vec3 blue;
};
void modify(inout ColorData colorData) {
colorData.red += vec3(0.5, 0.0, 0.0);
colorData.blue += vec3(0.0, 0.0, 0.5);
}
void main() {
ColorData colorData;
colorData.red = vec3(0.5, 0.0, 0.0);
colorData.blue = vec3(0.0, 0.0, 0.5);
vec3 red = vec3(1.0, 0.0, 0.0);
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 blue = vec3(0.0, 0.0, 1.0);
vec3 finalColor;
modify(colorData);
if (colorData.red == red && colorData.blue == blue)
finalColor = green;
else
finalColor = red;
gl_FragColor = vec4(finalColor, 1.0);
}
</script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("Testing structs as inout parameter");
debug('Regression test for <a href="http://crbug.com/851870">http://crbug.com/851870</a> / <a href="https://github.com/mrdoob/three.js/issues/14137">https://github.com/mrdoob/three.js/issues/14137</a>');
function prepend(floatPrecision) {
let source = document.getElementById('struct-inout-parameter-fs').text;
return 'precision ' + floatPrecision + ' float;\n' + source;
}
let tests = [
{
vShaderId: "simple-vs",
vShaderSuccess: true,
fShaderSource: prepend('lowp'),
fShaderSuccess: true,
linkSuccess: true,
render: true,
passMsg: "lowp struct used as inout parameter",
},
{
vShaderId: "simple-vs",
vShaderSuccess: true,
fShaderSource: prepend('mediump'),
fShaderSuccess: true,
linkSuccess: true,
render: true,
passMsg: "mediump struct used as inout parameter",
},
];
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext();
let precision = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
let highpSupported = (precision.rangeMin >= 62 && precision.rangeMax >= 62 && precision.precision >= 16);
debug("highp is" + (highpSupported ? "" : " not") + " supported in fragment shaders");
if (highpSupported) {
tests.push(
{
vShaderId: "simple-vs",
vShaderSuccess: true,
fShaderSource: prepend('highp'),
fShaderSuccess: true,
linkSuccess: true,
render: true,
passMsg: "highp struct used as inout parameter",
}
);
}
GLSLConformanceTester.runTests(tests);
debug("");
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -0,0 +1,136 @@
<!--
/*
** Copyright (c) 2018 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">
<title>GLSL Structure as Out Parameter Test</title>
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
<script src="../../../js/js-test-pre.js"></script>
<script src="../../../js/webgl-test-utils.js"> </script>
<script src="../../../js/glsl-conformance-test.js"></script>
<script id="simple-vs" type="x-shader/x-vertex">
attribute vec4 a_position;
void main(void) {
gl_Position = a_position;
}
</script>
<script id="struct-out-parameter-fs" type="x-shader/x-fragment">
struct ColorData {
vec3 red;
vec3 blue;
};
void modify(out ColorData colorData) {
colorData.red = vec3(1.0, 0.0, 0.0);
colorData.blue = vec3(0.0, 0.0, 1.0);
}
void main() {
ColorData colorData;
vec3 red = vec3(1.0, 0.0, 0.0);
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 blue = vec3(0.0, 0.0, 1.0);
vec3 finalColor;
modify(colorData);
if (colorData.red == red && colorData.blue == blue)
finalColor = green;
else
finalColor = red;
gl_FragColor = vec4(finalColor, 1.0);
}
</script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("Testing structs as out parameter");
debug('Regression test for <a href="http://crbug.com/851873">http://crbug.com/851873</a> / <a href="https://github.com/mrdoob/three.js/issues/14137">https://github.com/mrdoob/three.js/issues/14137</a>');
function prepend(floatPrecision) {
let source = document.getElementById('struct-out-parameter-fs').text;
return 'precision ' + floatPrecision + ' float;\n' + source;
}
let tests = [
{
vShaderId: "simple-vs",
vShaderSuccess: true,
fShaderSource: prepend('lowp'),
fShaderSuccess: true,
linkSuccess: true,
render: true,
passMsg: "lowp struct used as out parameter",
},
{
vShaderId: "simple-vs",
vShaderSuccess: true,
fShaderSource: prepend('mediump'),
fShaderSuccess: true,
linkSuccess: true,
render: true,
passMsg: "mediump struct used as out parameter",
},
];
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext();
let precision = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
let highpSupported = (precision.rangeMin >= 62 && precision.rangeMax >= 62 && precision.precision >= 16);
debug("highp is" + (highpSupported ? "" : " not") + " supported in fragment shaders");
if (highpSupported) {
tests.push(
{
vShaderId: "simple-vs",
vShaderSuccess: true,
fShaderSource: prepend('highp'),
fShaderSuccess: true,
linkSuccess: true,
render: true,
passMsg: "highp struct used as out parameter",
}
);
}
GLSLConformanceTester.runTests(tests);
debug("");
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -43,13 +43,21 @@
var wtu = WebGLTestUtils;
description("Tests that stencil mask/func are validated correctly when the front state and back state differ.");
var gl = wtu.create3DContext();
var gl;
function testStencilMaskCase(mask, error) {
function checkDrawError(errIfMismatch) {
wtu.shouldGenerateGLError(gl, errIfMismatch, "wtu.dummySetProgramAndDrawNothing(gl)");
}
function setStencilMask(mask) {
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMaskSeparate(gl.FRONT, " + mask[0] + ")");
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMaskSeparate(gl.BACK, " + mask[1] + ")");
}
function testStencilMaskCase(mask, error) {
setStencilMask(mask);
// If an error is generated, it should be at draw time.
wtu.shouldGenerateGLError(gl, error, "wtu.dummySetProgramAndDrawNothing(gl)");
checkDrawError(error);
}
function testStencilMask(errIfMismatch) {
@ -60,11 +68,15 @@ function testStencilMask(errIfMismatch) {
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMask(1023)", "resetting stencilMask");
}
function testStencilFuncCase(ref, mask, error) {
function setStencilFunc(ref, mask) {
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFuncSeparate(gl.FRONT, gl.ALWAYS, " + ref[0] + ", " + mask[0] + ")");
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFuncSeparate(gl.BACK, gl.ALWAYS, " + ref[1] + ", " + mask[1] + ")");
}
function testStencilFuncCase(ref, mask, error) {
setStencilFunc(ref, mask);
// If an error is generated, it should be at draw time.
wtu.shouldGenerateGLError(gl, error, "wtu.dummySetProgramAndDrawNothing(gl)");
checkDrawError(error);
}
function testStencilFunc(errIfMismatch) {
@ -97,6 +109,34 @@ function testStencilFunc(errIfMismatch) {
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFunc(gl.ALWAYS, 0, 1023)", "resetting stencilFunc");
}
//
// Tests of the default framebuffer
//
debug("");
debug("Testing default framebuffer with { stencil: true }");
gl = wtu.create3DContext(undefined, { stencil: true });
{
gl.enable(gl.STENCIL_TEST);
testStencilMaskCase([1, 256], gl.INVALID_OPERATION);
testStencilFuncCase([256, 0], [1023, 1023], gl.INVALID_OPERATION);
}
debug("Testing default framebuffer with { stencil: false }");
gl = wtu.create3DContext(undefined, { stencil: false });
{
// with { stencil: false }
gl.enable(gl.STENCIL_TEST);
testStencilMaskCase([1, 256], gl.NO_ERROR);
testStencilFuncCase([256, 0], [1023, 1023], gl.NO_ERROR);
}
// (continue using this GL context for the other tests)
//
// Tests with a framebuffer object
//
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
const colorRB = gl.createRenderbuffer();
@ -106,14 +146,7 @@ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "initial framebuffer setup")
function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, errIfMismatch) {
debug("");
debug("With depthbuffer=" + haveDepthBuffer +
", stencilbuffer=" + haveStencilBuffer +
", stencilTest=" + enableStencilTest +
", expecting error=" + wtu.glEnumToString(gl, errIfMismatch) +
" for mismatching mask or func settings.");
function runWithStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, fn) {
let rbo = null;
let attachment;
if (haveDepthBuffer || haveStencilBuffer) {
@ -143,10 +176,7 @@ function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTe
gl.disable(gl.STENCIL_TEST);
}
// Errors should be the same for both mask and func, because stencil test
// and stencil write are always enabled/disabled in tandem.
testStencilMask(errIfMismatch);
testStencilFunc(errIfMismatch);
fn();
if (rbo) {
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, null);
@ -157,6 +187,21 @@ function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTe
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "depth/stencil renderbuffer cleanup")
}
function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, errIfMismatch) {
debug("");
debug("With depthbuffer=" + haveDepthBuffer +
", stencilbuffer=" + haveStencilBuffer +
", stencilTest=" + enableStencilTest +
", expecting error=" + wtu.glEnumToString(gl, errIfMismatch) +
" for mismatching mask or func settings.");
runWithStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, () => {
// Errors should be the same for both mask and func, because stencil test
// and stencil write are always enabled/disabled in tandem.
testStencilMask(errIfMismatch);
testStencilFunc(errIfMismatch);
});
}
debug("");
debug("Base case checks:");
@ -177,6 +222,93 @@ testStencilSettings( true, false, true, gl.NO_ERROR);
testStencilSettings(false, true, true, gl.INVALID_OPERATION);
testStencilSettings( true, true, true, gl.INVALID_OPERATION);
//
// Tests to make sure the stencil validation check, if cached, is invalidated correctly.
//
debug("");
debug("Setup for stencil validation cache invalidation tests");
setStencilMask([1, 258]);
setStencilFunc([0, 256], [1023, 1023]);
debug("Test with enabling/disabling stencil test");
runWithStencilSettings(false, true, false, () => {
checkDrawError(gl.NO_ERROR);
gl.enable(gl.STENCIL_TEST);
checkDrawError(gl.INVALID_OPERATION);
gl.disable(gl.STENCIL_TEST);
checkDrawError(gl.NO_ERROR);
});
debug("Test with swapping in a new FBO");
runWithStencilSettings(false, false, true, () => {
// no error with no stencil buffer
checkDrawError(gl.NO_ERROR);
// swap in a new FBO with a stencil buffer
const fb2 = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
gl.bindRenderbuffer(gl.RENDERBUFFER, colorRB);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRB);
const rbo = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
// this draw sholud detect the new fbo state
checkDrawError(gl.INVALID_OPERATION);
gl.deleteFramebuffer(fb2);
gl.deleteRenderbuffer(rbo)
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
});
debug("Test with adding a stencil attachment");
runWithStencilSettings(false, false, true, () => {
// no error with no stencil buffer
checkDrawError(gl.NO_ERROR);
// add a stencil attachment
const rbo = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
// this draw sholud detect the new fbo state
checkDrawError(gl.INVALID_OPERATION);
gl.deleteRenderbuffer(rbo)
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
});
debug("Test with reallocating the DEPTH_STENCIL attachment from depth to depth+stencil");
runWithStencilSettings(false, false, true, () => {
// attach a depth buffer to the DEPTH_STENCIL attachment
const rbo = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
// this draw is invalid, but it still might trigger caching of the stencil validation
checkDrawError(gl.INVALID_FRAMEBUFFER_OPERATION);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, 1, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
// this draw sholud detect the new fbo state
checkDrawError(gl.INVALID_OPERATION);
gl.deleteRenderbuffer(rbo)
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
});
gl.deleteFramebuffer(fb);
gl.deleteRenderbuffer(colorRB);

View File

@ -28,7 +28,7 @@ precision mediump float;
#endif
varying vec4 color;
#define ERROR_EPSILON 0.1
#define ERROR_EPSILON 0.125
void main (void){
struct second_nest

View File

@ -27,7 +27,7 @@ attribute vec4 gtf_Vertex;
uniform mat4 gtf_ModelViewProjectionMatrix;
varying vec4 color;
#define ERROR_EPSILON 0.1
#define ERROR_EPSILON 0.125
void main (void)
{

View File

@ -46,6 +46,11 @@ description();
function test() {
var gl = wtu.create3DContext("example", {preserveDrawingBuffer: true});
if (!gl) {
testFailed("context does not exist");
finishTest();
return;
}
var program = wtu.setupColorQuad(gl);
var colorLoc = gl.getUniformLocation(program, "u_color");
gl.enable(gl.DEPTH_TEST);

View File

@ -1,3 +1,4 @@
--min-version 1.0.4 canvas-alpha-bug.html
--min-version 1.0.4 --max-version 1.9.9 clipping-wide-points.html
--min-version 1.0.2 culling.html
--min-version 1.0.4 default-texture-draw-bug.html
@ -13,6 +14,7 @@ gl-scissor-test.html
--min-version 1.0.2 gl-scissor-fbo-test.html
--min-version 1.0.3 gl-scissor-canvas-dimensions.html
--min-version 1.0.3 gl-viewport-test.html
--min-version 1.0.4 line-rendering-quality.html
--min-version 1.0.3 many-draw-calls.html
more-than-65536-indices.html
multisample-corruption.html
@ -31,4 +33,4 @@ line-loop-tri-fan.html
--min-version 1.0.4 framebuffer-texture-clear.html
--min-version 1.0.4 clear-after-copyTexImage2D.html
--min-version 1.0.4 texture-switch-performance.html
--min-version 1.0.4 rendering-stencil-large-viewport.html
--min-version 1.0.4 rendering-stencil-large-viewport.html

View File

@ -0,0 +1,137 @@
<!--
/*
** Copyright (c) 2018 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">
<title>Alpha blending bug on WebGL canvas</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<canvas id="canvas" width="128" height="128"> </canvas>
<script id="vshader" type="x-shader/x-vertex">
attribute vec2 a_position;
varying vec2 v_uv;
void main()
{
v_uv = a_position.xy * vec2(0.5, 0.5) + vec2(0.5, 0.5);
gl_Position = vec4(a_position.xy, 0.0, 1.0);
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
varying vec2 v_uv;
uniform sampler2D u_texture;
uniform vec4 u_color;
void main()
{
vec4 tex = texture2D(u_texture, v_uv);
gl_FragColor = tex * u_color;
}
</script>
<script>
"use strict";
// This test exposes an Intel driver issue on macOS.
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("canvas");
var program;
var offscreen_tex;
var fbo;
function init()
{
// Init program
program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position"]);
// Init offscreen render targets and specify the format of offscreen texture to be RGB.
offscreen_tex = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, offscreen_tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, canvas.width, canvas.height, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, offscreen_tex, 0);
// Init blend state
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
}
function draw_rect()
{
gl.useProgram(program);
gl.bindTexture(gl.TEXTURE_2D, offscreen_tex);
var u_tex_loc = gl.getUniformLocation(program, 'u_texture');
gl.uniform1i(u_tex_loc, 0);
wtu.setupUnitQuad(gl);
wtu.drawFloatColorQuad(gl, [1.0, 1.0, 1.0, 1.0]);
}
function test_canvas_alpha() {
init();
// Clear offscreen texture to Green
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.0, 1.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// Clear default framebuffer
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(1.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// Enable alpha blending and render to default framebuffer
gl.enable(gl.BLEND);
draw_rect();
wtu.checkCanvasRect(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, [0, 255, 0, 255]);
}
test_canvas_alpha();
description("Exposes alpha blending bug in Intel drivers on macOS - see https://crbug.com/886970");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -42,6 +42,7 @@
"use strict";
description("Test framebuffer switching. The test switches between two framebuffers, copying rendering results from one to the other.");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext("canvas");
var program = wtu.setupTexturedQuad(gl);

View File

@ -42,6 +42,7 @@
"use strict";
description("Test framebuffer texture attachment switching. The test uses one framebuffer object and switches its color attachment.");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext("canvas");
var program = wtu.setupTexturedQuad(gl);

View File

@ -1,7 +1,7 @@
<!--
/*
** Copyright (c) 2012 The Khronos Group Inc.
** Copyright (c) 2018 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
@ -28,37 +28,21 @@
<!DOCTYPE html>
<html>
<head>
<title>Line rendering quality test</title>
<meta charset="utf-8">
<title>WebGL Resource Sharing.</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<canvas id="example1" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
<canvas id="example2" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
<canvas id="testbed" width="256" height="256"></canvas>
<canvas id="testbed2" width="256" height="256"></canvas>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("Tests that resources can not be shared.");
debug("");
var wtu = WebGLTestUtils;
var gl1 = wtu.create3DContext("example1");
var gl2 = wtu.create3DContext("example2");
assertMsg(gl1 && gl2,
"Got 3d context.");
var vertexObject = gl1.createBuffer();
gl2.bindBuffer(gl2.ARRAY_BUFFER, vertexObject);
assertMsg(
gl2.getError() == gl2.INVALID_OPERATION,
"attempt to use a resource from the wrong context should fail with INVALID_OPERATION");
var successfullyParsed = true;
var contextVersion = 1;
</script>
<script src="../../js/tests/line-rendering-quality.js"></script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -49,9 +49,14 @@ debug('Regression test for <a href="https://code.google.com/p/chromium/issues/de
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("example", {antialias: true, preserveDrawingBuffer: true});
var test = IterableTest.createMultisampleCorruptionTest(gl);
var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 25;
IterableTest.run(test, iterations);
if (!gl) {
testFailed("context does not exist");
finishTest();
} else {
var test = IterableTest.createMultisampleCorruptionTest(gl);
var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 25;
IterableTest.run(test, iterations);
}
var successfullyParsed = true;
</script>

View File

@ -49,9 +49,14 @@ debug('Regression test for <a href="https://code.google.com/p/chromium/issues/de
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("example", {preserveDrawingBuffer: true});
var test = IterableTest.createPreserveDrawingBufferLeakTest(gl);
var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 50;
IterableTest.run(test, iterations);
if (!gl) {
testFailed("context does not exist");
finishTest();
} else {
var test = IterableTest.createPreserveDrawingBufferLeakTest(gl);
var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 50;
IterableTest.run(test, iterations);
}
var successfullyParsed = true;
</script>

View File

@ -1,4 +1,5 @@
--max-version 1.9.9 compressed-tex-image.html
--min-version 1.0.4 canvas-teximage-after-multiple-drawimages.html
compressed-tex-image.html
copy-tex-image-and-sub-image-2d.html
--min-version 1.0.2 copy-tex-image-2d-formats.html
--min-version 1.0.4 copy-tex-image-crash.html

View File

@ -0,0 +1,123 @@
<!--
/*
** Copyright (c) 2018 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">
<title>TexImage2D of 2D Canvas after multiple drawImages</title>
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
<script src="../../../js/js-test-pre.js"></script>
<script src="../../../js/webgl-test-utils.js"></script>
<script>
"use strict";
const wtu = WebGLTestUtils;
const sz = 512;
let greenImage = null;
function loadImageAndStart(startFunc) {
let c = document.createElement('canvas');
c.width = sz;
c.height = sz;
let ctx = c.getContext('2d');
ctx.fillStyle = 'rgb(0,255,0)';
ctx.fillRect(0, 0, sz, sz);
greenImage = wtu.makeImageFromCanvas(c, startFunc);
}
function runTest() {
description();
debug('Regression test for <a href="http://crbug.com/878545">http://crbug.com/878545</a>');
// Mimics the image-to-texture upload path from the old JavaScript
// port of O3D, salvaged at https://github.com/petersont/o3d .
// Create a canvas and draw the entire image into it.
let bigCanvas = document.createElement('canvas');
bigCanvas.width = greenImage.naturalWidth;
bigCanvas.height = greenImage.naturalHeight;
let bc = bigCanvas.getContext('2d');
bc.drawImage(greenImage, 0, 0, bigCanvas.width, bigCanvas.height);
// Create a temp canvas to flip vertically.
let tempCanvas = document.createElement('canvas');
tempCanvas.width = bigCanvas.width;
tempCanvas.height = bigCanvas.height;
let tc = tempCanvas.getContext('2d');
tc.translate(0, tempCanvas.height);
tc.scale(1, -1);
tc.drawImage(bigCanvas, 0, 0, tempCanvas.width, tempCanvas.height);
// Set up to draw via WebGL.
let c3d = document.getElementById('canvas');
let gl = wtu.create3DContext(c3d);
let prog = wtu.setupTexturedQuad(gl);
gl.uniform1i(gl.getUniformLocation(prog, 'tex'), 0);
let tex = gl.createTexture();
// Iterate through the large canvas, drawing pieces of it to a
// scratch canvas.
let scratchCanvas = document.createElement('canvas');
const width = tempCanvas.width / 2;
const height = tempCanvas.height / 2;
let bb = new Uint8Array(4 * c3d.width * c3d.height);
for (let jj = 0; jj < 2; ++jj) {
for (let ii = 0; ii < 2; ++ii) {
// Prepare texture.
scratchCanvas.width = width;
scratchCanvas.height = height;
let ctx = scratchCanvas.getContext('2d');
ctx.save();
ctx.translate(-(ii * width), -(jj * height));
ctx.scale(1.0, 1.0);
ctx.drawImage(tempCanvas, 0, 0, tempCanvas.width, tempCanvas.height);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
scratchCanvas);
ctx.restore();
gl.generateMipmap(gl.TEXTURE_2D);
// Draw and check that rendering occurred properly.
gl.uniform1i(gl.getUniformLocation(prog, 'tex'), 0);
wtu.drawUnitQuad(gl);
let tolerance = 2;
wtu.checkCanvasRect(gl, 1, 1, c3d.width - 2, c3d.height - 2,
[ 0, 255, 0, 255 ],
"should be green",
tolerance);
}
}
finishTest();
}
loadImageAndStart(runTest);
</script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<canvas id="canvas" width="40" height="40"></canvas>
</body>
</html>

View File

@ -29,7 +29,7 @@
<html>
<head>
<meta charset="utf-8">
<title>WebGL CompressedTexImage and CompressedTexSubImage Tests</title>
<title>WebGL compressed texture test</title>
<LINK rel="stylesheet" href="../../../resources/js-test-style.css"/>
<script src="../../../js/js-test-pre.js"></script>
<script src="../../../js/webgl-test-utils.js"></script>
@ -39,17 +39,13 @@
<div id="console"></div>
<script>
"use strict";
description("This test ensures WebGL implementations correctly implement compressedTexImage2D and compressedTexSubImage2D.");
description("This test ensures WebGL implementations correctly implement querying for compressed textures when extensions are disabled.");
debug("");
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext();
var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
var COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
var COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
var ETC1_RGB8_OES = 0x8D64;
var COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
var COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
@ -63,10 +59,6 @@ if (!gl) {
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 0, new Uint8Array(16))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ETC1_RGB8_OES, 4, 4, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");

View File

@ -119,7 +119,7 @@ function runNextTest() {
return;
}
}
wtu.waitForComposite(runNextTest)
wtu.dispatchTask(runNextTest);
}
function testFormatType(t, test) {

View File

@ -135,6 +135,9 @@ var runNextTest = function() {
var img = wtu.makeImage(test.src, function() {
testImage(test, img);
setTimeout(runNextTest, 0);
}, function () {
testFailed("could not create image" + (test.isSVG ? " (SVG)" : ""));
setTimeout(runNextTest, 0);
});
} else if (test.type == "video") {
debug("HTMLVideoElement (" + test.videoType + ")");

View File

@ -4,3 +4,4 @@ gl-vertex-attrib-i-render.html
--min-version 2.0.1 gl-vertex-attrib-normalized-int.html
gl-vertexattribipointer.html
gl-vertexattribipointer-offsets.html
--min-version 2.0.1 render-no-enabled-attrib-arrays.html

View File

@ -0,0 +1,87 @@
<!--
/*
** Copyright (c) 2018 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>
<title>Verify drawing without any enabled vertex attribute arrays</title>
<meta charset="utf-8">
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script id='vshader' type='x-shader/x-vertex'>#version 300 es
layout(location=0) in vec4 inColor;
out vec4 varyingColor;
void main()
{
varyingColor = inColor;
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
gl_PointSize = 1.0;
}
</script>
<script id='fshader' type='x-shader/x-fragment'>#version 300 es
precision mediump float;
in vec4 varyingColor;
layout(location=0) out vec4 oColor;
void main()
{
oColor = varyingColor;
}
</script>
<script>
"use strict";
function runTest() {
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("testCanvas", undefined, 2);
if (!gl) {
testFailed('could not create context');
return;
}
var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
gl.disableVertexAttribArray(0);
gl.vertexAttrib4f(0, 0.0, 1.0, 0.0, 1.0);
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 1);
wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "Canvas should be covered by a single green point");
}
</script>
</head>
<body>
<canvas id="testCanvas" width="1" height="1" style="width: 32px; height: 32px;"></canvas>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description();
runTest();
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -6,6 +6,7 @@ buffer-type-restrictions.html
buffer-overflow-test.html
--min-version 2.0.1 delete-buffer.html
get-buffer-sub-data.html
--min-version 2.0.1 get-buffer-sub-data-validity.html
one-large-uniform-buffer.html
uniform-buffers.html
--min-version 2.0.1 uniform-buffers-second-compile.html

View File

@ -0,0 +1,264 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL2 getBufferSubData validity tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"> </script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script id="vshader" type="x-shader/x-vertex">#version 300 es
in uint in_data;
flat out uint out_data;
void main() {
out_data = in_data;
}
</script>
<script id="fshader" type="x-shader/x-fragment">#version 300 es
void main() {}
</script>
<script>
"use strict";
description("Test that getBufferSubData returns valid data in edge cases");
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext(undefined, undefined, 2);
const srcData = new Uint8Array([ 1, 2, 3, 4, 5, 6, 7, 8 ]);
const noData = new Uint8Array(8);
const srcBuffer = gl.createBuffer();
gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer);
gl.bufferData(gl.COPY_READ_BUFFER, srcData, gl.STATIC_DRAW);
const badBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer);
gl.bufferData(gl.ARRAY_BUFFER, 8, gl.STATIC_DRAW);
let readbackBuffer;
function deleteReadbackBuffer() {
gl.deleteBuffer(readbackBuffer);
}
function recreateReadbackBuffer() {
readbackBuffer = gl.createBuffer();
gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
gl.bufferData(gl.COPY_WRITE_BUFFER, 8, gl.STREAM_READ);
}
recreateReadbackBuffer();
const dest = new Uint8Array(8);
// Makes a new "resolvable" Promise
function resolvable() {
let resolve;
const promise = new Promise(res => { resolve = res; });
promise.resolve = resolve;
return promise;
}
function fence() {
const promise = resolvable();
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.flush();
function check() {
const status = gl.clientWaitSync(sync, 0, 0);
if (status == gl.ALREADY_SIGNALED || status == gl.CONDITION_SATISFIED) {
gl.deleteSync(sync);
promise.resolve();
} else {
setTimeout(check, 0);
}
}
setTimeout(check, 0);
return promise;
}
function checkGetBufferSubData(err, data) {
dest.fill(0);
wtu.shouldGenerateGLError(gl, err, "gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)");
if (!err) {
shouldBeTrue(`areArraysEqual(dest, ${data})`);
}
}
const tfProgram = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
["out_data"], gl.SEPARATE_ATTRIBS,
["in_data"]);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error");
shouldBeNonNull("tfProgram");
const tf = gl.createTransformFeedback();
function copyBufferUsingTransformFeedback(src, dst) {
gl.enableVertexAttribArray(0);
gl.bindBuffer(gl.ARRAY_BUFFER, src);
gl.vertexAttribIPointer(0, 1, gl.UNSIGNED_INT, 0, 0);
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, dst);
gl.enable(gl.RASTERIZER_DISCARD);
gl.beginTransformFeedback(gl.POINTS);
// treats the input and output data as two uint32s
gl.drawArrays(gl.POINTS, 0, 2);
gl.endTransformFeedback();
gl.disable(gl.RASTERIZER_DISCARD);
gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer);
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
}
Promise.resolve()
.then(() => {
debug("");
debug("write-read");
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
checkGetBufferSubData(gl.NO_ERROR, "srcData");
})
.then(() => {
debug("");
debug("fence-wait-write-read");
return fence().then(() => {
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
checkGetBufferSubData(gl.NO_ERROR, "srcData");
});
})
.then(() => {
debug("");
debug("write-read-fence-wait");
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
checkGetBufferSubData(gl.NO_ERROR, "srcData");
return fence();
})
.then(() => {
debug("");
debug("write-fence-fence-wait-read");
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
fence();
return fence().then(() => {
checkGetBufferSubData(gl.NO_ERROR, "srcData");
});
})
.then(() => {
debug("");
debug("write-fence-wait-read");
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
return fence().then(() => {
checkGetBufferSubData(gl.NO_ERROR, "srcData");
});
})
.then(() => {
debug("");
debug("write-fence-wait-write-read");
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
return fence().then(() => {
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
checkGetBufferSubData(gl.NO_ERROR, "srcData");
});
})
.then(() => {
debug("");
debug("write-fence-write-wait-read");
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
const p = fence();
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
return p.then(() => {
checkGetBufferSubData(gl.NO_ERROR, "srcData");
});
})
.then(() => {
debug("");
debug("write-fence-transformfeedback-wait-read");
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
const p = fence();
gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
copyBufferUsingTransformFeedback(srcBuffer, readbackBuffer);
gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
return p.then(() => {
checkGetBufferSubData(gl.NO_ERROR, "srcData");
});
})
.then(() => {
debug("");
debug("write-unbind-fence-wait-bind-read");
gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
gl.bindBuffer(gl.ARRAY_BUFFER, readbackBuffer);
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.ARRAY_BUFFER, 0, 0, 8);
gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer);
return fence().then(() => {
gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
checkGetBufferSubData(gl.NO_ERROR, "srcData");
});
})
.then(() => {
debug("");
debug("write-fence-wait-delete-read");
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
return fence().then(() => {
deleteReadbackBuffer();
checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
recreateReadbackBuffer();
});
})
.then(() => {
debug("");
debug("write-fence-delete-wait-read");
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
const p = fence();
deleteReadbackBuffer();
return p.then(() => {
checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
recreateReadbackBuffer();
});
})
.then(() => {
debug("");
debug("write-fence-delete-wait-read");
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
deleteReadbackBuffer();
return fence().then(() => {
checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
recreateReadbackBuffer();
});
})
.then(finishTest);
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -1,8 +1,10 @@
constants-and-properties-2.html
context-attributes-depth-stencil-antialias-obeyed.html
--min-version 2.0.1 context-mode.html
--min-version 2.0.1 context-sharing-texture2darray-texture3d-data-bug.html
context-type-test-2.html
--min-version 2.0.1 context-resize-changes-buffer-binding-bug.html
--min-version 2.0.1 incorrect-context-object-behaviour.html
methods-2.html
--min-version 2.0.1 no-experimental-webgl2.html

View File

@ -0,0 +1,77 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL2 Canvas Context Mode Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("This test ensures WebGL 2.0 implementations respect the canvas's context mode.");
debug("");
assertMsg(window.WebGLRenderingContext,
"WebGL2RenderingContext should be a member of window");
assertMsg('WebGL2RenderingContext' in window,
"WebGL2RenderingContext should be 'in' window");
function testContextMode(mode, altMode) {
debug("Testing " + mode + " context type");
let c = document.createElement('canvas');
c.width = 2;
c.height = 2;
let gl = c.getContext(mode);
assertMsg(c.getContext(mode) == gl,
"Canvas.getContext('" + mode + "') should return the same value every time");
try {
assertMsg(c.getContext(altMode) == null,
"Canvas.getContext('" + altMode + "') after getContext('" + mode + "') should return null");
} catch (e) {
testFailed("Canvas.getContext('" + altMode + "') after getContext('" + mode + "') should not throw an exception");
}
}
testContextMode('webgl2', 'webgl');
testContextMode('webgl', 'webgl2');
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,242 @@
<!--
/*
** Copyright (c) 2018 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="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script id="tf-vshader" type="x-shader/x-vertex">#version 300 es
in uint in_data;
flat out uint out_data;
void main() {
out_data = in_data;
}
</script>
<script id="tf-fshader" type="x-shader/x-fragment">#version 300 es
void main() {}
</script>
<script>
"use strict";
description("Tests calling WebGL 2.0 APIs with objects from other contexts");
function loadTFProgram(context) {
const tfProgram = wtu.setupTransformFeedbackProgram(context, ["tf-vshader", "tf-fshader"],
["out_data"], context.SEPARATE_ATTRIBS,
["in_data"]);
wtu.glErrorShouldBe(context, context.NO_ERROR, "linking transform feedback shader should not set an error");
return tfProgram;
}
function create2DTextureArray4x4x4(context) {
const texture = context.createTexture();
context.bindTexture(context.TEXTURE_2D_ARRAY, texture);
context.texImage3D(context.TEXTURE_2D_ARRAY, 0, context.RGBA8, 4, 4, 4, 0, context.RGBA, context.UNSIGNED_BYTE, null);
wtu.glErrorShouldBe(context, context.NO_ERROR, "allocating 2D texture array should not set an error");
return texture;
}
var wtu = WebGLTestUtils;
var contextA = wtu.create3DContext(undefined, undefined, 2);
var contextB = wtu.create3DContext(undefined, undefined, 2);
var bufferA = contextA.createBuffer();
var bufferB = contextB.createBuffer();
var frameBufferA = contextA.createFramebuffer();
var frameBufferB = contextB.createFramebuffer();
var programB = wtu.loadStandardProgram(contextB);
var queryB = contextB.createQuery();
var samplerB = contextB.createSampler();
var syncB = contextB.fenceSync(contextB.SYNC_GPU_COMMANDS_COMPLETE, 0);
var transformFeedbackA = contextA.createTransformFeedback();
var transformFeedbackB = contextB.createTransformFeedback();
var vertexArrayA = contextA.createVertexArray();
var vertexArrayB = contextB.createVertexArray();
var tfProgramB = loadTFProgram(contextB);
var texture2DArrayA = create2DTextureArray4x4x4(contextA);
var texture2DArrayB = create2DTextureArray4x4x4(contextB);
var locationB = contextB.getUniformLocation(programB, 'u_modelViewProjMatrix');
var uniformData = [];
function generateFloat32Array(length) {
uniformData = new Float32Array(length);
}
function generateFloatArray(length) {
uniformData = new Array(length);
for (var i = 0; i < length; i++) {
uniformData[i] = 0.0;
}
}
function generateInt32Array(length) {
uniformData = new Int32Array(length);
}
function generateIntArray(length) {
uniformData = new Array(length);
for (var i = 0; i < length; i++) {
uniformData[i] = 0;
}
}
function generateUint32Array(length) {
uniformData = new Uint32Array(length);
}
// Make the bindable objects valid in both contexts first.
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, bufferA)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindBuffer(contextA.ARRAY_BUFFER, null)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, bufferB)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindBuffer(contextB.ARRAY_BUFFER, null)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTransformFeedback(contextA.TRANSFORM_FEEDBACK, transformFeedbackA)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindTransformFeedback(contextA.TRANSFORM_FEEDBACK, null)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTransformFeedback(contextB.TRANSFORM_FEEDBACK, transformFeedbackB)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindTransformFeedback(contextB.TRANSFORM_FEEDBACK, null)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindVertexArray(vertexArrayA)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindVertexArray(null)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindVertexArray(vertexArrayB)");
wtu.shouldGenerateGLError(contextB, contextB.NO_ERROR, "contextB.bindVertexArray(null)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferA)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferTextureLayer(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, texture2DArrayB, 0, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getFragDataLocation(tfProgramB, 'nonexistent_variable')");
// Unsigned int uniforms
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1ui(locationB, 0)");
generateUint32Array(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1uiv(locationB, uniformData)");
generateIntArray(1); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1uiv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2ui(locationB, 0, 0)");
generateUint32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2uiv(locationB, uniformData)");
generateIntArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2uiv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3ui(locationB, 0, 0, 0)");
generateUint32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3uiv(locationB, uniformData)");
generateIntArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3uiv(locationB, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4ui(locationB, 0, 0, 0, 0)");
generateUint32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4uiv(locationB, uniformData)");
generateIntArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4uiv(locationB, uniformData)");
// New uniform entry points with offsets
generateFloat32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData, 1)");
generateFloatArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1fv(locationB, uniformData, 1)");
generateInt32Array(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData, 1)");
generateIntArray(2); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform1iv(locationB, uniformData, 1)");
generateFloat32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData, 1)");
generateFloatArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2fv(locationB, uniformData, 1)");
generateInt32Array(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData, 1)");
generateIntArray(3); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform2iv(locationB, uniformData, 1)");
generateFloat32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData, 1)");
generateFloatArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3fv(locationB, uniformData, 1)");
generateInt32Array(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData, 1)");
generateIntArray(4); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform3iv(locationB, uniformData, 1)");
generateFloat32Array(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData, 1)");
generateFloatArray(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4fv(locationB, uniformData, 1)");
generateInt32Array(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData, 1)");
generateIntArray(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniform4iv(locationB, uniformData, 1)");
generateFloat32Array(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData, 1)");
generateFloatArray(5); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2fv(locationB, false, uniformData, 1)");
generateFloat32Array(10); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData, 1)");
generateFloatArray(10); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3fv(locationB, false, uniformData, 1)");
generateFloat32Array(17); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData, 1)");
generateFloatArray(17); wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4fv(locationB, false, uniformData, 1)");
// Non-rectangular matrix uniform entry points
generateFloat32Array(6);
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x2fv(locationB, false, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x3fv(locationB, false, uniformData)");
generateFloatArray(6);
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x2fv(locationB, false, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x3fv(locationB, false, uniformData)");
generateFloat32Array(8);
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x2fv(locationB, false, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x4fv(locationB, false, uniformData)");
generateFloatArray(8);
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x2fv(locationB, false, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix2x4fv(locationB, false, uniformData)");
generateFloat32Array(12);
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x3fv(locationB, false, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x4fv(locationB, false, uniformData)");
generateFloatArray(12);
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix4x3fv(locationB, false, uniformData)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformMatrix3x4fv(locationB, false, uniformData)");
// Query objects
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteQuery(queryB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isQuery(queryB)");
shouldBeFalse("contextA.isQuery(queryB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.beginQuery(contextA.ANY_SAMPLES_PASSED, queryB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getQueryParameter(queryB, contextA.QUERY_RESULT_AVAILABLE)");
// Sampler objects
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteSampler(samplerB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isSampler(samplerB)");
shouldBeFalse("contextA.isSampler(samplerB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.samplerParameteri(samplerB, contextA.TEXTURE_WRAP_S, contextA.CLAMP_TO_EDGE)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.samplerParameterf(samplerB, contextA.TEXTURE_MIN_LOD, -500.5)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getSamplerParameter(samplerB, contextA.TEXTURE_WRAP_S)");
// Sync objects
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteSync(syncB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isSync(syncB)");
shouldBeFalse("contextA.isSync(syncB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.clientWaitSync(syncB, 0, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.waitSync(syncB, 0, contextA.TIMEOUT_IGNORED)");
// Transform feedback
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteTransformFeedback(transformFeedbackB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isTransformFeedback(transformFeedbackB)");
shouldBeFalse("contextA.isTransformFeedback(transformFeedbackB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindTransformFeedback(contextA.TRANSFORM_FEEDBACK, transformFeedbackB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.transformFeedbackVaryings(tfProgramB, ['out_data'], contextA.SEPARATE_ATTRIBS)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getTransformFeedbackVarying(tfProgramB, 0)");
// Uniform buffer objects and transform feedback buffers
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindBufferBase(contextA.UNIFORM_BUFFER, 0, bufferB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindBufferRange(contextA.UNIFORM_BUFFER, 0, bufferB, 0, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformIndices(programB, ['u_modelViewProjMatrix'])");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniforms(programB, [0], contextA.UNIFORM_TYPE)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformBlockIndex(programB, 'nonexistent_uniform_block_name')");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniformBlockParameter(programB, 0, contextA.UNIFORM_BLOCK_BINDING)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getActiveUniformBlockName(programB, 0)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.uniformBlockBinding(programB, 0, 0)");
// Vertex Array objects
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.deleteVertexArray(vertexArrayB)");
wtu.shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.isVertexArray(vertexArrayB)");
shouldBeFalse("contextA.isVertexArray(vertexArrayB)");
wtu.shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindVertexArray(vertexArrayB)");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -2,6 +2,12 @@ ext-color-buffer-float.html
ext-disjoint-timer-query-webgl2.html
promoted-extensions.html
promoted-extensions-in-shaders.html
webgl-get-buffer-sub-data-async.html
webgl-get-buffer-sub-data-async-lose-context.html
webgl-get-buffer-sub-data-async-stress.html
--min-version 2.0.1 webgl_multiview.html
--min-version 2.0.1 webgl_multiview_depth.html
--min-version 2.0.1 webgl_multiview_draw_buffers.html
--min-version 2.0.1 webgl_multiview_flat_varying.html
--min-version 2.0.1 webgl_multiview_instanced_draw.html
--min-version 2.0.1 webgl_multiview_non_multiview_shaders.html
--min-version 2.0.1 webgl_multiview_single_view_operations.html
--min-version 2.0.1 webgl_multiview_timer_query.html
--min-version 2.0.1 webgl_multiview_transform_feedback.html

View File

@ -1,117 +0,0 @@
<!--
/*
** Copyright (c) 2016 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">
<title>WEBGL_get_buffer_sub_data_async context loss regression test.</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" width="1" height="1"></canvas>
<div id="console"></div>
<script>
"use strict";
description("This test makes sure that getBufferSubDataAsync does not cause crashes upon context loss.");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, undefined, 2);
var WEBGL_get_buffer_sub_data_async = gl.getExtension("WEBGL_get_buffer_sub_data_async");
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
if (!WEBGL_get_buffer_sub_data_async) {
testPassed("No WEBGL_get_buffer_sub_data_async support -- this is legal");
finishTest();
} else {
testPassed("Successfully enabled WEBGL_get_buffer_sub_data_async extension");
runTests();
}
var extension;
function runTests() {
var extensionName = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_lose_context");
if (!extensionName) {
debug("Could not find WEBGL_lose_context extension");
return;
}
extension = gl.getExtension(extensionName);
var iter = 0;
var ITERS = 20;
canvas.addEventListener("webglcontextrestored", test);
canvas.addEventListener("webglcontextlost", function(e) {
e.preventDefault();
webglHarnessCollectGarbage();
setTimeout(function() {
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "extension.restoreContext()");
}, 100);
});
test();
function test() {
shouldBeFalse("gl.isContextLost()");
if (iter >= ITERS) {
finishTest();
return;
}
iter++;
var pbo = gl.createBuffer();
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
gl.bufferData(gl.PIXEL_PACK_BUFFER, 4, gl.DYNAMIC_READ);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
var readbackBuffer = new Uint8Array(4);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
var promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.PIXEL_PACK_BUFFER, 0, readbackBuffer);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
var completed = false;
promise.then(function(buf) {
testFailed("should not resolve");
}, function(e) {
testPassed("correctly rejected with " + e);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no new errors from late rejection");
}).then(function() {
completed = true;
});
wtu.shouldGenerateGLError(gl, gl.CONTEXT_LOST_WEBGL, "extension.loseContext()");
}
}
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -1,108 +0,0 @@
<!--
/*
** Copyright (c) 2016 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">
<title>WEBGL_get_buffer_sub_data_async stress test.</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" width="1" height="1"></canvas>
<div id="console"></div>
<script>
"use strict";
description("This test makes sure that getBufferSubDataAsync acts under stress as expected governed by WebGL 2.");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, undefined, 2);
var WEBGL_get_buffer_sub_data_async = gl.getExtension("WEBGL_get_buffer_sub_data_async");
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
if (!WEBGL_get_buffer_sub_data_async) {
testPassed("No WEBGL_get_buffer_sub_data_async support -- this is legal");
finishTest();
} else {
testPassed("Successfully enabled WEBGL_get_buffer_sub_data_async extension");
runTests();
}
function runTests() {
var pbo = gl.createBuffer();
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
gl.bufferData(gl.PIXEL_PACK_BUFFER, 4, gl.DYNAMIC_READ);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
var readbackBuffer = new Uint8Array(4);
var TEST_COUNT = 300;
var lastCounter = -1;
var promises = [];
debug("kicking off " + TEST_COUNT + " getBufferSubDataAsync calls");
for (let counter = 0; counter < TEST_COUNT; counter++) {
let color = [counter & 0xff, (counter >> 8) & 0xff, (counter >> 16) & 0xff, 255];
gl.clearColor(color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
let promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.PIXEL_PACK_BUFFER, 0, readbackBuffer);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
promise = promise.then(function(buf) {
if (buf[0] == color[0] &&
buf[1] == color[1] &&
buf[2] == color[2] &&
buf[3] == color[3]) {
testPassed("color readback #" + counter + " was correct");
} else {
testFailed("color readback #" + counter + " was incorrect: was " +
buf + " but expected " + color);
}
if (counter == lastCounter + 1) {
testPassed(" and its Promise resolved in order after " + lastCounter);
} else {
testFailed(" and its Promise resolved out of order order after " + lastCounter);
}
lastCounter = counter;
}, function(e) {
testFailed(e.toString());
});
promises.push(promise);
}
Promise.all(promises).catch(function(e) {
testFailed(e.toString());
}).then(finishTest);
}
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -1,327 +0,0 @@
<!--
/*
** Copyright (c) 2016 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">
<title>WEBGL_get_buffer_sub_data_async test.</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("This test makes sure that getBufferSubDataAsync acts as expected governed by WebGL 2.");
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext(undefined, undefined, 2);
var WEBGL_get_buffer_sub_data_async = gl.getExtension("WEBGL_get_buffer_sub_data_async");
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
if (!WEBGL_get_buffer_sub_data_async) {
testPassed("No WEBGL_get_buffer_sub_data_async support -- this is legal");
finishTest();
} else {
testPassed("Successfully enabled WEBGL_get_buffer_sub_data_async extension");
runTests();
}
var floatArray, dstData, extraLargeBuffer, resolvedArray, promise;
function runTests() {
var vertices = [
1.1, 1.0, 1.3,
-1.0, -1.0, -5.0,
5.3, -1.0, 1.0
];
floatArray = new Float32Array(vertices);
dstData = new Float32Array(vertices.length);
extraLargeBuffer = new Float32Array(vertices.length + 1);
function clearDstData() {
dstData = new Float32Array(vertices.length);
}
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
function expectRejected(promise, message) {
return promise.then(function(v) {
testFailed("should be rejected but was " + v + ": " + message);
}, function(e) {
testPassed("correctly rejected with " + e + ": " + message);
});
}
var types = [
'ARRAY_BUFFER',
'ELEMENT_ARRAY_BUFFER',
'COPY_READ_BUFFER',
'COPY_WRITE_BUFFER',
'PIXEL_PACK_BUFFER',
'PIXEL_UNPACK_BUFFER',
'TRANSFORM_FEEDBACK_BUFFER',
'UNIFORM_BUFFER'
];
var buffers = [];
var buffer;
for (var i = 0; i < types.length; i++) {
buffer = gl.createBuffer();
gl.bindBuffer(gl[types[i]], buffer);
gl.bufferData(gl[types[i]], floatArray, gl.STATIC_DRAW);
buffers[i] = buffer;
}
var uninitializedBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, uninitializedBuffer);
gl.bufferData(gl.ARRAY_BUFFER, 36, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from buffer setup.");
// This long promise chain is to serialize the tests - so that the errors
// associated with a given test always appear underneath that test.
// For each test in this chain, if it performs test checks in a promise,
// it MUST return that promise so that it completes before the next test.
var allPromises = Promise.resolve();
allPromises = allPromises.then(function() {
debug("Testing promise rejection");
});
allPromises = allPromises.then(function() {
debug("Argument must be ArrayBufferView, not ArrayBuffer")
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, new ArrayBuffer(4))";
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, code);
shouldBeType("promise", "Promise");
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("Argument must be ArrayBufferView, not null")
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, null)";
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, code);
shouldBeType("promise", "Promise");
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("");
});
for (let i = 0; i < types.length; i++) {
allPromises = allPromises.then(function() {
debug("Test that getBufferSubDataAsync successfully works reading buffer data from gl." + type);
var type = types[i];
var buf = buffers[i];
gl.bindBuffer(gl[type], buf);
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl." + type + ", 0, dstData)");
gl.bindBuffer(gl[type], null);
return promise.then(function(arr) {
resolvedArray = arr;
shouldBe("resolvedArray", "dstData");
shouldBeTrue("areArraysEqual(resolvedArray, floatArray)");
});
});
}
allPromises = allPromises.then(function() {
debug("");
debug("Test that getBufferSubDataAsync successfully works with dstOffset");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
clearDstData();
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData, 2)");
return promise.then(function(arr) {
resolvedArray = arr;
shouldBeTrue("areArraysEqual(resolvedArray.slice(0, 2), [0, 0])");
shouldBeTrue("areArraysEqual(resolvedArray.slice(2), floatArray.slice(0, floatArray.length - 2))");
});
});
allPromises = allPromises.then(function() {
clearDstData();
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData, dstData.length)");
return promise.then(function(arr) {
resolvedArray = arr;
shouldBeTrue("areArraysEqual(resolvedArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])");
});
});
allPromises = allPromises.then(function() {
debug("Test that getBufferSubDataAsync fails when given a dstOffset beyond the end of dstData");
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData, dstData.length + 1)";
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, code);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("");
debug("Test that getBufferSubDataAsync successfully works with dstOffset and length");
clearDstData();
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData, 2, 2)");
return promise.then(function(arr) {
resolvedArray = arr;
shouldBeTrue("areArraysEqual(resolvedArray.slice(0, 2), [0, 0])");
shouldBeTrue("areArraysEqual(resolvedArray.slice(2, 4), floatArray.slice(0, 2))");
shouldBeTrue("areArraysEqual(resolvedArray.slice(4), [0, 0, 0, 0, 0])");
});
});
allPromises = allPromises.then(function() {
clearDstData();
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData, dstData.length, 0)");
return promise.then(function(arr) {
resolvedArray = arr;
shouldBeTrue("areArraysEqual(resolvedArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])");
});
});
allPromises = allPromises.then(function() {
debug("");
debug("Test that getBufferSubDataAsync successfully works with uninitialized buffers");
dstData = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
gl.bindBuffer(gl.ARRAY_BUFFER, uninitializedBuffer);
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData)");
return promise.then(function(arr) {
resolvedArray = arr;
shouldBeTrue("areArraysEqual(resolvedArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])");
});
});
allPromises = allPromises.then(function() {
debug("Test that getBufferSubDataAsync fails when given a dstOffset+length beyond the end of dstData");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData, dstData.length - 1, 2)";
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, code);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("");
debug("Test that getBufferSubDataAsync fails when given a buffer with its size larger than the original data");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, extraLargeBuffer)";
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, code);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("Test that getBufferSubDataAsync fails when offset summed with buffer length is larger than the size of the original data size");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, dstData.byteLength + 1, dstData)";
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, code);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 1, dstData)";
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, code);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("Test that getBufferSubDataAsync fails when no buffer is bound to the target");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ELEMENT_ARRAY_BUFFER, 0, dstData)";
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, code);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("Test that getBufferSubDataAsync fails when offset is less than 0");
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]);
var code = "promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, -1, dstData)";
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, code);
return expectRejected(promise, code);
});
allPromises = allPromises.then(function() {
debug("");
debug("Test that getBufferSubDataAsync works when a buffer is immediately resized to be too small");
buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW);
buffers[i] = buffer;
dstData = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData)");
gl.bufferData(gl.ARRAY_BUFFER, 4, gl.STATIC_DRAW);
return promise.then(function(arr) {
resolvedArray = arr;
shouldBeTrue("areArraysEqual(resolvedArray, floatArray)");
});
});
allPromises = allPromises.then(function() {
debug("");
debug("Test that getBufferSubDataAsync works when a buffer is immediately deleted");
dstData = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW);
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
"promise = WEBGL_get_buffer_sub_data_async.getBufferSubDataAsync(gl.ARRAY_BUFFER, 0, dstData)");
gl.deleteBuffer(buffer);
return promise.then(function(arr) {
resolvedArray = arr;
shouldBeTrue("areArraysEqual(resolvedArray, floatArray)");
});
});
allPromises.catch(function(e) {
testFailed(e.toString());
}).then(finishTest);
}
var successfullyParsed = true;
</script>
</body>
</html>

View File

@ -0,0 +1,541 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
<script id="macroFragmentShader" type="x-shader/x-fragment">#version 300 es
precision highp float;
out vec4 my_FragColor;
void main() {
#ifdef GL_OVR_multiview
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
#else
// Error expected
#error no GL_OVR_multiview;
#endif
}
</script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runExtensionDisabledTest()
{
debug("");
debug("Testing queries with extension disabled");
let maxViews = gl.getParameter(0x9631);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query MAX_VIEWS_OVR without enabling WEBGL_multiview");
let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9630);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR without enabling WEBGL_multiview");
let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9632);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR without enabling WEBGL_multiview");
}
function runQueryTest()
{
debug("");
debug("Testing querying MAX_VIEWS_OVR");
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from querying MAX_VIEWS_OVR");
if (typeof maxViews != 'number') {
testFailed("Type of the value of MAX_VIEWS_OVR should be number, was " + (typeof maxViews));
}
if (maxViews < 2) {
testFailed("Value of MAX_VIEWS_OVR should be at least two, was: " + maxViews);
}
}
function runDefaultFramebufferQueryTest()
{
debug("");
debug("Testing querying base view index and num views on the default framebuffer");
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
if (baseViewIndex != 0) {
testFailed('Unexpected baseViewIndex ' + baseViewIndex + ' on the default framebuffer');
} else {
testPassed('baseViewIndex on the default framebuffer was 0');
}
if (numViews != 0) {
testFailed('Unexpected numViews ' + numViews + ' on the default framebuffer');
} else {
testPassed('numViews on the default framebuffer was 0');
}
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from framebuffer queries on the default framebuffer");
}
function runInvalidTextureTypeTest()
{
debug("");
debug("Testing invalid texture types");
let tex2D = createTextureWithNearestFiltering(gl.TEXTURE_2D);
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0, 1);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 2D texture");
let texCube = createTextureWithNearestFiltering(gl.TEXTURE_CUBE_MAP);
gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.RGBA8, 128, 128);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texCube, 0, 0, 1);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a cube map texture");
let tex3D = createTextureWithNearestFiltering(gl.TEXTURE_3D);
gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 128, 128, 2);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 0, 2);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 3D texture");
}
/**
* If allocateStorage is true, the test will allocate texture storage. If it is false, attachments are done without allocations.
*/
function runFramebufferQueryTest(allocateStorage)
{
debug("");
debug("Testing querying attachment object type, baseViewIndex, numViews and framebuffer status. Texture storage is " + (allocateStorage ? "allocated" : "not allocated") + ".");
let checkQueryResult = function(actual, expected, name) {
if (actual != expected) {
testFailed('Unexpected ' + name + ': ' + actual + ' when it was set to ' + expected);
} else {
testPassed(name + ' was ' + actual + ' when queried from the framebuffer');
}
}
let setupAndQuery = function(colorTex, levelSet, baseViewIndexSet, numViewsSet) {
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, levelSet, baseViewIndexSet, numViewsSet);
let objectType = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
if (objectType != gl.TEXTURE) {
testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ', should be TEXTURE');
} else {
testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was TEXTURE');
}
let level = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
checkQueryResult(level, levelSet, "level");
let textureName = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
checkQueryResult(textureName, colorTex, "texture object");
let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
checkQueryResult(baseViewIndex, baseViewIndexSet, "baseViewIndex");
let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
checkQueryResult(numViews, numViewsSet, "numViews");
let layer = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
checkQueryResult(layer, baseViewIndexSet, "texture layer (should match baseViewIndex)");
}
let setupSecondAttachmentAndQueryStatus = function(colorTex2, baseViewIndex, numViews, expectedStatus, msg) {
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, colorTex2, 0, baseViewIndex, numViews);
let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != expectedStatus) {
testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus) + ' - ' + msg);
} else {
testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value - ' + msg);
}
}
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying baseViewIndex from a nonexistent attachment");
if (baseViewIndex != null) {
testFailed('Unexpected baseViewIndex ' + baseViewIndex + ' on a framebuffer without attachments');
} else {
testPassed('Querying baseViewIndex returned null on a framebuffer without attachments');
}
let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying numViews from a nonexistent attachment");
if (numViews != null) {
testFailed('Unexpected numViews ' + numViews + ' on a framebuffer without attachments');
} else {
testPassed('Querying numViews returned null on a framebuffer without attachments');
}
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
if (allocateStorage) {
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 2, gl.RGBA8, 128, 128, maxViews);
}
setupAndQuery(colorTex, 0, 0, maxViews);
setupAndQuery(colorTex, 1, 0, 2);
setupAndQuery(colorTex, 0, 1, maxViews - 1);
// Test matching and mismatching attachments for framebuffer status.
let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
if (allocateStorage) {
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 128, 128, maxViews);
}
setupSecondAttachmentAndQueryStatus(colorTex2, 1, maxViews - 1, allocateStorage ? gl.FRAMEBUFFER_COMPLETE : gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 'matching baseViewIndex and numViews on different attachments');
if (allocateStorage) {
setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'baseViewIndex mismatch');
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'numViews mismatch');
}
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from framebuffer queries");
}
function runInvalidViewsTest()
{
debug("");
debug("Testing invalid out-of-range values for baseViewIndex and numViews");
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
// Don't allocate storage since it's not needed for the validation.
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified too many views");
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified zero views");
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, -1, 2);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified negative baseViewIndex");
let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews + 1, maxViews);
// baseViewIndex + numViews = (maxLayers - maxViews + 1) + maxViews = maxLayers + 1
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified so many views that baseViewIndex + numViews is greater than MAX_ARRAY_TEXTURE_LAYERS");
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews, maxViews);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex + numViews is exactly MAX_ARRAY_TEXTURE_LAYERS");
}
function runDetachTest()
{
debug("");
debug("Testing detaching multiview attachments");
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, maxLayers + 1, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex and numViews are not validated when detaching");
let objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
if (objectType != gl.NONE) {
testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
} else {
testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
}
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Can detach with framebufferTexture2D as well.");
objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
if (objectType != gl.NONE) {
testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
} else {
testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
}
}
function runShaderCompileTest(extensionEnabled)
{
debug("");
debug("Testing shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
var macroFragmentProgram = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "macroFragmentShader"], undefined, undefined, true);
if (extensionEnabled) {
if (macroFragmentProgram) {
testPassed("GL_OVR_multiview defined in shaders when extension is enabled");
} else {
testFailed("GL_OVR_multiview not defined in shaders when extension is enabled");
}
} else {
if (macroFragmentProgram) {
testFailed("GL_OVR_multiview defined in shaders when extension is disabled");
} else {
testPassed("GL_OVR_multiview not defined in shaders when extension disabled");
}
}
if (!extensionEnabled) {
let multiviewShaders = [
getMultiviewPassthroughVertexShader(2),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (testProgram) {
testFailed("Compilation of shaders using extension functionality succeeded when the extension is disabled, should fail.");
} else {
testPassed("Compilation of shaders using extension functionality should fail when the extension is disabled.");
}
}
}
function runClearTest()
{
debug("");
debug("Testing that calling clear() clears all views");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
gl.clearColor(0, 1, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = [0, 255, 255, 255];
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be cyan');
}
}
function runFragmentShaderRenderTest()
{
debug("");
debug("Testing rendering with different colors in fragment shader");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewPassthroughVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
}
}
function runVertexShaderRenderTest()
{
debug("");
debug("Testing rendering with different colors in fragment shader, different offsets in vertex shader");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewOffsetVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
}
}
function runRealisticUseCaseRenderTest()
{
debug("");
debug("Testing rendering with a different transformation matrix chosen from a uniform array according to ViewID");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewRealisticUseCaseVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
let transformLocation = gl.getUniformLocation(testProgram, 'transform');
let transformData = new Float32Array (views * 16);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
let scaleX = 1.0 / views;
// offsetX is the position of the left edge of the quad we want to get in normalized device coordinates
let offsetX = viewIndex / views * 2.0 - 1.0;
setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX);
}
gl.uniformMatrix4fv(transformLocation, false, transformData);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
}
}
function runUniqueObjectTest()
{
debug("");
debug("Testing that getExtension() returns the same object each time");
gl.getExtension("WEBGL_multiview").myProperty = 2;
webglHarnessCollectGarbage();
shouldBe('gl.getExtension("WEBGL_multiview").myProperty', '2');
}
description("This test verifies the functionality of the WEBGL_multiview extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
runExtensionDisabledTest();
runShaderCompileTest(false);
debug("");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
runShaderCompileTest(true);
runQueryTest();
runDefaultFramebufferQueryTest();
runInvalidTextureTypeTest();
runFramebufferQueryTest(true);
runFramebufferQueryTest(false);
runInvalidViewsTest();
runDetachTest();
runClearTest();
wtu.setupUnitQuad(gl, 0, 1);
runFragmentShaderRenderTest();
runVertexShaderRenderTest();
runRealisticUseCaseRenderTest();
runUniqueObjectTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,159 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
<script id="macroFragmentShader" type="x-shader/x-fragment">#version 300 es
precision highp float;
out vec4 my_FragColor;
void main() {
#ifdef GL_OVR_multiview
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
#else
// Error expected
#error no GL_OVR_multiview;
#endif
}
</script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runDepthRenderTest()
{
debug("");
debug("Testing rendering with a depth texture array and depth test on");
let width = 64;
let height = 64;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewPassthroughVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
let depthTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.DEPTH32F_STENCIL8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, depthTex, 0, 0, views);
let expectedStatus = gl.FRAMEBUFFER_COMPLETE;
let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != expectedStatus) {
testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus));
} else {
testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value');
}
// Draw so that the depth test succeeds for all pixels.
gl.viewport(0, 0, width, height);
gl.enable(gl.DEPTH_TEST);
gl.clearDepth(1.0);
gl.clear(gl.DEPTH_BUFFER_BIT);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when depth test succeeds");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
}
// Draw so that the depth test fails for all pixels.
gl.clearDepth(0.0);
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when depth test fails");
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = [0, 0, 0, 0];
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
}
}
description("This test verifies drawing to depth buffers with the WEBGL_multiview extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
debug("");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
wtu.setupUnitQuad(gl, 0, 1);
runDepthRenderTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,179 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runDrawBuffersClearTest()
{
debug("");
debug("Testing that calling clear() clears all views in all draw buffers");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = [null, null, null];
let drawBuffers = [0, 0, 0];
for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
colorTex[texIndex] = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
drawBuffers[texIndex] = gl.COLOR_ATTACHMENT0 + texIndex;
}
gl.viewport(0, 0, width, height);
gl.drawBuffers(drawBuffers);
gl.clearColor(0, 1, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex[texIndex], 0, viewIndex);
let expectedColor = [0, 255, 255, 255];
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' of color attachment ' + texIndex + ' should be cyan');
}
debug("");
}
}
function runDrawBuffersRenderTest()
{
debug("");
debug("Testing rendering into multiple draw buffers with a different transformation matrix chosen from a uniform array according to ViewID");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = [null, null, null];
let drawBuffers = [0, 0, 0];
for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
colorTex[texIndex] = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
drawBuffers[texIndex] = gl.COLOR_ATTACHMENT0 + texIndex;
}
let multiviewShaders = [
getMultiviewRealisticUseCaseVertexShader(views),
getMultiviewColorFragmentShaderForDrawBuffers(colorTex.length)
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
gl.viewport(0, 0, width, height);
gl.drawBuffers(drawBuffers);
let transformLocation = gl.getUniformLocation(testProgram, 'transform');
let transformData = new Float32Array (views * 16);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
let scaleX = 1.0 / views;
// offsetX is the position of the left edge of the quad we want to get in normalized device coordinates
let offsetX = viewIndex / views * 2.0 - 1.0;
setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX);
}
gl.uniformMatrix4fv(transformLocation, false, transformData);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let texIndex = 0; texIndex < colorTex.length; ++texIndex) {
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex[texIndex], 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex + texIndex);
checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex + ' of color attachment ' + texIndex);
}
debug("");
}
}
description("This test verifies the functionality of the WEBGL_multiview extension when used with multiple draw buffers, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
runDrawBuffersClearTest();
wtu.setupUnitQuad(gl, 0, 1);
runDrawBuffersRenderTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,114 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runFlatVaryingTest()
{
debug("");
debug("Testing rendering with different colors in fragment shader");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewFlatVaryingVertexShader(views),
getMultiviewFlatVaryingFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
}
}
description("This test verifies that flat varyings work in multiview shaders using WEBGL_multiview extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
wtu.setupUnitQuad(gl, 0, 1);
runFlatVaryingTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,126 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runInstancedDrawTest()
{
debug("");
debug("Testing instanced rendering");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewInstancedVertexShader(views),
getInstanceColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, 2);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let colorRegionLeftEdge = (width / (views * 2)) * viewIndex;
let colorRegionRightEdge = (width / (views * 2)) * (viewIndex + 2);
let stripWidth = (colorRegionRightEdge - colorRegionLeftEdge) / 2;
if (colorRegionLeftEdge > 0) {
wtu.checkCanvasRect(gl, 0, 0, Math.floor(colorRegionLeftEdge) - 1, height, [0, 0, 0, 0], 'the left edge of view ' + viewIndex + ' should be untouched');
}
if (colorRegionRightEdge < width) {
wtu.checkCanvasRect(gl, colorRegionRightEdge + 1, 0, width - colorRegionRightEdge - 1, height, [0, 0, 0, 0], 'the right edge of view ' + viewIndex + ' should be untouched');
}
let expectedColor = getExpectedColor(0);
wtu.checkCanvasRect(gl, colorRegionLeftEdge + 1, 0, stripWidth - 2, height, expectedColor, 'a thin strip in view ' + viewIndex + ' drawn by instance 0 should be colored ' + expectedColor);
expectedColor = getExpectedColor(1);
wtu.checkCanvasRect(gl, colorRegionLeftEdge + stripWidth + 1, 0, stripWidth - 2, height, expectedColor, 'a thin strip in view ' + viewIndex + ' drawn by instance 1 should be colored ' + expectedColor);
}
}
description("This test verifies instanced draws together with the WEBGL_multiview extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
wtu.setupUnitQuad(gl, 0, 1);
runInstancedDrawTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,114 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runNonMultiviewShaderTest()
{
debug("");
debug("Testing rendering with shaders that don't declare num_views");
let width = 256;
let height = 256;
let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
let testProgram = wtu.setupSimpleColorProgram(gl);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let colorUniformLocation = gl.getUniformLocation(testProgram, 'u_color');
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
gl.viewport(0, 0, width, height);
gl.uniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when using a non-multiview shader as long as the number of views is 1");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0);
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], 'view 0 should be green');
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "draw should generate an INVALID_OPERATION error when using a non-multiview shader and the number of views is > 1");
}
description("This test verifies that non-multiview shaders work correctly with WEBGL_multiview extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
wtu.setupUnitQuad(gl, 0, 1);
runNonMultiviewShaderTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,274 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runSingleViewReadTest()
{
debug("");
debug("Testing reading from a multiview framebuffer with num_views = 1");
let width = 256;
let height = 256;
let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
gl.viewport(0, 0, width, height);
gl.clearColor(0.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
let buf = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from readPixels");
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'view 0 should be cyan');
gl.getError();
// Also test for the error case with two views
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to read from a framebuffer with two views");
}
function runSingleViewBlitTest()
{
debug("");
debug("Testing blitting from a multiview framebuffer with num_views = 1");
let width = 256;
let height = 256;
let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
gl.viewport(0, 0, width, height);
gl.clearColor(0.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
gl.canvas.width = width;
gl.canvas.height = height;
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.clearColor(0.0, 0.0, 0.0, 0.0)
gl.clear(gl.COLOR_BUFFER_BIT);
gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from blitFramebuffer");
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'view 0 blitted to the default framebuffer should be cyan');
// Also test for the error case with multiview blit target
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to blit to a multiview framebuffer even if it has just one view");
// Also test for the error case with two views
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to blit from a framebuffer with two views");
}
function runSingleViewCopyTexImage2DTest()
{
debug("");
debug("Testing copyTexImage2D from a multiview framebuffer with num_views = 1");
let width = 256;
let height = 256;
let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
gl.viewport(0, 0, width, height);
gl.clearColor(0.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
let copyTargetTex = createTextureWithNearestFiltering(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, width, height, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from copyTexImage2D");
let copyFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, copyFb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, copyTargetTex, 0);
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'copy of view 0 in the 2D texture should be cyan');
// Also test for the error case with two views
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, width, height, 0);
wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to copy from a framebuffer with two views");
}
function runSingleViewCopyTexSubImage2DTest()
{
debug("");
debug("Testing copyTexSubImage2D from a multiview framebuffer with num_views = 1");
let width = 256;
let height = 256;
let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
gl.viewport(0, 0, width, height);
gl.clearColor(0.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
let copyTargetTex = createTextureWithNearestFiltering(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from copyTexImage2D");
let copyFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, copyFb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, copyTargetTex, 0);
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'copy of view 0 in the 2D texture should be cyan');
// Also test for the error case with two views
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
gl.bindTexture(gl.TEXTURE_2D, copyTargetTex);
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to copy from a framebuffer with two views");
}
function runSingleViewCopyTexSubImage3DTest()
{
debug("");
debug("Testing copyTexSubImage3D from a multiview framebuffer with num_views = 1");
let width = 256;
let height = 256;
let depth = 2; // always supported so no need to query MAX_VIEWS_OVR.
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, depth);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
gl.viewport(0, 0, width, height);
gl.clearColor(0.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
let copyTargetTex = createTextureWithNearestFiltering(gl.TEXTURE_3D);
gl.bindTexture(gl.TEXTURE_3D, copyTargetTex);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, width, height, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, width, height);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from copyTexSubImage3D");
let copyFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, copyFb);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, copyTargetTex, 0, 0);
wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 255, 255], 'copy of view 0 in the 3D texture should be cyan');
// Also test for the error case with two views
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
gl.bindTexture(gl.TEXTURE_3D, copyTargetTex);
gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 0, 0, width, height);
wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "should be an error to copy from a framebuffer with two views");
}
description("This test verifies that framebuffers with only one view can be read from with WEBGL_multiview extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
runSingleViewReadTest();
runSingleViewBlitTest();
runSingleViewCopyTexImage2DTest();
runSingleViewCopyTexSubImage2DTest();
runSingleViewCopyTexSubImage3DTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,163 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
let queryExt = null;
function runClearTest()
{
debug("");
debug("Testing clear");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
gl.clearColor(1, 0, 0, 1);
let query = gl.createQuery();
gl.beginQuery(queryExt.TIME_ELAPSED_EXT, query);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from setup");
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "multiview clear should generate invalid operation when a timer query is active");
gl.endQuery(queryExt.TIME_ELAPSED_EXT);
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = [0, 0, 0, 0];
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be untouched');
}
}
function runFragmentShaderRenderTest()
{
debug("");
debug("Testing rendering with different colors in fragment shader");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewPassthroughVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
let query = gl.createQuery();
gl.beginQuery(queryExt.TIME_ELAPSED_EXT, query);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from setup");
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "multiview draw should generate invalid operation when a timer query is active");
gl.endQuery(queryExt.TIME_ELAPSED_EXT);
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = [0, 0, 0, 0];
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be untouched');
}
}
description("This test verifies the functionality of the WEBGL_multiview extension and its interaction with EXT_disjoint_timer_query_webgl2, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
if (!gl.getExtension("WEBGL_multiview") || !gl.getExtension("EXT_disjoint_timer_query_webgl2")) {
testPassed("No WEBGL_multiview support or no EXT_disjoint_timer_query_webgl2 support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview and EXT_disjoint_timer_query_webgl2 extensions");
ext = gl.getExtension('WEBGL_multiview');
queryExt = gl.getExtension('EXT_disjoint_timer_query_webgl2');
runClearTest();
wtu.setupUnitQuad(gl, 0, 1);
runFragmentShaderRenderTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,146 @@
<!--
/*
** Copyright (c) 2018 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">
<title>WebGL WEBGL_multiview Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/webgl_multiview_util.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
let queryExt = null;
function runTransformFeedbackTest()
{
debug("");
debug("Testing transform feedback combined with multiview rendering");
let width = 64;
let height = 64;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewVaryingVertexShader(views),
getMultiviewVaryingFragmentShader()
];
let testProgram = wtu.setupTransformFeedbackProgram(gl, multiviewShaders, ['testVarying'], gl.SEPARATE_ATTRIBS, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
let xfb = gl.createTransformFeedback();
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, xfb);
let xfbBuffer = gl.createBuffer();
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 128, gl.DYNAMIC_DRAW);
gl.viewport(0, 0, width, height);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from setup");
gl.beginTransformFeedback(gl.TRIANGLES);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "rendering to a multiview framebuffer with more than one view when there's an active transform feedback should result in invalid operation");
gl.pauseTransformFeedback();
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "rendering to a multiview framebuffer with more than one view when there's an active transform feedback should result in invalid operation even if the transform feedback is paused");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = [0, 0, 0, 0];
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be untouched');
}
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when transform feedback is unbound");
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
}
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, xfb);
gl.endTransformFeedback();
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from ending transform feedback");
}
description("This test verifies interaction between transform feedback and the WEBGL_multiview extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
if (!gl.getExtension("WEBGL_multiview")) {
testPassed("No WEBGL_multiview support -- this is legal");
} else {
testPassed("Successfully enabled WEBGL_multiview extension");
ext = gl.getExtension('WEBGL_multiview');
wtu.setupUnitQuad(gl, 0, 1);
runTransformFeedbackTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -12,6 +12,7 @@ bool-type-cast-bug-uint-ivec-uvec.html
compare-structs-containing-arrays.html
compound-assignment-type-combination.html
const-array-init.html
--min-version 2.0.1 const-struct-from-array-as-function-parameter.html
--min-version 2.0.1 float-parsing.html
forbidden-operators.html
--min-version 2.0.1 forward-declaration.html

View File

@ -0,0 +1,80 @@
<!--
/*
** Copyright (c) 2018 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">
<title>GLSL passing struct from a const array into a function parameter bug</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/glsl-conformance-test.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script id="fShaderTest" type="x-shader/x-fragment">#version 300 es
precision highp float;
struct S { float member; };
const S s[2] = S[]( S(1.), S(2.));
bool useStruct( S s) { return s.member > 0.0; }
out vec4 outColor;
void main( void )
{
outColor = vec4(0.0, 0.0, 0.0, 1.0);
for (int i = 0; i < 2; ++i) {
if (useStruct(s[i])) {
outColor.g++;
}
}
}
</script>
<script type="application/javascript">
"use strict";
description();
// Covers bug:
// http://crbug.com/871434
GLSLConformanceTester.runTests([
{
fShaderId: 'fShaderTest',
fShaderSuccess: true,
linkSuccess: true,
passMsg: 'Passing a struct from a dynamically indexed const array into a non-const function parameter should work.',
render: true
}
], 2);
</script>
</body>
</html>

View File

@ -22,17 +22,20 @@ draw-buffers.html
--min-version 2.0.1 draw-buffers-driver-hang.html
--min-version 2.0.1 draw-with-integer-texture-base-level.html
element-index-uint.html
--min-version 2.0.1 framebuffer-completeness-draw-framebuffer.html
framebuffer-completeness-unaffected.html
--min-version 2.0.1 framebuffer-texture-changing-base-level.html
--min-version 2.0.1 framebuffer-texture-level1.html
framebuffer-unsupported.html
--min-version 2.0.1 fs-color-type-mismatch-color-buffer-type.html
instanced-arrays.html
--min-version 2.0.1 instanced-rendering-bug.html
--min-version 2.0.1 instanced-rendering-large-divisor.html
--min-version 2.0.1 line-rendering-quality.html
--min-version 2.0.1 multisampling-fragment-evaluation.html
out-of-bounds-index-buffers-after-copying.html
--min-version 2.0.1 read-draw-when-missing-image.html
--min-version 2.0.1 rendering-sampling-feedback-loop.html
rgb-format-support.html
uniform-block-buffer-size.html
--min-version 2.0.1 framebuffer-texture-level1.html
--min-version 2.0.1 texture-switch-performance.html

View File

@ -82,13 +82,25 @@ function blit_region_test() {
gl.blitFramebuffer(0, 0, max, max, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
gl.blitFramebuffer(0, 0, width, height, 0, 0, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
gl.blitFramebuffer(0, 0, max, max, 0, 0, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Using max 32-bit integer as blitFramebuffer parameter should succeed.");
gl.blitFramebuffer(-1, -1, max - 1, max - 1, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
gl.blitFramebuffer(0, 0, width, height, -1, -1, max - 1, max - 1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
gl.blitFramebuffer(-1, -1, max - 1, max - 1, -1, -1, max - 1, max - 1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Using blitFramebuffer parameters where calculated width/height matches max 32-bit integer should succeed.");
gl.blitFramebuffer(-1, -1, max, max, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using source width/height greater than max 32-bit integer should fail.");
gl.blitFramebuffer(max, max, -1, -1, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using source width/height greater than max 32-bit integer should fail.");
gl.blitFramebuffer(0, 0, width, height, -1, -1, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using destination width/height greater than max 32-bit integer should fail.");
gl.blitFramebuffer(0, 0, width, height, max, max, -1, -1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using destination width/height greater than max 32-bit integer should fail.");
gl.blitFramebuffer(-1, -1, max, max, -1, -1, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using both source and destination width/height greater than max 32-bit integer should fail.");
gl.blitFramebuffer(-max - 1, -max - 1, max, max, -max - 1, -max - 1, max, max, gl.COLOR_BUFFER_BIT, gl.NEAREST);
testPassed("Congratulations! blitFramebuffer doesn't cause the browser crash when the computed width/height of src and/or dst region might overflow.");
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Using minimum and maximum integers for all boundaries should fail.");
gl.bindTexture(gl.TEXTURE_2D, null)
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);

View File

@ -76,6 +76,8 @@ function nextTest() {
if (!gl) {
testFailed("context does not exist");
wtu.requestAnimFrame(nextTest);
} else {
testPassed("context exists");

View File

@ -0,0 +1,95 @@
<!--
/*
** Copyright (c) 2018 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">
<title>Test draw framebuffer completeness when an incomplete framebuffer is bound to read framebuffer</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
// This exposes a bug in Chrome 67: If the read framebuffer is incomplete, then draw can fail even if the draw framebuffer is complete.
// http://anglebug.com/2737
"use strict";
description();
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext(undefined, undefined, 2);
if (!gl) {
testFailed("context does not exist");
} else {
testPassed("context exists");
var incompleteFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, incompleteFb);
var incompleteTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, incompleteTex);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, incompleteTex, 0);
shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT');
wtu.setupUnitQuad(gl, 0, 1);
var testProgram = wtu.setupSimpleColorProgram(gl, 0);
// If this is changed to gl.FRAMEBUFFER, the rendering succeeds on Chrome 67.
var drawFbTarget = gl.DRAW_FRAMEBUFFER;
var completeFb = gl.createFramebuffer();
gl.bindFramebuffer(drawFbTarget, completeFb);
var completeTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, completeTex);
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128);
gl.framebufferTexture2D(drawFbTarget, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, completeTex, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error after setup");
shouldBe('gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER)', 'gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT');
shouldBe('gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
gl.viewport(0, 0, 128, 128);
gl.uniform4f(gl.getUniformLocation(testProgram, 'u_color'), 0, 1, 0, 1);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error after draw");
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, completeFb);
wtu.checkCanvasRect(gl, 0, 0, 128, 128, [0, 255, 0, 255], 'should be green', 2);
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

View File

@ -171,8 +171,12 @@ function runOutputTests() {
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawArraysInstanced cannot have a count less than 0");
gl.vertexAttribDivisor(positionLoc, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawArraysInstanced");
gl.drawArrays(gl.TRIANGLES, 0, 6);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawArrays");
wtu.checkCanvas(gl, [0, 0, 0, 0], "Nothing should be drawn on the framebuffer when all attributes have non-zero divisors (not enough vertices per instance to form a triangle)");
gl.vertexAttribDivisor(positionLoc, 0);
gl.drawArraysInstanced(gl.POINTS, 0, 6, instanceCount);
@ -209,8 +213,12 @@ function runOutputTests() {
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "drawElementsInstanced cannot have a count less than 0");
gl.vertexAttribDivisor(positionLoc, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, instanceCount);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawElementsInstanced");
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "It's allowed for all vertex attributes to have non-zero divisors when calling drawElements");
wtu.checkCanvas(gl, [0, 0, 0, 0], "Nothing should be drawn on the framebuffer when all attributes have non-zero divisors (not enough vertices per instance to form a triangle)");
gl.vertexAttribDivisor(positionLoc, 0);
gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, instanceCount);

Some files were not shown because too many files have changed in this diff Show More