void WebGLContext::Clear(GLbitfield mask) { const char funcName[] = "clear"; if (IsContextLost()) return; MakeContextCurrent(); uint32_t m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT); if (mask != m) return ErrorInvalidValue("%s: invalid mask bits", funcName); if (mask == 0) { GenerateWarning("Calling gl.clear(0) has no effect."); } else if (mRasterizerDiscardEnabled) { GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects."); } if (mBoundDrawFramebuffer) { if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName)) return; gl->fClear(mask); return; } else { ClearBackbufferIfNeeded(); } // Ok, we're clearing the default framebuffer/screen. { ScopedMaskWorkaround autoMask(*this); gl->fClear(mask); } Invalidate(); mShouldPresent = true; }
bool WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset, GLsizei primcount, const char* info, GLuint* out_upperBound) { if (count < 0 || byteOffset < 0) { ErrorInvalidValue("%s: negative count or offset", info); return false; } if (primcount < 0) { ErrorInvalidValue("%s: negative primcount", info); return false; } if (!ValidateStencilParamsForDrawCall()) { return false; } // If count is 0, there's nothing to do. if (count == 0 || primcount == 0) return false; uint8_t bytesPerElem = 0; switch (type) { case LOCAL_GL_UNSIGNED_BYTE: bytesPerElem = 1; break; case LOCAL_GL_UNSIGNED_SHORT: bytesPerElem = 2; break; case LOCAL_GL_UNSIGNED_INT: if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_element_index_uint)) { bytesPerElem = 4; } break; } if (!bytesPerElem) { ErrorInvalidEnum("%s: Invalid `type`: 0x%04x", info, type); return false; } if (byteOffset % bytesPerElem != 0) { ErrorInvalidOperation("%s: `byteOffset` must be a multiple of the size of `type`", info); return false; } const GLsizei first = byteOffset / bytesPerElem; const CheckedUint32 checked_byteCount = bytesPerElem * CheckedUint32(count); if (!checked_byteCount.isValid()) { ErrorInvalidValue("%s: overflow in byteCount", info); return false; } // Any checks below this depend on a program being available. if (!mCurrentProgram) { ErrorInvalidOperation("%s: null CURRENT_PROGRAM", info); return false; } if (!mBoundVertexArray->mElementArrayBuffer) { ErrorInvalidOperation("%s: must have element array buffer binding", info); return false; } WebGLBuffer& elemArrayBuffer = *mBoundVertexArray->mElementArrayBuffer; if (!elemArrayBuffer.ByteLength()) { ErrorInvalidOperation("%s: bound element array buffer doesn't have any data", info); return false; } CheckedInt<GLsizei> checked_neededByteCount = checked_byteCount.toChecked<GLsizei>() + byteOffset; if (!checked_neededByteCount.isValid()) { ErrorInvalidOperation("%s: overflow in byteOffset+byteCount", info); return false; } if (uint32_t(checked_neededByteCount.value()) > elemArrayBuffer.ByteLength()) { ErrorInvalidOperation("%s: bound element array buffer is too small for given count and offset", info); return false; } if (!ValidateBufferFetching(info)) return false; if (!mMaxFetchedVertices || !elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count, out_upperBound)) { ErrorInvalidOperation( "%s: bound vertex attribute buffers do not have sufficient " "size for given indices from the bound element array", info); return false; } if (uint32_t(primcount) > mMaxFetchedInstances) { ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info); return false; } // Bug 1008310 - Check if buffer has been used with a different previous type if (elemArrayBuffer.IsElementArrayUsedWithMultipleTypes()) { GenerateWarning("%s: bound element array buffer previously used with a type other than " "%s, this will affect performance.", info, WebGLContext::EnumName(type)); } MOZ_ASSERT(gl->IsCurrent()); if (mBoundDrawFramebuffer) { if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(info)) return false; } else { ClearBackbufferIfNeeded(); } if (!DoFakeVertexAttrib0(mMaxFetchedVertices)) { return false; } return true; }
bool WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info) { if (first < 0 || count < 0) { ErrorInvalidValue("%s: negative first or count", info); return false; } if (primcount < 0) { ErrorInvalidValue("%s: negative primcount", info); return false; } if (!ValidateStencilParamsForDrawCall()) { return false; } // If count is 0, there's nothing to do. if (count == 0 || primcount == 0) { return false; } // Any checks below this depend on a program being available. if (!mCurrentProgram) { ErrorInvalidOperation("%s: null CURRENT_PROGRAM", info); return false; } if (!ValidateBufferFetching(info)) { return false; } CheckedInt<GLsizei> checked_firstPlusCount = CheckedInt<GLsizei>(first) + count; if (!checked_firstPlusCount.isValid()) { ErrorInvalidOperation("%s: overflow in first+count", info); return false; } if (uint32_t(checked_firstPlusCount.value()) > mMaxFetchedVertices) { ErrorInvalidOperation("%s: bound vertex attribute buffers do not have sufficient size for given first and count", info); return false; } if (uint32_t(primcount) > mMaxFetchedInstances) { ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info); return false; } MOZ_ASSERT(gl->IsCurrent()); if (mBoundDrawFramebuffer) { if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(info)) return false; } else { ClearBackbufferIfNeeded(); } if (!DoFakeVertexAttrib0(checked_firstPlusCount.value())) { return false; } return true; }