Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(409)

Side by Side Diff: Source/modules/webgl/WebGL2RenderingContextBase.cpp

Issue 1323613005: Better state tracking and validation for bindBufferBase and bindBufferRange (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fix logic errors pointed out by zmo@ Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/modules/webgl/WebGL2RenderingContextBase.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "modules/webgl/WebGL2RenderingContextBase.h" 6 #include "modules/webgl/WebGL2RenderingContextBase.h"
7 7
8 #include "bindings/modules/v8/WebGLAny.h" 8 #include "bindings/modules/v8/WebGLAny.h"
9 #include "core/html/HTMLCanvasElement.h" 9 #include "core/html/HTMLCanvasElement.h"
10 #include "core/html/HTMLImageElement.h" 10 #include "core/html/HTMLImageElement.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 77
78 m_max3DTextureSize = 0; 78 m_max3DTextureSize = 0;
79 webContext()->getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_max3DTextureSize); 79 webContext()->getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_max3DTextureSize);
80 m_max3DTextureLevel = WebGLTexture::computeLevelCount(m_max3DTextureSize, m_ max3DTextureSize, m_max3DTextureSize); 80 m_max3DTextureLevel = WebGLTexture::computeLevelCount(m_max3DTextureSize, m_ max3DTextureSize, m_max3DTextureSize);
81 81
82 GLint numCombinedTextureImageUnits = 0; 82 GLint numCombinedTextureImageUnits = 0;
83 webContext()->getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedT extureImageUnits); 83 webContext()->getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedT extureImageUnits);
84 m_samplerUnits.clear(); 84 m_samplerUnits.clear();
85 m_samplerUnits.resize(numCombinedTextureImageUnits); 85 m_samplerUnits.resize(numCombinedTextureImageUnits);
86 86
87 GLint maxTransformFeedbackSeparateAttribs = 0;
88 webContext()->getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxTr ansformFeedbackSeparateAttribs);
89 m_boundIndexedTransformFeedbackBuffers.clear();
90 m_boundIndexedTransformFeedbackBuffers.resize(maxTransformFeedbackSeparateAt tribs);
91
92 GLint maxUniformBufferBindings = 0;
93 webContext()->getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferB indings);
94 m_boundIndexedUniformBuffers.clear();
95 m_boundIndexedUniformBuffers.resize(maxUniformBufferBindings);
96 m_maxBoundUniformBufferIndex = 0;
97
87 WebGLRenderingContextBase::initializeNewContext(); 98 WebGLRenderingContextBase::initializeNewContext();
88 } 99 }
89 100
90 void WebGL2RenderingContextBase::copyBufferSubData(GLenum readTarget, GLenum wri teTarget, long long readOffset, long long writeOffset, long long size) 101 void WebGL2RenderingContextBase::copyBufferSubData(GLenum readTarget, GLenum wri teTarget, long long readOffset, long long writeOffset, long long size)
91 { 102 {
92 if (isContextLost()) 103 if (isContextLost())
93 return; 104 return;
94 105
95 if (!validateValueFitNonNegInt32("copyBufferSubData", "readOffset", readOffs et) 106 if (!validateValueFitNonNegInt32("copyBufferSubData", "readOffset", readOffs et)
96 || !validateValueFitNonNegInt32("copyBufferSubData", "writeOffset", writ eOffset) 107 || !validateValueFitNonNegInt32("copyBufferSubData", "writeOffset", writ eOffset)
(...skipping 1546 matching lines...) Expand 10 before | Expand all | Expand 10 after
1643 1654
1644 void WebGL2RenderingContextBase::bindBufferBase(GLenum target, GLuint index, Web GLBuffer* buffer) 1655 void WebGL2RenderingContextBase::bindBufferBase(GLenum target, GLuint index, Web GLBuffer* buffer)
1645 { 1656 {
1646 if (isContextLost()) 1657 if (isContextLost())
1647 return; 1658 return;
1648 bool deleted; 1659 bool deleted;
1649 if (!checkObjectToBeBound("bindBufferBase", buffer, deleted)) 1660 if (!checkObjectToBeBound("bindBufferBase", buffer, deleted))
1650 return; 1661 return;
1651 if (deleted) 1662 if (deleted)
1652 buffer = 0; 1663 buffer = 0;
1664 if (!validateAndUpdateBufferBindBaseTarget("bindBufferBase", target, index, buffer))
1665 return;
1653 webContext()->bindBufferBase(target, index, objectOrZero(buffer)); 1666 webContext()->bindBufferBase(target, index, objectOrZero(buffer));
1654 } 1667 }
1655 1668
1656 void WebGL2RenderingContextBase::bindBufferRange(GLenum target, GLuint index, We bGLBuffer* buffer, long long offset, long long size) 1669 void WebGL2RenderingContextBase::bindBufferRange(GLenum target, GLuint index, We bGLBuffer* buffer, long long offset, long long size)
1657 { 1670 {
1658 if (isContextLost() || !validateWebGLObject("bindBufferRange", buffer)) 1671 if (isContextLost())
1659 return; 1672 return;
1660 1673 bool deleted;
1674 if (!checkObjectToBeBound("bindBufferRange", buffer, deleted))
1675 return;
1676 if (deleted)
1677 buffer = 0;
1661 if (!validateValueFitNonNegInt32("bindBufferRange", "offset", offset) 1678 if (!validateValueFitNonNegInt32("bindBufferRange", "offset", offset)
1662 || !validateValueFitNonNegInt32("bindBufferRange", "size", size)) { 1679 || !validateValueFitNonNegInt32("bindBufferRange", "size", size)) {
1663 return; 1680 return;
1664 } 1681 }
1665 1682
1683 if (!validateAndUpdateBufferBindBaseTarget("bindBufferRange", target, index, buffer))
1684 return;
1685
1666 webContext()->bindBufferRange(target, index, objectOrZero(buffer), static_ca st<GLintptr>(offset), static_cast<GLsizeiptr>(size)); 1686 webContext()->bindBufferRange(target, index, objectOrZero(buffer), static_ca st<GLintptr>(offset), static_cast<GLsizeiptr>(size));
1667 } 1687 }
1668 1688
1669 ScriptValue WebGL2RenderingContextBase::getIndexedParameter(ScriptState* scriptS tate, GLenum target, GLuint index) 1689 ScriptValue WebGL2RenderingContextBase::getIndexedParameter(ScriptState* scriptS tate, GLenum target, GLuint index)
1670 { 1690 {
1671 if (isContextLost()) 1691 if (isContextLost())
1672 return ScriptValue::createNull(scriptState); 1692 return ScriptValue::createNull(scriptState);
1673 1693
1674 switch (target) { 1694 switch (target) {
1675 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: 1695 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1696 if (index >= m_boundIndexedTransformFeedbackBuffers.size()) {
1697 synthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", "index ou t of range");
1698 return ScriptValue::createNull(scriptState);
1699 }
1700 return WebGLAny(scriptState, m_boundIndexedTransformFeedbackBuffers[inde x].get());
1676 case GL_UNIFORM_BUFFER_BINDING: 1701 case GL_UNIFORM_BUFFER_BINDING:
1677 notImplemented(); 1702 if (index >= m_boundIndexedUniformBuffers.size()) {
1678 return ScriptValue::createNull(scriptState); 1703 synthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", "index ou t of range");
1704 return ScriptValue::createNull(scriptState);
1705 }
1706 return WebGLAny(scriptState, m_boundIndexedUniformBuffers[index].get());
1679 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: 1707 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1680 case GL_TRANSFORM_FEEDBACK_BUFFER_START: 1708 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1681 case GL_UNIFORM_BUFFER_SIZE: 1709 case GL_UNIFORM_BUFFER_SIZE:
1682 case GL_UNIFORM_BUFFER_START: 1710 case GL_UNIFORM_BUFFER_START:
1683 { 1711 {
1684 GLint64 value = -1; 1712 GLint64 value = -1;
1685 webContext()->getInteger64i_v(target, index, &value); 1713 webContext()->getInteger64i_v(target, index, &value);
1686 return WebGLAny(scriptState, value); 1714 return WebGLAny(scriptState, value);
1687 } 1715 }
1688 default: 1716 default:
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
2048 bool WebGL2RenderingContextBase::validateCapability(const char* functionName, GL enum cap) 2076 bool WebGL2RenderingContextBase::validateCapability(const char* functionName, GL enum cap)
2049 { 2077 {
2050 switch (cap) { 2078 switch (cap) {
2051 case GL_RASTERIZER_DISCARD: 2079 case GL_RASTERIZER_DISCARD:
2052 return true; 2080 return true;
2053 default: 2081 default:
2054 return WebGLRenderingContextBase::validateCapability(functionName, cap); 2082 return WebGLRenderingContextBase::validateCapability(functionName, cap);
2055 } 2083 }
2056 } 2084 }
2057 2085
2086 bool WebGL2RenderingContextBase::isBufferBoundToTransformFeedback(WebGLBuffer* b uffer)
2087 {
2088 ASSERT(buffer);
2089
2090 if (m_boundTransformFeedbackBuffer == buffer)
2091 return true;
2092
2093 for (size_t i = 0; i < m_boundIndexedTransformFeedbackBuffers.size(); ++i) {
2094 if (m_boundIndexedTransformFeedbackBuffers[i] == buffer)
2095 return true;
2096 }
2097
2098 return false;
2099 }
2100
2101 bool WebGL2RenderingContextBase::isBufferBoundToNonTransformFeedback(WebGLBuffer * buffer)
2102 {
2103 ASSERT(buffer);
2104
2105 if (m_boundArrayBuffer == buffer
2106 || m_boundVertexArrayObject->boundElementArrayBuffer() == buffer
2107 || m_boundCopyReadBuffer == buffer
2108 || m_boundCopyWriteBuffer == buffer
2109 || m_boundPixelPackBuffer == buffer
2110 || m_boundPixelUnpackBuffer == buffer
2111 || m_boundUniformBuffer == buffer) {
2112 return true;
2113 }
2114
2115 for (size_t i = 0; i <= m_maxBoundUniformBufferIndex; ++i) {
2116 if (m_boundIndexedUniformBuffers[i] == buffer)
2117 return true;
2118 }
2119
2120 return false;
2121 }
2122
2123 bool WebGL2RenderingContextBase::validateBufferTargetCompatibility(const char* f unctionName, GLenum target, WebGLBuffer* buffer)
2124 {
2125 ASSERT(buffer);
2126
2127 switch (buffer->getInitialTarget()) {
2128 case GL_ELEMENT_ARRAY_BUFFER:
2129 switch (target) {
2130 case GL_ARRAY_BUFFER:
2131 case GL_PIXEL_PACK_BUFFER:
2132 case GL_PIXEL_UNPACK_BUFFER:
2133 case GL_TRANSFORM_FEEDBACK_BUFFER:
2134 case GL_UNIFORM_BUFFER:
2135 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2136 "element array buffers can not be bound to a different target");
2137
2138 return false;
2139 default:
2140 break;
2141 }
2142 break;
2143 case GL_ARRAY_BUFFER:
2144 case GL_COPY_READ_BUFFER:
2145 case GL_COPY_WRITE_BUFFER:
2146 case GL_PIXEL_PACK_BUFFER:
2147 case GL_PIXEL_UNPACK_BUFFER:
2148 case GL_UNIFORM_BUFFER:
2149 case GL_TRANSFORM_FEEDBACK_BUFFER:
2150 if (target == GL_ELEMENT_ARRAY_BUFFER) {
2151 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2152 "buffers bound to non ELEMENT_ARRAY_BUFFER targets can not be bo und to ELEMENT_ARRAY_BUFFER target");
2153 return false;
2154 }
2155 break;
2156 default:
2157 break;
2158 }
2159
2160 if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
2161 if (isBufferBoundToNonTransformFeedback(buffer)) {
2162 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2163 "a buffer bound to TRANSFORM_FEEDBACK_BUFFER can not be bound to any other targets");
2164 return false;
2165 }
2166 } else if (isBufferBoundToTransformFeedback(buffer)) {
2167 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2168 "a buffer bound to TRANSFORM_FEEDBACK_BUFFER can not be bound to any other targets");
2169 return false;
2170 }
2171
2172 return true;
2173 }
2174
2058 bool WebGL2RenderingContextBase::validateBufferTarget(const char* functionName, GLenum target) 2175 bool WebGL2RenderingContextBase::validateBufferTarget(const char* functionName, GLenum target)
2059 { 2176 {
2060 switch (target) { 2177 switch (target) {
2061 case GL_ARRAY_BUFFER: 2178 case GL_ARRAY_BUFFER:
2062 case GL_COPY_READ_BUFFER: 2179 case GL_COPY_READ_BUFFER:
2063 case GL_COPY_WRITE_BUFFER: 2180 case GL_COPY_WRITE_BUFFER:
2064 case GL_ELEMENT_ARRAY_BUFFER: 2181 case GL_ELEMENT_ARRAY_BUFFER:
2065 case GL_PIXEL_PACK_BUFFER: 2182 case GL_PIXEL_PACK_BUFFER:
2066 case GL_PIXEL_UNPACK_BUFFER: 2183 case GL_PIXEL_UNPACK_BUFFER:
2067 case GL_TRANSFORM_FEEDBACK_BUFFER: 2184 case GL_TRANSFORM_FEEDBACK_BUFFER:
2068 case GL_UNIFORM_BUFFER: 2185 case GL_UNIFORM_BUFFER:
2069 return true; 2186 return true;
2070 default: 2187 default:
2071 synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); 2188 synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target");
2072 return false; 2189 return false;
2073 } 2190 }
2074 } 2191 }
2075 2192
2076 bool WebGL2RenderingContextBase::validateAndUpdateBufferBindTarget(const char* f unctionName, GLenum target, WebGLBuffer* buffer) 2193 bool WebGL2RenderingContextBase::validateAndUpdateBufferBindTarget(const char* f unctionName, GLenum target, WebGLBuffer* buffer)
2077 { 2194 {
2078 if (!validateBufferTarget(functionName, target)) 2195 if (!validateBufferTarget(functionName, target))
2079 return false; 2196 return false;
2080 2197
2081 if (buffer) { 2198 if (buffer && !validateBufferTargetCompatibility(functionName, target, buffe r))
2082 switch (buffer->getInitialTarget()) { 2199 return false;
2083 case GL_ELEMENT_ARRAY_BUFFER:
2084 switch (target) {
2085 case GL_ARRAY_BUFFER:
2086 case GL_PIXEL_PACK_BUFFER:
2087 case GL_PIXEL_UNPACK_BUFFER:
2088 case GL_TRANSFORM_FEEDBACK_BUFFER:
2089 case GL_UNIFORM_BUFFER:
2090 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2091 "element array buffers can not be bound to a different targe t");
2092
2093 return false;
2094 default:
2095 break;
2096 }
2097 break;
2098 case GL_ARRAY_BUFFER:
2099 case GL_COPY_READ_BUFFER:
2100 case GL_COPY_WRITE_BUFFER:
2101 case GL_PIXEL_PACK_BUFFER:
2102 case GL_PIXEL_UNPACK_BUFFER:
2103 case GL_UNIFORM_BUFFER:
2104 case GL_TRANSFORM_FEEDBACK_BUFFER:
2105 if (target == GL_ELEMENT_ARRAY_BUFFER) {
2106 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2107 "buffers bound to non ELEMENT_ARRAY_BUFFER targets can not b e bound to ELEMENT_ARRAY_BUFFER target");
2108 return false;
2109 }
2110 break;
2111 default:
2112 break;
2113 }
2114 if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
2115 if (m_boundArrayBuffer == buffer
2116 || m_boundVertexArrayObject->boundElementArrayBuffer() == buffer
2117 || m_boundCopyReadBuffer == buffer
2118 || m_boundCopyWriteBuffer == buffer
2119 || m_boundPixelPackBuffer == buffer
2120 || m_boundPixelUnpackBuffer == buffer
2121 || m_boundUniformBuffer == buffer) {
2122 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2123 "a buffer bound to TRANSFORM_FEEDBACK_BUFFER can not be boun d to any other targets");
2124 return false;
2125 }
2126 } else if (m_boundTransformFeedbackBuffer == buffer) {
2127 synthesizeGLError(GL_INVALID_OPERATION, functionName,
2128 "a buffer bound to TRANSFORM_FEEDBACK_BUFFER can not be bound to any other targets");
2129 return false;
2130 }
2131 }
2132 2200
2133 switch (target) { 2201 switch (target) {
2134 case GL_ARRAY_BUFFER: 2202 case GL_ARRAY_BUFFER:
2135 m_boundArrayBuffer = buffer; 2203 m_boundArrayBuffer = buffer;
2136 break; 2204 break;
2137 case GL_COPY_READ_BUFFER: 2205 case GL_COPY_READ_BUFFER:
2138 m_boundCopyReadBuffer = buffer; 2206 m_boundCopyReadBuffer = buffer;
2139 break; 2207 break;
2140 case GL_COPY_WRITE_BUFFER: 2208 case GL_COPY_WRITE_BUFFER:
2141 m_boundCopyWriteBuffer = buffer; 2209 m_boundCopyWriteBuffer = buffer;
(...skipping 16 matching lines...) Expand all
2158 default: 2226 default:
2159 ASSERT_NOT_REACHED(); 2227 ASSERT_NOT_REACHED();
2160 break; 2228 break;
2161 } 2229 }
2162 2230
2163 if (buffer && !buffer->getInitialTarget()) 2231 if (buffer && !buffer->getInitialTarget())
2164 buffer->setInitialTarget(target); 2232 buffer->setInitialTarget(target);
2165 return true; 2233 return true;
2166 } 2234 }
2167 2235
2236 bool WebGL2RenderingContextBase::validateBufferBaseTarget(const char* functionNa me, GLenum target)
2237 {
2238 switch (target) {
2239 case GL_TRANSFORM_FEEDBACK_BUFFER:
2240 case GL_UNIFORM_BUFFER:
2241 return true;
2242 default:
2243 synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target");
2244 return false;
2245 }
2246 }
2247
2248 bool WebGL2RenderingContextBase::validateAndUpdateBufferBindBaseTarget(const cha r* functionName, GLenum target, GLuint index, WebGLBuffer* buffer)
2249 {
2250 if (!validateBufferBaseTarget(functionName, target))
2251 return false;
2252
2253 if (buffer && !validateBufferTargetCompatibility(functionName, target, buffe r))
2254 return false;
2255
2256 switch (target) {
2257 case GL_TRANSFORM_FEEDBACK_BUFFER:
2258 if (index >= m_boundIndexedTransformFeedbackBuffers.size()) {
2259 synthesizeGLError(GL_INVALID_OPERATION, functionName, "index out of range");
2260 return false;
2261 }
2262 m_boundIndexedTransformFeedbackBuffers[index] = buffer;
2263 m_boundTransformFeedbackBuffer = buffer;
2264 break;
2265 case GL_UNIFORM_BUFFER:
2266 if (index >= m_boundIndexedUniformBuffers.size()) {
2267 synthesizeGLError(GL_INVALID_OPERATION, functionName, "index out of range");
2268 return false;
2269 }
2270 m_boundIndexedUniformBuffers[index] = buffer;
2271 m_boundUniformBuffer = buffer;
2272
2273 // Keep track of what the maximum bound uniform buffer index is
2274 if (buffer) {
2275 if (index > m_maxBoundUniformBufferIndex)
2276 m_maxBoundUniformBufferIndex = index;
2277 } else if (m_maxBoundUniformBufferIndex > 0 && index == m_maxBoundUnifor mBufferIndex) {
2278 size_t i = m_maxBoundUniformBufferIndex - 1;
2279 for (; i > 0; --i) {
2280 if (m_boundIndexedUniformBuffers[i].get())
2281 break;
2282 }
2283 m_maxBoundUniformBufferIndex = i;
2284 }
2285 break;
2286 default:
2287 ASSERT_NOT_REACHED();
2288 break;
2289 }
2290
2291 if (buffer && !buffer->getInitialTarget())
2292 buffer->setInitialTarget(target);
2293 return true;
2294 }
2295
2168 bool WebGL2RenderingContextBase::validateFramebufferTarget(GLenum target) 2296 bool WebGL2RenderingContextBase::validateFramebufferTarget(GLenum target)
2169 { 2297 {
2170 switch (target) { 2298 switch (target) {
2171 case GL_FRAMEBUFFER: 2299 case GL_FRAMEBUFFER:
2172 case GL_READ_FRAMEBUFFER: 2300 case GL_READ_FRAMEBUFFER:
2173 case GL_DRAW_FRAMEBUFFER: 2301 case GL_DRAW_FRAMEBUFFER:
2174 return true; 2302 return true;
2175 default: 2303 default:
2176 return false; 2304 return false;
2177 } 2305 }
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
2545 GLenum WebGL2RenderingContextBase::boundFramebufferColorFormat() 2673 GLenum WebGL2RenderingContextBase::boundFramebufferColorFormat()
2546 { 2674 {
2547 if (m_readFramebufferBinding && m_readFramebufferBinding->object()) 2675 if (m_readFramebufferBinding && m_readFramebufferBinding->object())
2548 return m_readFramebufferBinding->colorBufferFormat(); 2676 return m_readFramebufferBinding->colorBufferFormat();
2549 if (m_requestedAttributes.alpha()) 2677 if (m_requestedAttributes.alpha())
2550 return GL_RGBA; 2678 return GL_RGBA;
2551 return GL_RGB; 2679 return GL_RGB;
2552 } 2680 }
2553 2681
2554 } // namespace blink 2682 } // namespace blink
OLDNEW
« no previous file with comments | « Source/modules/webgl/WebGL2RenderingContextBase.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698