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

playn.html.HtmlGL20 Maven / Gradle / Ivy

There is a newer version: 2.0.8
Show newest version
/**
 * Copyright 2011 The PlayN Authors
 *
 * 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 playn.html;

import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.ImageElement;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayInteger;
import com.google.gwt.typedarrays.shared.ArrayBufferView;
import com.google.gwt.typedarrays.shared.Float32Array;
import com.google.gwt.typedarrays.shared.Int32Array;
import com.google.gwt.typedarrays.shared.TypedArrays;
import com.google.gwt.webgl.client.WebGLBuffer;
import com.google.gwt.webgl.client.WebGLFramebuffer;
import com.google.gwt.webgl.client.WebGLObject;
import com.google.gwt.webgl.client.WebGLProgram;
import com.google.gwt.webgl.client.WebGLRenderbuffer;
import com.google.gwt.webgl.client.WebGLRenderingContext;
import com.google.gwt.webgl.client.WebGLShader;
import com.google.gwt.webgl.client.WebGLTexture;
import com.google.gwt.webgl.client.WebGLUniformLocation;

import static com.google.gwt.webgl.client.WebGLRenderingContext.ARRAY_BUFFER;
import static com.google.gwt.webgl.client.WebGLRenderingContext.BYTE;
import static com.google.gwt.webgl.client.WebGLRenderingContext.COMPILE_STATUS;
import static com.google.gwt.webgl.client.WebGLRenderingContext.ELEMENT_ARRAY_BUFFER;
import static com.google.gwt.webgl.client.WebGLRenderingContext.FLOAT;
import static com.google.gwt.webgl.client.WebGLRenderingContext.INT;
import static com.google.gwt.webgl.client.WebGLRenderingContext.LINK_STATUS;
import static com.google.gwt.webgl.client.WebGLRenderingContext.ONE;
import static com.google.gwt.webgl.client.WebGLRenderingContext.SHORT;
import static com.google.gwt.webgl.client.WebGLRenderingContext.STREAM_DRAW;
import static com.google.gwt.webgl.client.WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL;
import static com.google.gwt.webgl.client.WebGLRenderingContext.UNSIGNED_BYTE;
import static com.google.gwt.webgl.client.WebGLRenderingContext.UNSIGNED_SHORT;

import playn.core.GL20;

/**
 * WebGL implementation of GL20. Maintains a set of VBOs to translate the NIO buffer based version
 * of glVertexAttribPointer to the VBO based version.
 *
 * @author Stefan Haustein
 */
public final class HtmlGL20 extends GL20 {

  static final int VERTEX_ATTRIB_ARRAY_COUNT = 5; //  position, color, texture0, texture1, normals

  enum WebGLObjectType {
    NULL, BUFFER, FRAME_BUFFER, PROGRAM, RENDER_BUFFER, SHADER, TEXTURE, UNIFORM_LOCATION,
  }

  private int previouslyEnabledArrays = 0;
  private int enabledArrays = 0;
  private int useNioBuffer = 0;

  private WebGLRenderingContext glc;
  private VertexAttribArrayState[] vertexAttribArrayState =
    new VertexAttribArrayState[VERTEX_ATTRIB_ARRAY_COUNT];

  @SuppressWarnings("unchecked")
  private JsArray webGLObjects = (JsArray) JsArray.createArray();
  private JsArrayInteger webGLObjectTypes = (JsArrayInteger) JsArrayInteger.createArray();

  private WebGLBuffer elementBuffer;
  private WebGLBuffer boundArrayBuffer;
  private WebGLBuffer requestedArrayBuffer;
  private WebGLBuffer boundElementArrayBuffer;
  private WebGLBuffer requestedElementArrayBuffer;

