mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 09:45:41 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
089182bee5
@ -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);
|
||||
},
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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(() => {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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}".`);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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/
|
||||
|
@ -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);
|
||||
|
@ -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(); },
|
||||
});
|
||||
|
@ -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(); },
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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])
|
||||
)
|
||||
),
|
||||
);
|
||||
|
@ -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.");
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
1
dom/canvas/test/webgl-conf/MERGE_BASE
Normal file
1
dom/canvas/test/webgl-conf/MERGE_BASE
Normal file
@ -0,0 +1 @@
|
||||
master
|
@ -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>
|
||||
|
@ -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");
|
||||
|
||||
|
@ -88,8 +88,8 @@ if (!gl) {
|
||||
|
||||
err = gl.getError();
|
||||
debug("");
|
||||
finishTest();
|
||||
}
|
||||
finishTest();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
@ -91,8 +91,8 @@ if (!gl) {
|
||||
|
||||
err = gl.getError();
|
||||
debug("");
|
||||
finishTest();
|
||||
}
|
||||
finishTest();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
@ -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.
|
||||
|
@ -91,6 +91,8 @@ function nextTest() {
|
||||
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
|
||||
wtu.requestAnimFrame(nextTest);
|
||||
} else {
|
||||
testPassed("context exists");
|
||||
|
||||
|
@ -51,6 +51,7 @@ var main = function() {
|
||||
|
||||
if (!gl) {
|
||||
testFailed("can't create 3d context");
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
@ -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>
|
@ -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.
|
||||
|
@ -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>
|
@ -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)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
@ -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'));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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))");
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -119,7 +119,7 @@ function runNextTest() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
wtu.waitForComposite(runNextTest)
|
||||
wtu.dispatchTask(runNextTest);
|
||||
}
|
||||
|
||||
function testFormatType(t, test) {
|
||||
|
@ -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 + ")");
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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
|
||||
|
@ -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>
|
@ -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
|
||||
|
||||
|
@ -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>
|
@ -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>
|
@ -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
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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
|
||||
|
@ -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>
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -76,6 +76,8 @@ function nextTest() {
|
||||
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
|
||||
wtu.requestAnimFrame(nextTest);
|
||||
} else {
|
||||
testPassed("context exists");
|
||||
|
||||
|
@ -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>
|
@ -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
Loading…
Reference in New Issue
Block a user