void WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount) { const char funcName[] = "drawArraysInstanced"; if (IsContextLost()) return; if (!ValidateDrawModeEnum(mode, funcName)) return; MakeContextCurrent(); bool error; ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error); if (error) return; if (!DrawArrays_check(first, count, primcount, funcName)) return; if (!DrawInstanced_check(funcName)) return; RunContextLossTimer(); { ScopedMaskWorkaround autoMask(*this); gl->fDrawArraysInstanced(mode, first, count, primcount); } Draw_cleanup(funcName); }
bool WebGLContext::DrawArrays_check(const char* funcName, GLenum mode, GLint first, GLsizei vertCount, GLsizei instanceCount) { if (!ValidateDrawModeEnum(mode, funcName)) return false; if (!ValidateNonNegative(funcName, "first", first) || !ValidateNonNegative(funcName, "vertCount", vertCount) || !ValidateNonNegative(funcName, "instanceCount", instanceCount)) { return false; } if (!ValidateStencilParamsForDrawCall()) return false; if (IsWebGL2() && !gl->IsSupported(gl::GLFeature::prim_restart_fixed)) { MOZ_ASSERT(gl->IsSupported(gl::GLFeature::prim_restart)); if (mPrimRestartTypeBytes != 0) { mPrimRestartTypeBytes = 0; // OSX appears to have severe perf issues with leaving this enabled. gl->fDisable(LOCAL_GL_PRIMITIVE_RESTART); } } if (!vertCount || !instanceCount) return false; // No error, just early out. if (!ValidateBufferFetching(funcName)) return false; const auto checked_firstPlusCount = CheckedInt<GLsizei>(first) + vertCount; if (!checked_firstPlusCount.isValid()) { ErrorInvalidOperation("%s: overflow in first+vertCount", funcName); 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.", funcName); return false; } return true; }
void WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type, WebGLintptr byteOffset) { const char funcName[] = "drawElements"; if (IsContextLost()) return; if (!ValidateDrawModeEnum(mode, funcName)) return; MakeContextCurrent(); bool error; ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error); if (error) return; GLuint upperBound = 0; if (!DrawElements_check(count, type, byteOffset, 1, funcName, &upperBound)) return; RunContextLossTimer(); { ScopedMaskWorkaround autoMask(*this); if (gl->IsSupported(gl::GLFeature::draw_range_elements)) { gl->fDrawRangeElements(mode, 0, upperBound, count, type, reinterpret_cast<GLvoid*>(byteOffset)); } else { gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset)); } } Draw_cleanup(funcName); }
void WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, WebGLintptr byteOffset, GLsizei primcount) { const char funcName[] = "drawElementsInstanced"; if (IsContextLost()) return; if (!ValidateDrawModeEnum(mode, funcName)) return; MakeContextCurrent(); bool error; ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error); if (error) return; GLuint upperBound = 0; if (!DrawElements_check(count, type, byteOffset, primcount, funcName, &upperBound)) return; if (!DrawInstanced_check(funcName)) return; RunContextLossTimer(); { ScopedMaskWorkaround autoMask(*this); gl->fDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset), primcount); } Draw_cleanup(funcName); }
bool WebGLContext::DrawElements_check(const char* funcName, GLenum mode, GLsizei vertCount, GLenum type, WebGLintptr byteOffset, GLsizei instanceCount) { if (!ValidateDrawModeEnum(mode, funcName)) return false; if (mBoundTransformFeedback && mBoundTransformFeedback->mIsActive && !mBoundTransformFeedback->mIsPaused) { ErrorInvalidOperation("%s: DrawElements* functions are incompatible with" " transform feedback.", funcName); return false; } if (!ValidateNonNegative(funcName, "vertCount", vertCount) || !ValidateNonNegative(funcName, "byteOffset", byteOffset) || !ValidateNonNegative(funcName, "instanceCount", instanceCount)) { return false; } if (!ValidateStencilParamsForDrawCall()) return false; if (!vertCount || !instanceCount) return false; // No error, just early out. 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", funcName, type); return false; } if (byteOffset % bytesPerElem != 0) { ErrorInvalidOperation("%s: `byteOffset` must be a multiple of the size of `type`", funcName); return false; } //// if (IsWebGL2() && !gl->IsSupported(gl::GLFeature::prim_restart_fixed)) { MOZ_ASSERT(gl->IsSupported(gl::GLFeature::prim_restart)); if (mPrimRestartTypeBytes != bytesPerElem) { mPrimRestartTypeBytes = bytesPerElem; const uint32_t ones = UINT32_MAX >> (32 - 8*mPrimRestartTypeBytes); gl->fEnable(LOCAL_GL_PRIMITIVE_RESTART); gl->fPrimitiveRestartIndex(ones); }