{"version":3,"sources":["jsdelivr-header.js","/npm/pex-context@4.1.0/index.js"],"names":[],"mappings":"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","file":"/npm/pex-context@4.1.0/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/pex-context@4.1.0/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import createGL from \"pex-gl\";\n\nimport createTexture from \"./texture.js\";\nimport createFramebuffer from \"./framebuffer.js\";\nimport createRenderbuffer from \"./renderbuffer.js\";\nimport createPass from \"./pass.js\";\nimport createPipeline from \"./pipeline.js\";\nimport createVertexArray from \"./vertex-array.js\";\nimport createTransformFeedback from \"./transform-feedback.js\";\nimport createProgram from \"./program.js\";\nimport createBuffer from \"./buffer.js\";\nimport createQuery from \"./query.js\";\n\nimport {\n  checkProps,\n  isWebGL2 as checkWebGL2Context,\n  compareFBOAttachments,\n  draw,\n  enableVertexData,\n  getUniformLocation,\n  is2DArray,\n  NAMESPACE,\n} from \"./utils.js\";\nimport polyfill from \"./polyfill.js\";\nimport { addEnums } from \"./types.js\";\n\nlet ID = 0;\n\nconst allowedCommandProps = [\n  \"name\",\n  \"pass\",\n  \"pipeline\",\n  \"uniforms\",\n  \"attributes\",\n  \"indices\",\n  \"count\",\n  \"first\",\n  \"baseVertex\",\n  \"baseInstance\",\n  \"multiDraw\",\n  \"instances\",\n  \"vertexArray\",\n  \"transformFeedback\",\n  \"viewport\",\n  \"scissor\",\n];\n\n/**\n * Create a context object\n * @param {import(\"./types.js\").PexContextOptions & import(\"pex-gl\").Options} [options]\n * @returns {ctx}\n */\nfunction createContext(options = {}) {\n  const opts = {\n    pixelRatio: 1,\n    type: \"webgl2\",\n    ...options,\n  };\n\n  if (options.pixelRatio) {\n    opts.pixelRatio = Math.min(opts.pixelRatio, window.devicePixelRatio);\n  }\n\n  const gl = opts.gl || createGL(opts);\n  console.assert(gl, \"pex-context: createContext failed\");\n  const isWebGL2 = checkWebGL2Context(gl);\n\n  /**\n   * @namespace ctx\n   */\n  const ctx = {\n    /**\n     * The `RenderingContext` returned by `pex-gl`\n     * @memberof ctx\n     */\n    gl,\n    /**\n     * Max capabilities and extensions availability. See {@link #capabilitiesTable|Capabilities Table}.\n     * @memberof ctx\n     */\n    capabilities: {\n      isWebGL2,\n      maxColorAttachments: 1,\n      maxTextureImageUnits: gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS),\n      maxSamples: isWebGL2 ? gl.getParameter(gl.MAX_SAMPLES) : 0,\n      maxVertexTextureImageUnits: gl.getParameter(\n        gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS,\n      ),\n      maxVertexAttribs: gl.getParameter(gl.MAX_VERTEX_ATTRIBS),\n      maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),\n      maxCubeMapTextureSize: gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE),\n      depthTexture: isWebGL2 || !!gl.getExtension(\"WEBGL_depth_texture\"),\n      shaderTextureLod: isWebGL2 || !!gl.getExtension(\"EXT_shader_texture_lod\"),\n      textureFloat: isWebGL2 || !!gl.getExtension(\"OES_texture_float\"),\n      textureFloatLinear: !!gl.getExtension(\"OES_texture_float_linear\"),\n      textureHalfFloat: isWebGL2 || !!gl.getExtension(\"OES_texture_half_float\"),\n      textureHalfFloatLinear:\n        isWebGL2 || !!gl.getExtension(\"OES_texture_half_float_linear\"),\n      textureFilterAnisotropic: !!gl.getExtension(\n        \"EXT_texture_filter_anisotropic\",\n      ),\n      sRGB: isWebGL2 || !!gl.getExtension(\"EXT_sRGB\"),\n      disjointTimerQuery: !!(\n        gl.getExtension(\"EXT_disjoint_timer_query_webgl2\") ||\n        gl.getExtension(\"EXT_disjoint_timer_query\")\n      ),\n      // Note: supported color buffer types vary\n      colorBufferFloat: isWebGL2\n        ? !!gl.getExtension(\"EXT_color_buffer_float\")\n        : !!gl.getExtension(\"WEBGL_color_buffer_float\"),\n      colorBufferHalfFloat: !!gl.getExtension(\"EXT_color_buffer_half_float\"),\n      floatBlend: !!gl.getExtension(\"EXT_float_blend\"),\n      multiDraw: !!gl.getExtension(\"WEBGL_multi_draw\"),\n      drawInstancedBase: !!gl.getExtension(\n        \"WEBGL_draw_instanced_base_vertex_base_instance\",\n      ),\n      multiDrawInstancedBase: !!gl.getExtension(\n        \"WEBGL_multi_draw_instanced_base_vertex_base_instance\",\n      ),\n    },\n    /**\n     * Getter for `gl.drawingBufferWidth`\n     * @memberof ctx\n     * @returns {number}\n     */\n    get width() {\n      return gl.drawingBufferWidth;\n    },\n    /**\n     * Getter for `gl.drawingBufferHeight`\n     * @memberof ctx\n     * @returns {number}\n     */\n    get height() {\n      return gl.drawingBufferHeight;\n    },\n  };\n\n  polyfill(ctx);\n  addEnums(ctx);\n\n  const defaultState = {\n    pass: {\n      framebuffer: {\n        id: `framebuffer_${ID++}`,\n        target: gl.FRAMEBUFFER,\n        handle: null,\n        width: gl.drawingBufferWidth,\n        height: gl.drawingBufferHeight,\n      },\n      clearColor: [0, 0, 0, 1],\n      clearDepth: 1,\n    },\n    pipeline: createPipeline(ctx, {}),\n    viewport: [0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight],\n    scissor: null,\n    count: 0,\n    framebuffer: undefined,\n    indexBuffer: undefined,\n    activeAttributes: undefined,\n    activeTextures: undefined,\n    vertexArray: undefined,\n    vertexLayout: undefined,\n    program: undefined,\n    cullFace: undefined,\n    cullFaceMode: undefined,\n    blend: undefined,\n    blendSrcRGBFactor: undefined,\n    blendSrcAlphaFactor: undefined,\n    blendDstRGBFactor: undefined,\n    blendDstAlphaFactor: undefined,\n    depthFunc: undefined,\n    depthTest: undefined,\n    depthWrite: undefined,\n  };\n\n  Object.assign(ctx, {\n    isDisposed: false,\n    debugMode: false,\n    debugCommands: [],\n    resources: [],\n    stats: {},\n    queries: [],\n    stack: [defaultState],\n    defaultState,\n    pixelRatio: opts.pixelRatio,\n    state: {\n      framebuffer: defaultState.pass.framebuffer,\n      pipeline: createPipeline(ctx, {}),\n      activeTextures: [],\n      activeAttributes: [],\n    },\n    getGLString(glEnum) {\n      let str = \"UNDEFINED\";\n      for (let key in gl) {\n        if (gl[key] === glEnum) {\n          str = key;\n          break;\n        }\n      }\n      return str;\n    },\n    checkError() {\n      if (this.debugMode) {\n        const error = gl.getError();\n        if (error) {\n          this.debugMode = false; // prevents rolling errors\n          console.debug(NAMESPACE, \"state\", this.state);\n          throw new Error(`GL error ${error}: ${this.getGLString(error)}`);\n        }\n      }\n    },\n    resource(res) {\n      res.id = `${res.class}_${ID++}`;\n      this.stats[res.class] ||= { alive: 0, total: 0 };\n      this.stats[res.class].alive++;\n      this.stats[res.class].total++;\n      this.resources.push(res);\n      this.checkError();\n      return res;\n    },\n\n    // Public API\n\n    /**\n     * Set the context size and pixelRatio\n     * The new size and resolution will not be applied immediately but before drawing the next frame to avoid flickering.\n     * Context's canvas doesn't resize automatically, even if you don't pass width/height on init and the canvas is assigned the dimensions of the window. To handle resizing use the following code:\n     * ```js\n     * window.addEventListener('resize', () => {\n     *   ctx.set({ width: window.innerWidth, height: window.innerHeight });\n     * })\n     * ```\n     * @memberof ctx\n     * @param {import(\"./types.js\").PexContextSetOptions} options\n     */\n    set({ pixelRatio, width, height }) {\n      if (pixelRatio) {\n        this.updatePixelRatio = Math.min(pixelRatio, window.devicePixelRatio);\n      }\n\n      if (width) {\n        this.updateWidth = width;\n      }\n\n      if (height) {\n        this.updateHeight = height;\n      }\n    },\n\n    /**\n     * Enable debug mode\n     * @param {boolean} [enabled]\n     * @memberof ctx\n     */\n    debug(enabled) {\n      this.debugMode = enabled;\n      if (enabled) this.debugCommands = [];\n    },\n\n    /**\n     * Render Loop\n     * @memberof ctx\n     * @param {Function} cb Request Animation Frame callback\n     */\n    frame(cb) {\n      requestAnimationFrame(\n        function frame() {\n          if (this.updatePixelRatio) {\n            this.pixelRatio = this.updatePixelRatio;\n            // we need to reaply width/height and update styles\n            if (!this.updateWidth) {\n              this.updateWidth =\n                parseInt(gl.canvas.style.width) || gl.canvas.width;\n            }\n            if (!this.updateHeight) {\n              this.updateHeight =\n                parseInt(gl.canvas.style.height) || gl.canvas.height;\n            }\n            this.updatePixelRatio = 0;\n          }\n          if (this.updateWidth) {\n            gl.canvas.style.width = `${this.updateWidth}px`;\n            gl.canvas.width = this.updateWidth * this.pixelRatio;\n            this.updateWidth = 0;\n          }\n          if (this.updateHeight) {\n            gl.canvas.style.height = `${this.updateHeight}px`;\n            gl.canvas.height = this.updateHeight * this.pixelRatio;\n            this.updateHeight = 0;\n          }\n          if (\n            this.defaultState.viewport[2] !== gl.drawingBufferWidth ||\n            this.defaultState.viewport[3] !== gl.drawingBufferHeight\n          ) {\n            this.defaultState.viewport[2] = gl.drawingBufferWidth;\n            this.defaultState.viewport[3] = gl.drawingBufferHeight;\n            this.defaultState.pass.framebuffer.width = gl.drawingBufferWidth;\n            this.defaultState.pass.framebuffer.height = gl.drawingBufferHeight;\n            gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n          }\n          if (this.isDisposed || cb() === false) return; // interrupt render loop\n          if (this.queries.length) {\n            this.queries = this.queries.filter((q) => !q._available(this, q));\n          }\n          requestAnimationFrame(frame.bind(this));\n        }.bind(this),\n      );\n    },\n\n    /**\n     * Submit a command to the GPU.\n     * Commands are plain js objects with GPU resources needed to complete a draw call.\n     *\n     * ```js\n     * const cmd = {\n     *   pass: Pass\n     *   pipeline: Pipeline,\n     *   attributes: { name:  VertexBuffer | { buffer: VertexBuffer, offset: number, stride: number } },\n     *   indices: IndexBuffer | { buffer: IndexBuffer, offset: number, count: number },\n     *   // or\n     *   count: number,\n     *   instances: number,\n     *   uniforms: { name: number, name: Array, name: Texture2D },\n     *   viewport: [0, 0, 1920, 1080],\n     *   scissor: [0, 0, 1920, 1080]\n     * }\n     * ```\n     *\n     * _Note: Either indices or count need to be specified when drawing geometry._\n     * _Note: Scissor region is by default set to null and scissor test disabled._\n     *\n     * @example\n     *\n     * - `ctx.submit(cmd, opts)`: submit partially updated command without modifying the original one.\n     * ```js\n     * // Draw mesh with custom color\n     * ctx.submit(cmd, {\n     *   uniforms: {\n     *     uColor: [1, 0, 0, 0]\n     *   }\n     * })\n     * ```\n     *\n     * - `ctx.submit(cmd, [opts1, opts2, opts3...])`: submit a batch of commands differences in opts.\n     * ```js\n     * // Draw same mesh twice with different material and position\n     * ctx.submit(cmd, [\n     *   { pipeline: material1, uniforms: { uModelMatrix: position1 },\n     *   { pipeline: material2, uniforms: { uModelMatrix: position2 }\n     * ])\n     * ```\n     *\n     * - `ctx.submit(cmd, cb)`: submit command while preserving state from another command. This approach allows to simulate state stack with automatic cleanup at the end of callback.\n     * ```js\n     * // Render to texture\n     * ctx.submit(renderToFboCmd, () => {\n     *   ctx.submit(drawMeshCmd)\n     * })\n     * ```\n     *\n     * @memberof ctx\n     * @param {import(\"./types.js\").PexCommand} cmd\n     * @param {import(\"./types.js\").PexCommand | import(\"./types.js\").PexCommand[]} [batches]\n     * @param {import(\"./types.js\").PexCommand} [subCommand]\n     */\n    submit(cmd, batches, subCommand) {\n      const prevFramebufferId = this.state.framebuffer?.id;\n      if (this.debugMode) {\n        checkProps(allowedCommandProps, cmd);\n\n        console.debug(NAMESPACE, \"submit\", cmd.name || cmd.id, {\n          depth: this.stack.length,\n          cmd,\n          batches,\n          subCommand,\n          state: this.state,\n          stack: this.stack,\n        });\n      }\n\n      if (batches) {\n        if (Array.isArray(batches)) {\n          // TODO: quick hack\n          for (const batch of batches) {\n            this.submit(this.mergeCommands(cmd, batch, true), subCommand);\n          }\n\n          return;\n        } else if (typeof batches === \"object\") {\n          this.submit(this.mergeCommands(cmd, batches, true), subCommand);\n          return;\n        } else {\n          subCommand = batches; // shift argument\n        }\n      }\n\n      const parentState = this.stack[this.stack.length - 1];\n      const cmdState = this.mergeCommands(parentState, cmd, false);\n      this.apply(cmdState);\n\n      if (this.debugMode) {\n        const currFramebufferId = this.state.framebuffer?.id;\n        const framebufferCanged = prevFramebufferId != currFramebufferId;\n        console.debug(\n          NAMESPACE,\n          \"fbo-state\",\n          \"  \".repeat(this.stack.length),\n          cmd.name,\n          framebufferCanged\n            ? `${prevFramebufferId} -> ${currFramebufferId}`\n            : currFramebufferId,\n          [...this.state.viewport],\n          this.state.scissor ? [...this.state.scissor] : \"[]\",\n        );\n\n        cmdState.debugId = this.debugCommands.length;\n        this.debugCommands.push({\n          cmd,\n          cmdState,\n          parentState,\n        });\n      }\n\n      if (subCommand) {\n        this.stack.push(cmdState);\n        subCommand();\n        this.stack.pop();\n      }\n\n      if (cmd.pass?.resolveFramebuffer) {\n        this.resolvePass(cmd.pass);\n      }\n\n      this.checkError();\n    },\n\n    program(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"program\", opts);\n      return this.resource(createProgram(this, opts));\n    },\n\n    /**\n     * Passes are responsible for setting render targets (textures) and their clearing values.\n     * FBOs are created internally and automatically.\n     * @memberof ctx\n     * @param {import(\"./pass.js\").PassOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const pass = ctx.pass({\n     *   color: [Texture2D, ...]\n     *   color: [{ texture: Texture2D | TextureCube, target: CubemapFace }, ...]\n     *   depth: Texture2D\n     *   clearColor: Array | Array[],\n     *   clearDepth: number,\n     * })\n     * ```\n     */\n    pass(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"pass\", opts);\n      return this.resource(createPass(this, opts));\n    },\n\n    /**\n     * Pipelines represent the state of the GPU rendering pipeline (shaders, blending, depth test etc).\n     * @memberof ctx\n     * @param {import(\"./pipeline.js\").PipelineOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     *  @example\n     * ```js\n     * const pipeline = ctx.pipeline({\n     *   vert: string,\n     *   frag: string,\n     *   depthWrite: boolean,\n     *   depthTest: boolean,\n     *   depthFunc: DepthFunc,\n     *   blend: boolean,\n     *   blendSrcRGBFactor: BlendFactor,\n     *   blendSrcAlphaFactor: BlendFactor,\n     *   blendDstRGBFactor: BlendFactor,\n     *   blendDstAlphaFactor: BlendFactor,\n     *   cullFace: boolean,\n     *   cullFaceMode: Face,\n     *   colorMask: Array,\n     *   primitive: Primitive\n     * })\n     * ```\n     */\n    pipeline(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"pipeline\", opts);\n      return this.resource(createPipeline(this, opts));\n    },\n\n    /**\n     * Create a VAO resource.\n     * @memberof ctx\n     * @param {import(\"./vertex-array.js\").VertexArrayOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const vertexLayout = {\n     *   aPosition: { location: 0, type: \"vec3\" },\n     *   aNormal: { location: 1, type: \"vec3\" },\n     * };\n     *\n     * const drawCmd = {\n     *   pipeline: ctx.pipeline({\n     *     vertexLayout,\n     *     // ...\n     *   }),\n     *   vertexArray: ctx.vertexArray({\n     *     vertexLayout,\n     *     attributes: {\n     *       aPosition: ctx.vertexBuffer(geom.positions),\n     *       aNormal: { buffer: ctx.vertexBuffer(geom.normals) },\n     *     },\n     *     indices: ctx.indexBuffer(geom.cells),\n     *   }),\n     *   // ...\n     * };\n     * ```\n     */\n    vertexArray(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"vertexArray\", opts);\n      return this.resource(createVertexArray(this, opts));\n    },\n\n    /**\n     * Create a transform feedback\n     * @memberof ctx\n     * @param {import(\"./transform-feedback.js\").TransformFeedbackOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const tex = ctx.transformFeedback({\n     *   varyings: {\n     *     outPosition: positionsBuf,\n     *   },\n     * })\n     * ```\n     */\n    transformFeedback(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"transformFeedback\", opts);\n      return this.resource(createTransformFeedback(this, opts));\n    },\n\n    /**\n     * Create a 2D Texture resource.\n     * @memberof ctx\n     * @param {HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | import(\"./texture.js\").TextureOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const tex = ctx.texture2D({\n     *   data: [255, 255, 255, 255, 0, 0, 0, 255],\n     *   width: 2,\n     *   height: 1,\n     *   pixelFormat: ctx.PixelFormat.RGBA8,\n     *   wrap: ctx.Wrap.Repeat\n     * })\n     * ```\n     */\n    texture2D(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"texture2D\", opts);\n      opts.target = gl.TEXTURE_2D;\n      return this.resource(createTexture(this, opts));\n    },\n    /**\n     * Create a 2D Texture Array resource.\n     * @memberof ctx\n     * @param {HTMLImageElement[] | HTMLVideoElement[] | HTMLCanvasElement[] | import(\"./texture.js\").TextureOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const tex = ctx.texture2DArray({\n     *   data: [img, img, img],\n     * })\n     * ```\n     */\n    texture2DArray(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"texture2DArray\", opts);\n      opts.target = gl.TEXTURE_2D_ARRAY;\n      return this.resource(createTexture(this, opts));\n    },\n    /**\n     * Create a 2D Texture cube resource.\n     * @memberof ctx\n     * @param {import(\"./texture.js\").TextureCubeOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const tex = ctx.textureCube({\n     *   data: [posx, negx, posy, negy, posz, negz],\n     *   width: 64,\n     *   height: 64\n     * ])\n     * ```\n     */\n    textureCube(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"textureCube\", opts);\n      opts.target = gl.TEXTURE_CUBE_MAP;\n      return this.resource(createTexture(this, opts));\n    },\n    // framebuffer({ color: [ Texture2D, .. ], depth: Texture2D }\n    // framebuffer({ color: [ { texture: Texture2D, target: Enum, level: int }, .. ], depth: { texture: Texture2D }})\n    framebuffer(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"framebuffer\", opts);\n      return this.resource(createFramebuffer(this, opts));\n    },\n\n    /**\n     * Renderbuffers represent pixel data store for rendering operations.\n     * @memberof ctx\n     * @param {import(\"./renderbuffer.js\").RenderbufferOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const tex = ctx.renderbuffer({\n     *   width: 1280,\n     *   height: 720,\n     *   pixelFormat: ctx.PixelFormat.DEPTH_COMPONENT16\n     * })\n     * ```\n     */\n    renderbuffer(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"renderbuffer\", opts);\n      return this.resource(createRenderbuffer(this, opts));\n    },\n\n    // TODO: Should we have named versions or generic 'ctx.buffer' command?\n    // In regl buffer() is ARRAY_BUFFER (aka VertexBuffer) and elements() is ELEMENT_ARRAY_BUFFER\n    // Now in WebGL2 we get more types Uniform, TransformFeedback, Copy\n    // Possible options: {\n    //    data: Array or ArrayBuffer\n    //    type: 'float', 'uint16' etc\n    // }\n\n    /**\n     * Create an attribute buffer (ARRAY_BUFFER) resource. Stores vertex data in the GPU memory.\n     * @memberof ctx\n     * @param {import(\"./buffer.js\").BufferOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const vertexBuffer = ctx.vertexBuffer({ data: Array|TypedArray|ArrayBuffer })\n     * ```\n     */\n    vertexBuffer(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"vertexBuffer\", opts);\n      if (opts.length) opts = { data: opts };\n      opts.target = gl.ARRAY_BUFFER;\n      return this.resource(createBuffer(this, opts));\n    },\n    /**\n     * Create an index buffer (ELEMENT_ARRAY_BUFFER) resource. Stores index data in the GPU memory.\n     * @memberof ctx\n     * @param {import(\"./buffer.js\").BufferOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const indexBuffer = ctx.vertexBuffer({ data: Array|TypedArray|ArrayBuffer })\n     * ```\n     */\n    indexBuffer(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"indexBuffer\", opts);\n      if (opts.length) opts = { data: opts };\n      opts.target = gl.ELEMENT_ARRAY_BUFFER;\n      return this.resource(createBuffer(this, opts));\n    },\n\n    /**\n     * Queries can be used for GPU timers.\n     * @memberof ctx\n     * @param {import(\"./query.js\").QueryOptions} opts\n     * @returns {import(\"./types.js\").PexResource}\n     *\n     * @example\n     * ```js\n     * const query = ctx.query({\n     *   target: QueryTarget\n     * })\n     * ```\n     */\n    query(opts) {\n      if (this.debugMode) console.debug(NAMESPACE, \"query\", opts);\n      return this.resource(createQuery(this, opts));\n    },\n    /**\n     * Begin the query measurement.\n     * @memberof ctx\n     * @param {import(\"./query.js\").PexQuery} query\n     * _Note: There can be only one query running at the time._\n     */\n    beginQuery(query) {\n      console.assert(\n        !this.activeQuery,\n        \"Only one query can be active at the time\",\n      );\n      if (query._begin(this, query)) {\n        this.activeQuery = query;\n      }\n    },\n    /**\n     * End the query measurement.\n     * @memberof ctx\n     * @param {import(\"./query.js\").PexQuery} query\n     * _Note: The result is not available immediately and will be `null` until the state changes from `ctx.QueryState.Pending` to `ctx.QueryState.Ready`._\n     */\n    endQuery(query) {\n      if (query._end(this, query)) {\n        this.queries.push(query);\n        this.activeQuery = null;\n      }\n    },\n\n    /**\n     * Helper to read a block of pixels from a specified rectangle of the current color framebuffer.\n     * @memberof ctx\n     * @param {{ x: number, y: number, width: number, height: number }} viewport\n     * @returns {Uint8Array}\n     */\n    readPixels({ x = 0, y = 0, width, height }) {\n      const pixels = new Uint8Array(width * height * 4);\n      gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);\n      return pixels;\n    },\n\n    /**\n     * Update a resource.\n     * @memberof ctx\n     * @param {import(\"./types.js\").PexResource} resource\n     * @param {object} opts\n     *\n     * @example\n     * ```js\n     * ctx.update(buffer, { data: [] })\n     *\n     * ctx.update(texture, {\n     *   width: 1,\n     *   height: 1,\n     *   data: new Uint8Array([255, 0, 0, 255])\n     * })\n     * ```\n     */\n    update(resource, opts) {\n      if (this.debugMode) {\n        console.debug(NAMESPACE, \"update\", { resource, opts });\n      }\n      resource._update(this, resource, opts);\n    },\n\n    /**\n     * Delete one or all resource(s). Disposed resources are no longer valid for use.\n     * @memberof ctx\n     * @param {import(\"./types.js\").PexResource} [resource]\n     *\n     * @example\n     *\n     * Delete all allocated resources:\n     * ```js\n     * ctx.dispose()\n     * ```\n     *\n     * Delete a single resource:\n     * ```js\n     * ctx.dispose(texture)\n     * ```\n     * _Note: Framebuffers are ref counted and released by Pass. Programs are also ref counted and released by Pipeline._\n     */\n    dispose(resource) {\n      if (this.debugMode) console.debug(NAMESPACE, \"dispose\", resource);\n      console.assert(\n        resource || arguments.length === 0,\n        \"Trying to dispose undefined resource\",\n      );\n      if (resource) {\n        if (!resource._dispose) {\n          console.assert(resource._dispose, \"Trying to dispose non resource\");\n        }\n        const idx = this.resources.indexOf(resource);\n        console.assert(\n          idx !== -1,\n          \"Trying to dispose resource from another context\",\n        );\n        this.resources.splice(idx, 1);\n        this.stats[resource.class].alive--;\n        resource._dispose();\n      } else {\n        this.isDisposed = true;\n        while (this.resources.length) {\n          this.dispose(this.resources[0]);\n        }\n        this.gl.canvas.width = 1;\n        this.gl.canvas.height = 1;\n      }\n    },\n\n    // Private API\n    // TODO: i don't like this inherit flag\n    mergeCommands(parent, cmd, inherit) {\n      // copy old state so we don't modify it's internals\n      const newCmd = Object.assign({}, parent);\n\n      if (!inherit) {\n        // clear values are not merged as they are applied only in the parent command\n        newCmd.pass = Object.assign({}, parent.pass);\n        newCmd.pass.clearColor = undefined;\n        newCmd.pass.clearDepth = undefined;\n      }\n\n      // overwrite properties from new command\n      Object.assign(newCmd, cmd);\n\n      // set viewport to FBO sizes when rendering to a texture\n      if (!cmd.viewport && cmd.pass && cmd.pass.opts.color) {\n        let tex = null;\n        if (cmd.pass.opts.color[0]) {\n          tex = cmd.pass.opts.color[0].texture || cmd.pass.opts.color[0];\n        }\n        if (cmd.pass.opts.depth) {\n          tex = cmd.pass.opts.depth.texture || cmd.pass.opts.depth;\n        }\n        if (tex) {\n          newCmd.viewport = [0, 0, tex.width, tex.height];\n        }\n      }\n\n      // merge uniforms\n      newCmd.uniforms =\n        parent.uniforms || cmd.uniforms\n          ? Object.assign({}, parent.uniforms, cmd.uniforms)\n          : null;\n      return newCmd;\n    },\n    applyPass(pass) {\n      const state = this.state;\n\n      // Need to find reliable way of deciding if i should update framebuffer\n      // 1. If pass has fbo, bind it\n      // 3. Else if there is another framebuffer on stack (currently bound) leave it\n      // 3. Else if there is only screen framebuffer on the stack and currently bound fbo is different, change it\n      // 4. TODO: If there is pass with fbo and another fbo on stack throw error (no interleaved passes are allowed)\n      if (pass.framebuffer) {\n        let framebuffer = pass.framebuffer;\n        if (framebuffer.id !== state.framebuffer.id) {\n          if (this.debugMode) {\n            console.debug(\n              NAMESPACE,\n              \"change framebuffer\",\n              state.framebuffer,\n              \"->\",\n              framebuffer,\n            );\n          }\n          if (\n            framebuffer._update &&\n            !compareFBOAttachments(framebuffer, pass.opts)\n          ) {\n            this.update(pass.framebuffer, pass.opts);\n          }\n          ctx.state.framebuffer = framebuffer;\n          gl.bindFramebuffer(framebuffer.target, framebuffer.handle);\n          if (framebuffer.drawBuffers && framebuffer.drawBuffers.length > 1) {\n            gl.drawBuffers(framebuffer.drawBuffers);\n          }\n        }\n      } else {\n        // inherit framebuffer from parent command\n        // if pass doesn't specify color or depth attachments\n        // and therefore doesn't have own framebuffer assigned\n        let framebuffer;\n        let i = ctx.stack.length - 1;\n        while (!framebuffer && i >= 0) {\n          if (ctx.stack[i].pass) {\n            framebuffer = ctx.stack[i].pass.framebuffer;\n          }\n          --i;\n        }\n        if (\n          framebuffer == ctx.defaultState.pass.framebuffer &&\n          ctx.state.framebuffer !== framebuffer\n        ) {\n          ctx.state.framebuffer = framebuffer;\n          gl.bindFramebuffer(framebuffer.target, framebuffer.handle);\n        }\n      }\n\n      this.checkError();\n    },\n    resolvePass: (pass) => {\n      const resolveFramebuffer = pass.resolveFramebuffer;\n      ctx.state.framebuffer = resolveFramebuffer;\n\n      // bind buffer for writing to\n      gl.bindFramebuffer(resolveFramebuffer.target, resolveFramebuffer.handle);\n\n      // bind buffer for reading from\n      gl.bindFramebuffer(gl.READ_FRAMEBUFFER, pass.framebuffer.handle);\n\n      let drawBuffers = resolveFramebuffer.color\n        ? resolveFramebuffer.color.map(() => gl.NONE)\n        : null;\n      // i = -1 is depth buffer, doing it so we can have only one for loop\n      const startIndex = resolveFramebuffer.depth ? -1 : 0;\n      for (let i = startIndex; i < resolveFramebuffer.color.length; i++) {\n        const isDepth = i == -1;\n        const attachment = isDepth\n          ? resolveFramebuffer.depth?.texture\n          : resolveFramebuffer.color[i].texture;\n        const mask = isDepth ? gl.DEPTH_BUFFER_BIT : gl.COLOR_BUFFER_BIT;\n        const filter = isDepth ? gl.NEAREST : gl.LINEAR;\n        if (i >= 0) {\n          // attachment we writing to, only one\n          drawBuffers[i] = gl.COLOR_ATTACHMENT0 + i;\n          gl.drawBuffers(drawBuffers);\n          // attachment we are reading from\n          gl.readBuffer(\n            gl.COLOR_ATTACHMENT0 + resolveFramebuffer.color[i].sourceIndex,\n          );\n        }\n        gl.blitFramebuffer(\n          0,\n          0,\n          attachment.width,\n          attachment.height,\n          0,\n          0,\n          attachment.width,\n          attachment.height,\n          mask,\n          filter,\n        );\n        if (i >= 0) {\n          // skip already written buffer on next write as we can only blit one attachment at the time\n          drawBuffers[i] = gl.NONE;\n          if (resolveFramebuffer.color[i].texture.mipmap) {\n            ctx.update(pass.resolveFramebuffer.color[i].texture, {\n              mipmap: true,\n            });\n          }\n        }\n      }\n      gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);\n    },\n    applyViewport(viewport) {\n      if (viewport && viewport !== this.state.viewport) {\n        this.state.viewport = viewport;\n        gl.viewport(\n          this.state.viewport[0],\n          this.state.viewport[1],\n          this.state.viewport[2],\n          this.state.viewport[3],\n        );\n      }\n\n      this.checkError();\n    },\n    applyScissor(scissor) {\n      if (scissor) {\n        if (scissor !== this.state.scissor) {\n          this.state.scissor = scissor;\n          gl.enable(gl.SCISSOR_TEST);\n          gl.scissor(\n            this.state.scissor[0],\n            this.state.scissor[1],\n            this.state.scissor[2],\n            this.state.scissor[3],\n          );\n        }\n      } else {\n        if (scissor !== this.state.scissor) {\n          this.state.scissor = scissor;\n          gl.disable(gl.SCISSOR_TEST);\n        }\n      }\n\n      this.checkError();\n    },\n    applyClear(pass) {\n      let clearBits = 0;\n      if (pass.clearColor !== undefined) {\n        if (this.debugMode) {\n          console.debug(NAMESPACE, \"clearing color\", pass.clearColor);\n        }\n\n        const clearValues = pass.clearColor;\n        const isClearBufferArray = is2DArray(clearValues);\n\n        if (isWebGL2 && isClearBufferArray) {\n          for (let i = 0; i < clearValues.length; i++) {\n            const color = clearValues[i];\n            if (color) gl.clearBufferfv(gl.COLOR, i, color);\n          }\n        } else {\n          clearBits |= gl.COLOR_BUFFER_BIT;\n          // TODO this might be unnecesary but we don't know because we don't store the clearColor in state\n          gl.clearColor(...(isClearBufferArray ? clearValues[0] : clearValues)); // Fallback in WebGL1 clearing all buffers\n        }\n      }\n\n      if (pass.clearDepth !== undefined) {\n        if (this.debugMode) {\n          console.debug(NAMESPACE, \"clearing depth\", pass.clearDepth);\n        }\n        clearBits |= gl.DEPTH_BUFFER_BIT;\n\n        if (!this.state.depthWrite) {\n          this.state.depthWrite = true;\n          gl.depthMask(true);\n        }\n        // TODO this might be unnecesary but we don't know because we don't store the clearDepth in state\n        gl.clearDepth(pass.clearDepth);\n      }\n\n      if (clearBits) gl.clear(clearBits);\n\n      this.checkError();\n    },\n    applyPipeline(pipeline) {\n      const state = this.state;\n\n      if (pipeline.depthWrite !== state.depthWrite) {\n        state.depthWrite = pipeline.depthWrite;\n        gl.depthMask(state.depthWrite);\n      }\n\n      if (pipeline.depthTest !== state.depthTest) {\n        state.depthTest = pipeline.depthTest;\n        state.depthTest ? gl.enable(gl.DEPTH_TEST) : gl.disable(gl.DEPTH_TEST);\n      }\n\n      if (pipeline.depthFunc !== state.depthFunc) {\n        state.depthFunc = pipeline.depthFunc;\n        gl.depthFunc(state.depthFunc);\n      }\n\n      if (\n        pipeline.blend !== state.blend ||\n        pipeline.blendSrcRGBFactor !== state.blendSrcRGBFactor ||\n        pipeline.blendSrcAlphaFactor !== state.blendSrcAlphaFactor ||\n        pipeline.blendDstRGBFactor !== state.blendDstRGBFactor ||\n        pipeline.blendDstAlphaFactor !== state.blendDstAlphaFactor\n      ) {\n        state.blend = pipeline.blend;\n        state.blendSrcRGBFactor = pipeline.blendSrcRGBFactor;\n        state.blendSrcAlphaFactor = pipeline.blendSrcAlphaFactor;\n        state.blendDstRGBFactor = pipeline.blendDstRGBFactor;\n        state.blendDstAlphaFactor = pipeline.blendDstAlphaFactor;\n        state.blend ? gl.enable(gl.BLEND) : gl.disable(gl.BLEND);\n        gl.blendFuncSeparate(\n          state.blendSrcRGBFactor,\n          state.blendDstRGBFactor,\n          state.blendSrcAlphaFactor,\n          state.blendDstAlphaFactor,\n        );\n      }\n\n      if (\n        pipeline.cullFace !== state.cullFace ||\n        pipeline.cullFaceMode !== state.cullFaceMode\n      ) {\n        state.cullFace = pipeline.cullFace;\n        state.cullFaceMode = pipeline.cullFaceMode;\n        state.cullFace ? gl.enable(gl.CULL_FACE) : gl.disable(gl.CULL_FACE);\n        if (state.cullFace) {\n          gl.cullFace(state.cullFaceMode);\n        }\n      }\n      if (\n        pipeline.colorMask[0] !== state.pipeline.colorMask[0] ||\n        pipeline.colorMask[1] !== state.pipeline.colorMask[1] ||\n        pipeline.colorMask[2] !== state.pipeline.colorMask[2] ||\n        pipeline.colorMask[3] !== state.pipeline.colorMask[3]\n      ) {\n        state.pipeline.colorMask[0] = pipeline.colorMask[0];\n        state.pipeline.colorMask[1] = pipeline.colorMask[1];\n        state.pipeline.colorMask[2] = pipeline.colorMask[2];\n        state.pipeline.colorMask[3] = pipeline.colorMask[3];\n        gl.colorMask(\n          pipeline.colorMask[0],\n          pipeline.colorMask[1],\n          pipeline.colorMask[2],\n          pipeline.colorMask[3],\n        );\n      }\n\n      if (pipeline.program !== state.program) {\n        state.program = pipeline.program;\n        if (state.program) {\n          gl.useProgram(state.program.handle);\n        }\n      }\n\n      if (pipeline.vertexLayout) state.vertexLayout = pipeline.vertexLayout;\n\n      this.checkError();\n    },\n    checkActiveProgram() {\n      if (!this.state.program) {\n        throw new Error(\"Trying to draw without an active program\");\n      }\n    },\n    applyUniforms(uniforms, cmd) {\n      this.checkActiveProgram();\n\n      const { program, activeTextures } = this.state;\n\n      let numTextures = 0;\n\n      const requiredUniforms = this.debugMode\n        ? Object.keys(program.uniforms)\n        : null;\n\n      for (const name in uniforms) {\n        let value = uniforms[name];\n        // TODO: find a better way to not trying to set unused uniforms that might have been inherited\n        if (!program.uniforms[name] && !program.uniforms[`${name}[0]`]) {\n          continue;\n        }\n        if (value === null || value === undefined) {\n          if (this.debugMode) console.debug(NAMESPACE, \"invalid command\", cmd);\n          throw new Error(`Can't set uniform \"${name}\" with a null value`);\n        }\n        // FIXME: uniform array hack\n        if (Array.isArray(value) && !program.uniforms[name]) {\n          if (this.debugMode) {\n            console.debug(\n              NAMESPACE,\n              \"unknown uniform\",\n              name,\n              Object.keys(program.uniforms),\n            );\n          }\n          for (let i = 0; i < value.length; i++) {\n            const nameIndex = `${name}[${i}]`;\n            program.setUniform(nameIndex, value[i]);\n            if (this.debugMode) {\n              requiredUniforms.splice(requiredUniforms.indexOf(nameIndex), 1);\n            }\n          }\n        } else if (value.target) {\n          // assuming texture\n          // FIXME: texture binding hack\n          const slot = numTextures++;\n          gl.activeTexture(gl.TEXTURE0 + slot);\n          if (activeTextures[slot] !== value) {\n            gl.bindTexture(value.target, value.handle);\n            activeTextures[slot] = value;\n          }\n          program.setUniform(name, slot);\n          if (this.debugMode) {\n            requiredUniforms.splice(requiredUniforms.indexOf(name), 1);\n          }\n        } else if (!value.length && typeof value === \"object\") {\n          if (this.debugMode) console.debug(NAMESPACE, \"invalid command\", cmd);\n          throw new Error(`Can't set uniform \"${name}\" with an Object value`);\n        } else {\n          program.setUniform(name, value);\n          if (this.debugMode) {\n            requiredUniforms.splice(requiredUniforms.indexOf(name), 1);\n          }\n        }\n      }\n      if (this.debugMode && requiredUniforms.length > 0) {\n        console.debug(NAMESPACE, \"invalid command\", cmd);\n        throw new Error(\n          `Trying to draw with missing uniforms: ${requiredUniforms.join(\", \")}`,\n        );\n      }\n      this.checkError();\n    },\n    applyTransformFeedback(transformFeedback) {\n      const { program } = this.state;\n\n      if (!program.varyings) {\n        program.varyings = Object.keys(transformFeedback.varyings);\n\n        gl.transformFeedbackVaryings(\n          program.handle,\n          program.varyings,\n          transformFeedback.bufferMode,\n        );\n        gl.linkProgram(program.handle);\n\n        Object.keys(program.uniforms).forEach((name) => {\n          program.uniforms[name].location = getUniformLocation(\n            gl,\n            program,\n            name,\n          );\n        });\n        this.checkError();\n      }\n    },\n    drawVertexData(cmd) {\n      this.checkActiveProgram();\n\n      const { vertexLayout, program, vertexArray } = this.state;\n\n      if (this.debugMode) {\n        // TODO: can vertex layout be ever different if it's derived from pipeline's shader?\n        if (\n          Object.keys(vertexLayout).length !==\n          Object.keys(program.attributes).length\n        ) {\n          console.debug(\n            NAMESPACE,\n            \"Invalid vertex layout not matching the shader\",\n            vertexLayout,\n            program.attributes,\n            cmd,\n          );\n          throw new Error(\n            \"Invalid vertex layout not matching the shader. Is any attribute not used in the shader?\",\n          );\n        }\n      }\n\n      if (cmd.vertexArray) {\n        //TODO: verify vertex layout\n        for (let i = 0; i < vertexLayout.length; i++) {\n          const [name, location] = vertexLayout[i];\n          if (\n            !cmd.vertexArray.attributes[name] ||\n            !cmd.vertexArray.attributes[name].location === location\n          ) {\n            if (this.debugMode) {\n              console.debug(\n                NAMESPACE,\n                \"invalid command\",\n                cmd,\n                \"vertex array doesn't satisfy vertex layout\",\n                vertexLayout,\n              );\n            }\n            throw new Error(\n              `Command is missing attribute \"${name}\" at location ${location}`,\n            );\n          }\n        }\n\n        if (vertexArray !== cmd.vertexArray.handle) {\n          this.state.vertexArray = cmd.vertexArray.handle;\n          gl.bindVertexArray(cmd.vertexArray.handle);\n        }\n        if (cmd.vertexArray.indices) {\n          let indexBuffer = cmd.vertexArray.indices.buffer;\n          if (!indexBuffer && cmd.vertexArray.indices.class === \"indexBuffer\") {\n            indexBuffer = cmd.vertexArray.indices;\n          }\n          this.state.indexBuffer = indexBuffer;\n        }\n      } else {\n        if (this.state.vertexArray !== undefined) {\n          this.state.vertexArray = undefined;\n          gl.bindVertexArray(null);\n        }\n\n        // Sets ctx.state.indexBuffer and ctx.state.activeAttributes\n        enableVertexData(ctx, vertexLayout, cmd, true);\n      }\n\n      if (cmd.transformFeedback) {\n        gl.enable(gl.RASTERIZER_DISCARD);\n        gl.bindTransformFeedback(\n          gl.TRANSFORM_FEEDBACK,\n          cmd.transformFeedback.handle,\n        );\n        gl.beginTransformFeedback(cmd.transformFeedback.primitiveMode);\n      }\n\n      draw(ctx, cmd);\n\n      if (cmd.transformFeedback) {\n        gl.endTransformFeedback();\n        gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);\n        gl.disable(gl.RASTERIZER_DISCARD);\n      }\n\n      this.checkError();\n    },\n\n    // TODO: switching to lightweight resources would allow to just clone state\n    // and use commands as state modifiers?\n    apply(cmd) {\n      if (this.debugMode) {\n        console.debug(NAMESPACE, \"apply\", cmd.name || cmd.id, {\n          cmd,\n          state: JSON.parse(JSON.stringify(this.state)),\n        });\n      }\n\n      this.checkError();\n\n      if (cmd.pass) this.applyPass(cmd.pass);\n\n      this.applyViewport(cmd.viewport);\n      this.applyScissor(cmd.scissor);\n\n      if (cmd.pass) this.applyClear(cmd.pass);\n\n      if (cmd.pipeline) this.applyPipeline(cmd.pipeline);\n\n      if (cmd.transformFeedback) {\n        this.applyTransformFeedback(cmd.transformFeedback);\n      }\n\n      if (cmd.uniforms) this.applyUniforms(cmd.uniforms);\n\n      if (cmd.attributes || cmd.vertexArray) this.drawVertexData(cmd);\n    },\n  });\n\n  if (opts.debug) ctx.debug(true);\n  console.debug(NAMESPACE, \"capabilities\", ctx.capabilities);\n\n  ctx.apply(defaultState);\n  return ctx;\n}\n\nexport default createContext;\n"]}