void WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usage) { const char funcName[] = "bufferData"; if (!ValidateBufferUsageEnum(mContext, funcName, usage)) return; if (mNumActiveTFOs) { mContext->ErrorInvalidOperation("%s: Buffer is bound to an active transform" " feedback object.", funcName); return; } const auto& gl = mContext->gl; gl->MakeCurrent(); const ScopedLazyBind lazyBind(gl, target, this); mContext->InvalidateBufferFetching(); #ifdef XP_MACOSX // bug 790879 if (gl->WorkAroundDriverBugs() && size > INT32_MAX) { mContext->ErrorOutOfMemory("%s: Allocation size too large.", funcName); return; } #endif const bool sizeChanges = (size != ByteLength()); if (sizeChanges) { gl::GLContext::LocalErrorScope errorScope(*gl); gl->fBufferData(target, size, data, usage); const auto error = errorScope.GetError(); if (error) { MOZ_ASSERT(error == LOCAL_GL_OUT_OF_MEMORY); mContext->ErrorOutOfMemory("%s: Error from driver: 0x%04x", funcName, error); return; } } else { gl->fBufferData(target, size, data, usage); } mUsage = usage; mByteLength = size; // Warning: Possibly shared memory. See bug 1225033. if (!ElementArrayCacheBufferData(data, size)) { mByteLength = 0; mContext->ErrorOutOfMemory("%s: Failed update index buffer cache.", funcName); } }
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"); } }
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"); }
void WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usage) { // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr // is like intptr_t. if (!CheckedInt<GLsizeiptr>(size).isValid()) return mContext->ErrorOutOfMemory("bad size"); if (!ValidateBufferUsageEnum(mContext, usage)) return; #ifdef XP_MACOSX // bug 790879 if (mContext->gl->WorkAroundDriverBugs() && size > INT32_MAX) { mContext->ErrorOutOfMemory("Allocation size too large."); return; } #endif const void* uploadData = data; UniqueBuffer newIndexCache; if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER && mContext->mNeedsIndexValidation) { newIndexCache = malloc(size); if (!newIndexCache) { mContext->ErrorOutOfMemory("Failed to alloc index cache."); return; } memcpy(newIndexCache.get(), data, size); uploadData = newIndexCache.get(); } const auto& gl = mContext->gl; const ScopedLazyBind lazyBind(gl, target, this); const bool sizeChanges = (size != ByteLength()); if (sizeChanges) { gl::GLContext::LocalErrorScope errorScope(*gl); gl->fBufferData(target, size, uploadData, usage); const auto error = errorScope.GetError(); if (error) { MOZ_ASSERT(error == LOCAL_GL_OUT_OF_MEMORY); mContext->ErrorOutOfMemory("Error from driver: 0x%04x", error); return; } } else { gl->fBufferData(target, size, uploadData, usage); } mContext->OnDataAllocCall(); mUsage = usage; mByteLength = size; mFetchInvalidator.InvalidateCaches(); mIndexCache = std::move(newIndexCache); if (mIndexCache) { if (!mIndexRanges.empty()) { mContext->GeneratePerfWarning("[%p] Invalidating %u ranges.", this, uint32_t(mIndexRanges.size())); mIndexRanges.clear(); } } ResetLastUpdateFenceId(); }