All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.badlogic.gdx.backends.gwt.GwtGL30 Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright 2022 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.badlogic.gdx.backends.gwt;

import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArrayBoolean;
import com.google.gwt.core.client.JsArrayInteger;
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
import com.google.gwt.typedarrays.shared.ArrayBufferView;
import com.google.gwt.typedarrays.shared.TypedArrays;
import com.google.gwt.typedarrays.shared.Uint32Array;
import com.google.gwt.webgl.client.WebGL2RenderingContext;
import com.google.gwt.webgl.client.WebGLFramebuffer;
import com.google.gwt.webgl.client.WebGLQuery;
import com.google.gwt.webgl.client.WebGLSampler;
import com.google.gwt.webgl.client.WebGLTexture;
import com.google.gwt.webgl.client.WebGLTransformFeedback;
import com.google.gwt.webgl.client.WebGLUniformLocation;
import com.google.gwt.webgl.client.WebGLVertexArrayObject;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.HasArrayBufferView;
import java.nio.IntBuffer;
import java.nio.LongBuffer;

/** @author Simon Gerst
 * @author JamesTKhan */
public class GwtGL30 extends GwtGL20 implements GL30 {
	private final IntMap queries = IntMap.create();
	private int nextQueryId = 1;
	private final IntMap samplers = IntMap.create();
	private int nextSamplerId = 1;
	private final IntMap feedbacks = IntMap.create();
	private int nextFeedbackId = 1;
	private final IntMap vertexArrays = IntMap.create();
	private int nextVertexArrayId = 1;
	private final Uint32Array uIntBuffer = TypedArrays.createUint32Array(2000 * 6);

	final protected WebGL2RenderingContext gl;

	protected GwtGL30 (WebGL2RenderingContext gl) {
		super(gl);
		this.gl = gl;
	}

	private Uint32Array copyUnsigned (IntBuffer buffer) {
		if (GWT.isProdMode()) {
			return ((Uint32Array)((HasArrayBufferView)buffer).getTypedArray()).subarray(buffer.position(), buffer.remaining());
		} else {
			ensureCapacity(buffer);
			for (int i = buffer.position(), j = 0; i < buffer.limit(); i++, j++) {
				uIntBuffer.set(j, buffer.get(i));
			}
			return uIntBuffer.subarray(0, buffer.remaining());
		}
	}

	private int allocateQueryId (WebGLQuery query) {
		int id = nextQueryId++;
		queries.put(id, query);
		return id;
	}

	private void deallocateQueryId (int id) {
		queries.remove(id);
	}

	private int allocateSamplerId (WebGLSampler query) {
		int id = nextSamplerId++;
		samplers.put(id, query);
		return id;
	}

	private void deallocateFeedbackId (int id) {
		feedbacks.remove(id);
	}

	private int allocateFeedbackId (WebGLTransformFeedback feedback) {
		int id = nextFeedbackId++;
		feedbacks.put(id, feedback);
		return id;
	}

	private void deallocateSamplerId (int id) {
		samplers.remove(id);
	}

	private int allocateVertexArrayId (WebGLVertexArrayObject vArray) {
		int id = nextVertexArrayId++;
		vertexArrays.put(id, vArray);
		return id;
	}

	private void deallocateVertexArrayId (int id) {
		vertexArrays.remove(id);
	}

	@Override
	public void glBeginQuery (int target, int id) {
		gl.beginQuery(target, queries.get(id));
	}

	@Override
	public void glBeginTransformFeedback (int primitiveMode) {
		gl.beginTransformFeedback(primitiveMode);
	}

	@Override
	public void glBindBufferBase (int target, int index, int buffer) {
		gl.bindBufferBase(target, index, buffers.get(buffer));
	}

	@Override
	public void glBindBufferRange (int target, int index, int buffer, int offset, int size) {
		gl.bindBufferRange(target, index, buffers.get(buffer), offset, size);
	}

