コード例 #1
0
void
WebGLContext::BufferSubDataImpl(GLenum target, WebGLsizeiptr dstByteOffset,
                                size_t dataLen, const uint8_t* data)
{
    const char funcName[] = "bufferSubData";

    if (!ValidateNonNegative(funcName, "byteOffset", dstByteOffset))
        return;

    const auto& buffer = ValidateBufferSelection(funcName, target);
    if (!buffer)
        return;

    if (!buffer->ValidateRange(funcName, dstByteOffset, dataLen))
        return;

    if (!CheckedInt<GLintptr>(dataLen).isValid()) {
        ErrorOutOfMemory("%s: Size too large.", funcName);
        return;
    }
    const GLintptr glDataLen(dataLen);

    ////

    MakeContextCurrent();
    const ScopedLazyBind lazyBind(gl, target, buffer);

    // Warning: Possibly shared memory.  See bug 1225033.
    gl->fBufferSubData(target, dstByteOffset, glDataLen, data);

    // Warning: Possibly shared memory.  See bug 1225033.
    buffer->ElementArrayCacheBufferSubData(dstByteOffset, data, size_t(glDataLen));
}
コード例 #2
0
void
WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
{
    if (IsContextLost())
        return;

    if (!ValidateBufferTarget(target, "bufferData"))
        return;

    WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);

    if (size < 0)
        return ErrorInvalidValue("bufferData: negative size");

    if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
        return;

    // careful: WebGLsizeiptr is always 64-bit, but GLsizeiptr is like intptr_t.
    if (!CheckedInt<GLsizeiptr>(size).isValid())
        return ErrorOutOfMemory("bufferData: bad size");

    WebGLBuffer* boundBuffer = bufferSlot.get();

    if (!boundBuffer)
        return ErrorInvalidOperation("bufferData: no buffer bound!");

    UniquePtr<uint8_t> zeroBuffer((uint8_t*)calloc(size, 1));
    if (!zeroBuffer)
        return ErrorOutOfMemory("bufferData: out of memory");

    MakeContextCurrent();
    InvalidateBufferFetching();

    GLenum error = CheckedBufferData(target, size, zeroBuffer.get(), usage);

    if (error) {
        GenerateWarning("bufferData generated error %s", ErrorName(error));
        return;
    }

    boundBuffer->SetByteLength(size);
    if (!boundBuffer->ElementArrayCacheBufferData(nullptr, size)) {
        return ErrorOutOfMemory("bufferData: out of memory");
    }
}
コード例 #3
0
ファイル: WebGLContextBuffers.cpp プロジェクト: jld/gecko-dev
void WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage) {
  const FuncScope funcScope(*this, "bufferData");
  if (IsContextLost()) return;

  if (!ValidateNonNegative("size", size)) return;

  ////

  const auto checkedSize = CheckedInt<size_t>(size);
  if (!checkedSize.isValid())
    return ErrorOutOfMemory("size too large for platform.");

  const UniqueBuffer zeroBuffer(calloc(checkedSize.value(), 1u));
  if (!zeroBuffer) return ErrorOutOfMemory("Failed to allocate zeros.");

  BufferDataImpl(target, uint64_t{checkedSize.value()},
                 (const uint8_t*)zeroBuffer.get(), usage);
}
コード例 #4
0
void
WebGLContext::BufferDataT(GLenum target,
                          const BufferT& data,
                          GLenum usage)
{
    if (IsContextLost())
        return;

    if (!ValidateBufferTarget(target, "bufferData"))
        return;

    const WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);

    data.ComputeLengthAndData();

    // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
    // is like intptr_t.
    if (!CheckedInt<GLsizeiptr>(data.Length()).isValid())
        return ErrorOutOfMemory("bufferData: bad size");

    if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
        return;

    WebGLBuffer* boundBuffer = bufferSlot.get();

    if (!boundBuffer)
        return ErrorInvalidOperation("bufferData: no buffer bound!");

    MakeContextCurrent();
    InvalidateBufferFetching();

    GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);

    if (error) {
        GenerateWarning("bufferData generated error %s", ErrorName(error));
        return;
    }

    boundBuffer->SetByteLength(data.Length());
    if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length()))
        return ErrorOutOfMemory("bufferData: out of memory");
}
コード例 #5
0
void
WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
{
    const char funcName[] = "bufferData";
    if (IsContextLost())
        return;

    if (!ValidateNonNegative(funcName, "size", size))
        return;

    ////

    const UniqueBuffer zeroBuffer(calloc(size, 1));
    if (!zeroBuffer)
        return ErrorOutOfMemory("%s: Failed to allocate zeros.", funcName);

    BufferDataImpl(target, size_t(size), (const uint8_t*)zeroBuffer.get(), usage);
}
コード例 #6
0
void
WebGL2Context::GetActiveUniforms(JSContext* cx, const WebGLProgram& program,
                                 const dom::Sequence<GLuint>& uniformIndices,
                                 GLenum pname, JS::MutableHandleValue retval)
{
    const char funcName[] = "getActiveUniforms";
    retval.setNull();
    if (IsContextLost())
        return;

    if (!ValidateUniformEnum(this, pname, funcName))
        return;

    if (!ValidateObject("getActiveUniforms: program", program))
        return;

    const auto& numActiveUniforms = program.LinkInfo()->uniforms.size();
    for (const auto& curIndex : uniformIndices) {
        if (curIndex >= numActiveUniforms) {
            ErrorInvalidValue("%s: Too-large active uniform index queried.", funcName);
            return;
        }
    }

    const auto& count = uniformIndices.Length();

    JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
    UniquePtr<GLint[]> samples(new GLint[count]);
    if (!array || !samples) {
        ErrorOutOfMemory("%s: Failed to allocate buffers.", funcName);
        return;
    }
    retval.setObject(*array);

    MakeContextCurrent();
    gl->fGetActiveUniformsiv(program.mGLName, count, uniformIndices.Elements(), pname,
                             samples.get());

    switch (pname) {
    case LOCAL_GL_UNIFORM_TYPE:
    case LOCAL_GL_UNIFORM_SIZE:
    case LOCAL_GL_UNIFORM_BLOCK_INDEX:
    case LOCAL_GL_UNIFORM_OFFSET:
    case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
    case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
        for (size_t i = 0; i < count; ++i) {
            JS::RootedValue value(cx);
            value = JS::Int32Value(samples[i]);
            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE))
                return;
        }
        break;
    case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
        for (size_t i = 0; i < count; ++i) {
            JS::RootedValue value(cx);
            value = JS::BooleanValue(samples[i]);
            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE))
                return;
        }
        break;

    default:
        MOZ_CRASH("Invalid pname");
    }
}
コード例 #7
0
bool
WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
{
    WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();

    if (MOZ_LIKELY(whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default))
        return true;

    if (!mAlreadyWarnedAboutFakeVertexAttrib0) {
        GenerateWarning("Drawing without vertex attrib 0 array enabled forces the browser "
                        "to do expensive emulation work when running on desktop OpenGL "
                        "platforms, for example on Mac. It is preferable to always draw "
                        "with vertex attrib 0 array enabled, by using bindAttribLocation "
                        "to bind some always-used attribute to location 0.");
        mAlreadyWarnedAboutFakeVertexAttrib0 = true;
    }

    CheckedUint32 checked_dataSize = CheckedUint32(vertexCount) * 4 * sizeof(GLfloat);

    if (!checked_dataSize.isValid()) {
        ErrorOutOfMemory("Integer overflow trying to construct a fake vertex attrib 0 array for a draw-operation "
                         "with %d vertices. Try reducing the number of vertices.", vertexCount);
        return false;
    }

    GLuint dataSize = checked_dataSize.value();

    if (!mFakeVertexAttrib0BufferObject) {
        gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
    }

    // if the VBO status is already exactly what we need, or if the only difference is that it's initialized and
    // we don't need it to be, then consider it OK
    bool vertexAttrib0BufferStatusOK =
        mFakeVertexAttrib0BufferStatus == whatDoesAttrib0Need ||
        (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray &&
         whatDoesAttrib0Need == WebGLVertexAttrib0Status::EmulatedUninitializedArray);

    if (!vertexAttrib0BufferStatusOK ||
        mFakeVertexAttrib0BufferObjectSize < dataSize ||
        mFakeVertexAttrib0BufferObjectVector[0] != mVertexAttrib0Vector[0] ||
        mFakeVertexAttrib0BufferObjectVector[1] != mVertexAttrib0Vector[1] ||
        mFakeVertexAttrib0BufferObjectVector[2] != mVertexAttrib0Vector[2] ||
        mFakeVertexAttrib0BufferObjectVector[3] != mVertexAttrib0Vector[3])
    {
        mFakeVertexAttrib0BufferStatus = whatDoesAttrib0Need;
        mFakeVertexAttrib0BufferObjectSize = dataSize;
        mFakeVertexAttrib0BufferObjectVector[0] = mVertexAttrib0Vector[0];
        mFakeVertexAttrib0BufferObjectVector[1] = mVertexAttrib0Vector[1];
        mFakeVertexAttrib0BufferObjectVector[2] = mVertexAttrib0Vector[2];
        mFakeVertexAttrib0BufferObjectVector[3] = mVertexAttrib0Vector[3];

        gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);

        GetAndFlushUnderlyingGLErrors();

        if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
            auto array = MakeUniqueFallible<GLfloat[]>(4 * vertexCount);
            if (!array) {
                ErrorOutOfMemory("Fake attrib0 array.");
                return false;
            }
            for(size_t i = 0; i < vertexCount; ++i) {
                array[4 * i + 0] = mVertexAttrib0Vector[0];
                array[4 * i + 1] = mVertexAttrib0Vector[1];
                array[4 * i + 2] = mVertexAttrib0Vector[2];
                array[4 * i + 3] = mVertexAttrib0Vector[3];
            }
            gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, array.get(), LOCAL_GL_DYNAMIC_DRAW);
        } else {
            gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nullptr, LOCAL_GL_DYNAMIC_DRAW);
        }
        GLenum error = GetAndFlushUnderlyingGLErrors();

        gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0);

        // note that we do this error checking and early return AFTER having restored the buffer binding above
        if (error) {
            ErrorOutOfMemory("Ran out of memory trying to construct a fake vertex attrib 0 array for a draw-operation "
                             "with %d vertices. Try reducing the number of vertices.", vertexCount);
            return false;
        }
    }

    gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
    gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0);

    return true;
}