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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp

Issue 2402273002: DrawingBuffer: Clean up GL state restoration (Closed)
Patch Set: Incorporate review feedback 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
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2010, Google Inc. All rights reserved. 2 * Copyright (c) 2010, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 #include "wtf/typed_arrays/ArrayBufferContents.h" 52 #include "wtf/typed_arrays/ArrayBufferContents.h"
53 #include <algorithm> 53 #include <algorithm>
54 #include <memory> 54 #include <memory>
55 55
56 namespace blink { 56 namespace blink {
57 57
58 namespace { 58 namespace {
59 59
60 const float s_resourceAdjustedRatio = 0.5; 60 const float s_resourceAdjustedRatio = 0.5;
61 61
62 class ScopedTextureUnit0BindingRestorer {
63 STACK_ALLOCATED();
64 WTF_MAKE_NONCOPYABLE(ScopedTextureUnit0BindingRestorer);
65
66 public:
67 ScopedTextureUnit0BindingRestorer(gpu::gles2::GLES2Interface* gl,
68 GLenum activeTextureUnit,
69 GLuint textureUnitZeroId)
70 : m_gl(gl),
71 m_oldActiveTextureUnit(activeTextureUnit),
72 m_oldTextureUnitZeroId(textureUnitZeroId) {
73 m_gl->ActiveTexture(GL_TEXTURE0);
74 }
75 ~ScopedTextureUnit0BindingRestorer() {
76 m_gl->BindTexture(GL_TEXTURE_2D, m_oldTextureUnitZeroId);
77 m_gl->ActiveTexture(m_oldActiveTextureUnit);
78 }
79
80 private:
81 gpu::gles2::GLES2Interface* m_gl;
82 GLenum m_oldActiveTextureUnit;
83 GLuint m_oldTextureUnitZeroId;
84 };
85
86 static bool shouldFailDrawingBufferCreationForTesting = false; 62 static bool shouldFailDrawingBufferCreationForTesting = false;
87 63
88 } // namespace 64 } // namespace
89 65
90 PassRefPtr<DrawingBuffer> DrawingBuffer::create( 66 PassRefPtr<DrawingBuffer> DrawingBuffer::create(
91 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, 67 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
68 Client* client,
92 const IntSize& size, 69 const IntSize& size,
93 bool premultipliedAlpha, 70 bool premultipliedAlpha,
94 bool wantAlphaChannel, 71 bool wantAlphaChannel,
95 bool wantDepthBuffer, 72 bool wantDepthBuffer,
96 bool wantStencilBuffer, 73 bool wantStencilBuffer,
97 bool wantAntialiasing, 74 bool wantAntialiasing,
98 PreserveDrawingBuffer preserve, 75 PreserveDrawingBuffer preserve,
99 WebGLVersion webGLVersion, 76 WebGLVersion webGLVersion,
100 ChromiumImageUsage chromiumImageUsage) { 77 ChromiumImageUsage chromiumImageUsage) {
101 ASSERT(contextProvider); 78 ASSERT(contextProvider);
(...skipping 26 matching lines...) Expand all
128 else 105 else
129 extensionsUtil->ensureExtensionEnabled( 106 extensionsUtil->ensureExtensionEnabled(
130 "GL_EXT_multisampled_render_to_texture"); 107 "GL_EXT_multisampled_render_to_texture");
131 } 108 }
132 bool discardFramebufferSupported = 109 bool discardFramebufferSupported =
133 extensionsUtil->supportsExtension("GL_EXT_discard_framebuffer"); 110 extensionsUtil->supportsExtension("GL_EXT_discard_framebuffer");
134 if (discardFramebufferSupported) 111 if (discardFramebufferSupported)
135 extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer"); 112 extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer");
136 113
137 RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer( 114 RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(
138 std::move(contextProvider), std::move(extensionsUtil), 115 std::move(contextProvider), std::move(extensionsUtil), client,
139 discardFramebufferSupported, wantAlphaChannel, premultipliedAlpha, 116 discardFramebufferSupported, wantAlphaChannel, premultipliedAlpha,
140 preserve, webGLVersion, wantDepthBuffer, wantStencilBuffer, 117 preserve, webGLVersion, wantDepthBuffer, wantStencilBuffer,
141 chromiumImageUsage)); 118 chromiumImageUsage));
142 if (!drawingBuffer->initialize(size, multisampleSupported)) { 119 if (!drawingBuffer->initialize(size, multisampleSupported)) {
143 drawingBuffer->beginDestruction(); 120 drawingBuffer->beginDestruction();
144 return PassRefPtr<DrawingBuffer>(); 121 return PassRefPtr<DrawingBuffer>();
145 } 122 }
146 return drawingBuffer.release(); 123 return drawingBuffer.release();
147 } 124 }
148 125
149 void DrawingBuffer::forceNextDrawingBufferCreationToFail() { 126 void DrawingBuffer::forceNextDrawingBufferCreationToFail() {
150 shouldFailDrawingBufferCreationForTesting = true; 127 shouldFailDrawingBufferCreationForTesting = true;
151 } 128 }
152 129
153 DrawingBuffer::DrawingBuffer( 130 DrawingBuffer::DrawingBuffer(
154 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, 131 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
155 std::unique_ptr<Extensions3DUtil> extensionsUtil, 132 std::unique_ptr<Extensions3DUtil> extensionsUtil,
133 Client* client,
156 bool discardFramebufferSupported, 134 bool discardFramebufferSupported,
157 bool wantAlphaChannel, 135 bool wantAlphaChannel,
158 bool premultipliedAlpha, 136 bool premultipliedAlpha,
159 PreserveDrawingBuffer preserve, 137 PreserveDrawingBuffer preserve,
160 WebGLVersion webGLVersion, 138 WebGLVersion webGLVersion,
161 bool wantDepth, 139 bool wantDepth,
162 bool wantStencil, 140 bool wantStencil,
163 ChromiumImageUsage chromiumImageUsage) 141 ChromiumImageUsage chromiumImageUsage)
164 : m_preserveDrawingBuffer(preserve), 142 : m_client(client),
143 m_preserveDrawingBuffer(preserve),
165 m_webGLVersion(webGLVersion), 144 m_webGLVersion(webGLVersion),
166 m_contextProvider(std::move(contextProvider)), 145 m_contextProvider(std::move(contextProvider)),
167 m_gl(m_contextProvider->contextGL()), 146 m_gl(m_contextProvider->contextGL()),
168 m_extensionsUtil(std::move(extensionsUtil)), 147 m_extensionsUtil(std::move(extensionsUtil)),
169 m_discardFramebufferSupported(discardFramebufferSupported), 148 m_discardFramebufferSupported(discardFramebufferSupported),
170 m_wantAlphaChannel(wantAlphaChannel), 149 m_wantAlphaChannel(wantAlphaChannel),
171 m_premultipliedAlpha(premultipliedAlpha), 150 m_premultipliedAlpha(premultipliedAlpha),
172 m_softwareRendering(m_contextProvider->isSoftwareRendering()), 151 m_softwareRendering(m_contextProvider->isSoftwareRendering()),
173 m_wantDepth(wantDepth), 152 m_wantDepth(wantDepth),
174 m_wantStencil(wantStencil), 153 m_wantStencil(wantStencil),
175 m_chromiumImageUsage(chromiumImageUsage) { 154 m_chromiumImageUsage(chromiumImageUsage) {
176 memset(m_colorMask, 0, 4 * sizeof(GLboolean));
177 memset(m_clearColor, 0, 4 * sizeof(GLfloat));
178 // Used by browser tests to detect the use of a DrawingBuffer. 155 // Used by browser tests to detect the use of a DrawingBuffer.
179 TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation", 156 TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation",
180 TRACE_EVENT_SCOPE_GLOBAL); 157 TRACE_EVENT_SCOPE_GLOBAL);
181 } 158 }
182 159
183 DrawingBuffer::~DrawingBuffer() { 160 DrawingBuffer::~DrawingBuffer() {
184 DCHECK(m_destructionInProgress); 161 DCHECK(m_destructionInProgress);
185 m_layer.reset(); 162 m_layer.reset();
186 m_contextProvider.reset(); 163 m_contextProvider.reset();
187 } 164 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 198
222 void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) { 199 void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) {
223 if (m_filterQuality != filterQuality) { 200 if (m_filterQuality != filterQuality) {
224 m_filterQuality = filterQuality; 201 m_filterQuality = filterQuality;
225 if (m_layer) 202 if (m_layer)
226 m_layer->setNearestNeighbor(filterQuality == kNone_SkFilterQuality); 203 m_layer->setNearestNeighbor(filterQuality == kNone_SkFilterQuality);
227 } 204 }
228 } 205 }
229 206
230 bool DrawingBuffer::requiresAlphaChannelToBePreserved() { 207 bool DrawingBuffer::requiresAlphaChannelToBePreserved() {
231 return !m_drawFramebufferBinding && 208 return m_client->DrawingBufferClientIsBoundForDraw() &&
232 defaultBufferRequiresAlphaChannelToBePreserved(); 209 defaultBufferRequiresAlphaChannelToBePreserved();
233 } 210 }
234 211
235 bool DrawingBuffer::defaultBufferRequiresAlphaChannelToBePreserved() { 212 bool DrawingBuffer::defaultBufferRequiresAlphaChannelToBePreserved() {
236 if (wantExplicitResolve()) { 213 if (wantExplicitResolve()) {
237 return !m_wantAlphaChannel && 214 return !m_wantAlphaChannel &&
238 getMultisampledRenderbufferFormat() == GL_RGBA8_OES; 215 getMultisampledRenderbufferFormat() == GL_RGBA8_OES;
239 } 216 }
240 217
241 bool rgbEmulation = 218 bool rgbEmulation =
(...skipping 15 matching lines...) Expand all
257 DCHECK(recycled.size == m_size); 234 DCHECK(recycled.size == m_size);
258 return std::move(recycled.bitmap); 235 return std::move(recycled.bitmap);
259 } 236 }
260 237
261 return Platform::current()->allocateSharedBitmap(m_size); 238 return Platform::current()->allocateSharedBitmap(m_size);
262 } 239 }
263 240
264 bool DrawingBuffer::PrepareTextureMailbox( 241 bool DrawingBuffer::PrepareTextureMailbox(
265 cc::TextureMailbox* outMailbox, 242 cc::TextureMailbox* outMailbox,
266 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) { 243 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
244 ScopedStateRestorer scopedStateRestorer(this);
267 bool forceGpuResult = false; 245 bool forceGpuResult = false;
268 return prepareTextureMailboxInternal(outMailbox, outReleaseCallback, 246 return prepareTextureMailboxInternal(outMailbox, outReleaseCallback,
269 forceGpuResult); 247 forceGpuResult);
270 } 248 }
271 249
272 bool DrawingBuffer::prepareTextureMailboxInternal( 250 bool DrawingBuffer::prepareTextureMailboxInternal(
273 cc::TextureMailbox* outMailbox, 251 cc::TextureMailbox* outMailbox,
274 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback, 252 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback,
275 bool forceGpuResult) { 253 bool forceGpuResult) {
276 if (m_destructionInProgress) { 254 if (m_destructionInProgress) {
(...skipping 14 matching lines...) Expand all
291 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) 269 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
292 return false; 270 return false;
293 271
294 TRACE_EVENT0("blink,rail", "DrawingBuffer::prepareMailbox"); 272 TRACE_EVENT0("blink,rail", "DrawingBuffer::prepareMailbox");
295 273
296 if (m_newMailboxCallback) 274 if (m_newMailboxCallback)
297 (*m_newMailboxCallback)(); 275 (*m_newMailboxCallback)();
298 276
299 // Resolve the multisampled buffer into m_backColorBuffer texture. 277 // Resolve the multisampled buffer into m_backColorBuffer texture.
300 if (m_antiAliasingMode != None) 278 if (m_antiAliasingMode != None)
301 commit(); 279 resolveMultisampleFramebufferInternal();
302 280
303 if (m_softwareRendering && !forceGpuResult) { 281 if (m_softwareRendering && !forceGpuResult) {
304 return finishPrepareTextureMailboxSoftware(outMailbox, outReleaseCallback); 282 return finishPrepareTextureMailboxSoftware(outMailbox, outReleaseCallback);
305 } else { 283 } else {
306 return finishPrepareTextureMailboxGpu(outMailbox, outReleaseCallback); 284 return finishPrepareTextureMailboxGpu(outMailbox, outReleaseCallback);
307 } 285 }
308 } 286 }
309 287
310 bool DrawingBuffer::finishPrepareTextureMailboxSoftware( 288 bool DrawingBuffer::finishPrepareTextureMailboxSoftware(
311 cc::TextureMailbox* outMailbox, 289 cc::TextureMailbox* outMailbox,
(...skipping 24 matching lines...) Expand all
336 WTF::passed(std::move(bitmap)), m_size); 314 WTF::passed(std::move(bitmap)), m_size);
337 *outReleaseCallback = 315 *outReleaseCallback =
338 cc::SingleReleaseCallback::Create(convertToBaseCallback(std::move(func))); 316 cc::SingleReleaseCallback::Create(convertToBaseCallback(std::move(func)));
339 return true; 317 return true;
340 } 318 }
341 319
342 bool DrawingBuffer::finishPrepareTextureMailboxGpu( 320 bool DrawingBuffer::finishPrepareTextureMailboxGpu(
343 cc::TextureMailbox* outMailbox, 321 cc::TextureMailbox* outMailbox,
344 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) { 322 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
345 if (m_webGLVersion > WebGL1) { 323 if (m_webGLVersion > WebGL1) {
324 m_stateRestorer->setPixelUnpackBufferBindingDirty();
346 m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 325 m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
347 } 326 }
348 327
349 // We must restore the texture binding since creating new textures,
350 // consuming and producing mailboxes changes it.
351 ScopedTextureUnit0BindingRestorer restorer(m_gl, m_activeTextureUnit,
352 m_texture2DBinding);
353
354 // Specify the buffer that we will put in the mailbox. 328 // Specify the buffer that we will put in the mailbox.
355 RefPtr<ColorBuffer> colorBufferForMailbox; 329 RefPtr<ColorBuffer> colorBufferForMailbox;
356 if (m_preserveDrawingBuffer == Discard) { 330 if (m_preserveDrawingBuffer == Discard) {
357 // If we can discard the backbuffer, send the old backbuffer directly 331 // If we can discard the backbuffer, send the old backbuffer directly
358 // into the mailbox, and allocate (or recycle) a new backbuffer. 332 // into the mailbox, and allocate (or recycle) a new backbuffer.
359 colorBufferForMailbox = m_backColorBuffer; 333 colorBufferForMailbox = m_backColorBuffer;
360 m_backColorBuffer = createOrRecycleColorBuffer(); 334 m_backColorBuffer = createOrRecycleColorBuffer();
361 attachColorBufferToReadFramebuffer(); 335 attachColorBufferToReadFramebuffer();
362 336
363 // Explicitly specify that m_fbo (which is now bound to the just-allocated 337 // Explicitly specify that m_fbo (which is now bound to the just-allocated
364 // m_backColorBuffer) is not initialized, to save GPU memory bandwidth for 338 // m_backColorBuffer) is not initialized, to save GPU memory bandwidth for
365 // tile-based GPU architectures. 339 // tile-based GPU architectures.
366 if (m_discardFramebufferSupported) { 340 if (m_discardFramebufferSupported) {
367 const GLenum attachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, 341 const GLenum attachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
368 GL_STENCIL_ATTACHMENT}; 342 GL_STENCIL_ATTACHMENT};
343 m_stateRestorer->setFramebufferBindingDirty();
369 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 344 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
370 m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments); 345 m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments);
371 } 346 }
372 } else { 347 } else {
373 // If we can't discard the backbuffer, create (or recycle) a buffer to put 348 // If we can't discard the backbuffer, create (or recycle) a buffer to put
374 // in the mailbox, and copy backbuffer's contents there. 349 // in the mailbox, and copy backbuffer's contents there.
375 colorBufferForMailbox = createOrRecycleColorBuffer(); 350 colorBufferForMailbox = createOrRecycleColorBuffer();
376 m_gl->CopySubTextureCHROMIUM( 351 m_gl->CopySubTextureCHROMIUM(
377 m_backColorBuffer->textureId, colorBufferForMailbox->textureId, 0, 0, 0, 352 m_backColorBuffer->textureId, colorBufferForMailbox->textureId, 0, 0, 0,
378 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE); 353 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE);
(...skipping 27 matching lines...) Expand all
406 // mailbox is released (and while the release callback is running). 381 // mailbox is released (and while the release callback is running).
407 auto func = WTF::bind(&DrawingBuffer::mailboxReleasedGpu, 382 auto func = WTF::bind(&DrawingBuffer::mailboxReleasedGpu,
408 RefPtr<DrawingBuffer>(this), colorBufferForMailbox); 383 RefPtr<DrawingBuffer>(this), colorBufferForMailbox);
409 *outReleaseCallback = cc::SingleReleaseCallback::Create( 384 *outReleaseCallback = cc::SingleReleaseCallback::Create(
410 convertToBaseCallback(std::move(func))); 385 convertToBaseCallback(std::move(func)));
411 } 386 }
412 387
413 // Point |m_frontColorBuffer| to the buffer that we are now presenting. 388 // Point |m_frontColorBuffer| to the buffer that we are now presenting.
414 m_frontColorBuffer = colorBufferForMailbox; 389 m_frontColorBuffer = colorBufferForMailbox;
415 390
416 // Restore any state that we may have dirtied, and update dirty bits.
417 restoreFramebufferBindings();
418 restorePixelUnpackBufferBindings();
419 m_contentsChanged = false; 391 m_contentsChanged = false;
420 setBufferClearNeeded(true); 392 setBufferClearNeeded(true);
421 return true; 393 return true;
422 } 394 }
423 395
424 void DrawingBuffer::mailboxReleasedGpu(RefPtr<ColorBuffer> colorBuffer, 396 void DrawingBuffer::mailboxReleasedGpu(RefPtr<ColorBuffer> colorBuffer,
425 const gpu::SyncToken& syncToken, 397 const gpu::SyncToken& syncToken,
426 bool lostResource) { 398 bool lostResource) {
427 // If the mailbox has been returned by the compositor then it is no 399 // If the mailbox has been returned by the compositor then it is no
428 // longer being presented, and so is no longer the front buffer. 400 // longer being presented, and so is no longer the front buffer.
(...skipping 28 matching lines...) Expand all
457 bool lostResource) { 429 bool lostResource) {
458 DCHECK(!syncToken.HasData()); // No sync tokens for software resources. 430 DCHECK(!syncToken.HasData()); // No sync tokens for software resources.
459 if (m_destructionInProgress || lostResource || m_isHidden || size != m_size) 431 if (m_destructionInProgress || lostResource || m_isHidden || size != m_size)
460 return; // Just delete the bitmap. 432 return; // Just delete the bitmap.
461 433
462 RecycledBitmap recycled = {std::move(bitmap), m_size}; 434 RecycledBitmap recycled = {std::move(bitmap), m_size};
463 m_recycledBitmaps.append(std::move(recycled)); 435 m_recycledBitmaps.append(std::move(recycled));
464 } 436 }
465 437
466 PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() { 438 PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() {
439 ScopedStateRestorer scopedStateRestorer(this);
440
467 // This can be null if the context is lost before the first call to 441 // This can be null if the context is lost before the first call to
468 // grContext(). 442 // grContext().
469 GrContext* grContext = m_contextProvider->grContext(); 443 GrContext* grContext = m_contextProvider->grContext();
470 444
471 cc::TextureMailbox textureMailbox; 445 cc::TextureMailbox textureMailbox;
472 std::unique_ptr<cc::SingleReleaseCallback> releaseCallback; 446 std::unique_ptr<cc::SingleReleaseCallback> releaseCallback;
473 bool success = false; 447 bool success = false;
474 if (grContext) { 448 if (grContext) {
475 bool forceGpuResult = true; 449 bool forceGpuResult = true;
476 success = prepareTextureMailboxInternal(&textureMailbox, &releaseCallback, 450 success = prepareTextureMailboxInternal(&textureMailbox, &releaseCallback,
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 GLuint imageId) 584 GLuint imageId)
611 : drawingBuffer(drawingBuffer), 585 : drawingBuffer(drawingBuffer),
612 parameters(parameters), 586 parameters(parameters),
613 size(size), 587 size(size),
614 textureId(textureId), 588 textureId(textureId),
615 imageId(imageId) { 589 imageId(imageId) {
616 drawingBuffer->contextGL()->GenMailboxCHROMIUM(mailbox.name); 590 drawingBuffer->contextGL()->GenMailboxCHROMIUM(mailbox.name);
617 } 591 }
618 592
619 DrawingBuffer::ColorBuffer::~ColorBuffer() { 593 DrawingBuffer::ColorBuffer::~ColorBuffer() {
620 gpu::gles2::GLES2Interface* gl = drawingBuffer->contextGL(); 594 gpu::gles2::GLES2Interface* gl = drawingBuffer->m_gl;
621 if (receiveSyncToken.HasData()) 595 if (receiveSyncToken.HasData())
622 gl->WaitSyncTokenCHROMIUM(receiveSyncToken.GetConstData()); 596 gl->WaitSyncTokenCHROMIUM(receiveSyncToken.GetConstData());
623 if (imageId) { 597 if (imageId) {
624 gl->BindTexture(parameters.target, textureId); 598 gl->BindTexture(parameters.target, textureId);
625 gl->ReleaseTexImage2DCHROMIUM(parameters.target, imageId); 599 gl->ReleaseTexImage2DCHROMIUM(parameters.target, imageId);
626 gl->DestroyImageCHROMIUM(imageId); 600 gl->DestroyImageCHROMIUM(imageId);
601 switch (parameters.target) {
602 case GL_TEXTURE_2D:
603 // Restore the texture binding for GL_TEXTURE_2D, since the client will
604 // expect the previous state.
605 if (drawingBuffer->m_client)
606 drawingBuffer->m_client->DrawingBufferClientRestoreTexture2DBinding();
607 break;
608 case GC3D_TEXTURE_RECTANGLE_ARB:
609 // Rectangle textures aren't exposed to WebGL, so don't bother
610 // restoring this state (there is no meaningful way to restore it).
611 break;
612 default:
613 NOTREACHED();
614 break;
615 }
627 } 616 }
628 gl->DeleteTextures(1, &textureId); 617 gl->DeleteTextures(1, &textureId);
629 } 618 }
630 619
631 bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) { 620 bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
621 ScopedStateRestorer scopedStateRestorer(this);
622
632 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { 623 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
633 // Need to try to restore the context again later. 624 // Need to try to restore the context again later.
634 return false; 625 return false;
635 } 626 }
636 627
637 m_gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); 628 m_gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
638 629
639 int maxSampleCount = 0; 630 int maxSampleCount = 0;
640 m_antiAliasingMode = None; 631 m_antiAliasingMode = None;
641 if (useMultisampling) { 632 if (useMultisampling) {
(...skipping 11 matching lines...) Expand all
653 // The Linux ATI bot fails 644 // The Linux ATI bot fails
654 // WebglConformance.conformance_textures_misc_tex_image_webgl, so use storage 645 // WebglConformance.conformance_textures_misc_tex_image_webgl, so use storage
655 // textures only if ScreenSpaceAntialiasing is enabled, because 646 // textures only if ScreenSpaceAntialiasing is enabled, because
656 // ScreenSpaceAntialiasing is much faster with storage textures. 647 // ScreenSpaceAntialiasing is much faster with storage textures.
657 m_storageTextureSupported = 648 m_storageTextureSupported =
658 (m_webGLVersion > WebGL1 || 649 (m_webGLVersion > WebGL1 ||
659 m_extensionsUtil->supportsExtension("GL_EXT_texture_storage")) && 650 m_extensionsUtil->supportsExtension("GL_EXT_texture_storage")) &&
660 m_antiAliasingMode == ScreenSpaceAntialiasing; 651 m_antiAliasingMode == ScreenSpaceAntialiasing;
661 m_sampleCount = std::min(4, maxSampleCount); 652 m_sampleCount = std::min(4, maxSampleCount);
662 653
654 m_stateRestorer->setFramebufferBindingDirty();
663 m_gl->GenFramebuffers(1, &m_fbo); 655 m_gl->GenFramebuffers(1, &m_fbo);
664 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 656 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
665 if (wantExplicitResolve()) { 657 if (wantExplicitResolve()) {
666 m_gl->GenFramebuffers(1, &m_multisampleFBO); 658 m_gl->GenFramebuffers(1, &m_multisampleFBO);
667 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 659 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
668 m_gl->GenRenderbuffers(1, &m_multisampleRenderbuffer); 660 m_gl->GenRenderbuffers(1, &m_multisampleRenderbuffer);
669 } 661 }
670 if (!reset(size)) 662 if (!resizeFramebufferInternal(size))
671 return false; 663 return false;
672 664
673 if (m_depthStencilBuffer) { 665 if (m_depthStencilBuffer) {
674 DCHECK(wantDepthOrStencil()); 666 DCHECK(wantDepthOrStencil());
675 m_hasImplicitStencilBuffer = !m_wantStencil; 667 m_hasImplicitStencilBuffer = !m_wantStencil;
676 } 668 }
677 669
678 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { 670 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
679 // It's possible that the drawing buffer allocation provokes a context loss, 671 // It's possible that the drawing buffer allocation provokes a context loss,
680 // so check again just in case. http://crbug.com/512302 672 // so check again just in case. http://crbug.com/512302
681 return false; 673 return false;
682 } 674 }
683 675
684 return true; 676 return true;
685 } 677 }
686 678
687 bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl, 679 bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl,
688 GLuint texture, 680 GLuint texture,
689 GLenum internalFormat, 681 GLenum internalFormat,
690 GLenum destType, 682 GLenum destType,
691 GLint level, 683 GLint level,
692 bool premultiplyAlpha, 684 bool premultiplyAlpha,
693 bool flipY, 685 bool flipY,
694 SourceDrawingBuffer sourceBuffer) { 686 SourceDrawingBuffer sourceBuffer) {
687 ScopedStateRestorer scopedStateRestorer(this);
688
695 if (m_contentsChanged) { 689 if (m_contentsChanged) {
696 if (m_antiAliasingMode != None) { 690 if (m_antiAliasingMode != None)
697 commit(); 691 resolveMultisampleFramebufferInternal();
698 restoreFramebufferBindings();
699 }
700 m_gl->Flush(); 692 m_gl->Flush();
701 } 693 }
702 694
703 // Assume that the destination target is GL_TEXTURE_2D. 695 // Assume that the destination target is GL_TEXTURE_2D.
704 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM( 696 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(
705 GL_TEXTURE_2D, internalFormat, destType, level)) 697 GL_TEXTURE_2D, internalFormat, destType, level))
706 return false; 698 return false;
707 699
708 // Contexts may be in a different share group. We must transfer the texture 700 // Contexts may be in a different share group. We must transfer the texture
709 // through a mailbox first. 701 // through a mailbox first.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM(); 737 const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM();
746 738
747 gl->Flush(); 739 gl->Flush();
748 gpu::SyncToken syncToken; 740 gpu::SyncToken syncToken;
749 gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData()); 741 gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData());
750 m_gl->WaitSyncTokenCHROMIUM(syncToken.GetData()); 742 m_gl->WaitSyncTokenCHROMIUM(syncToken.GetData());
751 743
752 return true; 744 return true;
753 } 745 }
754 746
755 GLuint DrawingBuffer::framebuffer() const {
756 return m_fbo;
757 }
758
759 WebLayer* DrawingBuffer::platformLayer() { 747 WebLayer* DrawingBuffer::platformLayer() {
760 if (!m_layer) { 748 if (!m_layer) {
761 m_layer = 749 m_layer =
762 Platform::current()->compositorSupport()->createExternalTextureLayer( 750 Platform::current()->compositorSupport()->createExternalTextureLayer(
763 this); 751 this);
764 752
765 m_layer->setOpaque(!m_wantAlphaChannel); 753 m_layer->setOpaque(!m_wantAlphaChannel);
766 m_layer->setBlendBackgroundColor(m_wantAlphaChannel); 754 m_layer->setBlendBackgroundColor(m_wantAlphaChannel);
767 m_layer->setPremultipliedAlpha(m_premultipliedAlpha); 755 m_layer->setPremultipliedAlpha(m_premultipliedAlpha);
768 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); 756 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 790
803 m_backColorBuffer = nullptr; 791 m_backColorBuffer = nullptr;
804 m_frontColorBuffer = nullptr; 792 m_frontColorBuffer = nullptr;
805 m_multisampleRenderbuffer = 0; 793 m_multisampleRenderbuffer = 0;
806 m_depthStencilBuffer = 0; 794 m_depthStencilBuffer = 0;
807 m_multisampleFBO = 0; 795 m_multisampleFBO = 0;
808 m_fbo = 0; 796 m_fbo = 0;
809 797
810 if (m_layer) 798 if (m_layer)
811 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); 799 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
800
801 m_client = nullptr;
812 } 802 }
813 803
814 bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) { 804 bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
815 // Recreate m_backColorBuffer. 805 // Recreate m_backColorBuffer.
816 m_backColorBuffer = createColorBuffer(size); 806 m_backColorBuffer = createColorBuffer(size);
817 807
818 attachColorBufferToReadFramebuffer(); 808 attachColorBufferToReadFramebuffer();
819 809
820 if (wantExplicitResolve()) { 810 if (wantExplicitResolve()) {
811 m_stateRestorer->setFramebufferBindingDirty();
812 m_stateRestorer->setRenderbufferBindingDirty();
821 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 813 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
822 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_multisampleRenderbuffer); 814 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_multisampleRenderbuffer);
823 m_gl->RenderbufferStorageMultisampleCHROMIUM( 815 m_gl->RenderbufferStorageMultisampleCHROMIUM(
824 GL_RENDERBUFFER, m_sampleCount, getMultisampledRenderbufferFormat(), 816 GL_RENDERBUFFER, m_sampleCount, getMultisampledRenderbufferFormat(),
825 size.width(), size.height()); 817 size.width(), size.height());
826 818
827 if (m_gl->GetError() == GL_OUT_OF_MEMORY) 819 if (m_gl->GetError() == GL_OUT_OF_MEMORY)
828 return false; 820 return false;
829 821
830 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 822 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
831 GL_RENDERBUFFER, m_multisampleRenderbuffer); 823 GL_RENDERBUFFER, m_multisampleRenderbuffer);
832 } 824 }
833 825
834 if (wantDepthOrStencil()) { 826 if (wantDepthOrStencil()) {
827 m_stateRestorer->setFramebufferBindingDirty();
828 m_stateRestorer->setRenderbufferBindingDirty();
835 m_gl->BindFramebuffer(GL_FRAMEBUFFER, 829 m_gl->BindFramebuffer(GL_FRAMEBUFFER,
836 m_multisampleFBO ? m_multisampleFBO : m_fbo); 830 m_multisampleFBO ? m_multisampleFBO : m_fbo);
837 if (!m_depthStencilBuffer) 831 if (!m_depthStencilBuffer)
838 m_gl->GenRenderbuffers(1, &m_depthStencilBuffer); 832 m_gl->GenRenderbuffers(1, &m_depthStencilBuffer);
839 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); 833 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
840 if (m_antiAliasingMode == MSAAImplicitResolve) { 834 if (m_antiAliasingMode == MSAAImplicitResolve) {
841 m_gl->RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, 835 m_gl->RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount,
842 GL_DEPTH24_STENCIL8_OES, 836 GL_DEPTH24_STENCIL8_OES,
843 size.width(), size.height()); 837 size.width(), size.height());
844 } else if (m_antiAliasingMode == MSAAExplicitResolve) { 838 } else if (m_antiAliasingMode == MSAAExplicitResolve) {
845 m_gl->RenderbufferStorageMultisampleCHROMIUM( 839 m_gl->RenderbufferStorageMultisampleCHROMIUM(
846 GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), 840 GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(),
847 size.height()); 841 size.height());
848 } else { 842 } else {
849 m_gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, 843 m_gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
850 size.width(), size.height()); 844 size.width(), size.height());
851 } 845 }
852 // For ES 2.0 contexts DEPTH_STENCIL is not available natively, so we 846 // For ES 2.0 contexts DEPTH_STENCIL is not available natively, so we
853 // emulate 847 // emulate
854 // it at the command buffer level for WebGL contexts. 848 // it at the command buffer level for WebGL contexts.
855 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 849 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
856 GL_RENDERBUFFER, m_depthStencilBuffer); 850 GL_RENDERBUFFER, m_depthStencilBuffer);
857 m_gl->BindRenderbuffer(GL_RENDERBUFFER, 0); 851 m_gl->BindRenderbuffer(GL_RENDERBUFFER, 0);
858 } 852 }
859 853
860 if (wantExplicitResolve()) { 854 if (wantExplicitResolve()) {
855 m_stateRestorer->setFramebufferBindingDirty();
861 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 856 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
862 if (m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 857 if (m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
863 return false; 858 return false;
864 } 859 }
865 860
861 m_stateRestorer->setFramebufferBindingDirty();
866 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 862 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
867 return m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) == 863 return m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
868 GL_FRAMEBUFFER_COMPLETE; 864 GL_FRAMEBUFFER_COMPLETE;
869 } 865 }
870 866
871 void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) { 867 void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) {
868 ScopedStateRestorer scopedStateRestorer(this);
869 clearFramebuffersInternal(clearMask);
870 }
871
872 void DrawingBuffer::clearFramebuffersInternal(GLbitfield clearMask) {
873 m_stateRestorer->setFramebufferBindingDirty();
872 // We will clear the multisample FBO, but we also need to clear the 874 // We will clear the multisample FBO, but we also need to clear the
873 // non-multisampled buffer. 875 // non-multisampled buffer.
874 if (m_multisampleFBO) { 876 if (m_multisampleFBO) {
875 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 877 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
876 m_gl->Clear(GL_COLOR_BUFFER_BIT); 878 m_gl->Clear(GL_COLOR_BUFFER_BIT);
877 } 879 }
878 880
879 m_gl->BindFramebuffer(GL_FRAMEBUFFER, 881 m_gl->BindFramebuffer(GL_FRAMEBUFFER,
880 m_multisampleFBO ? m_multisampleFBO : m_fbo); 882 m_multisampleFBO ? m_multisampleFBO : m_fbo);
881 m_gl->Clear(clearMask); 883 m_gl->Clear(clearMask);
882 } 884 }
883 885
884 IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize, 886 IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize,
885 const IntSize& curSize, 887 const IntSize& curSize,
886 int maxTextureSize) { 888 int maxTextureSize) {
887 IntSize adjustedSize = desiredSize; 889 IntSize adjustedSize = desiredSize;
888 890
889 // Clamp if the desired size is greater than the maximum texture size for the 891 // Clamp if the desired size is greater than the maximum texture size for the
890 // device. 892 // device.
891 if (adjustedSize.height() > maxTextureSize) 893 if (adjustedSize.height() > maxTextureSize)
892 adjustedSize.setHeight(maxTextureSize); 894 adjustedSize.setHeight(maxTextureSize);
893 895
894 if (adjustedSize.width() > maxTextureSize) 896 if (adjustedSize.width() > maxTextureSize)
895 adjustedSize.setWidth(maxTextureSize); 897 adjustedSize.setWidth(maxTextureSize);
896 898
897 return adjustedSize; 899 return adjustedSize;
898 } 900 }
899 901
900 bool DrawingBuffer::reset(const IntSize& newSize) { 902 bool DrawingBuffer::resize(const IntSize& newSize) {
903 ScopedStateRestorer scopedStateRestorer(this);
904 return resizeFramebufferInternal(newSize);
905 }
906
907 bool DrawingBuffer::resizeFramebufferInternal(const IntSize& newSize) {
901 CHECK(!newSize.isEmpty()); 908 CHECK(!newSize.isEmpty());
902 IntSize adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize); 909 IntSize adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize);
903 if (adjustedSize.isEmpty()) 910 if (adjustedSize.isEmpty())
904 return false; 911 return false;
905 912
906 if (adjustedSize != m_size) { 913 if (adjustedSize != m_size) {
907 do { 914 do {
908 if (!resizeDefaultFramebuffer(adjustedSize)) { 915 if (!resizeDefaultFramebuffer(adjustedSize)) {
909 adjustedSize.scale(s_resourceAdjustedRatio); 916 adjustedSize.scale(s_resourceAdjustedRatio);
910 continue; 917 continue;
911 } 918 }
912 break; 919 break;
913 } while (!adjustedSize.isEmpty()); 920 } while (!adjustedSize.isEmpty());
914 921
915 m_size = adjustedSize; 922 m_size = adjustedSize;
916 // Free all mailboxes, because they are now of the wrong size. Only the 923 // Free all mailboxes, because they are now of the wrong size. Only the
917 // first call in this loop has any effect. 924 // first call in this loop has any effect.
918 m_recycledColorBufferQueue.clear(); 925 m_recycledColorBufferQueue.clear();
919 m_recycledBitmaps.clear(); 926 m_recycledBitmaps.clear();
920 927
921 if (adjustedSize.isEmpty()) 928 if (adjustedSize.isEmpty())
922 return false; 929 return false;
923 } 930 }
924 931
932 m_stateRestorer->setClearStateDirty();
925 m_gl->Disable(GL_SCISSOR_TEST); 933 m_gl->Disable(GL_SCISSOR_TEST);
926 m_gl->ClearColor(0, 0, 0, 934 m_gl->ClearColor(0, 0, 0,
927 defaultBufferRequiresAlphaChannelToBePreserved() ? 1 : 0); 935 defaultBufferRequiresAlphaChannelToBePreserved() ? 1 : 0);
928 m_gl->ColorMask(true, true, true, true); 936 m_gl->ColorMask(true, true, true, true);
929 937
930 GLbitfield clearMask = GL_COLOR_BUFFER_BIT; 938 GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
931 if (!!m_depthStencilBuffer) { 939 if (!!m_depthStencilBuffer) {
932 m_gl->ClearDepthf(1.0f); 940 m_gl->ClearDepthf(1.0f);
933 clearMask |= GL_DEPTH_BUFFER_BIT; 941 clearMask |= GL_DEPTH_BUFFER_BIT;
934 m_gl->DepthMask(true); 942 m_gl->DepthMask(true);
935 } 943 }
936 if (!!m_depthStencilBuffer) { 944 if (!!m_depthStencilBuffer) {
937 m_gl->ClearStencil(0); 945 m_gl->ClearStencil(0);
938 clearMask |= GL_STENCIL_BUFFER_BIT; 946 clearMask |= GL_STENCIL_BUFFER_BIT;
939 m_gl->StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF); 947 m_gl->StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
940 } 948 }
941 949
942 clearFramebuffers(clearMask); 950 clearFramebuffersInternal(clearMask);
943 return true; 951 return true;
944 } 952 }
945 953
946 void DrawingBuffer::commit() { 954 void DrawingBuffer::resolveAndBindForReadAndDraw() {
955 {
956 ScopedStateRestorer scopedStateRestorer(this);
957 resolveMultisampleFramebufferInternal();
958 }
959 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
960 }
961
962 void DrawingBuffer::resolveMultisampleFramebufferInternal() {
963 m_stateRestorer->setFramebufferBindingDirty();
947 if (wantExplicitResolve() && !m_contentsChangeCommitted) { 964 if (wantExplicitResolve() && !m_contentsChangeCommitted) {
965 m_stateRestorer->setClearStateDirty();
948 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO); 966 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO);
949 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo); 967 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo);
950 968 m_gl->Disable(GL_SCISSOR_TEST);
951 if (m_scissorEnabled)
952 m_gl->Disable(GL_SCISSOR_TEST);
953 969
954 int width = m_size.width(); 970 int width = m_size.width();
955 int height = m_size.height(); 971 int height = m_size.height();
956 // Use NEAREST, because there is no scale performed during the blit. 972 // Use NEAREST, because there is no scale performed during the blit.
957 GLuint filter = GL_NEAREST; 973 GLuint filter = GL_NEAREST;
958 974
959 m_gl->BlitFramebufferCHROMIUM(0, 0, width, height, 0, 0, width, height, 975 m_gl->BlitFramebufferCHROMIUM(0, 0, width, height, 0, 0, width, height,
960 GL_COLOR_BUFFER_BIT, filter); 976 GL_COLOR_BUFFER_BIT, filter);
961 977
962 // On old AMD GPUs on OS X, glColorMask doesn't work correctly for 978 // On old AMD GPUs on OS X, glColorMask doesn't work correctly for
963 // multisampled renderbuffers and the alpha channel can be overwritten. 979 // multisampled renderbuffers and the alpha channel can be overwritten.
964 // Clear the alpha channel of |m_fbo|. 980 // Clear the alpha channel of |m_fbo|.
965 if (defaultBufferRequiresAlphaChannelToBePreserved() && 981 if (defaultBufferRequiresAlphaChannelToBePreserved() &&
966 contextProvider() 982 contextProvider()
967 ->getCapabilities() 983 ->getCapabilities()
968 .disable_multisampling_color_mask_usage) { 984 .disable_multisampling_color_mask_usage) {
969 m_gl->ClearColor(0, 0, 0, 1); 985 m_gl->ClearColor(0, 0, 0, 1);
970 m_gl->ColorMask(false, false, false, true); 986 m_gl->ColorMask(false, false, false, true);
971 m_gl->Clear(GL_COLOR_BUFFER_BIT);
972
973 m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
974 m_clearColor[3]);
975 m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
976 m_colorMask[3]);
977 } 987 }
978
979 if (m_scissorEnabled)
980 m_gl->Enable(GL_SCISSOR_TEST);
981 } 988 }
982 989
983 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 990 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
984 if (m_antiAliasingMode == ScreenSpaceAntialiasing) { 991 if (m_antiAliasingMode == ScreenSpaceAntialiasing)
985 m_gl->ApplyScreenSpaceAntialiasingCHROMIUM(); 992 m_gl->ApplyScreenSpaceAntialiasingCHROMIUM();
986 }
987 m_contentsChangeCommitted = true; 993 m_contentsChangeCommitted = true;
988 } 994 }
989 995
990 void DrawingBuffer::restorePixelUnpackBufferBindings() { 996 void DrawingBuffer::restoreFramebufferBindings() {
991 if (m_webGLVersion > WebGL1) { 997 m_client->DrawingBufferClientRestoreFramebufferBinding();
992 m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixelUnpackBufferBinding);
993 }
994 } 998 }
995 999
996 void DrawingBuffer::restoreFramebufferBindings() { 1000 void DrawingBuffer::restoreAllState() {
997 if (m_drawFramebufferBinding && m_readFramebufferBinding) { 1001 m_client->DrawingBufferClientRestoreScissorTest();
998 if (m_drawFramebufferBinding == m_readFramebufferBinding) { 1002 m_client->DrawingBufferClientRestoreMaskAndClearValues();
999 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_readFramebufferBinding); 1003 m_client->DrawingBufferClientRestorePixelPackAlignment();
1000 } else { 1004 m_client->DrawingBufferClientRestoreTexture2DBinding();
1001 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding); 1005 m_client->DrawingBufferClientRestoreRenderbufferBinding();
1002 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding); 1006 m_client->DrawingBufferClientRestoreFramebufferBinding();
1003 } 1007 m_client->DrawingBufferClientRestorePixelUnpackBufferBinding();
1004 return;
1005 }
1006 if (!m_drawFramebufferBinding && !m_readFramebufferBinding) {
1007 bind(GL_FRAMEBUFFER);
1008 return;
1009 }
1010 if (!m_drawFramebufferBinding) {
1011 bind(GL_DRAW_FRAMEBUFFER);
1012 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding);
1013 } else {
1014 bind(GL_READ_FRAMEBUFFER);
1015 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding);
1016 }
1017 } 1008 }
1018 1009
1019 bool DrawingBuffer::multisample() const { 1010 bool DrawingBuffer::multisample() const {
1020 return m_antiAliasingMode != None; 1011 return m_antiAliasingMode != None;
1021 } 1012 }
1022 1013
1023 void DrawingBuffer::bind(GLenum target) { 1014 void DrawingBuffer::bind(GLenum target) {
1024 m_gl->BindFramebuffer(target, 1015 m_gl->BindFramebuffer(target,
1025 wantExplicitResolve() ? m_multisampleFBO : m_fbo); 1016 wantExplicitResolve() ? m_multisampleFBO : m_fbo);
1026 } 1017 }
1027 1018
1028 void DrawingBuffer::setPackAlignment(GLint param) {
1029 m_packAlignment = param;
1030 }
1031
1032 bool DrawingBuffer::paintRenderingResultsToImageData( 1019 bool DrawingBuffer::paintRenderingResultsToImageData(
1033 int& width, 1020 int& width,
1034 int& height, 1021 int& height,
1035 SourceDrawingBuffer sourceBuffer, 1022 SourceDrawingBuffer sourceBuffer,
1036 WTF::ArrayBufferContents& contents) { 1023 WTF::ArrayBufferContents& contents) {
1024 ScopedStateRestorer scopedStateRestorer(this);
1025
1037 ASSERT(!m_premultipliedAlpha); 1026 ASSERT(!m_premultipliedAlpha);
1038 width = size().width(); 1027 width = size().width();
1039 height = size().height(); 1028 height = size().height();
1040 1029
1041 CheckedNumeric<int> dataSize = 4; 1030 CheckedNumeric<int> dataSize = 4;
1042 dataSize *= width; 1031 dataSize *= width;
1043 dataSize *= height; 1032 dataSize *= height;
1044 if (!dataSize.IsValid()) 1033 if (!dataSize.IsValid())
1045 return false; 1034 return false;
1046 1035
1047 WTF::ArrayBufferContents pixels(width * height, 4, 1036 WTF::ArrayBufferContents pixels(width * height, 4,
1048 WTF::ArrayBufferContents::NotShared, 1037 WTF::ArrayBufferContents::NotShared,
1049 WTF::ArrayBufferContents::DontInitialize); 1038 WTF::ArrayBufferContents::DontInitialize);
1050 1039
1051 GLuint fbo = 0; 1040 GLuint fbo = 0;
1041 m_stateRestorer->setFramebufferBindingDirty();
1052 if (sourceBuffer == FrontBuffer && m_frontColorBuffer) { 1042 if (sourceBuffer == FrontBuffer && m_frontColorBuffer) {
1053 m_gl->GenFramebuffers(1, &fbo); 1043 m_gl->GenFramebuffers(1, &fbo);
1054 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo); 1044 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
1055 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 1045 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1056 m_frontColorBuffer->parameters.target, 1046 m_frontColorBuffer->parameters.target,
1057 m_frontColorBuffer->textureId, 0); 1047 m_frontColorBuffer->textureId, 0);
1058 } else { 1048 } else {
1059 m_gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer()); 1049 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
1060 } 1050 }
1061 1051
1062 readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height, 1052 readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height,
1063 ReadbackRGBA, WebGLImageConversion::AlphaDoNothing); 1053 ReadbackRGBA, WebGLImageConversion::AlphaDoNothing);
1064 flipVertically(static_cast<uint8_t*>(pixels.data()), width, height); 1054 flipVertically(static_cast<uint8_t*>(pixels.data()), width, height);
1065 1055
1066 if (fbo) { 1056 if (fbo) {
1067 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 1057 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1068 m_frontColorBuffer->parameters.target, 0, 0); 1058 m_frontColorBuffer->parameters.target, 0, 0);
1069 m_gl->DeleteFramebuffers(1, &fbo); 1059 m_gl->DeleteFramebuffers(1, &fbo);
1070 } 1060 }
1071 1061
1072 restoreFramebufferBindings();
1073
1074 pixels.transfer(contents); 1062 pixels.transfer(contents);
1075 return true; 1063 return true;
1076 } 1064 }
1077 1065
1078 void DrawingBuffer::readBackFramebuffer(unsigned char* pixels, 1066 void DrawingBuffer::readBackFramebuffer(unsigned char* pixels,
1079 int width, 1067 int width,
1080 int height, 1068 int height,
1081 ReadbackOrder readbackOrder, 1069 ReadbackOrder readbackOrder,
1082 WebGLImageConversion::AlphaOp op) { 1070 WebGLImageConversion::AlphaOp op) {
1083 if (m_packAlignment > 4) 1071 m_stateRestorer->setPixelPackAlignmentDirty();
1084 m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1); 1072 m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
1085 m_gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 1073 m_gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1086 if (m_packAlignment > 4)
1087 m_gl->PixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
1088 1074
1089 size_t bufferSize = 4 * width * height; 1075 size_t bufferSize = 4 * width * height;
1090 1076
1091 if (readbackOrder == ReadbackSkia) { 1077 if (readbackOrder == ReadbackSkia) {
1092 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT 1078 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
1093 // Swizzle red and blue channels to match SkBitmap's byte ordering. 1079 // Swizzle red and blue channels to match SkBitmap's byte ordering.
1094 // TODO(kbr): expose GL_BGRA as extension. 1080 // TODO(kbr): expose GL_BGRA as extension.
1095 for (size_t i = 0; i < bufferSize; i += 4) { 1081 for (size_t i = 0; i < bufferSize; i += 4) {
1096 std::swap(pixels[i], pixels[i + 2]); 1082 std::swap(pixels[i], pixels[i + 2]);
1097 } 1083 }
(...skipping 21 matching lines...) Expand all
1119 uint8_t* rowA = framebuffer + i * rowBytes; 1105 uint8_t* rowA = framebuffer + i * rowBytes;
1120 uint8_t* rowB = framebuffer + (height - i - 1) * rowBytes; 1106 uint8_t* rowB = framebuffer + (height - i - 1) * rowBytes;
1121 memcpy(scanline.data(), rowB, rowBytes); 1107 memcpy(scanline.data(), rowB, rowBytes);
1122 memcpy(rowB, rowA, rowBytes); 1108 memcpy(rowB, rowA, rowBytes);
1123 memcpy(rowA, scanline.data(), rowBytes); 1109 memcpy(rowA, scanline.data(), rowBytes);
1124 } 1110 }
1125 } 1111 }
1126 1112
1127 RefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::createColorBuffer( 1113 RefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::createColorBuffer(
1128 const IntSize& size) { 1114 const IntSize& size) {
1115 m_stateRestorer->setFramebufferBindingDirty();
1116 m_stateRestorer->setTextureBindingDirty();
1117
1129 // Select the Parameters for the texture object. Allocate the backing 1118 // Select the Parameters for the texture object. Allocate the backing
1130 // GpuMemoryBuffer and GLImage, if one is going to be used. 1119 // GpuMemoryBuffer and GLImage, if one is going to be used.
1131 ColorBufferParameters parameters; 1120 ColorBufferParameters parameters;
1132 GLuint imageId = 0; 1121 GLuint imageId = 0;
1133 if (shouldUseChromiumImage()) { 1122 if (shouldUseChromiumImage()) {
1134 parameters = gpuMemoryBufferColorBufferParameters(); 1123 parameters = gpuMemoryBufferColorBufferParameters();
1135 imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM( 1124 imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(
1136 size.width(), size.height(), parameters.creationInternalColorFormat, 1125 size.width(), size.height(), parameters.creationInternalColorFormat,
1137 GC3D_SCANOUT_CHROMIUM); 1126 GC3D_SCANOUT_CHROMIUM);
1138 } else { 1127 } else {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 parameters.creationInternalColorFormat, size.width(), 1160 parameters.creationInternalColorFormat, size.width(),
1172 size.height(), 0, parameters.colorFormat, 1161 size.height(), 0, parameters.colorFormat,
1173 GL_UNSIGNED_BYTE, 0); 1162 GL_UNSIGNED_BYTE, 0);
1174 } 1163 }
1175 } 1164 }
1176 1165
1177 // Clear the alpha channel if this is RGB emulated. 1166 // Clear the alpha channel if this is RGB emulated.
1178 if (imageId && !m_wantAlphaChannel && 1167 if (imageId && !m_wantAlphaChannel &&
1179 contextProvider()->getCapabilities().chromium_image_rgb_emulation) { 1168 contextProvider()->getCapabilities().chromium_image_rgb_emulation) {
1180 GLuint fbo = 0; 1169 GLuint fbo = 0;
1170
1171 m_stateRestorer->setClearStateDirty();
1181 m_gl->GenFramebuffers(1, &fbo); 1172 m_gl->GenFramebuffers(1, &fbo);
1182 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo); 1173 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
1183 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 1174 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1184 parameters.target, textureId, 0); 1175 parameters.target, textureId, 0);
1185 m_gl->ClearColor(0, 0, 0, 1); 1176 m_gl->ClearColor(0, 0, 0, 1);
1186 m_gl->ColorMask(false, false, false, true); 1177 m_gl->ColorMask(false, false, false, true);
1187 m_gl->Clear(GL_COLOR_BUFFER_BIT); 1178 m_gl->Clear(GL_COLOR_BUFFER_BIT);
1188 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 1179 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1189 parameters.target, 0, 0); 1180 parameters.target, 0, 0);
1190 m_gl->DeleteFramebuffers(1, &fbo); 1181 m_gl->DeleteFramebuffers(1, &fbo);
1191 restoreFramebufferBindings();
1192 m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
1193 m_clearColor[3]);
1194 m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
1195 m_colorMask[3]);
1196 } 1182 }
1197 1183
1198 return adoptRef(new ColorBuffer(this, parameters, size, textureId, imageId)); 1184 return adoptRef(new ColorBuffer(this, parameters, size, textureId, imageId));
1199 } 1185 }
1200 1186
1201 void DrawingBuffer::attachColorBufferToReadFramebuffer() { 1187 void DrawingBuffer::attachColorBufferToReadFramebuffer() {
1188 m_stateRestorer->setFramebufferBindingDirty();
1189 m_stateRestorer->setTextureBindingDirty();
1190
1202 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 1191 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
1203 1192
1204 GLenum target = m_backColorBuffer->parameters.target; 1193 GLenum target = m_backColorBuffer->parameters.target;
1205 GLenum id = m_backColorBuffer->textureId; 1194 GLenum id = m_backColorBuffer->textureId;
1206 1195
1207 m_gl->BindTexture(target, id); 1196 m_gl->BindTexture(target, id);
1208 1197
1209 if (m_antiAliasingMode == MSAAImplicitResolve) 1198 if (m_antiAliasingMode == MSAAImplicitResolve)
1210 m_gl->FramebufferTexture2DMultisampleEXT( 1199 m_gl->FramebufferTexture2DMultisampleEXT(
1211 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id, 0, m_sampleCount); 1200 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id, 0, m_sampleCount);
1212 else 1201 else
1213 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id, 1202 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id,
1214 0); 1203 0);
1215
1216 restoreTextureBindings();
1217 restoreFramebufferBindings();
1218 } 1204 }
1219 1205
1220 bool DrawingBuffer::wantExplicitResolve() { 1206 bool DrawingBuffer::wantExplicitResolve() {
1221 return m_antiAliasingMode == MSAAExplicitResolve; 1207 return m_antiAliasingMode == MSAAExplicitResolve;
1222 } 1208 }
1223 1209
1224 bool DrawingBuffer::wantDepthOrStencil() { 1210 bool DrawingBuffer::wantDepthOrStencil() {
1225 return m_wantDepth || m_wantStencil; 1211 return m_wantDepth || m_wantStencil;
1226 } 1212 }
1227 1213
1228 GLenum DrawingBuffer::getMultisampledRenderbufferFormat() { 1214 GLenum DrawingBuffer::getMultisampledRenderbufferFormat() {
1229 DCHECK(wantExplicitResolve()); 1215 DCHECK(wantExplicitResolve());
1230 if (m_wantAlphaChannel) 1216 if (m_wantAlphaChannel)
1231 return GL_RGBA8_OES; 1217 return GL_RGBA8_OES;
1232 if (shouldUseChromiumImage() && 1218 if (shouldUseChromiumImage() &&
1233 contextProvider()->getCapabilities().chromium_image_rgb_emulation) 1219 contextProvider()->getCapabilities().chromium_image_rgb_emulation)
1234 return GL_RGBA8_OES; 1220 return GL_RGBA8_OES;
1235 if (contextProvider() 1221 if (contextProvider()
1236 ->getCapabilities() 1222 ->getCapabilities()
1237 .disable_webgl_rgb_multisampling_usage) 1223 .disable_webgl_rgb_multisampling_usage)
1238 return GL_RGBA8_OES; 1224 return GL_RGBA8_OES;
1239 return GL_RGB8_OES; 1225 return GL_RGB8_OES;
1240 } 1226 }
1241 1227
1242 void DrawingBuffer::restoreTextureBindings() { 1228 DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer(
1243 // This class potentially modifies the bindings for GL_TEXTURE_2D and 1229 DrawingBuffer* drawingBuffer)
1244 // GL_TEXTURE_RECTANGLE. Only GL_TEXTURE_2D needs to be restored since 1230 : m_drawingBuffer(drawingBuffer) {
1245 // the public interface for WebGL does not support GL_TEXTURE_RECTANGLE. 1231 DCHECK(!m_drawingBuffer->m_stateRestorer);
1246 m_gl->BindTexture(GL_TEXTURE_2D, m_texture2DBinding); 1232 m_drawingBuffer->m_stateRestorer = this;
1233 }
1234
1235 DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() {
1236 m_drawingBuffer->m_stateRestorer = nullptr;
1237 Client* client = m_drawingBuffer->m_client;
1238 if (!client)
1239 return;
1240
1241 if (m_clearStateDirty) {
1242 client->DrawingBufferClientRestoreScissorTest();
1243 client->DrawingBufferClientRestoreMaskAndClearValues();
1244 }
1245 if (m_pixelPackAlignmentDirty)
1246 client->DrawingBufferClientRestorePixelPackAlignment();
1247 if (m_textureBindingDirty)
1248 client->DrawingBufferClientRestoreTexture2DBinding();
1249 if (m_renderbufferBindingDirty)
1250 client->DrawingBufferClientRestoreRenderbufferBinding();
1251 if (m_framebufferBindingDirty)
1252 client->DrawingBufferClientRestoreFramebufferBinding();
1253 if (m_pixelUnpackBufferBindingDirty)
1254 client->DrawingBufferClientRestorePixelUnpackBufferBinding();
1247 } 1255 }
1248 1256
1249 bool DrawingBuffer::shouldUseChromiumImage() { 1257 bool DrawingBuffer::shouldUseChromiumImage() {
1250 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() && 1258 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() &&
1251 m_chromiumImageUsage == AllowChromiumImage; 1259 m_chromiumImageUsage == AllowChromiumImage;
1252 } 1260 }
1253 1261
1254 } // namespace blink 1262 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698