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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h

Issue 2407753002: Fix crash from state management cleanup (Closed)
Patch Set: Fix state restore missed Created 4 years, 2 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 | « third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp ('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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "gpu/command_buffer/common/capabilities.h" 5 #include "gpu/command_buffer/common/capabilities.h"
6 #include "platform/RuntimeEnabledFeatures.h" 6 #include "platform/RuntimeEnabledFeatures.h"
7 #include "platform/graphics/gpu/DrawingBuffer.h" 7 #include "platform/graphics/gpu/DrawingBuffer.h"
8 #include "platform/graphics/gpu/Extensions3DUtil.h" 8 #include "platform/graphics/gpu/Extensions3DUtil.h"
9 #include "public/platform/WebGraphicsContext3DProvider.h" 9 #include "public/platform/WebGraphicsContext3DProvider.h"
10 #include "testing/gmock/include/gmock/gmock.h" 10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
11 12
12 namespace blink { 13 namespace blink {
13 14
14 enum { 15 enum {
15 InitialWidth = 100, 16 InitialWidth = 100,
16 InitialHeight = 100, 17 InitialHeight = 100,
17 AlternateHeight = 50, 18 AlternateHeight = 50,
18 }; 19 };
19 20
20 class DrawingBufferForTests : public DrawingBuffer { 21 class DrawingBufferForTests : public DrawingBuffer {
21 public: 22 public:
22 static PassRefPtr<DrawingBufferForTests> create( 23 static PassRefPtr<DrawingBufferForTests> create(
23 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, 24 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
25 DrawingBuffer::Client* client,
24 const IntSize& size, 26 const IntSize& size,
25 PreserveDrawingBuffer preserve) { 27 PreserveDrawingBuffer preserve) {
26 std::unique_ptr<Extensions3DUtil> extensionsUtil = 28 std::unique_ptr<Extensions3DUtil> extensionsUtil =
27 Extensions3DUtil::create(contextProvider->contextGL()); 29 Extensions3DUtil::create(contextProvider->contextGL());
28 RefPtr<DrawingBufferForTests> drawingBuffer = 30 RefPtr<DrawingBufferForTests> drawingBuffer = adoptRef(
29 adoptRef(new DrawingBufferForTests( 31 new DrawingBufferForTests(std::move(contextProvider),
30 std::move(contextProvider), std::move(extensionsUtil), preserve)); 32 std::move(extensionsUtil), client, preserve));
31 bool multisampleExtensionSupported = false; 33 bool multisampleExtensionSupported = false;
32 if (!drawingBuffer->initialize(size, multisampleExtensionSupported)) { 34 if (!drawingBuffer->initialize(size, multisampleExtensionSupported)) {
33 drawingBuffer->beginDestruction(); 35 drawingBuffer->beginDestruction();
34 return nullptr; 36 return nullptr;
35 } 37 }
36 return drawingBuffer.release(); 38 return drawingBuffer.release();
37 } 39 }
38 40
39 DrawingBufferForTests( 41 DrawingBufferForTests(
40 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, 42 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
41 std::unique_ptr<Extensions3DUtil> extensionsUtil, 43 std::unique_ptr<Extensions3DUtil> extensionsUtil,
44 DrawingBuffer::Client* client,
42 PreserveDrawingBuffer preserve) 45 PreserveDrawingBuffer preserve)
43 : DrawingBuffer( 46 : DrawingBuffer(
44 std::move(contextProvider), 47 std::move(contextProvider),
45 std::move(extensionsUtil), 48 std::move(extensionsUtil),
49 client,
46 false /* discardFramebufferSupported */, 50 false /* discardFramebufferSupported */,
47 true /* wantAlphaChannel */, 51 true /* wantAlphaChannel */,
48 false /* premultipliedAlpha */, 52 false /* premultipliedAlpha */,
49 preserve, 53 preserve,
50 WebGL1, 54 WebGL1,
51 false /* wantDepth */, 55 false /* wantDepth */,
52 false /* wantStencil */, 56 false /* wantStencil */,
53 DrawingBuffer::AllowChromiumImage /* ChromiumImageUsage */), 57 DrawingBuffer::AllowChromiumImage /* ChromiumImageUsage */),
54 m_live(0) {} 58 m_live(0) {}
55 59
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 #endif 98 #endif
95 } 99 }
96 100
97 // The target to use when preparing a mailbox texture. 101 // The target to use when preparing a mailbox texture.
98 GLenum drawingBufferTextureTarget() { 102 GLenum drawingBufferTextureTarget() {
99 if (RuntimeEnabledFeatures::webGLImageChromiumEnabled()) 103 if (RuntimeEnabledFeatures::webGLImageChromiumEnabled())
100 return imageCHROMIUMTextureTarget(); 104 return imageCHROMIUMTextureTarget();
101 return GL_TEXTURE_2D; 105 return GL_TEXTURE_2D;
102 } 106 }
103 107
104 class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub { 108 class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub,
109 public DrawingBuffer::Client {
105 public: 110 public:
111 // GLES2InterfaceStub implementation:
106 void BindTexture(GLenum target, GLuint texture) override { 112 void BindTexture(GLenum target, GLuint texture) override {
107 if (target != m_boundTextureTarget && texture == 0) 113 if (target == GL_TEXTURE_2D)
108 return; 114 m_state.activeTexture2DBinding = texture;
115 m_boundTextures[target] = texture;
116 }
109 117
110 // For simplicity, only allow one target to ever be bound. 118 void BindFramebuffer(GLenum target, GLuint framebuffer) override {
111 ASSERT_TRUE(m_boundTextureTarget == 0 || target == m_boundTextureTarget); 119 switch (target) {
112 m_boundTextureTarget = target; 120 case GL_FRAMEBUFFER:
113 m_boundTexture = texture; 121 m_state.drawFramebufferBinding = framebuffer;
122 m_state.readFramebufferBinding = framebuffer;
123 break;
124 case GL_DRAW_FRAMEBUFFER:
125 m_state.drawFramebufferBinding = framebuffer;
126 break;
127 case GL_READ_FRAMEBUFFER:
128 m_state.readFramebufferBinding = framebuffer;
129 break;
130 default:
131 break;
132 }
133 }
134
135 void BindRenderbuffer(GLenum target, GLuint renderbuffer) override {
136 m_state.renderbufferBinding = renderbuffer;
137 }
138
139 void Enable(GLenum cap) {
140 if (cap == GL_SCISSOR_TEST)
141 m_state.scissorEnabled = true;
142 }
143
144 void Disable(GLenum cap) {
145 if (cap == GL_SCISSOR_TEST)
146 m_state.scissorEnabled = false;
147 }
148
149 void ClearColor(GLfloat red,
150 GLfloat green,
151 GLfloat blue,
152 GLfloat alpha) override {
153 m_state.clearColor[0] = red;
154 m_state.clearColor[1] = green;
155 m_state.clearColor[2] = blue;
156 m_state.clearColor[3] = alpha;
157 }
158
159 void ClearDepthf(GLfloat depth) override { m_state.clearDepth = depth; }
160
161 void ClearStencil(GLint s) override { m_state.clearStencil = s; }
162
163 void ColorMask(GLboolean red,
164 GLboolean green,
165 GLboolean blue,
166 GLboolean alpha) override {
167 m_state.colorMask[0] = red;
168 m_state.colorMask[1] = green;
169 m_state.colorMask[2] = blue;
170 m_state.colorMask[3] = alpha;
171 }
172
173 void DepthMask(GLboolean flag) override { m_state.depthMask = flag; }
174
175 void StencilMask(GLuint mask) override { m_state.stencilMask = mask; }
176
177 void StencilMaskSeparate(GLenum face, GLuint mask) override {
178 if (face == GL_FRONT)
179 m_state.stencilMask = mask;
180 }
181
182 void PixelStorei(GLenum pname, GLint param) override {
183 if (pname == GL_PACK_ALIGNMENT)
184 m_state.packAlignment = param;
185 }
186
187 void BindBuffer(GLenum target, GLuint buffer) override {
188 if (target == GL_PIXEL_UNPACK_BUFFER)
189 m_state.pixelUnpackBufferBinding = buffer;
114 } 190 }
115 191
116 GLuint64 InsertFenceSyncCHROMIUM() override { 192 GLuint64 InsertFenceSyncCHROMIUM() override {
117 static GLuint64 syncPointGenerator = 0; 193 static GLuint64 syncPointGenerator = 0;
118 return ++syncPointGenerator; 194 return ++syncPointGenerator;
119 } 195 }
120 196
121 void WaitSyncTokenCHROMIUM(const GLbyte* syncToken) override { 197 void WaitSyncTokenCHROMIUM(const GLbyte* syncToken) override {
122 memcpy(&m_mostRecentlyWaitedSyncToken, syncToken, 198 memcpy(&m_mostRecentlyWaitedSyncToken, syncToken,
123 sizeof(m_mostRecentlyWaitedSyncToken)); 199 sizeof(m_mostRecentlyWaitedSyncToken));
(...skipping 27 matching lines...) Expand all
151 void TexImage2D(GLenum target, 227 void TexImage2D(GLenum target,
152 GLint level, 228 GLint level,
153 GLint internalformat, 229 GLint internalformat,
154 GLsizei width, 230 GLsizei width,
155 GLsizei height, 231 GLsizei height,
156 GLint border, 232 GLint border,
157 GLenum format, 233 GLenum format,
158 GLenum type, 234 GLenum type,
159 const void* pixels) override { 235 const void* pixels) override {
160 if (target == GL_TEXTURE_2D && !level) { 236 if (target == GL_TEXTURE_2D && !level) {
161 m_textureSizes.set(m_boundTexture, IntSize(width, height)); 237 m_textureSizes.set(m_boundTextures[target], IntSize(width, height));
162 } 238 }
163 } 239 }
164 240
165 GLuint CreateGpuMemoryBufferImageCHROMIUM(GLsizei width, 241 GLuint CreateGpuMemoryBufferImageCHROMIUM(GLsizei width,
166 GLsizei height, 242 GLsizei height,
167 GLenum internalformat, 243 GLenum internalformat,
168 GLenum usage) override { 244 GLenum usage) override {
169 if (m_createImageChromiumFail) 245 if (m_createImageChromiumFail)
170 return 0; 246 return 0;
171 m_imageSizes.set(m_currentImageId, IntSize(width, height)); 247 m_imageSizes.set(m_currentImageId, IntSize(width, height));
172 return m_currentImageId++; 248 return m_currentImageId++;
173 } 249 }
174 250
175 MOCK_METHOD1(DestroyImageMock, void(GLuint imageId)); 251 MOCK_METHOD1(DestroyImageMock, void(GLuint imageId));
176 void DestroyImageCHROMIUM(GLuint imageId) { 252 void DestroyImageCHROMIUM(GLuint imageId) {
177 m_imageSizes.remove(imageId); 253 m_imageSizes.remove(imageId);
178 // No textures should be bound to this. 254 // No textures should be bound to this.
179 CHECK(m_imageToTextureMap.find(imageId) == m_imageToTextureMap.end()); 255 CHECK(m_imageToTextureMap.find(imageId) == m_imageToTextureMap.end());
180 m_imageSizes.remove(imageId); 256 m_imageSizes.remove(imageId);
181 DestroyImageMock(imageId); 257 DestroyImageMock(imageId);
182 } 258 }
183 259
184 MOCK_METHOD1(BindTexImage2DMock, void(GLint imageId)); 260 MOCK_METHOD1(BindTexImage2DMock, void(GLint imageId));
185 void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { 261 void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) {
186 if (target == imageCHROMIUMTextureTarget()) { 262 if (target == imageCHROMIUMTextureTarget()) {
187 m_textureSizes.set(m_boundTexture, m_imageSizes.find(imageId)->value); 263 m_textureSizes.set(m_boundTextures[target],
188 m_imageToTextureMap.set(imageId, m_boundTexture); 264 m_imageSizes.find(imageId)->value);
265 m_imageToTextureMap.set(imageId, m_boundTextures[target]);
189 BindTexImage2DMock(imageId); 266 BindTexImage2DMock(imageId);
190 } 267 }
191 } 268 }
192 269
193 MOCK_METHOD1(ReleaseTexImage2DMock, void(GLint imageId)); 270 MOCK_METHOD1(ReleaseTexImage2DMock, void(GLint imageId));
194 void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { 271 void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) {
195 if (target == imageCHROMIUMTextureTarget()) { 272 if (target == imageCHROMIUMTextureTarget()) {
196 m_imageSizes.set(m_currentImageId, IntSize()); 273 m_imageSizes.set(m_currentImageId, IntSize());
197 m_imageToTextureMap.remove(imageId); 274 m_imageToTextureMap.remove(imageId);
198 ReleaseTexImage2DMock(imageId); 275 ReleaseTexImage2DMock(imageId);
199 } 276 }
200 } 277 }
201 278
202 void GenSyncTokenCHROMIUM(GLuint64 fenceSync, GLbyte* syncToken) override { 279 void GenSyncTokenCHROMIUM(GLuint64 fenceSync, GLbyte* syncToken) override {
203 static uint64_t uniqueId = 1; 280 static uint64_t uniqueId = 1;
204 gpu::SyncToken source(gpu::GPU_IO, 1, 281 gpu::SyncToken source(gpu::GPU_IO, 1,
205 gpu::CommandBufferId::FromUnsafeValue(uniqueId++), 2); 282 gpu::CommandBufferId::FromUnsafeValue(uniqueId++), 2);
206 memcpy(syncToken, &source, sizeof(source)); 283 memcpy(syncToken, &source, sizeof(source));
207 } 284 }
208 285
209 void GenTextures(GLsizei n, GLuint* textures) override { 286 void GenTextures(GLsizei n, GLuint* textures) override {
210 static GLuint id = 1; 287 static GLuint id = 1;
211 for (GLsizei i = 0; i < n; ++i) 288 for (GLsizei i = 0; i < n; ++i)
212 textures[i] = id++; 289 textures[i] = id++;
213 } 290 }
214 291
215 GLuint boundTexture() const { return m_boundTexture; } 292 // DrawingBuffer::Client implementation.
216 GLuint boundTextureTarget() const { return m_boundTextureTarget; } 293 bool DrawingBufferClientIsBoundForDraw() override {
294 return !m_state.drawFramebufferBinding;
295 }
296 void DrawingBufferClientRestoreScissorTest() override {
297 m_state.scissorEnabled = m_savedState.scissorEnabled;
298 }
299 void DrawingBufferClientRestoreMaskAndClearValues() override {
300 memcpy(m_state.colorMask, m_savedState.colorMask,
301 sizeof(m_state.colorMask));
302 m_state.clearDepth = m_savedState.clearDepth;
303 m_state.clearStencil = m_savedState.clearStencil;
304
305 memcpy(m_state.clearColor, m_savedState.clearColor,
306 sizeof(m_state.clearColor));
307 m_state.depthMask = m_savedState.depthMask;
308 m_state.stencilMask = m_savedState.stencilMask;
309 }
310 void DrawingBufferClientRestorePixelPackAlignment() override {
311 m_state.packAlignment = m_savedState.packAlignment;
312 }
313 void DrawingBufferClientRestoreTexture2DBinding() override {
314 m_state.activeTexture2DBinding = m_savedState.activeTexture2DBinding;
315 }
316 void DrawingBufferClientRestoreRenderbufferBinding() override {
317 m_state.renderbufferBinding = m_savedState.renderbufferBinding;
318 }
319 void DrawingBufferClientRestoreFramebufferBinding() override {
320 m_state.drawFramebufferBinding = m_savedState.drawFramebufferBinding;
321 m_state.readFramebufferBinding = m_savedState.readFramebufferBinding;
322 }
323 void DrawingBufferClientRestorePixelUnpackBufferBinding() override {
324 m_state.pixelUnpackBufferBinding = m_savedState.pixelUnpackBufferBinding;
325 }
326
327 // Testing methods.
217 gpu::SyncToken mostRecentlyWaitedSyncToken() const { 328 gpu::SyncToken mostRecentlyWaitedSyncToken() const {
218 return m_mostRecentlyWaitedSyncToken; 329 return m_mostRecentlyWaitedSyncToken;
219 } 330 }
220 GLuint nextImageIdToBeCreated() const { return m_currentImageId; } 331 GLuint nextImageIdToBeCreated() const { return m_currentImageId; }
221 IntSize mostRecentlyProducedSize() const { 332 IntSize mostRecentlyProducedSize() const {
222 return m_mostRecentlyProducedSize; 333 return m_mostRecentlyProducedSize;
223 } 334 }
224 335
225 void setCreateImageChromiumFail(bool fail) { 336 void setCreateImageChromiumFail(bool fail) {
226 m_createImageChromiumFail = fail; 337 m_createImageChromiumFail = fail;
227 } 338 }
228 339
340 // Saves current GL state for later verification.
341 void SaveState() { m_savedState = m_state; }
342 void VeriyStateHasNotChangedSinceSave() const {
343 for (size_t i = 0; i < 4; ++i) {
344 EXPECT_EQ(m_state.clearColor[0], m_savedState.clearColor[0]);
345 EXPECT_EQ(m_state.colorMask[0], m_savedState.colorMask[0]);
346 }
347 EXPECT_EQ(m_state.clearDepth, m_savedState.clearDepth);
348 EXPECT_EQ(m_state.clearStencil, m_savedState.clearStencil);
349 EXPECT_EQ(m_state.depthMask, m_savedState.depthMask);
350 EXPECT_EQ(m_state.stencilMask, m_savedState.stencilMask);
351 EXPECT_EQ(m_state.packAlignment, m_savedState.packAlignment);
352 EXPECT_EQ(m_state.activeTexture2DBinding,
353 m_savedState.activeTexture2DBinding);
354 EXPECT_EQ(m_state.renderbufferBinding, m_savedState.renderbufferBinding);
355 EXPECT_EQ(m_state.drawFramebufferBinding,
356 m_savedState.drawFramebufferBinding);
357 EXPECT_EQ(m_state.readFramebufferBinding,
358 m_savedState.readFramebufferBinding);
359 EXPECT_EQ(m_state.pixelUnpackBufferBinding,
360 m_savedState.pixelUnpackBufferBinding);
361 }
362
229 private: 363 private:
230 GLuint m_boundTexture = 0; 364 std::map<GLenum, GLuint> m_boundTextures;
231 GLuint m_boundTextureTarget = 0; 365
366 // State tracked to verify that it is restored correctly.
367 struct State {
368 bool scissorEnabled = false;
369
370 GLfloat clearColor[4] = {0, 0, 0, 0};
371 GLfloat clearDepth = 0;
372 GLint clearStencil = 0;
373
374 GLboolean colorMask[4] = {0, 0, 0, 0};
375 GLboolean depthMask = 0;
376 GLuint stencilMask = 0;
377
378 GLint packAlignment = 4;
379
380 // The bound 2D texture for the active texture unit.
381 GLuint activeTexture2DBinding = 0;
382 GLuint renderbufferBinding = 0;
383 GLuint drawFramebufferBinding = 0;
384 GLuint readFramebufferBinding = 0;
385 GLuint pixelUnpackBufferBinding = 0;
386 };
387 State m_state;
388 State m_savedState;
389
232 gpu::SyncToken m_mostRecentlyWaitedSyncToken; 390 gpu::SyncToken m_mostRecentlyWaitedSyncToken;
233 GLbyte m_currentMailboxByte = 0; 391 GLbyte m_currentMailboxByte = 0;
234 IntSize m_mostRecentlyProducedSize; 392 IntSize m_mostRecentlyProducedSize;
235 bool m_createImageChromiumFail = false; 393 bool m_createImageChromiumFail = false;
236 GLuint m_currentImageId = 1; 394 GLuint m_currentImageId = 1;
237 HashMap<GLuint, IntSize> m_textureSizes; 395 HashMap<GLuint, IntSize> m_textureSizes;
238 HashMap<GLuint, IntSize> m_imageSizes; 396 HashMap<GLuint, IntSize> m_imageSizes;
239 HashMap<GLuint, GLuint> m_imageToTextureMap; 397 HashMap<GLuint, GLuint> m_imageToTextureMap;
240 }; 398 };
241 399
242 } // blink 400 } // blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698