	@Override
	public void glBindSampler (int unit, int sampler) {
		gl.bindSampler(unit, samplers.get(sampler));
	}

	@Override
	public void glBindTransformFeedback (int target, int id) {
		gl.bindTransformFeedback(target, feedbacks.get(id));
	}

	@Override
	public void glBindVertexArray (int array) {
		gl.bindVertexArray(vertexArrays.get(array));
	}

	@Override
	public void glBlitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1,
		int mask, int filter) {
		gl.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
	}

	@Override
	public void glClearBufferfi (int buffer, int drawbuffer, float depth, int stencil) {
		gl.clearBufferfi(buffer, drawbuffer, depth, stencil);
	}

	@Override
	public void glClearBufferfv (int buffer, int drawbuffer, FloatBuffer value) {
		gl.clearBufferfv(buffer, drawbuffer, copy(value));
	}

	@Override
	public void glClearBufferiv (int buffer, int drawbuffer, IntBuffer value) {
		gl.clearBufferiv(buffer, drawbuffer, copy(value));
	}

	@Override
	public void glClearBufferuiv (int buffer, int drawbuffer, IntBuffer value) {
		gl.clearBufferuiv(buffer, drawbuffer, copy(value));
	}

	@Override
	public void glCopyBufferSubData (int readTarget, int writeTarget, int readOffset, int writeOffset, int size) {
		gl.copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
	}

	@Override
	public void glCopyTexSubImage3D (int target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width,
		int height) {
		gl.copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
	}

	@Override
	public void glDeleteQueries (int n, int[] ids, int offset) {
		for (int i = offset; i < offset + n; i++) {
			int id = ids[i];
			WebGLQuery query = queries.get(id);
			deallocateQueryId(id);
			gl.deleteQuery(query);
		}
	}

	@Override
	public void glDeleteQueries (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			int id = ids.get();
			WebGLQuery query = queries.get(id);
			deallocateQueryId(id);
			gl.deleteQuery(query);
		}
		ids.position(startPosition);
	}

	@Override
	public void glDeleteSamplers (int count, int[] samplers, int offset) {
		for (int i = offset; i < offset + count; i++) {
			int id = samplers[i];
			WebGLSampler sampler = this.samplers.get(id);
			deallocateSamplerId(id);
			gl.deleteSampler(sampler);
		}
	}

	@Override
	public void glDeleteSamplers (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			int id = ids.get();
			WebGLSampler sampler = samplers.get(id);
			deallocateSamplerId(id);
			gl.deleteSampler(sampler);
		}
		ids.position(startPosition);
	}

	@Override
	public void glDeleteTransformFeedbacks (int n, int[] ids, int offset) {
		for (int i = offset; i < offset + n; i++) {
			int id = ids[i];
			WebGLTransformFeedback feedback = feedbacks.get(id);
			deallocateFeedbackId(id);
			gl.deleteTransformFeedback(feedback);
		}
	}

	@Override
	public void glDeleteTransformFeedbacks (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			int id = ids.get();
			WebGLTransformFeedback feedback = feedbacks.get(id);
			deallocateFeedbackId(id);
			gl.deleteTransformFeedback(feedback);
		}
		ids.position(startPosition);
	}

	@Override
	public void glDeleteVertexArrays (int n, int[] arrays, int offset) {
		for (int i = offset; i < offset + n; i++) {
			int id = arrays[i];
			WebGLVertexArrayObject vArray = vertexArrays.get(id);
			deallocateVertexArrayId(id);
			gl.deleteVertexArray(vArray);
		}
	}

	@Override
	public void glDeleteVertexArrays (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			int id = ids.get();
			WebGLVertexArrayObject vArray = vertexArrays.get(id);
			deallocateVertexArrayId(id);
			gl.deleteVertexArray(vArray);
		}
		ids.position(startPosition);
	}

	@Override
	public void glDrawArraysInstanced (int mode, int first, int count, int instanceCount) {
		gl.drawArraysInstanced(mode, first, count, instanceCount);
	}

	@Override
	public void glDrawBuffers (int n, IntBuffer bufs) {
		int startPosition = bufs.position();
		gl.drawBuffers(copy((IntBuffer)bufs).subarray(0, n));
		bufs.position(startPosition);
	}

	@Override
	public void glDrawElementsInstanced (int mode, int count, int type, int indicesOffset, int instanceCount) {
		gl.drawElementsInstanced(mode, count, type, indicesOffset, instanceCount);
	}

	@Override
	public void glDrawRangeElements (int mode, int start, int end, int count, int type, Buffer indices) {
		gl.drawRangeElements(mode, start, end, count, type, indices.position());
	}

	@Override
	public void glDrawRangeElements (int mode, int start, int end, int count, int type, int offset) {
		gl.drawRangeElements(mode, start, end, count, type, offset);
	}

	@Override
	public void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type,
		int offset) {
		gl.texImage2D(target, level, internalformat, width, height, border, format, type, offset);
	}

	@Override
	public void glEndQuery (int target) {
		gl.endQuery(target);
	}

	@Override
	public void glEndTransformFeedback () {
		gl.endTransformFeedback();
	}

	@Override
	public void glFlushMappedBufferRange (int target, int offset, int length) {
		throw new UnsupportedOperationException("glFlushMappedBufferRange not supported on WebGL2");
	}

	@Override
	public void glFramebufferTextureLayer (int target, int attachment, int texture, int level, int layer) {
		gl.framebufferTextureLayer(target, attachment, textures.get(texture), level, layer);
	}

	@Override
	public void glGenQueries (int n, int[] ids, int offset) {
		for (int i = offset; i < offset + n; i++) {
			WebGLQuery query = gl.createQuery();
			int id = allocateQueryId(query);
			ids[i] = id;
		}
	}

	@Override
	public void glGenQueries (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			WebGLQuery query = gl.createQuery();
			int id = allocateQueryId(query);
			ids.put(id);
		}
		ids.position(startPosition);
	}

	@Override
	public void glGenSamplers (int count, int[] samplers, int offset) {
		for (int i = offset; i < offset + count; i++) {
			WebGLSampler sampler = gl.createSampler();
			int id = allocateSamplerId(sampler);
			samplers[i] = id;
		}
	}

	@Override
	public void glGenSamplers (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			WebGLSampler sampler = gl.createSampler();
			int id = allocateSamplerId(sampler);
			ids.put(id);
		}
		ids.position(startPosition);
	}

	@Override
	public void glGenTransformFeedbacks (int n, int[] ids, int offset) {
		for (int i = offset; i < offset + n; i++) {
			WebGLTransformFeedback feedback = gl.createTransformFeedback();
			int id = allocateFeedbackId(feedback);
			ids[i] = id;
		}
	}

	@Override
	public void glGenTransformFeedbacks (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			WebGLTransformFeedback feedback = gl.createTransformFeedback();
			int id = allocateFeedbackId(feedback);
			ids.put(id);
		}
		ids.position(startPosition);
	}

	@Override
	public void glGenVertexArrays (int n, int[] arrays, int offset) {
		for (int i = offset; i < offset + n; i++) {
			WebGLVertexArrayObject vArray = gl.createVertexArray();
			int id = allocateVertexArrayId(vArray);
			arrays[i] = id;
		}
	}

	@Override
	public void glGenVertexArrays (int n, IntBuffer ids) {
		int startPosition = ids.position();
		for (int i = 0; i < n; i++) {
			WebGLVertexArrayObject vArray = gl.createVertexArray();
			int id = allocateVertexArrayId(vArray);
			ids.put(id);
		}
		ids.position(startPosition);
	}

	@Override
	public void glGetActiveUniformBlockiv (int program, int uniformBlockIndex, int pname, IntBuffer params) {
		if (pname == GL30.GL_UNIFORM_BLOCK_BINDING || pname == GL30.GL_UNIFORM_BLOCK_DATA_SIZE
			|| pname == GL30.GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS) {
			params.put(gl.getActiveUniformBlockParameteri(programs.get(program), uniformBlockIndex, pname));
		} else if (pname == GL30.GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
			Uint32Array array = gl.getActiveUniformBlockParameterv(programs.get(program), uniformBlockIndex, pname);
			for (int i = 0; i < array.length(); i++) {
				params.put(i, (int)array.get(i));
			}
		} else if (pname == GL30.GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER
			|| pname == GL30.GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER) {
			boolean result = gl.getActiveUniformBlockParameterb(programs.get(program), uniformBlockIndex, pname);
			params.put(result ? GL20.GL_TRUE : GL20.GL_FALSE);
		} else {
			throw new GdxRuntimeException("Unsupported pname passed to glGetActiveUniformBlockiv");
		}
		params.flip();
	}

	@Override
	public String glGetActiveUniformBlockName (int program, int uniformBlockIndex) {
		return gl.getActiveUniformBlockName(programs.get(program), uniformBlockIndex);
	}

	@Override
	public void glGetActiveUniformBlockName (int program, int uniformBlockIndex, Buffer length, Buffer uniformBlockName) {
		throw new UnsupportedOperationException("glGetActiveUniformBlockName with Buffer parameters not supported on WebGL2");
	}

	@Override
	public void glGetActiveUniformsiv (int program, int uniformCount, IntBuffer uniformIndices, int pname, IntBuffer params) {
		if (pname == GL30.GL_UNIFORM_IS_ROW_MAJOR) {
			JsArrayBoolean arr = gl.getActiveUniformsb(programs.get(program), copy(uniformIndices).subarray(0, uniformCount), pname);
			for (int i = 0; i < uniformCount; i++) {
				params.put(i, arr.get(i) ? GL20.GL_TRUE : GL20.GL_FALSE);
			}
		} else {
			JsArrayInteger arr = gl.getActiveUniformsi(programs.get(program), copy(uniformIndices).subarray(0, uniformCount), pname);
			for (int i = 0; i < uniformCount; i++) {
				params.put(i, arr.get(i));
			}
		}
		params.flip();
	}

	@Override
	public void glGetBufferParameteri64v (int target, int pname, LongBuffer params) {
		throw new UnsupportedOperationException("glGetBufferParameteri64v not supported on WebGL2");
	}

	@Override
	public Buffer glGetBufferPointerv (int target, int pname) {
		throw new UnsupportedOperationException("glGetBufferPointerv not supported on WebGL2");
	}

	@Override
	public void glGetFloatv (int pname, FloatBuffer params) {
		// Override GwtGL20 method to check if it's a pname introduced with GL30.
		if (pname == GL30.GL_MAX_TEXTURE_LOD_BIAS) {
			params.put(0, gl.getParameterf(pname));
			params.flip();
		} else {
			super.glGetFloatv(pname, params);
		}
	}

	@Override
	public int glGetFragDataLocation (int program, String name) {
		return gl.getFragDataLocation(programs.get(program), name);
	}

	@Override
	public void glGetIntegerv (int pname, IntBuffer params) {
		// Override GwtGL20 method to check if it's a pname introduced with GL30.
		switch (pname) {
		case GL30.GL_DRAW_BUFFER0:
		case GL30.GL_DRAW_BUFFER1:
		case GL30.GL_DRAW_BUFFER2:
		case GL30.GL_DRAW_BUFFER3:
		case GL30.GL_DRAW_BUFFER4:
		case GL30.GL_DRAW_BUFFER5:
		case GL30.GL_DRAW_BUFFER6:
		case GL30.GL_DRAW_BUFFER7:
		case GL30.GL_DRAW_BUFFER8:
		case GL30.GL_DRAW_BUFFER9:
		case GL30.GL_DRAW_BUFFER10:
		case GL30.GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
		case GL30.GL_MAX_3D_TEXTURE_SIZE:
		case GL30.GL_MAX_ARRAY_TEXTURE_LAYERS:
		case GL30.GL_MAX_COLOR_ATTACHMENTS:
		case GL30.GL_MAX_DRAW_BUFFERS:
		case GL30.GL_MAX_ELEMENTS_INDICES:
		case GL30.GL_MAX_ELEMENTS_VERTICES:
		case GL30.GL_MAX_FRAGMENT_INPUT_COMPONENTS:
		case GL30.GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
		case GL30.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
		case GL30.GL_MAX_PROGRAM_TEXEL_OFFSET:
		case GL30.GL_MAX_SAMPLES:
		case GL30.GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
		case GL30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
		case GL30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
		case GL30.GL_MAX_UNIFORM_BUFFER_BINDINGS:
		case GL30.GL_MAX_VARYING_COMPONENTS:
		case GL30.GL_MAX_VERTEX_OUTPUT_COMPONENTS:
		case GL30.GL_MAX_VERTEX_UNIFORM_BLOCKS:
		case GL30.GL_MAX_VERTEX_UNIFORM_COMPONENTS:
		case GL30.GL_MIN_PROGRAM_TEXEL_OFFSET:
		case GL30.GL_PACK_ROW_LENGTH:
		case GL30.GL_PACK_SKIP_PIXELS:
		case GL30.GL_PACK_SKIP_ROWS:
		case GL30.GL_READ_BUFFER:
		case GL30.GL_UNPACK_IMAGE_HEIGHT:
		case GL30.GL_UNPACK_ROW_LENGTH:
		case GL30.GL_UNPACK_SKIP_IMAGES:
		case GL30.GL_UNPACK_SKIP_PIXELS:
		case GL30.GL_UNPACK_SKIP_ROWS:
			params.put(0, gl.getParameteri(pname));
			params.flip();
			return;
		case GL30.GL_DRAW_FRAMEBUFFER_BINDING:
		case GL30.GL_READ_FRAMEBUFFER_BINDING:
			WebGLFramebuffer fbo = gl.getParametero(pname);
			if (fbo == null) {
				params.put(0);
			} else {
				params.put(frameBuffers.getKey(fbo));
			}
			params.flip();
			return;
		case GL30.GL_TEXTURE_BINDING_2D_ARRAY:
		case GL30.GL_TEXTURE_BINDING_3D:
			WebGLTexture tex = gl.getParametero(pname);
			if (tex == null) {
				params.put(0);
			} else {
				params.put(textures.getKey(tex));
			}
			params.flip();
			return;
		case GL30.GL_VERTEX_ARRAY_BINDING:
			WebGLVertexArrayObject obj = gl.getParametero(pname);
			if (obj == null) {
				params.put(0);
			} else {
				params.put(vertexArrays.getKey(obj));
			}
			params.flip();
			return;
		default:
			// Assume it is a GL20 pname
			super.glGetIntegerv(pname, params);
		}
	}

	@Override
	public void glGetInteger64v (int pname, LongBuffer params) {
		switch (pname) {
		case GL30.GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
		case GL30.GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
		case GL30.GL_MAX_ELEMENT_INDEX:
		case GL30.GL_MAX_SERVER_WAIT_TIMEOUT:
		case GL30.GL_MAX_UNIFORM_BLOCK_SIZE:
			params.put(gl.getParameteri64(pname));
			params.flip();
			return;
		default:
			throw new UnsupportedOperationException("Given glGetInteger64v enum not supported on WebGL2");
		}
	}

	@Override
	public void glGetFramebufferAttachmentParameteriv (int target, int attachment, int pname, IntBuffer params) {
		switch (pname) {
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
		case GL30.GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
			params.put(0, gl.getFramebufferAttachmentParameteri(target, attachment, pname));
			params.flip();
			break;
		default:
			// Assume it is a GL20 pname
			super.glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
		}
	}

	@Override
	public void glGetQueryiv (int target, int pname, IntBuffer params) {
		// Not 100% clear on this one. Returning the integer key for the query.
		// Similar to how GwtGL20 handles FBO in glGetIntegerv
		WebGLQuery query = gl.getQuery(target, pname);
		if (query == null) {
			params.put(0);
		} else {
			params.put(queries.getKey(query));
		}
		params.flip();
	}

	@Override
	public void glGetQueryObjectuiv (int id, int pname, IntBuffer params) {
		// In WebGL2 getQueryObject was renamed to getQueryParameter
		if (pname == GL30.GL_QUERY_RESULT) {
			params.put(gl.getQueryParameteri(queries.get(id), pname));
		} else if (pname == GL30.GL_QUERY_RESULT_AVAILABLE) {
			boolean result = gl.getQueryParameterb(queries.get(id), pname);
			params.put(result ? GL20.GL_TRUE : GL20.GL_FALSE);
		} else {
			throw new GdxRuntimeException("Unsupported pname passed to glGetQueryObjectuiv");
		}
		params.flip();
	}

	@Override
	public void glGetSamplerParameterfv (int sampler, int pname, FloatBuffer params) {
		params.put(gl.getSamplerParameterf(samplers.get(sampler), pname));
		params.flip();
	}

	@Override
	public void glGetSamplerParameteriv (int sampler, int pname, IntBuffer params) {
		params.put(gl.getSamplerParameteri(samplers.get(sampler), pname));
		params.flip();
	}

	@Override
	public String glGetStringi (int name, int index) {
		throw new UnsupportedOperationException("glGetStringi not supported on WebGL2");
	}

	@Override
	public int glGetUniformBlockIndex (int program, String uniformBlockName) {
		return gl.getUniformBlockIndex(programs.get(program), uniformBlockName);
	}

	@Override
	public void glGetUniformIndices (int program, String[] uniformNames, IntBuffer uniformIndices) {
		JsArrayInteger array = gl.getUniformIndices(programs.get(program), uniformNames);
		for (int i = 0; i < array.length(); i++) {
			uniformIndices.put(i, array.get(i));
		}
		uniformIndices.flip();
	}

	@Override
	public void glGetUniformuiv (int program, int location, IntBuffer params) {
		// fv and iv also not implemented in GwtGL20
		throw new UnsupportedOperationException("glGetUniformuiv not implemented on WebGL2");
	}

	@Override
	public void glGetVertexAttribIiv (int index, int pname, IntBuffer params) {
		// fv and iv also not implemented in GwtGL20
		throw new UnsupportedOperationException("glGetVertexAttribIiv not implemented on WebGL2");
	}

	@Override
	public void glGetVertexAttribIuiv (int index, int pname, IntBuffer params) {
		// fv and iv also not implemented in GwtGL20
		throw new UnsupportedOperationException("glGetVertexAttribIuiv not implemented on WebGL2");
	}

	@Override
	public void glInvalidateFramebuffer (int target, int numAttachments, IntBuffer attachments) {
		int startPosition = attachments.position();
		gl.invalidateFramebuffer(target, copy((IntBuffer)attachments).subarray(0, numAttachments));
		attachments.position(startPosition);
	}

	@Override
	public void glInvalidateSubFramebuffer (int target, int numAttachments, IntBuffer attachments, int x, int y, int width,
		int height) {
		int startPosition = attachments.position();
		gl.invalidateSubFramebuffer(target, copy((IntBuffer)attachments).subarray(0, numAttachments), x, y, width, height);
		attachments.position(startPosition);
	}

	@Override
	public boolean glIsQuery (int id) {
		return gl.isQuery(queries.get(id));
	}

	@Override
	public boolean glIsSampler (int id) {
		return gl.isSampler(samplers.get(id));
	}

	@Override
	public boolean glIsTransformFeedback (int id) {
		return gl.isTransformFeedback(feedbacks.get(id));
	}

	@Override
	public boolean glIsVertexArray (int id) {
		return gl.isVertexArray(vertexArrays.get(id));
	}

	@Override
	public Buffer glMapBufferRange (int target, int offset, int length, int access) {
		throw new UnsupportedOperationException("glMapBufferRange not supported on WebGL2");
	}

	@Override
	public void glPauseTransformFeedback () {
		gl.pauseTransformFeedback();
	}

	@Override
	public void glProgramParameteri (int program, int pname, int value) {
		// Per WebGL2 spec: Accessing binary representations of compiled shader programs is not supported in the WebGL 2.0 API.
		// This includes OpenGL ES 3.0 GetProgramBinary, ProgramBinary, and ProgramParameteri entry points
		throw new UnsupportedOperationException("glProgramParameteri not supported on WebGL2");
	}

	@Override
	public void glReadBuffer (int mode) {
		gl.readBuffer(mode);
	}

	@Override
	public void glRenderbufferStorageMultisample (int target, int samples, int internalformat, int width, int height) {
		gl.renderbufferStorageMultisample(target, samples, internalformat, width, height);
	}

	@Override
	public void glResumeTransformFeedback () {
		gl.resumeTransformFeedback();
	}

	@Override
	public void glSamplerParameterf (int sampler, int pname, float param) {
		gl.samplerParameterf(samplers.get(sampler), pname, param);
	}

	@Override
	public void glSamplerParameterfv (int sampler, int pname, FloatBuffer param) {
		gl.samplerParameterf(samplers.get(sampler), pname, param.get());
	}

	@Override
	public void glSamplerParameteri (int sampler, int pname, int param) {
		gl.samplerParameteri(samplers.get(sampler), pname, param);
	}

	@Override
	public void glSamplerParameteriv (int sampler, int pname, IntBuffer param) {
		gl.samplerParameterf(samplers.get(sampler), pname, param.get());
	}

	@Override
	public void glTexImage3D (int target, int level, int internalformat, int width, int height, int depth, int border, int format,
		int type, Buffer pixels) {
		// Taken from glTexImage2D
		if (pixels == null) {
			gl.texImage3D(target, level, internalformat, width, height, depth, border, format, type, (ArrayBufferView)null);
			return;
		}

		if (pixels.limit() > 1) {
			HasArrayBufferView arrayHolder = (HasArrayBufferView)pixels;
			ArrayBufferView webGLArray = arrayHolder.getTypedArray();
			ArrayBufferView buffer;
			if (pixels instanceof FloatBuffer) {
				buffer = webGLArray;
			} else {
				int length = pixels.remaining();
				if (!(pixels instanceof ByteBuffer)) {
					// It seems for ByteBuffer we don't need this byte conversion
					length *= 4;
				}
				int byteOffset = webGLArray.byteOffset() + pixels.position() * 4;
				buffer = Uint8ArrayNative.create(webGLArray.buffer(), byteOffset, length);
			}
			gl.texImage3D(target, level, internalformat, width, height, depth, border, format, type, buffer);
		} else {
			Pixmap pixmap = Pixmap.pixmaps.get(((IntBuffer)pixels).get(0));
			// Prefer to use the HTMLImageElement when possible, since reading from the CanvasElement can be lossy.
			if (pixmap.canUseImageElement()) {
				gl.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixmap.getImageElement());
			} else if (pixmap.canUseVideoElement()) {
				gl.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixmap.getVideoElement());
			} else {
				gl.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixmap.getCanvasElement());
			}
		}
	}

	@Override
	public void glTexImage3D (int target, int level, int internalformat, int width, int height, int depth, int border, int format,
		int type, int offset) {
		gl.texImage3D(target, level, internalformat, width, height, depth, border, format, type, offset);
	}

	@Override
	public void glTexSubImage2D (int target, int level, int xoffset, int yoffset, int width, int height, int format, int type,
		int offset) {
		gl.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, offset);
	}

	@Override
	public void glTexSubImage3D (int target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth,
		int format, int type, Buffer pixels) {
		// Taken from glTexSubImage2D
		if (pixels.limit() > 1) {
			HasArrayBufferView arrayHolder = (HasArrayBufferView)pixels;
			ArrayBufferView webGLArray = arrayHolder.getTypedArray();
			ArrayBufferView buffer;
			if (pixels instanceof FloatBuffer) {
				buffer = webGLArray;
			} else {
				int length = pixels.remaining();
				if (!(pixels instanceof ByteBuffer)) {
					// It seems for ByteBuffer we don't need this byte conversion
					length *= 4;
				}
				int byteOffset = webGLArray.byteOffset() + pixels.position() * 4;
				buffer = Uint8ArrayNative.create(webGLArray.buffer(), byteOffset, length);
			}
			gl.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, buffer);
		} else {
			Pixmap pixmap = Pixmap.pixmaps.get(((IntBuffer)pixels).get(0));
			gl.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type,
				pixmap.getCanvasElement());
		}
	}

	@Override
	public void glTexSubImage3D (int target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth,
		int format, int type, int offset) {
		gl.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, offset);
	}

	@Override
	public void glTransformFeedbackVaryings (int program, String[] varyings, int bufferMode) {
		gl.transformFeedbackVaryings(programs.get(program), varyings, bufferMode);
	}

	@Override
	public void glUniform1uiv (int location, int count, IntBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniform1uiv(loc, copyUnsigned(value), 0, count);
	}

	@Override
	public void glUniform3uiv (int location, int count, IntBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniform3uiv(loc, copyUnsigned(value), 0, count);
	}

	@Override
	public void glUniform4uiv (int location, int count, IntBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniform4uiv(loc, copyUnsigned(value), 0, count);
	}

	@Override
	public void glUniformBlockBinding (int program, int uniformBlockIndex, int uniformBlockBinding) {
		gl.uniformBlockBinding(programs.get(program), uniformBlockIndex, uniformBlockBinding);
	}

	@Override
	public void glUniformMatrix2x3fv (int location, int count, boolean transpose, FloatBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniformMatrix2x3fv(loc, transpose, copy(value));
	}

	@Override
	public void glUniformMatrix2x4fv (int location, int count, boolean transpose, FloatBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniformMatrix2x4fv(loc, transpose, copy(value), 0, count);
	}

	@Override
	public void glUniformMatrix3x2fv (int location, int count, boolean transpose, FloatBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniformMatrix3x2fv(loc, transpose, copy(value), 0, count);
	}

	@Override
	public void glUniformMatrix3x4fv (int location, int count, boolean transpose, FloatBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniformMatrix3x4fv(loc, transpose, copy(value), 0, count);
	}

	@Override
	public void glUniformMatrix4x2fv (int location, int count, boolean transpose, FloatBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniformMatrix4x2fv(loc, transpose, copy(value), 0, count);
	}

	@Override
	public void glUniformMatrix4x3fv (int location, int count, boolean transpose, FloatBuffer value) {
		WebGLUniformLocation loc = getUniformLocation(location);
		gl.uniformMatrix4x3fv(loc, transpose, copy(value), 0, count);
	}

	@Override
	public boolean glUnmapBuffer (int target) {
		throw new UnsupportedOperationException("glUnmapBuffer not supported on WebGL2");
	}

	@Override
	public void glVertexAttribDivisor (int index, int divisor) {
		gl.vertexAttribDivisor(index, divisor);
	}

	@Override
	public void glVertexAttribI4i (int index, int x, int y, int z, int w) {
		gl.vertexAttribI4i(index, x, y, z, w);
	}

	@Override
	public void glVertexAttribI4ui (int index, int x, int y, int z, int w) {
		gl.vertexAttribI4ui(index, x, y, z, w);
	}

	@Override
	public void glVertexAttribIPointer (int index, int size, int type, int stride, int offset) {
		gl.vertexAttribIPointer(index, size, type, stride, offset);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy