blob: dfb87a1386cf6d2ccd337a7b6c19b8e2df45a4d3 [file] [log] [blame]
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WI.ShaderProgram = class ShaderProgram extends WI.Object
{
constructor(identifier, programType, canvas, {sharesVertexFragmentShader} = {})
{
console.assert(identifier);
console.assert(Object.values(ShaderProgram.ProgramType).includes(programType));
console.assert(canvas instanceof WI.Canvas);
console.assert(ShaderProgram.contextTypeSupportsProgramType(canvas.contextType, programType));
super();
this._identifier = identifier;
this._programType = programType;
this._canvas = canvas;
this._sharesVertexFragmentShader = !!sharesVertexFragmentShader;
console.assert(!this._sharesVertexFragmentShader || (this._canvas.contextType === WI.Canvas.ContextType.WebGPU && this._programType === ShaderProgram.ProgramType.Render));
this._disabled = false;
}
// Static
static contextTypeSupportsProgramType(contextType, programType)
{
switch (contextType) {
case WI.Canvas.ContextType.WebGL:
case WI.Canvas.ContextType.WebGL2:
return programType === ShaderProgram.ProgramType.Render;
case WI.Canvas.ContextType.WebGPU:
return programType === ShaderProgram.ProgramType.Compute
|| programType === ShaderProgram.ProgramType.Render;
}
console.assert();
return false;
}
static programTypeSupportsShaderType(programType, shaderType)
{
switch (programType) {
case ShaderProgram.ProgramType.Compute:
return shaderType === ShaderProgram.ShaderType.Compute;
case ShaderProgram.ProgramType.Render:
return shaderType === ShaderProgram.ShaderType.Fragment
|| shaderType === ShaderProgram.ShaderType.Vertex;
}
console.assert();
return false;
}
// Public
get identifier() { return this._identifier; }
get programType() { return this._programType; }
get canvas() { return this._canvas; }
get sharesVertexFragmentShader() { return this._sharesVertexFragmentShader; }
get displayName()
{
let format = null;
switch (this._canvas.contextType) {
case WI.Canvas.ContextType.WebGL:
case WI.Canvas.ContextType.WebGL2:
format = WI.UIString("Program %d");
break;
case WI.Canvas.ContextType.WebGPU:
switch (this._programType) {
case ShaderProgram.ProgramType.Compute:
format = WI.UIString("Compute Pipeline %d");
break;
case ShaderProgram.ProgramType.Render:
format = WI.UIString("Render Pipeline %d");
break;
}
break;
}
console.assert(format);
if (!this._uniqueDisplayNumber)
this._uniqueDisplayNumber = this._canvas.nextShaderProgramDisplayNumberForProgramType(this._programType);
return format.format(this._uniqueDisplayNumber);
}
get disabled()
{
return this._disabled;
}
set disabled(disabled)
{
console.assert(this._programType === ShaderProgram.ProgramType.Render);
console.assert(this._canvas.contextType === WI.Canvas.ContextType.WebGL || this._canvas.contextType === WI.Canvas.ContextType.WebGL2);
if (this._canvas.contextType === WI.Canvas.ContextType.WebGPU)
return;
if (this._disabled === disabled)
return;
this._disabled = disabled;
let target = WI.assumingMainTarget();
target.CanvasAgent.setShaderProgramDisabled(this._identifier, disabled);
this.dispatchEventToListeners(ShaderProgram.Event.DisabledChanged);
}
requestShaderSource(shaderType, callback)
{
console.assert(Object.values(ShaderProgram.ShaderType).includes(shaderType));
console.assert(ShaderProgram.programTypeSupportsShaderType(this._programType, shaderType));
let target = WI.assumingMainTarget();
// COMPATIBILITY (iOS 13): `content` was renamed to `source`.
target.CanvasAgent.requestShaderSource(this._identifier, shaderType, (error, source) => {
if (error) {
WI.reportInternalError(error);
callback(null);
return;
}
callback(source);
});
}
updateShader(shaderType, source)
{
console.assert(Object.values(ShaderProgram.ShaderType).includes(shaderType));
console.assert(ShaderProgram.programTypeSupportsShaderType(this._programType, shaderType));
let target = WI.assumingMainTarget();
target.CanvasAgent.updateShader(this._identifier, shaderType, source);
}
showHighlight()
{
console.assert(this._programType === ShaderProgram.ProgramType.Render);
console.assert(this._canvas.contextType === WI.Canvas.ContextType.WebGL || this._canvas.contextType === WI.Canvas.ContextType.WebGL2);
let target = WI.assumingMainTarget();
target.CanvasAgent.setShaderProgramHighlighted(this._identifier, true);
}
hideHighlight()
{
console.assert(this._programType === ShaderProgram.ProgramType.Render);
console.assert(this._canvas.contextType === WI.Canvas.ContextType.WebGL || this._canvas.contextType === WI.Canvas.ContextType.WebGL2);
let target = WI.assumingMainTarget();
target.CanvasAgent.setShaderProgramHighlighted(this._identifier, false);
}
};
WI.ShaderProgram.ProgramType = {
Compute: "compute",
Render: "render",
};
WI.ShaderProgram.ShaderType = {
Compute: "compute",
Fragment: "fragment",
Vertex: "vertex",
};
WI.ShaderProgram.Event = {
DisabledChanged: "shader-program-disabled-changed",
};