Chromium Code Reviews| Index: Source/core/html/canvas/WebGLRenderingContext.cpp |
| diff --git a/Source/core/html/canvas/WebGLRenderingContext.cpp b/Source/core/html/canvas/WebGLRenderingContext.cpp |
| index f6071a6e5e5a61480e4ed9508e6a072dc4292705..3580fee2a2f41f59dcd4d6998f4ee466383c617f 100644 |
| --- a/Source/core/html/canvas/WebGLRenderingContext.cpp |
| +++ b/Source/core/html/canvas/WebGLRenderingContext.cpp |
| @@ -43,6 +43,7 @@ |
| #include "core/html/canvas/OESTextureHalfFloat.h" |
| #include "core/html/canvas/OESTextureHalfFloatLinear.h" |
| #include "core/html/canvas/OESVertexArrayObject.h" |
| +#include "core/html/canvas/WebGLAcquireSharedResourceCallback.h" |
| #include "core/html/canvas/WebGLActiveInfo.h" |
| #include "core/html/canvas/WebGLBuffer.h" |
| #include "core/html/canvas/WebGLCompressedTextureATC.h" |
| @@ -61,6 +62,8 @@ |
| #include "core/html/canvas/WebGLRenderbuffer.h" |
| #include "core/html/canvas/WebGLShader.h" |
| #include "core/html/canvas/WebGLShaderPrecisionFormat.h" |
| +#include "core/html/canvas/WebGLShareGroup.h" |
| +#include "core/html/canvas/WebGLSharedResources.h" |
| #include "core/html/canvas/WebGLTexture.h" |
| #include "core/html/canvas/WebGLUniformLocation.h" |
| #include "core/inspector/InspectorInstrumentation.h" |
| @@ -524,7 +527,11 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen |
| if (extensions->supports("GL_EXT_debug_marker")) |
| extensions->pushGroupMarkerEXT("WebGLRenderingContext"); |
| - OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRenderingContext(canvas, context, attributes, requestedAttributes)); |
| + RefPtr<WebGLContextGroup> contextGroup(attrs->group() |
| + ? attrs->group()->contextGroup() |
| + : WebGLContextGroup::create()); |
| + |
| + OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRenderingContext(canvas, context, attributes, requestedAttributes, contextGroup)); |
| renderingContext->suspendIfNeeded(); |
| if (renderingContext->m_drawingBuffer->isZeroSized()) { |
| @@ -535,10 +542,11 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen |
| return renderingContext.release(); |
| } |
| -WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context, GraphicsContext3D::Attributes attributes, GraphicsContext3D::Attributes requestedAttributes) |
| +WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context, GraphicsContext3D::Attributes attributes, GraphicsContext3D::Attributes requestedAttributes, PassRefPtr<WebGLContextGroup> contextGroup) |
| : CanvasRenderingContext(passedCanvas) |
| , ActiveDOMObject(passedCanvas->document()) |
| , m_context(context) |
| + , m_contextGroup(contextGroup) |
| , m_drawingBuffer(0) |
| , m_dispatchContextLostEventTimer(this, &WebGLRenderingContext::dispatchContextLostEvent) |
| , m_restoreAllowed(false) |
| @@ -556,7 +564,6 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa |
| ASSERT(m_context); |
| ScriptWrappable::init(this); |
| - m_contextGroup = WebGLContextGroup::create(); |
| m_contextGroup->addContext(this); |
| m_maxViewportDims[0] = m_maxViewportDims[1] = 0; |
| @@ -597,6 +604,7 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa |
| registerExtension<ANGLEInstancedArrays>(m_angleInstancedArrays, false, true, false, unprefixed); |
| registerExtension<EXTFragDepth>(m_extFragDepth, false, true, false, unprefixed); |
| registerExtension<WebGLDrawBuffers>(m_webglDrawBuffers, false, true, false, unprefixed); |
| + registerExtension<WebGLSharedResources>(m_webglSharedResources, false, true, false, unprefixed); |
| // Register privileged extensions. |
| registerExtension<WebGLDebugRendererInfo>(m_webglDebugRendererInfo, true, false, false, unprefixed); |
| @@ -1002,20 +1010,33 @@ void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec) |
| void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) |
| + bool boundSinceLastAcquire; |
| + bool deleted; |
| + if (isContextLost() |
| + || !validateWebGLSharedObject("attachShader", program, WebGLSharedObject::Exclusive) |
| + || !checkSharedObjectToBeBound("attachShader", shader, deleted, boundSinceLastAcquire)) { |
| return; |
| + } |
| + if (deleted) { |
| + shader = 0; |
| + } |
| if (!program->attachShader(shader)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader"); |
| return; |
| } |
| m_context->attachShader(objectOrZero(program), objectOrZero(shader)); |
| - shader->onAttached(); |
| + if (shader) { |
| + shader->onAttached(); |
| + if (!boundSinceLastAcquire) { |
| + shader->markAsBoundSinceLastAcquireForContext(this); |
| + } |
| + } |
| } |
| void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("bindAttribLocation", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("bindAttribLocation", program, WebGLSharedObject::Exclusive)) |
| return; |
| if (!validateLocationLength("bindAttribLocation", name)) |
| return; |
| @@ -1032,14 +1053,28 @@ void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint i |
| m_context->bindAttribLocation(objectOrZero(program), index, name); |
| } |
| -bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted) |
| +bool WebGLRenderingContext::checkContextObjectToBeBound(const char* functionName, WebGLContextObject* object, bool& deleted) |
| { |
| deleted = false; |
| if (isContextLost()) |
| return false; |
| if (object) { |
| if (!object->validate(contextGroup(), this)) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context"); |
| + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this share group"); |
| + return false; |
| + } |
| + deleted = !object->object(); |
| + } |
| + return true; |
| +} |
| + |
| +bool WebGLRenderingContext::checkSharedObjectToBeBound(const char* functionName, WebGLSharedObject* object, bool& deleted, bool& boundSinceLastAcquire) |
| +{ |
| + deleted = false; |
| + if (isContextLost()) |
| + return false; |
| + if (object) { |
| + if (!object->validate(functionName, this, WebGLSharedObject::ReadOnly, false, &boundSinceLastAcquire)) { |
| return false; |
| } |
| deleted = !object->object(); |
| @@ -1051,7 +1086,8 @@ void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, Exc |
| { |
| UNUSED_PARAM(ec); |
| bool deleted; |
| - if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) |
| + bool boundSinceLastAcquire; |
| + if (!checkSharedObjectToBeBound("bindBuffer", buffer, deleted, boundSinceLastAcquire)) |
| return; |
| if (deleted) |
| buffer = 0; |
| @@ -1069,15 +1105,19 @@ void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, Exc |
| } |
| m_context->bindBuffer(target, objectOrZero(buffer)); |
| - if (buffer) |
| + if (buffer) { |
| buffer->setTarget(target); |
| + if (!boundSinceLastAcquire) { |
| + buffer->markAsBoundSinceLastAcquireForContext(this); |
| + } |
| + } |
| } |
| void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| bool deleted; |
| - if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) |
| + if (!checkContextObjectToBeBound("bindFramebuffer", buffer, deleted)) |
| return; |
| if (deleted) |
| buffer = 0; |
| @@ -1101,7 +1141,8 @@ void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* |
| { |
| UNUSED_PARAM(ec); |
| bool deleted; |
| - if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) |
| + bool boundSinceLastAcquire; |
| + if (!checkSharedObjectToBeBound("bindRenderbuffer", renderBuffer, deleted, boundSinceLastAcquire)) |
| return; |
| if (deleted) |
| renderBuffer = 0; |
| @@ -1111,15 +1152,20 @@ void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* |
| } |
| m_renderbufferBinding = renderBuffer; |
| m_context->bindRenderbuffer(target, objectOrZero(renderBuffer)); |
| - if (renderBuffer) |
| + if (renderBuffer) { |
| renderBuffer->setHasEverBeenBound(); |
| + if (!boundSinceLastAcquire) { |
| + renderBuffer->markAsBoundSinceLastAcquireForContext(this); |
| + } |
| + } |
| } |
| void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| bool deleted; |
| - if (!checkObjectToBeBound("bindTexture", texture, deleted)) |
| + bool boundSinceLastAcquire; |
| + if (!checkSharedObjectToBeBound("bindTexture", texture, deleted, boundSinceLastAcquire)) |
| return; |
| if (deleted) |
| texture = 0; |
| @@ -1143,8 +1189,12 @@ void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, |
| return; |
| } |
| m_context->bindTexture(target, objectOrZero(texture)); |
| - if (texture) |
| + if (texture) { |
| texture->setTarget(target, maxLevel); |
| + if (!boundSinceLastAcquire) { |
| + texture->markAsBoundSinceLastAcquireForContext(this); |
| + } |
| + } |
| // Note: previously we used to automatically set the TEXTURE_WRAP_R |
| // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL |
| @@ -1285,14 +1335,20 @@ GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target) |
| { |
| if (isContextLost()) |
| return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED; |
| - if (target != GraphicsContext3D::FRAMEBUFFER) { |
| + switch (target) { |
| + case GraphicsContext3D::FRAMEBUFFER: |
| + case Extensions3D::READ_FRAMEBUFFER: |
| + case Extensions3D::DRAW_FRAMEBUFFER: |
| + break; |
| + default: |
| synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target"); |
| return 0; |
| } |
| if (!m_framebufferBinding || !m_framebufferBinding->object()) |
| return GraphicsContext3D::FRAMEBUFFER_COMPLETE; |
| const char* reason = "framebuffer incomplete"; |
| - GC3Denum result = m_framebufferBinding->checkStatus(&reason); |
| + WebGLSharedObject::AcquireMode neededAccessMode = (target == Extensions3D::READ_FRAMEBUFFER) ? WebGLSharedObject::ReadOnly : WebGLSharedObject::Exclusive; |
| + GC3Denum result = m_framebufferBinding->checkStatus(this, neededAccessMode, &reason); |
| if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { |
| printGLWarningToConsole("checkFramebufferStatus", reason); |
| return result; |
| @@ -1310,7 +1366,7 @@ void WebGLRenderingContext::clear(GC3Dbitfield mask) |
| return; |
| } |
| const char* reason = "framebuffer incomplete"; |
| - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { |
| + if (m_framebufferBinding && !m_framebufferBinding->onAccess(this, WebGLSharedObject::Exclusive, &reason)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason); |
| return; |
| } |
| @@ -1368,7 +1424,7 @@ void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dbo |
| void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("compileShader", shader)) |
| + if (isContextLost() || !validateWebGLSharedObject("compileShader", shader, WebGLSharedObject::Exclusive)) |
| return; |
| m_context->compileShader(objectOrZero(shader)); |
| } |
| @@ -1394,7 +1450,7 @@ void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, |
| if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data)) |
| return; |
| - WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true); |
| + WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true, WebGLSharedObject::Exclusive); |
| if (!tex) |
| return; |
| if (!isGLES2NPOTStrict()) { |
| @@ -1422,7 +1478,7 @@ void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint lev |
| if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data)) |
| return; |
| - WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true); |
| + WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true, WebGLSharedObject::Exclusive); |
| if (!tex) |
| return; |
| @@ -1455,7 +1511,7 @@ void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De |
| return; |
| if (!validateSettableTexFormat("copyTexImage2D", internalformat)) |
| return; |
| - WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true); |
| + WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true, WebGLSharedObject::Exclusive); |
| if (!tex) |
| return; |
| if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) { |
| @@ -1467,7 +1523,7 @@ void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De |
| return; |
| } |
| const char* reason = "framebuffer incomplete"; |
| - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { |
| + if (m_framebufferBinding && !m_framebufferBinding->onAccess(this, WebGLSharedObject::ReadOnly, &reason)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason); |
| return; |
| } |
| @@ -1484,7 +1540,7 @@ void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC |
| return; |
| if (!validateTexFuncLevel("copyTexSubImage2D", target, level)) |
| return; |
| - WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true); |
| + WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true, WebGLSharedObject::Exclusive); |
| if (!tex) |
| return; |
| if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height)) |
| @@ -1506,7 +1562,7 @@ void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC |
| return; |
| } |
| const char* reason = "framebuffer incomplete"; |
| - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { |
| + if (m_framebufferBinding && !m_framebufferBinding->onAccess(this, WebGLSharedObject::ReadOnly, &reason)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason); |
| return; |
| } |
| @@ -1594,12 +1650,27 @@ void WebGLRenderingContext::cullFace(GC3Denum mode) |
| m_context->cullFace(mode); |
| } |
| -bool WebGLRenderingContext::deleteObject(WebGLObject* object) |
| +bool WebGLRenderingContext::deleteContextObject(const char* functionName, WebGLContextObject* object) |
| { |
| if (isContextLost() || !object) |
| return false; |
| if (!object->validate(contextGroup(), this)) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context"); |
| + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this share group"); |
| + return false; |
| + } |
| + if (object->object()) { |
| + // We need to pass in context here because we want |
| + // things in this context unbound. |
| + object->deleteObject(graphicsContext3D()); |
| + } |
| + return true; |
| +} |
| + |
| +bool WebGLRenderingContext::deleteSharedObject(const char* functionName, WebGLSharedObject* object) |
| +{ |
| + if (isContextLost() || !object) |
| + return false; |
| + if (!object->validate(functionName, this, WebGLSharedObject::Exclusive, true, 0)) { |
|
Ken Russell (switch to Gerrit)
2013/06/19 03:51:24
What happens if the implementation tries to force
greggman
2013/06/21 19:54:21
I don't think so. context lost doesn't go through
|
| return false; |
| } |
| if (object->object()) |
| @@ -1611,7 +1682,7 @@ bool WebGLRenderingContext::deleteObject(WebGLObject* object) |
| void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer) |
| { |
| - if (!deleteObject(buffer)) |
| + if (!deleteSharedObject("deleteBuffer", buffer)) |
| return; |
| if (m_boundArrayBuffer == buffer) |
| m_boundArrayBuffer = 0; |
| @@ -1621,7 +1692,7 @@ void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer) |
| void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer) |
| { |
| - if (!deleteObject(framebuffer)) |
| + if (!deleteContextObject("deleteFramebuffer", framebuffer)) |
| return; |
| if (framebuffer == m_framebufferBinding) { |
| m_framebufferBinding = 0; |
| @@ -1633,14 +1704,14 @@ void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer) |
| void WebGLRenderingContext::deleteProgram(WebGLProgram* program) |
| { |
| - deleteObject(program); |
| + deleteSharedObject("deleteProgram", program); |
| // We don't reset m_currentProgram to 0 here because the deletion of the |
| // current program is delayed. |
| } |
| void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer) |
| { |
| - if (!deleteObject(renderbuffer)) |
| + if (!deleteSharedObject("deleteRenderbuffer", renderbuffer)) |
| return; |
| if (renderbuffer == m_renderbufferBinding) |
| m_renderbufferBinding = 0; |
| @@ -1650,12 +1721,12 @@ void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer) |
| void WebGLRenderingContext::deleteShader(WebGLShader* shader) |
| { |
| - deleteObject(shader); |
| + deleteSharedObject("deleteShader", shader); |
| } |
| void WebGLRenderingContext::deleteTexture(WebGLTexture* texture) |
| { |
| - if (!deleteObject(texture)) |
| + if (!deleteSharedObject("deleteTexture", texture)) |
| return; |
| for (size_t i = 0; i < m_textureUnits.size(); ++i) { |
| if (texture == m_textureUnits[i].m_texture2DBinding) |
| @@ -1696,8 +1767,20 @@ void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar) |
| void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) |
| + bool boundSinceLastAcquire; |
| + bool deleted; |
| + // NOTE: We explicitly don't check the shader has been bound since the only way to mark a shader as bound is to attach it which means |
| + // there would be no way to detach a shader in context other than the one |
| + // that attached it. |
| + if (isContextLost() |
| + || !validateWebGLSharedObject("detachShader", program, WebGLSharedObject::Exclusive) |
| + || !checkSharedObjectToBeBound("detachShader", shader, deleted, boundSinceLastAcquire)) { |
| return; |
| + } |
| + if (deleted) { |
| + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader deleted"); |
| + return; |
| + } |
| if (!program->detachShader(shader)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached"); |
| return; |
| @@ -1737,35 +1820,88 @@ void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCo |
| m_context->disableVertexAttribArray(index); |
| } |
| -bool WebGLRenderingContext::validateRenderingState() |
| +bool WebGLRenderingContext::validateRenderingState(const char* functionName) |
| { |
| if (!m_currentProgram) |
| return false; |
| + if (!isAcquiredForReading(functionName, m_currentProgram.get())) { |
| + return false; |
| + } |
| + |
| // Look in each enabled vertex attrib and check if they've been bound to a buffer. |
| for (unsigned i = 0; i < m_maxVertexAttribs; ++i) { |
| - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); |
| - if (state.enabled |
| - && (!state.bufferBinding || !state.bufferBinding->object())) |
| - return false; |
| + WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); |
| + if (state.enabled) { |
| + if (!state.bufferBinding || !state.bufferBinding->object()) { |
| + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs enabled with no buffer bound"); |
| + return false; |
| + } |
| + if (!isAcquiredForReading(functionName, state.bufferBinding.get())) { |
| + return false; |
| + } |
| + } |
| } |
| return true; |
| } |
| -bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object) |
| +bool WebGLRenderingContext::isAcquiredForModification(const char* functionName, WebGLSharedObject* object) |
| +{ |
| + return validateWebGLSharedObject(functionName, object, WebGLSharedObject::Exclusive); |
| +} |
| + |
| +bool WebGLRenderingContext::isAcquiredForReading(const char* functionName, WebGLSharedObject* object) |
| +{ |
| + return validateWebGLSharedObject(functionName, object, WebGLSharedObject::ReadOnly); |
| +} |
| + |
| +bool WebGLRenderingContext::validateWebGLSharedObject(const char* functionName, WebGLSharedObject* object, WebGLSharedObject::AcquireMode acquireMode) |
| { |
| if (!object || !object->object()) { |
| synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted"); |
| return false; |
| } |
| - if (!object->validate(contextGroup(), this)) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context"); |
| + if (!object->validate(functionName, this, acquireMode, true, 0)) { |
| return false; |
| } |
| return true; |
| } |
| +long WebGLRenderingContext::acquireSharedResource(WebGLSharedObject* object, WebGLSharedObject::AcquireMode desiredMode, PassRefPtr<WebGLAcquireSharedResourceCallback> callback, ExceptionCode& ec) |
| +{ |
| + UNUSED_PARAM(ec); |
| + if (!object) { |
| + return 0; |
| + } |
| + |
| + long id; |
| + if (!object->addAcquireRequest(this, desiredMode, callback, id)) { |
| + return 0; |
| + } |
| + |
| + return id; |
| +} |
| + |
| +void WebGLRenderingContext::releaseSharedResource(WebGLSharedObject* object, ExceptionCode& ec) |
| +{ |
| + UNUSED_PARAM(ec); |
| + |
| + if (!object) { |
| + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "releaseSharedResource", "no resource"); |
| + return; |
| + } |
| + |
| + if (!object->release(this)) { |
| + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "releaseSharedResource", "resource not acquired"); |
| + } |
| +} |
| + |
| +void WebGLRenderingContext::cancelAcquireSharedResource(long id) |
| +{ |
| + m_contextGroup->cancelAcquireSharedResource(this, id); |
| +} |
| + |
| void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| @@ -1773,12 +1909,15 @@ void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei c |
| if (!validateDrawArrays("drawArrays", mode, first, count)) |
| return; |
| - clearIfComposited(); |
| - |
| - handleTextureCompleteness("drawArrays", true); |
| - m_context->drawArrays(mode, first, count); |
| - handleTextureCompleteness("drawArrays", false); |
| - markContextChanged(); |
| + bool texturesReplaced; |
| + if (handleTextureCompleteness("drawArrays", true, &texturesReplaced)) { |
| + clearIfComposited(); |
| + m_context->drawArrays(mode, first, count); |
| + markContextChanged(); |
| + } |
| + if (texturesReplaced) { |
| + handleTextureCompleteness("drawArrays", false, 0); |
| + } |
| } |
| void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec) |
| @@ -1788,12 +1927,15 @@ void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denu |
| if (!validateDrawElements("drawElements", mode, count, type, offset)) |
| return; |
| - clearIfComposited(); |
| - |
| - handleTextureCompleteness("drawElements", true); |
| - m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset)); |
| - handleTextureCompleteness("drawElements", false); |
| - markContextChanged(); |
| + bool texturesReplaced; |
| + if (handleTextureCompleteness("drawElements", true, &texturesReplaced)) { |
| + clearIfComposited(); |
| + m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset)); |
| + markContextChanged(); |
| + } |
| + if (texturesReplaced) { |
| + handleTextureCompleteness("drawElements", false, 0); |
| + } |
| } |
| void WebGLRenderingContext::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) |
| @@ -1804,12 +1946,15 @@ void WebGLRenderingContext::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint firs |
| if (!validateDrawInstanced("drawArraysInstancedANGLE", primcount)) |
| return; |
| - clearIfComposited(); |
| - |
| - handleTextureCompleteness("drawArraysInstancedANGLE", true); |
| - m_context->getExtensions()->drawArraysInstancedANGLE(mode, first, count, primcount); |
| - handleTextureCompleteness("drawArraysInstancedANGLE", false); |
| - markContextChanged(); |
| + bool texturesReplaced; |
| + if (handleTextureCompleteness("drawArraysInstancedANGLE", true, &texturesReplaced)) { |
| + clearIfComposited(); |
| + m_context->getExtensions()->drawArraysInstancedANGLE(mode, first, count, primcount); |
| + markContextChanged(); |
| + } |
| + if (texturesReplaced) { |
| + handleTextureCompleteness("drawArraysInstancedANGLE", false, 0); |
| + } |
| } |
| void WebGLRenderingContext::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) |
| @@ -1820,12 +1965,15 @@ void WebGLRenderingContext::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei |
| if (!validateDrawInstanced("drawElementsInstancedANGLE", primcount)) |
| return; |
| - clearIfComposited(); |
| - |
| - handleTextureCompleteness("drawElementsInstancedANGLE", true); |
| - m_context->getExtensions()->drawElementsInstancedANGLE(mode, count, type, static_cast<GC3Dintptr>(offset), primcount); |
| - handleTextureCompleteness("drawElementsInstancedANGLE", false); |
| - markContextChanged(); |
| + bool texturesReplaced; |
| + if (handleTextureCompleteness("drawElementsInstancedANGLE", true, &texturesReplaced)) { |
| + clearIfComposited(); |
| + m_context->getExtensions()->drawElementsInstancedANGLE(mode, count, type, static_cast<GC3Dintptr>(offset), primcount); |
| + markContextChanged(); |
| + } |
| + if (texturesReplaced) { |
| + handleTextureCompleteness("drawElementsInstancedANGLE", false, 0); |
| + } |
| } |
| void WebGLRenderingContext::enable(GC3Denum cap) |
| @@ -1883,8 +2031,8 @@ void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum at |
| synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target"); |
| return; |
| } |
| - if (buffer && !buffer->validate(contextGroup(), this)) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context"); |
| + bool hasBeenBoundSinceLastAcquire; |
| + if (buffer && !buffer->validate("framebufferRenderbuffer", this, WebGLSharedObject::ReadOnly, false, &hasBeenBoundSinceLastAcquire)) { |
| return; |
| } |
| // Don't allow the default framebuffer to be mutated; all current |
| @@ -1895,6 +2043,9 @@ void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum at |
| return; |
| } |
| Platform3DObject bufferObject = objectOrZero(buffer); |
| + if (buffer && !hasBeenBoundSinceLastAcquire) { |
| + buffer->markAsBoundSinceLastAcquireForContext(this); |
| + } |
| switch (attachment) { |
| case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: |
| if (isDepthStencilSupported() || !buffer) { |
| @@ -1926,8 +2077,8 @@ void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attac |
| synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0"); |
| return; |
| } |
| - if (texture && !texture->validate(contextGroup(), this)) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context"); |
| + bool hasBeenBoundSinceLastAcquire; |
| + if (texture && !texture->validate("framebufferTexture2D", this, WebGLSharedObject::ReadOnly, false, &hasBeenBoundSinceLastAcquire)) { |
| return; |
| } |
| // Don't allow the default framebuffer to be mutated; all current |
| @@ -1938,6 +2089,9 @@ void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attac |
| return; |
| } |
| Platform3DObject textureObject = objectOrZero(texture); |
| + if (texture && !hasBeenBoundSinceLastAcquire) { |
| + texture->markAsBoundSinceLastAcquireForContext(this); |
| + } |
| switch (attachment) { |
| case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: |
| m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level); |
| @@ -1967,7 +2121,7 @@ void WebGLRenderingContext::generateMipmap(GC3Denum target) |
| { |
| if (isContextLost()) |
| return; |
| - WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); |
| + WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false, WebGLSharedObject::Exclusive); |
| if (!tex) |
| return; |
| if (!tex->canGenerateMipmaps()) { |
| @@ -1997,7 +2151,7 @@ void WebGLRenderingContext::generateMipmap(GC3Denum target) |
| PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("getActiveAttrib", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("getActiveAttrib", program, WebGLSharedObject::ReadOnly)) |
| return 0; |
| ActiveInfo info; |
| if (!m_context->getActiveAttrib(objectOrZero(program), index, info)) |
| @@ -2008,7 +2162,7 @@ PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* |
| PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("getActiveUniform", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("getActiveUniform", program, WebGLSharedObject::ReadOnly)) |
| return 0; |
| ActiveInfo info; |
| if (!m_context->getActiveUniform(objectOrZero(program), index, info)) |
| @@ -2020,7 +2174,7 @@ bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<Ref |
| { |
| UNUSED_PARAM(ec); |
| shaderObjects.clear(); |
| - if (isContextLost() || !validateWebGLObject("getAttachedShaders", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("getAttachedShaders", program, WebGLSharedObject::ReadOnly)) |
| return false; |
| const GC3Denum shaderType[] = { |
| @@ -2037,7 +2191,7 @@ bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<Ref |
| GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name) |
| { |
| - if (isContextLost() || !validateWebGLObject("getAttribLocation", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("getAttribLocation", program, WebGLSharedObject::ReadOnly)) |
| return -1; |
| if (!validateLocationLength("getAttribLocation", name)) |
| return -1; |
| @@ -2045,7 +2199,7 @@ GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const St |
| return -1; |
| if (isPrefixReserved(name)) |
| return -1; |
| - if (!program->getLinkStatus()) { |
| + if (!program->getLinkStatus(this)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked"); |
| return 0; |
| } |
| @@ -2057,8 +2211,9 @@ WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum |
| UNUSED_PARAM(ec); |
| if (isContextLost()) |
| return WebGLGetInfo(); |
| - if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target"); |
| + |
| + WebGLBuffer* buffer = getBufferForTarget("getBufferParameter", target); |
| + if (!buffer) { |
| return WebGLGetInfo(); |
| } |
| @@ -2067,6 +2222,10 @@ WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum |
| return WebGLGetInfo(); |
| } |
| + if (!isAcquiredForReading("getBufferParameter", buffer)) { |
| + return WebGLGetInfo(); |
| + } |
| + |
| GC3Dint value = 0; |
| m_context->getBufferParameteriv(target, pname, &value); |
| if (pname == GraphicsContext3D::BUFFER_SIZE) |
| @@ -2435,7 +2594,7 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& |
| WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("getProgramParameter", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("getProgramParameter", program, WebGLSharedObject::ReadOnly)) |
| return WebGLGetInfo(); |
| GC3Dint value = 0; |
| @@ -2446,7 +2605,7 @@ WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, G |
| m_context->getProgramiv(objectOrZero(program), pname, &value); |
| return WebGLGetInfo(static_cast<bool>(value)); |
| case GraphicsContext3D::LINK_STATUS: |
| - return WebGLGetInfo(program->getLinkStatus()); |
| + return WebGLGetInfo(program->getLinkStatus(this)); |
| case GraphicsContext3D::ATTACHED_SHADERS: |
| case GraphicsContext3D::ACTIVE_ATTRIBUTES: |
| case GraphicsContext3D::ACTIVE_UNIFORMS: |
| @@ -2463,7 +2622,7 @@ String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, Exception |
| UNUSED_PARAM(ec); |
| if (isContextLost()) |
| return String(); |
| - if (!validateWebGLObject("getProgramInfoLog", program)) |
| + if (!validateWebGLSharedObject("getProgramInfoLog", program, WebGLSharedObject::ReadOnly)) |
| return ""; |
| return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program))); |
| } |
| @@ -2482,6 +2641,10 @@ WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC |
| return WebGLGetInfo(); |
| } |
| + if (!isAcquiredForReading("getRenderbufferParameter", m_renderbufferBinding.get())) { |
| + return WebGLGetInfo(); |
| + } |
| + |
| GC3Dint value = 0; |
| switch (pname) { |
| case GraphicsContext3D::RENDERBUFFER_WIDTH: |
| @@ -2513,7 +2676,7 @@ WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC |
| WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("getShaderParameter", shader)) |
| + if (isContextLost() || !validateWebGLSharedObject("getShaderParameter", shader, WebGLSharedObject::ReadOnly)) |
| return WebGLGetInfo(); |
| GC3Dint value = 0; |
| switch (pname) { |
| @@ -2536,7 +2699,7 @@ String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCod |
| UNUSED_PARAM(ec); |
| if (isContextLost()) |
| return String(); |
| - if (!validateWebGLObject("getShaderInfoLog", shader)) |
| + if (!validateWebGLSharedObject("getShaderInfoLog", shader, WebGLSharedObject::ReadOnly)) |
| return ""; |
| return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader))); |
| } |
| @@ -2578,7 +2741,7 @@ String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode |
| UNUSED_PARAM(ec); |
| if (isContextLost()) |
| return String(); |
| - if (!validateWebGLObject("getShaderSource", shader)) |
| + if (!validateWebGLSharedObject("getShaderSource", shader, WebGLSharedObject::ReadOnly)) |
| return ""; |
| return ensureNotNull(shader->getSource()); |
| } |
| @@ -2607,7 +2770,7 @@ WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pn |
| UNUSED_PARAM(ec); |
| if (isContextLost()) |
| return WebGLGetInfo(); |
| - WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false); |
| + WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false, WebGLSharedObject::ReadOnly); |
| if (!tex) |
| return WebGLGetInfo(); |
| GC3Dint value = 0; |
| @@ -2634,7 +2797,7 @@ WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pn |
| WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("getUniform", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("getUniform", program, WebGLSharedObject::ReadOnly)) |
| return WebGLGetInfo(); |
| if (!uniformLocation || uniformLocation->program() != program) { |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program"); |
| @@ -2777,7 +2940,7 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG |
| PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("getUniformLocation", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("getUniformLocation", program, WebGLSharedObject::ReadOnly)) |
| return 0; |
| if (!validateLocationLength("getUniformLocation", name)) |
| return 0; |
| @@ -2785,7 +2948,7 @@ PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGL |
| return 0; |
| if (isPrefixReserved(name)) |
| return 0; |
| - if (!program->getLinkStatus()) { |
| + if (!program->getLinkStatus(this)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked"); |
| return 0; |
| } |
| @@ -2872,7 +3035,7 @@ GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer) |
| return m_context->isBuffer(buffer->object()); |
| } |
| -bool WebGLRenderingContext::isContextLost() |
| +bool WebGLRenderingContext::isContextLost() const |
| { |
| return m_contextLost; |
| } |
| @@ -2945,7 +3108,7 @@ void WebGLRenderingContext::lineWidth(GC3Dfloat width) |
| void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("linkProgram", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("linkProgram", program, WebGLSharedObject::Exclusive)) |
| return; |
| m_context->linkProgram(objectOrZero(program)); |
| @@ -3038,7 +3201,7 @@ void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC |
| return; |
| } |
| const char* reason = "framebuffer incomplete"; |
| - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { |
| + if (m_framebufferBinding && !m_framebufferBinding->onAccess(this, WebGLSharedObject::ReadOnly, &reason)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason); |
| return; |
| } |
| @@ -3091,6 +3254,8 @@ void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum intern |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); |
| return; |
| } |
| + if (!isAcquiredForModification("renderbufferStorage", m_renderbufferBinding.get())) |
| + return; |
| if (!validateSize("renderbufferStorage", width, height)) |
| return; |
| switch (internalformat) { |
| @@ -3149,7 +3314,7 @@ void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Ds |
| void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("shaderSource", shader)) |
| + if (isContextLost() || !validateWebGLSharedObject("shaderSource", shader, WebGLSharedObject::Exclusive)) |
| return; |
| String stringWithoutComments = StripComments(string).result(); |
| if (!validateString("shaderSource", stringWithoutComments)) |
| @@ -3249,7 +3414,7 @@ void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3De |
| // All calling functions check isContextLost, so a duplicate check is not needed here. |
| // FIXME: For now we ignore any errors returned |
| ec = 0; |
| - WebGLTexture* tex = validateTextureBinding("texImage2D", target, true); |
| + WebGLTexture* tex = validateTextureBinding("texImage2D", target, true, WebGLSharedObject::Exclusive); |
| ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type)); |
| ASSERT(tex); |
| ASSERT(!level || !WebGLTexture::isNPOT(width, height)); |
| @@ -3295,7 +3460,7 @@ bool WebGLRenderingContext::validateTexFunc(const char* functionName, TexFuncVal |
| if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type)) |
| return false; |
| - WebGLTexture* texture = validateTextureBinding(functionName, target, true); |
| + WebGLTexture* texture = validateTextureBinding(functionName, target, true, WebGLSharedObject::Exclusive); |
| if (!texture) |
| return false; |
| @@ -3406,7 +3571,7 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum |
| if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0)) |
| return; |
| - WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); |
| + WebGLTexture* texture = validateTextureBinding("texImage2D", target, true, WebGLSharedObject::Exclusive); |
| // If possible, copy from the canvas element directly to the texture |
| // via the GPU, without a read-back to system memory. |
| if (GraphicsContext3D::TEXTURE_2D == target && texture) { |
| @@ -3448,7 +3613,7 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum |
| // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible. |
| // Otherwise, it will fall back to the normal SW path. |
| - WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); |
| + WebGLTexture* texture = validateTextureBinding("texImage2D", target, true, WebGLSharedObject::Exclusive); |
| if (GraphicsContext3D::TEXTURE_2D == target && texture) { |
| if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
| texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type); |
| @@ -3467,7 +3632,7 @@ void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfl |
| { |
| if (isContextLost()) |
| return; |
| - WebGLTexture* tex = validateTextureBinding("texParameter", target, false); |
| + WebGLTexture* tex = validateTextureBinding("texParameter", target, false, WebGLSharedObject::Exclusive); |
| if (!tex) |
| return; |
| switch (pname) { |
| @@ -3519,7 +3684,7 @@ void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC |
| ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type)); |
| ASSERT(validateSize("texSubImage2D", xoffset, yoffset)); |
| ASSERT(validateSettableTexFormat("texSubImage2D", format)); |
| - WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true); |
| + WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true, WebGLSharedObject::Exclusive); |
| if (!tex) { |
| ASSERT_NOT_REACHED(); |
| return; |
| @@ -3662,7 +3827,7 @@ void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din |
| void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| + if (!validateUniformParameters("uniform1f", location)) |
| return; |
| if (location->program() != m_currentProgram) { |
| @@ -3676,7 +3841,7 @@ void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3D |
| void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1)) |
| + if (!validateUniformParameters("uniform1fv", location, v, 1)) |
| return; |
| m_context->uniform1fv(location->location(), v->length(), v->data()); |
| @@ -3685,7 +3850,7 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Flo |
| void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1)) |
| + if (!validateUniformParameters("uniform1fv", location, v, size, 1)) |
| return; |
| m_context->uniform1fv(location->location(), size, v); |
| @@ -3694,7 +3859,7 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3 |
| void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| + if (!validateUniformParameters("uniform1i", location)) |
| return; |
| if (location->program() != m_currentProgram) { |
| @@ -3702,45 +3867,43 @@ void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3D |
| return; |
| } |
| + m_currentProgram->setSampler(this, location->location(), 1, &x); |
| m_context->uniform1i(location->location(), x); |
| } |
| void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1)) |
| + if (!validateUniformParameters("uniform1iv", location, v, 1)) |
| return; |
| + m_currentProgram->setSampler(this, location->location(), v->length(), v->data()); |
| m_context->uniform1iv(location->location(), v->length(), v->data()); |
| } |
| void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1)) |
| + if (!validateUniformParameters("uniform1iv", location, v, size, 1)) |
| return; |
| + m_currentProgram->setSampler(this, location->location(), size, v); |
| m_context->uniform1iv(location->location(), size, v); |
| } |
| void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| + if (!validateUniformParameters("uniform2f", location)) |
| return; |
| - if (location->program() != m_currentProgram) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program"); |
| - return; |
| - } |
| - |
| m_context->uniform2f(location->location(), x, y); |
| } |
| void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2)) |
| + if (!validateUniformParameters("uniform2fv", location, v, 2)) |
| return; |
| m_context->uniform2fv(location->location(), v->length() / 2, v->data()); |
| @@ -3749,7 +3912,7 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Flo |
| void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2)) |
| + if (!validateUniformParameters("uniform2fv", location, v, size, 2)) |
| return; |
| m_context->uniform2fv(location->location(), size / 2, v); |
| @@ -3758,13 +3921,8 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3 |
| void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| - return; |
| - |
| - if (location->program() != m_currentProgram) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program"); |
| + if (!validateUniformParameters("uniform2i", location)) |
| return; |
| - } |
| m_context->uniform2i(location->location(), x, y); |
| } |
| @@ -3772,7 +3930,7 @@ void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3D |
| void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2)) |
| + if (!validateUniformParameters("uniform2iv", location, v, 2)) |
| return; |
| m_context->uniform2iv(location->location(), v->length() / 2, v->data()); |
| @@ -3781,7 +3939,7 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int |
| void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2)) |
| + if (!validateUniformParameters("uniform2iv", location, v, size, 2)) |
| return; |
| m_context->uniform2iv(location->location(), size / 2, v); |
| @@ -3790,21 +3948,16 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3 |
| void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| + if (!validateUniformParameters("uniform3f", location)) |
| return; |
| - if (location->program() != m_currentProgram) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program"); |
| - return; |
| - } |
| - |
| m_context->uniform3f(location->location(), x, y, z); |
| } |
| void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3)) |
| + if (!validateUniformParameters("uniform3fv", location, v, 3)) |
| return; |
| m_context->uniform3fv(location->location(), v->length() / 3, v->data()); |
| @@ -3813,7 +3966,7 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Flo |
| void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3)) |
| + if (!validateUniformParameters("uniform3fv", location, v, size, 3)) |
| return; |
| m_context->uniform3fv(location->location(), size / 3, v); |
| @@ -3822,21 +3975,16 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3 |
| void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| + if (!validateUniformParameters("uniform3i", location)) |
| return; |
| - if (location->program() != m_currentProgram) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program"); |
| - return; |
| - } |
| - |
| m_context->uniform3i(location->location(), x, y, z); |
| } |
| void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3)) |
| + if (!validateUniformParameters("uniform3iv", location, v, 3)) |
| return; |
| m_context->uniform3iv(location->location(), v->length() / 3, v->data()); |
| @@ -3845,7 +3993,7 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int |
| void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3)) |
| + if (!validateUniformParameters("uniform3iv", location, v, size, 3)) |
| return; |
| m_context->uniform3iv(location->location(), size / 3, v); |
| @@ -3854,21 +4002,16 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3 |
| void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| + if (!validateUniformParameters("uniform4f", location)) |
| return; |
| - if (location->program() != m_currentProgram) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program"); |
| - return; |
| - } |
| - |
| m_context->uniform4f(location->location(), x, y, z, w); |
| } |
| void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4)) |
| + if (!validateUniformParameters("uniform4fv", location, v, 4)) |
| return; |
| m_context->uniform4fv(location->location(), v->length() / 4, v->data()); |
| @@ -3877,7 +4020,7 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Flo |
| void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4)) |
| + if (!validateUniformParameters("uniform4fv", location, v, size, 4)) |
| return; |
| m_context->uniform4fv(location->location(), size / 4, v); |
| @@ -3886,21 +4029,16 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3 |
| void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !location) |
| + if (!validateUniformParameters("uniform4i", location)) |
| return; |
| - if (location->program() != m_currentProgram) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program"); |
| - return; |
| - } |
| - |
| m_context->uniform4i(location->location(), x, y, z, w); |
| } |
| void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4)) |
| + if (!validateUniformParameters("uniform4iv", location, v, 4)) |
| return; |
| m_context->uniform4iv(location->location(), v->length() / 4, v->data()); |
| @@ -3909,7 +4047,7 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int |
| void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4)) |
| + if (!validateUniformParameters("uniform4iv", location, v, size, 4)) |
| return; |
| m_context->uniform4iv(location->location(), size / 4, v); |
| @@ -3918,7 +4056,7 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3 |
| void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) |
| + if (!validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) |
| return; |
| m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data()); |
| } |
| @@ -3926,7 +4064,7 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio |
| void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4)) |
| + if (!validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4)) |
| return; |
| m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v); |
| } |
| @@ -3934,7 +4072,7 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio |
| void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) |
| + if (!validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) |
| return; |
| m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data()); |
| } |
| @@ -3942,7 +4080,7 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio |
| void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9)) |
| + if (!validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9)) |
| return; |
| m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v); |
| } |
| @@ -3950,7 +4088,7 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio |
| void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) |
| + if (!validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) |
| return; |
| m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data()); |
| } |
| @@ -3958,7 +4096,7 @@ void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio |
| void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16)) |
| + if (!validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16)) |
| return; |
| m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v); |
| } |
| @@ -3967,11 +4105,12 @@ void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| bool deleted; |
| - if (!checkObjectToBeBound("useProgram", program, deleted)) |
| + bool boundSinceLastAcquire; |
| + if (!checkSharedObjectToBeBound("useProgram", program, deleted, boundSinceLastAcquire)) |
| return; |
| if (deleted) |
| program = 0; |
| - if (program && !program->getLinkStatus()) { |
| + if (program && !program->getLinkStatus(this)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid"); |
| return; |
| } |
| @@ -3983,12 +4122,15 @@ void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec) |
| if (program) |
| program->onAttached(); |
| } |
| + if (program && !boundSinceLastAcquire) { |
| + program->markAsBoundSinceLastAcquireForContext(this); |
| + } |
| } |
| void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec) |
| { |
| UNUSED_PARAM(ec); |
| - if (isContextLost() || !validateWebGLObject("validateProgram", program)) |
| + if (isContextLost() || !validateWebGLSharedObject("validateProgram", program, WebGLSharedObject::ReadOnly)) |
| return; |
| m_context->validateProgram(objectOrZero(program)); |
| } |
| @@ -4093,6 +4235,9 @@ void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC |
| } |
| GC3Dsizei bytesPerElement = size * typeSize; |
| + if (!isAcquiredForReading("vertexAttribPointer", m_boundArrayBuffer.get())) { |
| + return; |
| + } |
| m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer); |
| m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset)); |
| } |
| @@ -4330,43 +4475,69 @@ WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname) |
| return WebGLGetInfo(Int32Array::create(value, length)); |
| } |
| -void WebGLRenderingContext::handleTextureCompleteness(const char* functionName, bool prepareToDraw) |
| +bool WebGLRenderingContext::handleTextureCompleteness(const char* functionName, bool prepareToDraw, bool* texturesReplaced) |
| { |
| + if (texturesReplaced) { |
| + *texturesReplaced = false; |
| + } |
| // All calling functions check isContextLost, so a duplicate check is not needed here. |
| bool resetActiveUnit = false; |
| WebGLTexture::TextureExtensionFlag flag = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureFloatLinearExtensionEnabled : 0) |
| | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureHalfFloatLinearExtensionEnabled : 0)); |
| - for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) { |
| - if ((m_textureUnits[ii].m_texture2DBinding.get() && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) |
| - || (m_textureUnits[ii].m_textureCubeMapBinding.get() && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag))) { |
| - if (ii != m_activeTextureUnit) { |
| - m_context->activeTexture(ii); |
| - resetActiveUnit = true; |
| - } else if (resetActiveUnit) { |
| - m_context->activeTexture(ii); |
| - resetActiveUnit = false; |
| + |
| + const WebGLProgram::SamplerTextureUnitMap& samplerMap = m_currentProgram->samplerLocationTextureUnitMap(); |
| + for (WebGLProgram::SamplerTextureUnitMap::const_iterator it = samplerMap.begin(); it != samplerMap.end(); ++it) { |
| + GC3Dint unit = it->value.unit; |
| + GC3Denum type = it->value.type; |
| + WebGLTexture* texture; |
| + WebGLTexture* blackTexture; |
| + GC3Denum target; |
| + switch (it->value.type) { |
| + case GraphicsContext3D::SAMPLER_2D: |
| + target = GraphicsContext3D::TEXTURE_2D; |
| + texture = m_textureUnits[unit].m_texture2DBinding.get(); |
| + blackTexture = m_blackTexture2D.get(); |
| + break; |
| + case GraphicsContext3D::SAMPLER_CUBE: |
| + target = GraphicsContext3D::TEXTURE_CUBE_MAP; |
| + texture = m_textureUnits[unit].m_textureCubeMapBinding.get(); |
| + blackTexture = m_blackTextureCubeMap.get(); |
| + break; |
| + default: |
| + notImplemented(); |
| + } |
| + |
| + if (!texture) { |
| + continue; |
| + } |
| + |
| + if (prepareToDraw && !isAcquiredForReading(functionName, texture)) { |
| + return false; |
|
Ken Russell (switch to Gerrit)
2013/06/19 03:51:24
The code associated with resetActiveUnit isn't run
greggman
2013/06/21 19:54:21
Yes, added a comment
|
| + } |
| + |
| + if (texture->needToUseBlackTexture(flag)) { |
| + if (texturesReplaced) { |
| + *texturesReplaced = true; |
| } |
| - WebGLTexture* tex2D; |
| - WebGLTexture* texCubeMap; |
| + m_context->activeTexture(GraphicsContext3D::TEXTURE0 + unit); |
| + resetActiveUnit = true; |
| + WebGLTexture* tex; |
| if (prepareToDraw) { |
| - String msg(String("texture bound to texture unit ") + String::number(ii) |
| + String msg(String("texture bound to texture unit ") + String::number(unit) |
| + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'." |
| + " Or the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled."); |
| printGLWarningToConsole(functionName, msg.utf8().data()); |
| - tex2D = m_blackTexture2D.get(); |
| - texCubeMap = m_blackTextureCubeMap.get(); |
| + tex = blackTexture; |
| } else { |
| - tex2D = m_textureUnits[ii].m_texture2DBinding.get(); |
| - texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get(); |
| + tex = texture; |
| } |
| - if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) |
| - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D)); |
| - if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag)) |
| - m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); |
| + m_context->bindTexture(target, objectOrZero(tex)); |
| } |
| } |
| if (resetActiveUnit) |
| m_context->activeTexture(m_activeTextureUnit); |
| + |
| + return true; |
| } |
| void WebGLRenderingContext::createFallbackBlackTextures1x1() |
| @@ -4426,7 +4597,7 @@ int WebGLRenderingContext::getBoundFramebufferHeight() |
| return m_drawingBuffer->size().height(); |
| } |
| -WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap) |
| +WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap, WebGLSharedObject::AcquireMode mode) |
| { |
| WebGLTexture* tex = 0; |
| switch (target) { |
| @@ -4458,6 +4629,21 @@ WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* function |
| } |
| if (!tex) |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture"); |
| + switch (mode) { |
| + case WebGLSharedObject::ReadOnly: |
| + if (!isAcquiredForReading(functionName, tex)) { |
| + return 0; |
| + } |
| + break; |
| + case WebGLSharedObject::Exclusive: |
| + if (!isAcquiredForModification(functionName, tex)) { |
| + return 0; |
| + } |
| + break; |
| + default: |
| + notImplemented(); |
| + break; |
| + } |
| return tex; |
| } |
| @@ -5036,7 +5222,25 @@ bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denu |
| } |
| } |
| -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize) |
| +bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location) |
| +{ |
| + if (isContextLost() || !location) { |
| + return false; |
| + } |
| + |
| + if (location->program() != m_currentProgram) { |
| + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program"); |
| + return false; |
| + } |
| + |
| + if (!isAcquiredForModification(functionName, m_currentProgram.get())) { |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize) |
| { |
| if (!v) { |
| synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); |
| @@ -5045,7 +5249,7 @@ bool WebGLRenderingContext::validateUniformParameters(const char* functionName, |
| return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); |
| } |
| -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize) |
| +bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize) |
| { |
| if (!v) { |
| synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); |
| @@ -5070,12 +5274,16 @@ bool WebGLRenderingContext::validateUniformMatrixParameters(const char* function |
| bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) |
| { |
| - if (!location) |
| + if (isContextLost() || !location) |
| return false; |
| if (location->program() != m_currentProgram) { |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program"); |
| return false; |
| } |
| + if (!isAcquiredForModification(functionName, m_currentProgram.get())) { |
| + return false; |
| + } |
| + |
| if (!v) { |
| synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); |
| return false; |
| @@ -5091,7 +5299,7 @@ bool WebGLRenderingContext::validateUniformMatrixParameters(const char* function |
| return true; |
| } |
| -WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage) |
| +WebGLBuffer* WebGLRenderingContext::getBufferForTarget(const char* functionName, GC3Denum target) |
| { |
| WebGLBuffer* buffer = 0; |
| switch (target) { |
| @@ -5109,6 +5317,18 @@ WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* fun |
| synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer"); |
| return 0; |
| } |
| + return buffer; |
| +} |
| + |
| +WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage) |
| +{ |
| + WebGLBuffer* buffer = getBufferForTarget(functionName, target); |
| + if (!buffer) { |
| + return 0; |
| + } |
| + |
| + if (!isAcquiredForModification(functionName, buffer)) |
| + return 0; |
| switch (usage) { |
| case GraphicsContext3D::STREAM_DRAW: |
| case GraphicsContext3D::STATIC_DRAW: |
| @@ -5181,13 +5401,12 @@ bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denu |
| return false; |
| } |
| - if (!validateRenderingState()) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly"); |
| + if (!validateRenderingState(functionName)) { |
| return false; |
| } |
| const char* reason = "framebuffer incomplete"; |
| - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { |
| + if (m_framebufferBinding && !m_framebufferBinding->onAccess(this, WebGLSharedObject::Exclusive, &reason)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason); |
| return false; |
| } |
| @@ -5232,13 +5451,16 @@ bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3De |
| return false; |
| } |
| - if (!validateRenderingState()) { |
| - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly"); |
| + if (!isAcquiredForReading(functionName, m_boundVertexArrayObject->getElementArrayBuffer().get())) { |
| + return false; |
| + } |
| + |
| + if (!validateRenderingState(functionName)) { |
| return false; |
| } |
| const char* reason = "framebuffer incomplete"; |
| - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { |
| + if (m_framebufferBinding && !m_framebufferBinding->onAccess(this, WebGLSharedObject::Exclusive, &reason)) { |
| synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason); |
| return false; |
| } |