Chromium Code Reviews| Index: third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
| diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
| index 7589a6d6b6bdfe7a7fac9180e97214cdefeba2bd..7d31db4c229efda79715902d12f575b9070eda9d 100644 |
| --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
| +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
| @@ -873,6 +873,7 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCa |
| , m_dispatchContextLostEventTimer(this, &WebGLRenderingContextBase::dispatchContextLostEvent) |
| , m_restoreAllowed(false) |
| , m_restoreTimer(this, &WebGLRenderingContextBase::maybeRestoreContext) |
| + , m_preservedDefaultVAOObjectWrapper(false) |
| , m_generatedImageCache(4) |
| , m_requestedAttributes(requestedAttributes) |
| , m_synthesizedErrorsToConsole(true) |
| @@ -993,6 +994,8 @@ void WebGLRenderingContextBase::initializeNewContext() |
| m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectBase::VaoTypeDefault); |
| } |
| addContextObject(m_defaultVertexArrayObject.get()); |
| + // We can't preserve this object's wrapper yet since there's no ScriptState available. |
| + m_preservedDefaultVAOObjectWrapper = false; |
| m_boundVertexArrayObject = m_defaultVertexArrayObject; |
| m_vertexAttribValue.resize(m_maxVertexAttribs); |
| @@ -1364,7 +1367,7 @@ void WebGLRenderingContextBase::activeTexture(GLenum texture) |
| } |
| -void WebGLRenderingContextBase::attachShader(WebGLProgram* program, WebGLShader* shader) |
| +void WebGLRenderingContextBase::attachShader(ScriptState* scriptState, WebGLProgram* program, WebGLShader* shader) |
| { |
| if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) |
| return; |
| @@ -1374,6 +1377,7 @@ void WebGLRenderingContextBase::attachShader(WebGLProgram* program, WebGLShader* |
| } |
| webContext()->attachShader(objectOrZero(program), objectOrZero(shader)); |
| shader->onAttached(); |
| + preserveObjectWrapper(scriptState, program, "shader", shader->type(), shader); |
| } |
| void WebGLRenderingContextBase::bindAttribLocation(WebGLProgram* program, GLuint index, const String& name) |
| @@ -1437,7 +1441,7 @@ bool WebGLRenderingContextBase::validateAndUpdateBufferBindTarget(const char* fu |
| return true; |
| } |
| -void WebGLRenderingContextBase::bindBuffer(GLenum target, WebGLBuffer* buffer) |
| +void WebGLRenderingContextBase::bindBuffer(ScriptState* scriptState, GLenum target, WebGLBuffer* buffer) |
| { |
| bool deleted; |
| if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) |
| @@ -1448,9 +1452,11 @@ void WebGLRenderingContextBase::bindBuffer(GLenum target, WebGLBuffer* buffer) |
| return; |
| webContext()->bindBuffer(target, objectOrZero(buffer)); |
| + preserveObjectWrapper(scriptState, this, "buffer", target, buffer); |
| + maybePreserveDefaultVAOObjectWrapper(scriptState); |
| } |
| -void WebGLRenderingContextBase::bindFramebuffer(GLenum target, WebGLFramebuffer* buffer) |
| +void WebGLRenderingContextBase::bindFramebuffer(ScriptState* scriptState, GLenum target, WebGLFramebuffer* buffer) |
| { |
| bool deleted; |
| if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) |
| @@ -1465,9 +1471,11 @@ void WebGLRenderingContextBase::bindFramebuffer(GLenum target, WebGLFramebuffer* |
| } |
| setFramebuffer(target, buffer); |
| + if (scriptState) |
| + preserveObjectWrapper(scriptState, this, "framebuffer", 0, buffer); |
| } |
| -void WebGLRenderingContextBase::bindRenderbuffer(GLenum target, WebGLRenderbuffer* renderBuffer) |
| +void WebGLRenderingContextBase::bindRenderbuffer(ScriptState* scriptState, GLenum target, WebGLRenderbuffer* renderBuffer) |
| { |
| bool deleted; |
| if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) |
| @@ -1480,11 +1488,12 @@ void WebGLRenderingContextBase::bindRenderbuffer(GLenum target, WebGLRenderbuffe |
| } |
| m_renderbufferBinding = renderBuffer; |
| webContext()->bindRenderbuffer(target, objectOrZero(renderBuffer)); |
| + preserveObjectWrapper(scriptState, this, "renderbuffer", 0, renderBuffer); |
| if (renderBuffer) |
| renderBuffer->setHasEverBeenBound(); |
| } |
| -void WebGLRenderingContextBase::bindTexture(GLenum target, WebGLTexture* texture) |
| +void WebGLRenderingContextBase::bindTexture(ScriptState* scriptState, GLenum target, WebGLTexture* texture) |
| { |
| bool deleted; |
| if (!checkObjectToBeBound("bindTexture", texture, deleted)) |
| @@ -1495,23 +1504,34 @@ void WebGLRenderingContextBase::bindTexture(GLenum target, WebGLTexture* texture |
| synthesizeGLError(GL_INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets"); |
| return; |
| } |
| + |
| + const char* bindingPointName = nullptr; |
| if (target == GL_TEXTURE_2D) { |
| m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture; |
| if (!m_activeTextureUnit) |
| drawingBuffer()->setTexture2DBinding(objectOrZero(texture)); |
| + bindingPointName = "texture_2d"; |
| } else if (target == GL_TEXTURE_CUBE_MAP) { |
| m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture; |
| + bindingPointName = "texture_cube_map"; |
| } else if (isWebGL2OrHigher() && target == GL_TEXTURE_2D_ARRAY) { |
| m_textureUnits[m_activeTextureUnit].m_texture2DArrayBinding = texture; |
| + bindingPointName = "texture_2d_array"; |
| } else if (isWebGL2OrHigher() && target == GL_TEXTURE_3D) { |
| m_textureUnits[m_activeTextureUnit].m_texture3DBinding = texture; |
| + bindingPointName = "texture_3d"; |
| } else { |
| synthesizeGLError(GL_INVALID_ENUM, "bindTexture", "invalid target"); |
| return; |
| } |
| webContext()->bindTexture(target, objectOrZero(texture)); |
| + // This is called both internally and externally (from JavaScript). We only update which wrapper |
| + // is preserved when it's called from JavaScript. |
| + if (scriptState) { |
| + preserveObjectWrapper(scriptState, this, bindingPointName, m_activeTextureUnit, texture); |
| + } |
| if (texture) { |
| texture->setTarget(target, getMaxTextureLevelForTarget(target)); |
| m_onePlusMaxNonDefaultTextureUnit = max(m_activeTextureUnit + 1, m_onePlusMaxNonDefaultTextureUnit); |
| @@ -1941,6 +1961,16 @@ WebGLRenderbuffer* WebGLRenderingContextBase::ensureEmulatedStencilBuffer(GLenum |
| return renderbuffer->emulatedStencilBuffer(); |
| } |
| +void WebGLRenderingContextBase::setBoundVertexArrayObject(ScriptState* scriptState, WebGLVertexArrayObjectBase* arrayObject) |
| +{ |
| + if (arrayObject) |
| + m_boundVertexArrayObject = arrayObject; |
| + else |
| + m_boundVertexArrayObject = m_defaultVertexArrayObject; |
| + |
| + preserveObjectWrapper(scriptState, this, "boundvao", 0, arrayObject); |
| +} |
| + |
| WebGLShader* WebGLRenderingContextBase::createShader(GLenum type) |
| { |
| if (isContextLost()) |
| @@ -2097,7 +2127,7 @@ void WebGLRenderingContextBase::depthRange(GLfloat zNear, GLfloat zFar) |
| webContext()->depthRange(zNear, zFar); |
| } |
| -void WebGLRenderingContextBase::detachShader(WebGLProgram* program, WebGLShader* shader) |
| +void WebGLRenderingContextBase::detachShader(ScriptState* scriptState, WebGLProgram* program, WebGLShader* shader) |
| { |
| if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) |
| return; |
| @@ -2107,6 +2137,7 @@ void WebGLRenderingContextBase::detachShader(WebGLProgram* program, WebGLShader* |
| } |
| webContext()->detachShader(objectOrZero(program), objectOrZero(shader)); |
| shader->onDetached(webContext()); |
| + preserveObjectWrapper(scriptState, program, "shader", shader->type(), nullptr); |
| } |
| void WebGLRenderingContextBase::disable(GLenum cap) |
| @@ -2266,7 +2297,7 @@ void WebGLRenderingContextBase::flush() |
| webContext()->flush(); |
| } |
| -void WebGLRenderingContextBase::framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer* buffer) |
| +void WebGLRenderingContextBase::framebufferRenderbuffer(ScriptState* scriptState, GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer* buffer) |
| { |
| if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment)) |
| return; |
| @@ -2314,9 +2345,10 @@ void WebGLRenderingContextBase::framebufferRenderbuffer(GLenum target, GLenum at |
| framebufferBinding->setAttachmentForBoundFramebuffer(target, attachment, buffer); |
| } |
| applyStencilTest(); |
| + preserveObjectWrapper(scriptState, framebufferBinding, "renderbuffer", attachment, buffer); |
| } |
| -void WebGLRenderingContextBase::framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture* texture, GLint level) |
| +void WebGLRenderingContextBase::framebufferTexture2D(ScriptState* scriptState, GLenum target, GLenum attachment, GLenum textarget, WebGLTexture* texture, GLint level) |
| { |
| if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment)) |
| return; |
| @@ -2356,6 +2388,7 @@ void WebGLRenderingContextBase::framebufferTexture2D(GLenum target, GLenum attac |
| } |
| framebufferBinding->setAttachmentForBoundFramebuffer(target, attachment, textarget, texture, level); |
| applyStencilTest(); |
| + preserveObjectWrapper(scriptState, framebufferBinding, "texture2d", attachment, texture); |
| } |
| void WebGLRenderingContextBase::frontFace(GLenum mode) |
| @@ -2560,6 +2593,7 @@ bool WebGLRenderingContextBase::extensionSupportedAndAllowed(const ExtensionTrac |
| ScriptValue WebGLRenderingContextBase::getExtension(ScriptState* scriptState, const String& name) |
| { |
| WebGLExtension* extension = nullptr; |
| + bool linkContextToExtension = false; |
| if (!isContextLost()) { |
| for (size_t i = 0; i < m_extensions.size(); ++i) { |
| @@ -2567,15 +2601,27 @@ ScriptValue WebGLRenderingContextBase::getExtension(ScriptState* scriptState, co |
| if (tracker->matchesNameWithPrefixes(name)) { |
| if (extensionSupportedAndAllowed(tracker)) { |
| extension = tracker->getExtension(this); |
| - if (extension) |
| - m_extensionEnabled[extension->name()] = true; |
| + if (extension) { |
| + if (!m_extensionEnabled[extension->name()]) { |
| + linkContextToExtension = true; |
| + m_extensionEnabled[extension->name()] = true; |
| + } |
| + } |
| } |
| break; |
| } |
| } |
| } |
| - return ScriptValue(scriptState, toV8(extension, scriptState->context()->Global(), scriptState->isolate())); |
| + v8::Local<v8::Value> wrappedExtension = toV8(extension, scriptState->context()->Global(), scriptState->isolate()); |
| + |
| + if (linkContextToExtension) { |
| + // Keep the extension's JavaScript wrapper alive as long as the context is alive, so that |
| + // expando properties that are added to the extension persist. |
| + preserveObjectWrapper(scriptState, this, "extension", static_cast<unsigned long>(extension->name()), extension); |
| + } |
| + |
| + return ScriptValue(scriptState, wrappedExtension); |
| } |
| ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(ScriptState* scriptState, GLenum target, GLenum attachment, GLenum pname) |
| @@ -4853,7 +4899,7 @@ void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* loc |
| webContext()->uniformMatrix4fv(location->location(), v.size() >> 4, transpose, v.data()); |
| } |
| -void WebGLRenderingContextBase::useProgram(WebGLProgram* program) |
| +void WebGLRenderingContextBase::useProgram(ScriptState* scriptState, WebGLProgram* program) |
| { |
| bool deleted; |
| if (!checkObjectToBeBound("useProgram", program, deleted)) |
| @@ -4871,6 +4917,7 @@ void WebGLRenderingContextBase::useProgram(WebGLProgram* program) |
| webContext()->useProgram(objectOrZero(program)); |
| if (program) |
| program->onAttached(); |
| + preserveObjectWrapper(scriptState, this, "program", 0, program); |
| } |
| } |
| @@ -4941,7 +4988,7 @@ void WebGLRenderingContextBase::vertexAttrib4fv(GLuint index, const Vector<GLflo |
| vertexAttribfvImpl("vertexAttrib4fv", index, v.data(), v.size(), 4); |
| } |
| -void WebGLRenderingContextBase::vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, long long offset) |
| +void WebGLRenderingContextBase::vertexAttribPointer(ScriptState* scriptState, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, long long offset) |
| { |
| if (isContextLost()) |
| return; |
| @@ -4980,6 +5027,8 @@ void WebGLRenderingContextBase::vertexAttribPointer(GLuint index, GLint size, GL |
| m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GLintptr>(offset), m_boundArrayBuffer); |
| webContext()->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GLintptr>(offset)); |
| + maybePreserveDefaultVAOObjectWrapper(scriptState); |
| + preserveObjectWrapper(scriptState, m_boundVertexArrayObject, "arraybuffer", index, m_boundArrayBuffer); |
|
bajones
2015/10/03 14:39:23
I don't think so, but just so we're clear: This wo
Ken Russell (switch to Gerrit)
2015/10/05 22:42:03
No. These properties don't show up on the object.
|
| } |
| void WebGLRenderingContextBase::vertexAttribDivisorANGLE(GLuint index, GLuint divisor) |
| @@ -5101,6 +5150,31 @@ void WebGLRenderingContextBase::setFilterQuality(SkFilterQuality filterQuality) |
| } |
| } |
| +void WebGLRenderingContextBase::preserveObjectWrapper(ScriptState* scriptState, ScriptWrappable* sourceObject, const char* baseName, unsigned long index, ScriptWrappable* targetObject) |
| +{ |
| + v8::Local<v8::Value> value; |
| + |
| + StringBuilder builder; |
| + builder.append(baseName); |
| + builder.appendNumber(static_cast<unsigned>(index)); |
| + CString name = builder.toString().utf8(); |
| + if (targetObject) { |
| + value = targetObject->newLocalWrapper(scriptState->isolate()); |
| + } else { |
| + value = v8::Null(scriptState->isolate()); |
| + } |
| + |
| + V8HiddenValue::setHiddenValue( |
| + scriptState->isolate(), |
| + sourceObject->newLocalWrapper(scriptState->isolate()), |
| + v8::String::NewFromUtf8( |
| + scriptState->isolate(), |
| + name.data(), |
| + v8::NewStringType::kNormal, |
| + name.length()).ToLocalChecked(), |
| + value); |
| +} |
| + |
| Extensions3DUtil* WebGLRenderingContextBase::extensionsUtil() |
| { |
| if (!m_extensionsUtil) { |
| @@ -6642,12 +6716,12 @@ void WebGLRenderingContextBase::setFramebuffer(GLenum target, WebGLFramebuffer* |
| void WebGLRenderingContextBase::restoreCurrentFramebuffer() |
| { |
| - bindFramebuffer(GL_FRAMEBUFFER, m_framebufferBinding.get()); |
| + bindFramebuffer(nullptr, GL_FRAMEBUFFER, m_framebufferBinding.get()); |
| } |
| void WebGLRenderingContextBase::restoreCurrentTexture2D() |
| { |
| - bindTexture(GL_TEXTURE_2D, m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()); |
| + bindTexture(nullptr, GL_TEXTURE_2D, m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()); |
| } |
| void WebGLRenderingContextBase::multisamplingChanged(bool enabled) |
| @@ -6672,6 +6746,17 @@ void WebGLRenderingContextBase::findNewMaxNonDefaultTextureUnit() |
| m_onePlusMaxNonDefaultTextureUnit = 0; |
| } |
| +void WebGLRenderingContextBase::maybePreserveDefaultVAOObjectWrapper(ScriptState* scriptState) |
| +{ |
| + if (!m_preservedDefaultVAOObjectWrapper) { |
| + // The default VAO does not have a JavaScript wrapper created for it, but one is needed to |
| + // link up the WebGLBuffers associated with the vertex attributes. |
| + m_defaultVertexArrayObject->wrap(scriptState->isolate(), scriptState->context()->Global()); |
| + preserveObjectWrapper(scriptState, this, "defaultvao", 0, m_defaultVertexArrayObject); |
| + m_preservedDefaultVAOObjectWrapper = true; |
| + } |
| +} |
| + |
| DEFINE_TRACE(WebGLRenderingContextBase::TextureUnitState) |
| { |
| visitor->trace(m_texture2DBinding); |