  public HtmlGL20 () {
    super(new Buffers() {
      public ByteBuffer createByteBuffer(int size) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        buffer.order(ByteOrder.nativeOrder());
        return buffer;
      }
    }, HtmlUrlParameters.checkGLErrors);
  }

  void init (WebGLRenderingContext glc) {
    // TODO: do we always want to do this?
    glc.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL, ONE);
    this.glc = glc;

    webGLObjects.push(null);
    webGLObjectTypes.push(WebGLObjectType.NULL.ordinal());
    elementBuffer = glc.createBuffer();

    for (int ii = 0; ii < VERTEX_ATTRIB_ARRAY_COUNT; ii++) {
      VertexAttribArrayState data = new VertexAttribArrayState();
      data.webGlBuffer = glc.createBuffer();
      vertexAttribArrayState[ii] = data;
    }
  }

  protected boolean isObjectType (int index,  WebGLObjectType type) {
    return webGLObjectTypes.get(index) == type.ordinal();
  }

  private WebGLBuffer getBuffer (int index) {
    return (WebGLBuffer) webGLObjects.get(index);
  }

  private WebGLFramebuffer getFramebuffer (int index) {
    return (WebGLFramebuffer) webGLObjects.get(index);
  }

  private WebGLProgram getProgram (int index) {
    return (WebGLProgram) webGLObjects.get(index);
  }

  private WebGLRenderbuffer getRenderbuffer(int index) {
    return (WebGLRenderbuffer) webGLObjects.get(index);
  }

  private WebGLShader getShader(int index) {
    return (WebGLShader) webGLObjects.get(index);
  }

  protected WebGLUniformLocation getUniformLocation(int index) {
    return (WebGLUniformLocation) webGLObjects.get(index);
  }

  protected WebGLTexture getTexture(int index) {
    return (WebGLTexture) webGLObjects.get(index);
  }

  protected void deleteObject(int index, WebGLObjectType type) {
    WebGLObject object = webGLObjects.get(index);
    webGLObjects.set(index, null);
    webGLObjectTypes.set(index, WebGLObjectType.NULL.ordinal());
    switch(type) {
    case BUFFER:
      glc.deleteBuffer((WebGLBuffer) object);
      break;
    case FRAME_BUFFER:
      glc.deleteFramebuffer((WebGLFramebuffer) object);
      break;
    case PROGRAM:
      glc.deleteProgram((WebGLProgram) object);
      break;
    case RENDER_BUFFER:
      glc.deleteRenderbuffer((WebGLRenderbuffer) object);
      break;
    case SHADER:
      glc.deleteShader((WebGLShader) object);
      break;
    case TEXTURE:
      glc.deleteTexture((WebGLTexture) object);
      break;
    default:
      break;
    }
  }

  protected void deleteObjects(int count, IntBuffer indices, WebGLObjectType type) {
    for (int i = 0; i < count; i++) {
      int index = indices.get(indices.position() + i);
      deleteObject(index, type);
    }
  }

  protected void deleteObjects(int count, int[] indices, int offset, WebGLObjectType type) {
    for (int i = 0; i < count; i++) {
      deleteObject(indices[offset+i], type);
    }
  }

  protected int createObject(WebGLObject object, WebGLObjectType type) {
    // TODO (haustein) keep track of empty positions.
//    for (int i = 0; i < webGLObjects.size(); i++) {
//      if (webGLObjects.get(i) == null) {
//        webGLObjects.set(i, container);
//        return i;
//      }
//    }
    webGLObjects.push(object);
    webGLObjectTypes.push(type.ordinal());
    return webGLObjects.length() - 1;
  }

  protected WebGLObject genObject(WebGLObjectType type) {
    switch(type) {
    case BUFFER:
      return glc.createBuffer();
    case FRAME_BUFFER:
      return glc.createFramebuffer();
    case PROGRAM:
      return glc.createProgram();
    case RENDER_BUFFER:
      return glc.createRenderbuffer();
    case TEXTURE:
      return glc.createTexture();
    default:
      throw new RuntimeException("genObject(s) not supported for type " + type);
    }
  }

  protected void genObjects(int count, int[] names, int offset, WebGLObjectType type) {
    // createObject loop
    for (int i = 0; i < count; i++) {
      WebGLObject object = genObject(type);
      names[i + offset] = createObject(object, type);
    }
  }

  protected void genObjects(int count, IntBuffer names, WebGLObjectType type) {
    // createObject loop
    for (int i = 0; i < count; i++) {
      WebGLObject object = genObject(type);
      names.put(i + names.position(), createObject(object, type));
    }
  }

  /**
   * The content of non-VBO buffers may be changed between the glVertexAttribPointer call
   * and the glDrawXxx call. Thus, we need to defer copying them to a VBO buffer until just
   * before the actual glDrawXxx call.
   */
  protected void prepareDraw() {
    VertexAttribArrayState previousNio = null;
    int previousElementSize = 0;

    if (useNioBuffer == 0 && enabledArrays == previouslyEnabledArrays) {
      return;
    }

    for(int i = 0; i < VERTEX_ATTRIB_ARRAY_COUNT; i++) {
      int mask = 1 << i;
      int enabled = enabledArrays & mask;
      if (enabled != (previouslyEnabledArrays & mask)) {
        if (enabled != 0) {
          glc.enableVertexAttribArray(i);
        } else {
          glc.disableVertexAttribArray(i);
        }
      }
      if (enabled != 0 && (useNioBuffer & mask) != 0) {
        VertexAttribArrayState data = vertexAttribArrayState[i];
        if (previousNio != null && previousNio.nioBuffer == data.nioBuffer &&
            previousNio.nioBufferLimit >= data.nioBufferLimit) {
          if (boundArrayBuffer != previousNio.webGlBuffer) {
            glc.bindBuffer(ARRAY_BUFFER, previousNio.webGlBuffer);
            boundArrayBuffer = data.webGlBuffer;
          }
          glc.vertexAttribPointer(i, data.size, data.type, data.normalize, data.stride,
                                 data.nioBufferPosition * previousElementSize);
        } else {
          if (boundArrayBuffer != data.webGlBuffer) {
            glc.bindBuffer(ARRAY_BUFFER, data.webGlBuffer);
            boundArrayBuffer = data.webGlBuffer;
          }
          int elementSize = getElementSize(data.nioBuffer);
          int savePosition = data.nioBuffer.position();
          if (data.nioBufferPosition * elementSize < data.stride) {
            data.nioBuffer.position(0);
            glc.bufferData(ARRAY_BUFFER, getTypedArray(data.nioBuffer, data.type, data.nioBufferLimit *
                                                      elementSize), STREAM_DRAW);
            glc.vertexAttribPointer(i, data.size, data.type, data.normalize, data.stride,
                                   data.nioBufferPosition * elementSize);
            previousNio = data;
            previousElementSize = elementSize;
          } else {
            data.nioBuffer.position(data.nioBufferPosition);
            glc.bufferData(ARRAY_BUFFER, getTypedArray(data.nioBuffer, data.type,
                                                      (data.nioBufferLimit - data.nioBufferPosition) *
                                                      elementSize), STREAM_DRAW);
            glc.vertexAttribPointer(i, data.size, data.type, data.normalize, data.stride, 0);
          }
          data.nioBuffer.position(savePosition);
        }
      }
    }

    previouslyEnabledArrays = enabledArrays;
  }

  /**
   * Returns the typed array of the given native buffer. Set byteSize to -1 to use remaining().
   */
  private ArrayBufferView getTypedArray(Buffer buffer, int type, int byteSize) {
    if (!(buffer instanceof HasArrayBufferView)) {
      throw new RuntimeException("Native buffer required " + buffer);
    }
    HasArrayBufferView arrayHolder = (HasArrayBufferView) buffer;
    int bufferElementSize = arrayHolder.getElementSize();

    ArrayBufferView webGLArray = arrayHolder.getTypedArray();
    if (byteSize == -1) {
      byteSize = buffer.remaining() * bufferElementSize;
    }
    if (byteSize == buffer.capacity() * bufferElementSize && type == arrayHolder.getElementType()) {
      return webGLArray;
    }

    int byteOffset = webGLArray.byteOffset() + buffer.position() * bufferElementSize;

    switch (type) {
      case FLOAT:
        return TypedArrays.createFloat32Array(webGLArray.buffer(), byteOffset, byteSize / 4);
      case UNSIGNED_BYTE:
        return TypedArrays.createUint8Array(webGLArray.buffer(), byteOffset, byteSize);
      case UNSIGNED_SHORT:
        return TypedArrays.createUint16Array(webGLArray.buffer(), byteOffset, byteSize / 2);
      case INT:
        return TypedArrays.createInt32Array(webGLArray.buffer(), byteOffset, byteSize / 4);
      case SHORT:
        return TypedArrays.createInt16Array(webGLArray.buffer(), byteOffset, byteSize / 2);
      case BYTE:
        return TypedArrays.createInt8Array(webGLArray.buffer(), byteOffset, byteSize);
      default:
        throw new IllegalArgumentException("Type: " + type);
    }
  }

  private static int getElementSize(Buffer buffer) {
    if ((buffer instanceof FloatBuffer) || (buffer instanceof IntBuffer)) return 4;
    else if (buffer instanceof ShortBuffer) return 2;
    else if (buffer instanceof ByteBuffer) return 1;
    else throw new RuntimeException("Unrecognized buffer type: " + buffer.getClass());
  }

  public void glTexImage2D(int target, int level, int internalformat, int format, int type, ImageElement image) {
    glc.texImage2D(target, level, internalformat, format, type, image);
    checkError("texImage2D");
  }

  public void glTexImage2D(int target, int level, int internalformat, int format, int type, CanvasElement image) {
    glc.texImage2D(target, level, internalformat, format, type, image);
    checkError("texImage2D");
  }

  @Override public void glDepthFunc(int func) {
    glc.depthFunc(func);
  }

  @Override public void glDepthMask(boolean b) {
    glc.depthMask(b);
  }

  @Override public void glDrawElements(int mode, int count, int type, Buffer indices) {
    prepareDraw();
    if (boundElementArrayBuffer != elementBuffer) {
      glc.bindBuffer(ELEMENT_ARRAY_BUFFER, elementBuffer);
      boundElementArrayBuffer = elementBuffer;
    }
    glc.bufferData(ELEMENT_ARRAY_BUFFER, getTypedArray(indices, type, count * getTypeSize(type)),
                  STREAM_DRAW);
//    if ("ModelPart".equals(debugInfo)) {
//      HtmlPlatform.log.info("drawElements f. ModelPart; count: " + count);
//    }
    glc.drawElements(mode, count, type, 0);
  }

  private int getTypeSize(int type) {
    switch(type) {
    case GL_FLOAT:
    case GL_INT:
      return 4;
    case GL_SHORT:
    case GL_UNSIGNED_SHORT:
      return 2;
    case GL_BYTE:
    case GL_UNSIGNED_BYTE:
      return 1;
    default:
      throw new IllegalArgumentException();
    }
  }

  @Override public void glFinish() {
    glc.finish();
  }

  @Override public String glGetString(int id) {
    return glc.getParameterString(id);
  }

  @Override public void glPixelStorei(int i, int j) {
    glc.pixelStorei(i, j);
  }

  @Override public void glBindTexture(int target, int textureId) {
    glc.bindTexture(target, getTexture(textureId));
  }

  @Override public final void glClear(int mask) {
    glc.clear(mask);
  }
  @Override public final void glClearColor(float f, float g, float h, float i) {
    glc.clearColor(f, g, h, i);
  }

  @Override public void glDrawArrays(int mode, int first, int count) {
    prepareDraw();
    glc.drawArrays(mode, first, count);
  }

  @Override public final int glGetError() {
    return glc.getError();
  }

  @Override public final void glScissor(int i, int j, int width, int height) {
    glc.scissor(i, j, width, height);
  }

  @Override public void glTexParameteri(int glTexture2d, int glTextureMinFilter, int glFilterMin) {
    glc.texParameteri(glTexture2d, glTextureMinFilter, glFilterMin);
  }
  @Override public void glTexParameterf(int target, int pname, float param) {
    glc.texParameterf(target, pname, param);
  }

  @Override public final void glCullFace(int c) {
    glc.cullFace(c);
  }

  @Override public void glViewport(int x, int y, int w, int h) {
    glc.viewport(x, y, w, h);
//    checkError("glViewport");
  }

  // arrayId (index) is in the range 0..GL_MAX_VERTEX_ATTRIBS-1
  @Override public void glVertexAttribPointer(int arrayId, int size, int type, boolean normalize,
                                    int byteStride, Buffer nioBuffer) {

    VertexAttribArrayState data = vertexAttribArrayState[arrayId];

//    HtmlPlatform.log.info("glVertexAttribPointer Data size: " + nioBuffer.remaining());
    useNioBuffer |= 1 << arrayId;
    data.nioBuffer = nioBuffer;
    data.nioBufferPosition = nioBuffer.position();
    data.nioBufferLimit = nioBuffer.limit();
    data.size = size;
    data.type = type;
    data.normalize = normalize;
    data.stride = byteStride == 0 ? size * getTypeSize(type) : byteStride;
  }

  @Override public void glClearDepthf(float depth) {
    glc.clearDepth(depth);
  }
  @Override public void glClearStencil(int s) {
    glc.clearStencil(s);
  }

  @Override public void glColorMask(boolean red, boolean green, boolean blue, boolean alpha) {
    glc.colorMask(red, green, blue, alpha);
  }

  @Override public void glCompressedTexImage2D(int target, int level, int internalformat, int width, int height, int border, int imageSize, Buffer data) {
    throw new RuntimeException("NYI glCompressedTexImage2D");
  }
  @Override public void glCompressedTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int imageSize, Buffer data) {
    throw new RuntimeException("NYI glCompressedTexSubImage2D");
  }

  @Override public void glCopyTexImage2D(int target, int level, int internalformat, int x, int y, int width, int height, int border) {
    glc.copyTexImage2D(target, level, internalformat, x, y, width, height, border);
  }
  @Override public void glCopyTexSubImage2D(int target, int level, int xoffset, int yoffset, int x, int y, int width, int height) {
    glc.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
  }

  @Override public void glDepthRangef(float zNear, float zFar) {
    glc.depthRange(zNear, zFar);
  }

  @Override public void glFlush() {
    glc.flush();
  }

  @Override public void glFrontFace(int mode) {
    glc.frontFace(mode);
  }

  @Override public int glGetInteger(int pname) {
    return glc.getParameteri(pname);
  }
  @Override public void glGetIntegerv(int pname, IntBuffer params) {
    Int32Array result = (Int32Array) glc.getParameterv(pname);
    int pos = params.position();
    int len = result.length();
    for (int i = 0; i < len; i++) {
      params.put(pos + i, result.get(i));
    }
  }

  @Override public void glHint(int target, int mode) {
    glc.hint(target, mode);
  }

  @Override public void glLineWidth(float width) {
    glc.lineWidth(width);
  }

  @Override public void glPolygonOffset(float factor, float units) {
    glc.polygonOffset(factor, units);
  }

  @Override public void glReadPixels(int x, int y, int width, int height, int format, int type, Buffer pixels) {
    glc.readPixels(x, y, width, height, format, type, getTypedArray(pixels, type, -1));
  }

  @Override public void glStencilFunc(int func, int ref, int mask) {
    glc.stencilFunc(func, ref, mask);
  }
  @Override public void glStencilMask(int mask) {
    glc.stencilMask(mask);
  }
  @Override public void glStencilOp(int fail, int zfail, int zpass) {
    glc.stencilOp(fail, zfail, zpass);
  }

  @Override public void glTexImage2D(int target, int level, int internalformat, int width,
                           int height, int border, int format, int type, Buffer pixels) {
    ArrayBufferView buffer = (pixels == null) ? null : getTypedArray(pixels, type, -1);
    glc.texImage2D(target, level, internalformat, width, height, border, format, type, buffer);
  }
  @Override public void glTexSubImage2D(int target, int level, int xoffset, int yoffset,
                              int width, int height, int format, int type, Buffer pixels) {
    glc.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
                     getTypedArray(pixels, type, -1));
  }

  @Override public void glAttachShader(int program, int shader) {
    glc.attachShader((WebGLProgram) webGLObjects.get(program),
                    (WebGLShader) webGLObjects.get(shader));
  }

  @Override public void glBindAttribLocation(int program, int index, String name) {
    glc.bindAttribLocation((WebGLProgram) webGLObjects.get(program), index, name);
  }

  @Override public void glBindBuffer(int target, int buffer) {
    // Yes, bindBuffer is so expensive that this makes sense..
    WebGLBuffer webGlBuf = getBuffer(buffer);
    if (target == GL_ARRAY_BUFFER) {
      requestedArrayBuffer = webGlBuf;
    } else if (target == GL_ELEMENT_ARRAY_BUFFER) {
      requestedElementArrayBuffer = webGlBuf;
    } else {
      glc.bindBuffer(target, webGlBuf);
    }
  }
  @Override public void glBindFramebuffer(int target, int framebuffer) {
    glc.bindFramebuffer(target, getFramebuffer(framebuffer));
  }
  @Override public void glBindRenderbuffer(int target, int renderbuffer) {
    glc.bindRenderbuffer(target, getRenderbuffer(renderbuffer));
  }

  @Override public final void glBlendFunc(int a, int b) {
    glc.blendFunc(a, b);
  }
  @Override public void glBlendColor(float red, float green, float blue, float alpha) {
    glc.blendColor(red, green, blue, alpha);
  }
  @Override public void glBlendEquation(int mode) {
    glc.blendEquation(mode);
  }
  @Override public void glBlendEquationSeparate(int modeRGB, int modeAlpha) {
    glc.blendEquationSeparate(modeRGB, modeAlpha);
  }
  @Override public void glBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha,
                                  int dstAlpha) {
    glc.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
  }

  @Override public void glBufferData(int target, int byteSize, Buffer data, int usage) {
    if (target == GL_ARRAY_BUFFER) {
      if (requestedArrayBuffer != boundArrayBuffer) {
        glc.bindBuffer(target, requestedArrayBuffer);
        boundArrayBuffer = requestedArrayBuffer;
      }
    } else if (target == GL_ELEMENT_ARRAY_BUFFER) {
      if (requestedElementArrayBuffer != boundElementArrayBuffer) {
        glc.bindBuffer(target, requestedElementArrayBuffer);
        boundElementArrayBuffer = requestedElementArrayBuffer;
      }
    }
    glc.bufferData(target, getTypedArray(data, GL_BYTE, byteSize), usage);
  }
  @Override public void glBufferSubData(int target, int offset, int size, Buffer data) {
    if (target == GL_ARRAY_BUFFER && requestedArrayBuffer != boundArrayBuffer) {
      glc.bindBuffer(target, requestedArrayBuffer);
      boundArrayBuffer = requestedArrayBuffer;
    }
    throw new RuntimeException("NYI glBufferSubData");
  }

  @Override public int glCheckFramebufferStatus(int target) {
    return glc.checkFramebufferStatus(target);
  }

  @Override public void glCompileShader(int shader) {
    glc.compileShader(getShader(shader));
  }

  @Override public int glCreateProgram() {
    return createObject(glc.createProgram(), WebGLObjectType.PROGRAM);
  }
  @Override public int glCreateShader(int type) {
    return createObject(glc.createShader(type), WebGLObjectType.SHADER);
  }

  @Override public void glDeleteTextures(int n, IntBuffer texnumBuffer) {
    deleteObjects(n, texnumBuffer, WebGLObjectType.TEXTURE);
  }
  @Override public void glDeleteBuffers(int n, IntBuffer buffers) {
    deleteObjects(n, buffers, WebGLObjectType.BUFFER);
  }
  @Override public void glDeleteFramebuffers(int n, IntBuffer framebuffers) {
    deleteObjects(n, framebuffers, WebGLObjectType.FRAME_BUFFER);
  }
  @Override public void glDeleteProgram(int program) {
    deleteObject(program, WebGLObjectType.PROGRAM);
  }
  @Override public void glDeleteRenderbuffers(int n, IntBuffer renderbuffers) {
    deleteObjects(n, renderbuffers, WebGLObjectType.RENDER_BUFFER);
  }

  @Override public void glDeleteShader(int shader) {
    deleteObject(shader, WebGLObjectType.SHADER);
  }

  @Override public void glDetachShader(int program, int shader) {
    glc.detachShader(getProgram(program), getShader(shader));
  }

  @Override public void glDisableVertexAttribArray(int index) {
    enabledArrays &= ~(1 << index);
  }

  @Override public void glDrawElements(int mode, int count, int type, int indices) {
    prepareDraw();
    if (requestedElementArrayBuffer != boundElementArrayBuffer) {
      glc.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, requestedElementArrayBuffer);
      boundElementArrayBuffer = requestedElementArrayBuffer;
    }
    glc.drawElements(mode, count, type, indices);
  }

  @Override public void glEnableVertexAttribArray(int index) {
    enabledArrays |= (1 << index);
  }

  @Override public void glFramebufferRenderbuffer(int target, int attachment, int renderbuffertarget, int renderbuffer) {
    glc.framebufferRenderbuffer(target, attachment, renderbuffertarget,
                               getRenderbuffer(renderbuffer));
  }
  @Override public void glFramebufferTexture2D(int target, int attachment, int textarget, int texture, int level) {
    glc.framebufferTexture2D(target, attachment, textarget, getTexture(texture), level);
  }

  @Override public void glGenerateMipmap(int t) {
    glc.generateMipmap(t);
  }

  @Override public void glGenBuffers(int n, IntBuffer buffers) {
    genObjects(n, buffers, WebGLObjectType.BUFFER);
  }
  @Override public void glGenFramebuffers(int n, IntBuffer framebuffers) {
    genObjects(n, framebuffers, WebGLObjectType.FRAME_BUFFER);
  }
  @Override public void glGenRenderbuffers(int n, IntBuffer renderbuffers) {
    genObjects(n, renderbuffers, WebGLObjectType.RENDER_BUFFER);
  }
  @Override public void glGenTextures(int n, IntBuffer textures) {
    genObjects(n, textures, WebGLObjectType.TEXTURE);
  }

  @Override public void glGenBuffers(int n, int[] buffers, int offset) {
    genObjects(n, buffers, offset, WebGLObjectType.BUFFER);
  }
  @Override public void glGenFramebuffers(int n, int[] framebuffers, int offset) {
    genObjects(n, framebuffers, offset, WebGLObjectType.FRAME_BUFFER);
  }
  @Override public void glGenRenderbuffers(int n, int[] renderbuffers, int offset) {
    genObjects(n, renderbuffers, offset, WebGLObjectType.RENDER_BUFFER);
  }
  @Override public void glGenTextures(int n, int[] textures, int offset) {
    genObjects(n, textures, offset, WebGLObjectType.TEXTURE);
  }

  @Override public int glGetAttribLocation(int program, String name) {
    return glc.getAttribLocation(getProgram(program), name);
  }

  @Override public void glGetBufferParameteriv(int target, int pname, IntBuffer params) {
    params.put(params.position(), glc.getBufferParameter(target, pname));
  }

  @Override public float glGetFloat(int pname) {
    return glc.getParameterf(pname);
  }
  @Override public void glGetFloatv(int pname, FloatBuffer params) {
    throw new RuntimeException("NYI glGetFloatv");
  }

  @Override public void glGetFramebufferAttachmentParameteriv(int target, int attachment,
                                                    int pname, IntBuffer params) {
    throw new RuntimeException("NYI glGetFramebufferAttachmentParameteriv");
  }

  @Override public void glGetProgramiv(int program, int pname, IntBuffer params) {
    if (pname == GL_LINK_STATUS) {
      params.put(glc.getProgramParameterb(getProgram(program), LINK_STATUS) ? GL_TRUE : GL_FALSE);
    } else {
      throw new RuntimeException("NYI glGetProgramiv");
    }
  }

  @Override public String glGetProgramInfoLog(int program) {
    return glc.getProgramInfoLog(getProgram(program));
  }

  @Override public void glGetRenderbufferParameteriv(int target, int pname, IntBuffer params) {
    throw new RuntimeException("NYI glGetRenderbufferParameteriv");
  }

  @Override public void glGetShaderiv(int shader, int pname, IntBuffer params) {
    if (pname == GL_COMPILE_STATUS) {
      params.put(glc.getShaderParameterb(getShader(shader), COMPILE_STATUS) ? GL_TRUE : GL_FALSE);
    } else {
      throw new RuntimeException("NYI glGetShaderiv: " + pname);
    }
  }

  @Override public String glGetShaderInfoLog(int shader) {
    return glc.getShaderInfoLog(getShader(shader));
  }

  @Override public void glGetShaderPrecisionFormat(int shadertype, int precisiontype,
                                         IntBuffer range, IntBuffer precision) {
    throw new RuntimeException("NYI glGetShaderInfoLog");
  }

  @Override public void glGetTexParameterfv(int target, int pname, FloatBuffer params) {
    params.put(params.position(), glc.getTexParameter(target, pname));
  }
  @Override public void glGetTexParameteriv(int target, int pname, IntBuffer params) {
    params.put(params.position(), glc.getTexParameter(target, pname));
  }

  @Override public void glGetUniformfv(int program, int location, FloatBuffer params) {
    Float32Array v = glc.getUniformv(getProgram(program), getUniformLocation(location));
    for (int i = 0; i < v.length(); i++) {
      params.put(params.position() + i, v.get(i));
    }
  }
  @Override public void glGetUniformiv(int program, int location, IntBuffer params) {
    Int32Array v = glc.getUniformv(getProgram(program), getUniformLocation(location));
    for (int i = 0; i < v.length(); i++) {
      params.put(params.position() + i, v.get(i));
    }
  }

  @Override public int glGetUniformLocation(int program, String name) {
    return createObject(glc.getUniformLocation(getProgram(program), name),
                        WebGLObjectType.UNIFORM_LOCATION);
  }

  @Override public void glGetVertexAttribfv(int index, int pname, FloatBuffer params) {
    Float32Array v = glc.getVertexAttribv(index, pname);
    for (int i = 0; i < v.length(); i++) {
      params.put(params.position() + i, v.get(i));
    }
  }

  @Override public void glGetVertexAttribiv(int index, int pname, IntBuffer params) {
    throw new UnsupportedOperationException("NYI glGetVertexAttribiv: WebGL getVertexAttribv always returns a float buffer.");
  }

  @Override public boolean glIsBuffer(int buffer) {
    return isObjectType(buffer, WebGLObjectType.BUFFER);
  }
  @Override public boolean glIsEnabled(int cap) {
    return glc.isEnabled(cap);
  }
  @Override public boolean glIsFramebuffer(int framebuffer) {
    return isObjectType(framebuffer, WebGLObjectType.FRAME_BUFFER);
  }
  @Override public boolean glIsProgram(int program) {
    return isObjectType(program, WebGLObjectType.PROGRAM);
  }
  @Override public boolean glIsRenderbuffer(int renderbuffer) {
    return isObjectType(renderbuffer, WebGLObjectType.FRAME_BUFFER);
  }
  @Override public boolean glIsShader(int shader) {
    return isObjectType(shader, WebGLObjectType.SHADER);
  }
  @Override public boolean glIsTexture(int texture) {
    return isObjectType(texture, WebGLObjectType.TEXTURE);
  }

  @Override public void glLinkProgram(int program) {
    glc.linkProgram(getProgram(program));
  }

  @Override public void glReleaseShaderCompiler() {
    throw new RuntimeException("NYI glReleaseShaderCompiler");
  }

  @Override public void glRenderbufferStorage(int target, int internalformat, int width,
                                    int height) {
    glc.renderbufferStorage(target, internalformat, width, height);
  }

  @Override public void glSampleCoverage(float value, boolean invert) {
    glc.sampleCoverage(value, invert);
  }

  @Override public void glShaderBinary(int n, IntBuffer shaders, int binaryformat, Buffer binary, int length) {
    throw new RuntimeException("NYI glReleaseShaderCompiler");
  }
  @Override public void glShaderSource(int shader, String string) {
    glc.shaderSource(getShader(shader), string);
  }

  @Override public void glStencilFuncSeparate(int face, int func, int ref, int mask) {
    glc.stencilFuncSeparate(face, func, ref, mask);
  }
  @Override public void glStencilMaskSeparate(int face, int mask) {
    glc.stencilMaskSeparate(face, mask);
  }
  @Override public void glStencilOpSeparate(int face, int fail, int zfail, int zpass) {
    glc.stencilOpSeparate(face, fail, zfail, zpass);
  }

  @Override public void glTexParameterfv(int target, int pname, FloatBuffer params) {
    throw new RuntimeException("NYI glTexParameterfv");
  }
  @Override public void glTexParameteriv(int target, int pname, IntBuffer params) {
    throw new RuntimeException("NYI glTexParameteriv");
  }

  @Override public void glUniform1f(int location, float x) {
    glc.uniform1f(getUniformLocation(location), x);
  }
  @Override public void glUniform1fv(int location, int count, FloatBuffer v) {
    throw new RuntimeException("NYI glUniform1fv");
  }
  @Override public void glUniform1i(int location, int x) {
    glc.uniform1i(getUniformLocation(location), x);
  }
  @Override public void glUniform1iv(int location, int count, IntBuffer v) {
    glc.uniform1iv(getUniformLocation(location), (Int32Array) getTypedArray(v, GL_INT, count * 4));
  }
  @Override public void glUniform2f(int location, float x, float y) {
    glc.uniform2f(getUniformLocation(location), x, y);
  }
  @Override public void glUniform2fv(int location, int count, FloatBuffer v) {
    glc.uniform2fv(getUniformLocation(location),
                  (Float32Array) getTypedArray(v, GL_FLOAT, count * 2 * 4));
  }
  @Override public void glUniform2i(int location, int x, int y) {
    glc.uniform2i(getUniformLocation(location), x, y);
  }
  @Override public void glUniform2iv(int location, int count, IntBuffer v) {
    throw new RuntimeException("NYI glUniform2iv");
  }
  @Override public void glUniform3f(int location, float x, float y, float z) {
    glc.uniform3f(getUniformLocation(location), x, y, z);
  }
  @Override public void glUniform3fv(int location, int count, FloatBuffer v) {
    throw new RuntimeException("NYI glUniform3fv");
  }
  @Override public void glUniform3i(int location, int x, int y, int z) {
    glc.uniform3i(getUniformLocation(location), x, y, z);
  }
  @Override public void glUniform3iv(int location, int count, IntBuffer v) {
    throw new RuntimeException("NYI glUniform3fi");
  }
  @Override public void glUniform4f(int location, float x, float y, float z, float w) {
    glc.uniform4f(getUniformLocation(location), x, y, z, w);
  }
  @Override public void glUniform4fv(int location, int count, FloatBuffer v) {
    glc.uniform4fv(getUniformLocation(location),
                  (Float32Array) getTypedArray(v, GL_FLOAT, 4 * 4 * count));
  }
  @Override public void glUniform4i(int location, int x, int y, int z, int w) {
    glc.uniform4i(getUniformLocation(location), x, y, z, w);
  }
  @Override public void glUniform4iv(int location, int count, IntBuffer v) {
    throw new RuntimeException("NYI glUniform4iv");
  }

  @Override public void glUniformMatrix2fv(int location, int count, boolean transpose,
                                 FloatBuffer value) {
    throw new RuntimeException("NYI glUniformMatrix2fv");
  }
  @Override public void glUniformMatrix3fv(int location, int count, boolean transpose,
                                 FloatBuffer value) {
    throw new RuntimeException("NYI glUniformMatrix3fv");
  }
  @Override public void glUniformMatrix4fv(int location, int count, boolean transpose, FloatBuffer value) {
    glc.uniformMatrix4fv(getUniformLocation(location), transpose,
                         (Float32Array) getTypedArray(value, GL_FLOAT, count * 16 * 4));
  }

  @Override public void glUseProgram(int program) {
    glc.useProgram(getProgram(program));
  }

  @Override public void glValidateProgram(int program) {
    glc.validateProgram(getProgram(program));
  }

  @Override public void glVertexAttrib1f(int indx, float x) {
    glc.vertexAttrib1f(indx, x);
  }
  @Override public void glVertexAttrib1fv(int indx, FloatBuffer values) {
    throw new RuntimeException("NYI glVertexAttrib1fv");
  }
  @Override public void glVertexAttrib2f(int indx, float x, float y) {
    glc.vertexAttrib2f(indx, x, y);
  }
  @Override public void glVertexAttrib2fv(int indx, FloatBuffer values) {
    throw new RuntimeException("NYI glVertexAttrib2fv");
  }
  @Override public void glVertexAttrib3f(int indx, float x, float y, float z) {
    glc.vertexAttrib3f(indx, x, y, z);
  }
  @Override public void glVertexAttrib3fv(int indx, FloatBuffer values) {
    throw new RuntimeException("NYI glVertexAttrib3fv");
  }
  @Override public void glVertexAttrib4f(int indx, float x, float y, float z, float w) {
    glc.vertexAttrib4f(indx, x, y, z, w);
  }
  @Override public void glVertexAttrib4fv(int indx, FloatBuffer values) {
    throw new RuntimeException("NYI glVertexAttrib4fv");
  }

  @Override public void glVertexAttribPointer(int indx, int size, int type, boolean normalized, int stride, int ptr) {
    useNioBuffer &= ~(1 << indx);
    if (boundArrayBuffer != requestedArrayBuffer) {
      glc.bindBuffer(GL_ARRAY_BUFFER, requestedArrayBuffer);
      boundArrayBuffer = requestedArrayBuffer;
    }

    glc.vertexAttribPointer(indx, size, type, normalized, stride, ptr);
  }

  @Override public void glDisable(int cap) {
    glc.disable(cap);
  }
  @Override public void glEnable(int cap) {
    glc.enable(cap);
  }

  @Override public void glActiveTexture(int texture) {
    glc.activeTexture(texture);
  }

  class VertexAttribArrayState {
    int type;
    int size;
    int stride;
    boolean normalize;
    Buffer nioBuffer;
    int nioBufferPosition;
    int nioBufferLimit;
    WebGLBuffer webGlBuffer;
  }

  @Override public String getPlatformGLExtensions() {
    throw new RuntimeException("NYI getPlatformGLExtensions");
  }

  @Override public int getSwapInterval() {
    throw new RuntimeException("NYI getSwapInterval");
  }

  @Override public void glClearDepth(double depth) {
    throw new RuntimeException("NYI glClearDepth");
  }

  @Override public void glCompressedTexImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, Buffer arg8) {
    throw new RuntimeException("NYI glCompressedTexImage3D");
  }
  @Override public void glCompressedTexSubImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, Buffer arg10) {
    throw new RuntimeException("NYI glCompressedTexSubImage3D");
  }
  @Override public void glCopyTexSubImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8) {
    throw new RuntimeException("NYI glCopyTexSubImage3D");
  }

  @Override public void glDeleteBuffers(int n, int[] buffers, int offset) {
    deleteObjects(n, buffers, offset, WebGLObjectType.BUFFER);
  }
  @Override public void glDeleteFramebuffers(int n, int[] framebuffers, int offset) {
    deleteObjects(n, framebuffers, offset, WebGLObjectType.FRAME_BUFFER);
  }
  @Override public void glDeleteRenderbuffers(int n, int[] renderbuffers, int offset) {
    deleteObjects(n, renderbuffers, offset, WebGLObjectType.RENDER_BUFFER);
  }
  @Override public void glDeleteTextures(int n, int[] textures, int offset) {
    deleteObjects(n, textures, offset, WebGLObjectType.TEXTURE);
  }

  @Override public void glDepthRange(double zNear, double zFar) {
    throw new RuntimeException("NYI glDepthRange");
  }

  @Override public void glFramebufferTexture3D(int target, int attachment, int textarget, int texture, int level, int zoffset) {
    throw new RuntimeException("NYI glFramebufferTexture3D");
  }

  @Override public void glGetActiveAttrib(int program, int index, int bufsize, int[] length, int lengthOffset, int[] size, int sizeOffset, int[] type, int typeOffset, byte[] name, int nameOffset) {
    throw new RuntimeException("NYI glGetActiveAttrib");
  }
  @Override public void glGetActiveAttrib(int program, int index, int bufsize, IntBuffer length, IntBuffer size, IntBuffer type, ByteBuffer name) {
    throw new RuntimeException("NYI glGetActiveAttrib");
  }
  @Override public void glGetActiveUniform(int program, int index, int bufsize, int[] length, int lengthOffset, int[] size, int sizeOffset, int[] type, int typeOffset, byte[] name, int nameOffset) {
    throw new RuntimeException("NYI glGetActiveUniform");
  }
  @Override public void glGetActiveUniform(int program, int index, int bufsize, IntBuffer length, IntBuffer size, IntBuffer type, ByteBuffer name) {
    throw new RuntimeException("NYI glGetActiveUniform");
  }
  @Override public void glGetAttachedShaders(int program, int maxcount, int[] count, int countOffset, int[] shaders, int shadersOffset) {
    throw new RuntimeException("NYI glGetAttachedShaders");
  }
  @Override public void glGetAttachedShaders(int program, int maxcount, IntBuffer count, IntBuffer shaders) {
    throw new RuntimeException("NYI glGetAttachedShaders");
  }

  @Override public boolean glGetBoolean(int pname) {
    return glc.getParameterb(pname);
  }
  @Override public void glGetBooleanv(int pname, ByteBuffer params) {
    throw new RuntimeException("NYI glGetBooleanv");
  }

  @Override public int glGetBoundBuffer(int arg0) {
    throw new RuntimeException("NYI glGetBoundBuffer");
  }

  @Override public void glGetProgramBinary(int arg0, int arg1, IntBuffer arg2, IntBuffer arg3, Buffer arg4) {
    throw new RuntimeException("NYI glGetProgramBinary");
  }
  @Override public void glGetProgramInfoLog(int program, int bufsize, IntBuffer length, ByteBuffer infolog) {
    throw new RuntimeException("NYI glGetProgramInfoLog");
  }

  @Override public void glGetProgramiv(int program, int pname, int[] params, int offset) {
    if (pname == GL_LINK_STATUS) params[offset] = glc.getProgramParameterb(getProgram(program), LINK_STATUS) ? GL_TRUE : GL_FALSE;
    else throw new RuntimeException("NYI glGetProgramiv: " + pname);
  }

  @Override public void glGetShaderInfoLog(int shader, int bufsize, IntBuffer length, ByteBuffer infolog) {
    throw new RuntimeException("NYI glGetShaderInfoLog");
  }

  @Override public void glGetShaderiv(int shader, int pname, int[] params, int offset) {
    if (pname == GL_COMPILE_STATUS) params[offset] = glc.getShaderParameterb(getShader(shader), COMPILE_STATUS) ? GL_TRUE : GL_FALSE;
    else throw new RuntimeException("NYI glGetShaderiv: " + pname);
  }

  @Override public void glGetShaderPrecisionFormat(int shadertype, int precisiontype, int[] range, int rangeOffset, int[] precision, int precisionOffset) {
    throw new RuntimeException("NYI glGetShaderPrecisionFormat");
  }
  @Override public void glGetShaderSource(int shader, int bufsize, int[] length, int lengthOffset, byte[] source, int sourceOffset) {
    throw new RuntimeException("NYI glGetShaderSource");
  }
  @Override public void glGetShaderSource(int shader, int bufsize, IntBuffer length, ByteBuffer source) {
    throw new RuntimeException("NYI glGetShaderSource");
  }

  @Override public boolean glIsVBOArrayEnabled() {
    throw new RuntimeException("NYI glIsVBOArrayEnabled");
  }
  @Override public boolean glIsVBOElementEnabled() {
    throw new RuntimeException("NYI glIsVBOElementEnabled");
  }

  @Override public ByteBuffer glMapBuffer(int arg0, int arg1) {
    throw new RuntimeException("NYI glMapBuffer");
  }

  @Override public void glProgramBinary(int arg0, int arg1, Buffer arg2, int arg3) {
    throw new RuntimeException("NYI glProgramBinary");
  }
  @Override public void glShaderBinary(int n, int[] shaders, int offset, int binaryformat, Buffer binary, int length) {
    throw new RuntimeException("NYI glShaderBinary");
  }
  @Override public void glShaderSource(int shader, int count, String[] strings, int[] length, int lengthOffset) {
    throw new RuntimeException("NYI glShaderSource");
  }
  @Override public void glShaderSource(int shader, int count, String[] strings, IntBuffer length) {
    throw new RuntimeException("NYI glShaderSource");
  }

  @Override public void glTexImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, Buffer arg9) {
    throw new RuntimeException("NYI glTexImage3D");
  }
  @Override public void glTexSubImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, Buffer arg10) {
    throw new RuntimeException("NYI glTexSubImage3D");
  }

  @Override public boolean glUnmapBuffer(int arg0) {
    throw new RuntimeException("NYI glUnmapBuffer");
  }

  @Override public boolean hasGLSL() {
    return true;
  }

  @Override public boolean isExtensionAvailable(String extension) {
    throw new RuntimeException("NYI isExtensionAvailable");
  }
  @Override public boolean isFunctionAvailable(String function) {
    throw new RuntimeException("NYI isFunctionAvailable");
  }

  @Override public void glCompressedTexImage2D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) {
    throw new RuntimeException("NYI glCompressedTexImage2D");
  }
  @Override public void glCompressedTexImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8) {
    throw new RuntimeException("NYI glCompressedTexImage3D");
  }
  @Override public void glCompressedTexSubImage2D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8) {
    throw new RuntimeException("NYI glCompressedTexSubImage2D");
  }
  @Override public void glCompressedTexSubImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10) {
    throw new RuntimeException("NYI glCompressedTexSubImage3D");
  }

  @Override public void glReadPixels(int x, int y, int width, int height, int format, int type, int pixelsBufferOffset) {
    throw new RuntimeException("NYI glReadPixels");
  }

  @Override public void glTexImage2D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8) {
    throw new RuntimeException("NYI glTexImage2D");
  }
  @Override public void glTexImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9) {
    throw new RuntimeException("NYI glTexImage3D");
  }
  @Override public void glTexSubImage2D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8) {
    throw new RuntimeException("NYI glTexSubImage2D");
  }
  @Override public void glTexSubImage3D(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10) {
    throw new RuntimeException("NYI glTexSubImage3D");
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy