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

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

Issue 2402603002: State management cleanup (Closed)
Patch Set: Make state dirtying explosive 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 #include "wtf/typed_arrays/ArrayBufferContents.h" 53 #include "wtf/typed_arrays/ArrayBufferContents.h"
54 #include <algorithm> 54 #include <algorithm>
55 #include <memory> 55 #include <memory>
56 56
57 namespace blink { 57 namespace blink {
58 58
59 namespace { 59 namespace {
60 60
61 const float s_resourceAdjustedRatio = 0.5; 61 const float s_resourceAdjustedRatio = 0.5;
62 62
63 class ScopedTextureUnit0BindingRestorer {
64 STACK_ALLOCATED();
65 WTF_MAKE_NONCOPYABLE(ScopedTextureUnit0BindingRestorer);
66
67 public:
68 ScopedTextureUnit0BindingRestorer(gpu::gles2::GLES2Interface* gl,
69 GLenum activeTextureUnit,
70 GLuint textureUnitZeroId)
71 : m_gl(gl),
72 m_oldActiveTextureUnit(activeTextureUnit),
73 m_oldTextureUnitZeroId(textureUnitZeroId) {
74 m_gl->ActiveTexture(GL_TEXTURE0);
75 }
76 ~ScopedTextureUnit0BindingRestorer() {
77 m_gl->BindTexture(GL_TEXTURE_2D, m_oldTextureUnitZeroId);
78 m_gl->ActiveTexture(m_oldActiveTextureUnit);
79 }
80
81 private:
82 gpu::gles2::GLES2Interface* m_gl;
83 GLenum m_oldActiveTextureUnit;
84 GLuint m_oldTextureUnitZeroId;
85 };
86
87 static bool shouldFailDrawingBufferCreationForTesting = false; 63 static bool shouldFailDrawingBufferCreationForTesting = false;
88 64
89 } // namespace 65 } // namespace
90 66
91 PassRefPtr<DrawingBuffer> DrawingBuffer::create( 67 PassRefPtr<DrawingBuffer> DrawingBuffer::create(
92 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, 68 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
69 DrawingBufferStateTracker* drawingBufferRestoreSource,
93 const IntSize& size, 70 const IntSize& size,
94 bool premultipliedAlpha, 71 bool premultipliedAlpha,
95 bool wantAlphaChannel, 72 bool wantAlphaChannel,
96 bool wantDepthBuffer, 73 bool wantDepthBuffer,
97 bool wantStencilBuffer, 74 bool wantStencilBuffer,
98 bool wantAntialiasing, 75 bool wantAntialiasing,
99 PreserveDrawingBuffer preserve, 76 PreserveDrawingBuffer preserve,
100 WebGLVersion webGLVersion, 77 WebGLVersion webGLVersion,
101 ChromiumImageUsage chromiumImageUsage) { 78 ChromiumImageUsage chromiumImageUsage) {
102 ASSERT(contextProvider); 79 ASSERT(contextProvider);
(...skipping 27 matching lines...) Expand all
130 extensionsUtil->ensureExtensionEnabled( 107 extensionsUtil->ensureExtensionEnabled(
131 "GL_EXT_multisampled_render_to_texture"); 108 "GL_EXT_multisampled_render_to_texture");
132 } 109 }
133 bool discardFramebufferSupported = 110 bool discardFramebufferSupported =
134 extensionsUtil->supportsExtension("GL_EXT_discard_framebuffer"); 111 extensionsUtil->supportsExtension("GL_EXT_discard_framebuffer");
135 if (discardFramebufferSupported) 112 if (discardFramebufferSupported)
136 extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer"); 113 extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer");
137 114
138 RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer( 115 RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(
139 std::move(contextProvider), std::move(extensionsUtil), 116 std::move(contextProvider), std::move(extensionsUtil),
140 discardFramebufferSupported, wantAlphaChannel, premultipliedAlpha, 117 drawingBufferRestoreSource, discardFramebufferSupported, wantAlphaChannel,
141 preserve, webGLVersion, wantDepthBuffer, wantStencilBuffer, 118 premultipliedAlpha, preserve, webGLVersion, wantDepthBuffer,
142 chromiumImageUsage)); 119 wantStencilBuffer, chromiumImageUsage));
143 if (!drawingBuffer->initialize(size, multisampleSupported)) { 120 if (!drawingBuffer->initialize(size, multisampleSupported)) {
144 drawingBuffer->beginDestruction(); 121 drawingBuffer->beginDestruction();
145 return PassRefPtr<DrawingBuffer>(); 122 return PassRefPtr<DrawingBuffer>();
146 } 123 }
147 return drawingBuffer.release(); 124 return drawingBuffer.release();
148 } 125 }
149 126
150 void DrawingBuffer::forceNextDrawingBufferCreationToFail() { 127 void DrawingBuffer::forceNextDrawingBufferCreationToFail() {
151 shouldFailDrawingBufferCreationForTesting = true; 128 shouldFailDrawingBufferCreationForTesting = true;
152 } 129 }
153 130
154 DrawingBuffer::DrawingBuffer( 131 DrawingBuffer::DrawingBuffer(
155 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, 132 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
156 std::unique_ptr<Extensions3DUtil> extensionsUtil, 133 std::unique_ptr<Extensions3DUtil> extensionsUtil,
134 DrawingBufferStateTracker* stateTracker,
157 bool discardFramebufferSupported, 135 bool discardFramebufferSupported,
158 bool wantAlphaChannel, 136 bool wantAlphaChannel,
159 bool premultipliedAlpha, 137 bool premultipliedAlpha,
160 PreserveDrawingBuffer preserve, 138 PreserveDrawingBuffer preserve,
161 WebGLVersion webGLVersion, 139 WebGLVersion webGLVersion,
162 bool wantDepth, 140 bool wantDepth,
163 bool wantStencil, 141 bool wantStencil,
164 ChromiumImageUsage chromiumImageUsage) 142 ChromiumImageUsage chromiumImageUsage)
165 : m_preserveDrawingBuffer(preserve), 143 : m_stateTracker(stateTracker),
144 m_preserveDrawingBuffer(preserve),
166 m_webGLVersion(webGLVersion), 145 m_webGLVersion(webGLVersion),
167 m_contextProvider(std::move(contextProvider)), 146 m_contextProvider(std::move(contextProvider)),
168 m_gl(m_contextProvider->contextGL()), 147 m_gl(m_contextProvider->contextGL()),
169 m_extensionsUtil(std::move(extensionsUtil)), 148 m_extensionsUtil(std::move(extensionsUtil)),
170 m_discardFramebufferSupported(discardFramebufferSupported), 149 m_discardFramebufferSupported(discardFramebufferSupported),
171 m_wantAlphaChannel(wantAlphaChannel), 150 m_wantAlphaChannel(wantAlphaChannel),
172 m_premultipliedAlpha(premultipliedAlpha), 151 m_premultipliedAlpha(premultipliedAlpha),
173 m_softwareRendering(m_contextProvider->isSoftwareRendering()), 152 m_softwareRendering(m_contextProvider->isSoftwareRendering()),
174 m_wantDepth(wantDepth), 153 m_wantDepth(wantDepth),
175 m_wantStencil(wantStencil), 154 m_wantStencil(wantStencil),
176 m_chromiumImageUsage(chromiumImageUsage) { 155 m_chromiumImageUsage(chromiumImageUsage) {
177 memset(m_colorMask, 0, 4 * sizeof(GLboolean));
178 memset(m_clearColor, 0, 4 * sizeof(GLfloat));
179 // Used by browser tests to detect the use of a DrawingBuffer. 156 // Used by browser tests to detect the use of a DrawingBuffer.
180 TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation", 157 TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation",
181 TRACE_EVENT_SCOPE_GLOBAL); 158 TRACE_EVENT_SCOPE_GLOBAL);
182 } 159 }
183 160
184 DrawingBuffer::~DrawingBuffer() { 161 DrawingBuffer::~DrawingBuffer() {
185 DCHECK(m_destructionInProgress); 162 DCHECK(m_destructionInProgress);
186 m_layer.reset(); 163 m_layer.reset();
187 m_contextProvider.reset(); 164 m_contextProvider.reset();
188 } 165 }
(...skipping 21 matching lines...) Expand all
210 187
211 WebGraphicsContext3DProvider* DrawingBuffer::contextProvider() { 188 WebGraphicsContext3DProvider* DrawingBuffer::contextProvider() {
212 return m_contextProvider.get(); 189 return m_contextProvider.get();
213 } 190 }
214 191
215 void DrawingBuffer::setIsHidden(bool hidden) { 192 void DrawingBuffer::setIsHidden(bool hidden) {
216 if (m_isHidden == hidden) 193 if (m_isHidden == hidden)
217 return; 194 return;
218 m_isHidden = hidden; 195 m_isHidden = hidden;
219 if (m_isHidden) 196 if (m_isHidden)
220 m_recycledMailboxQueue.clear(); 197 m_recycledColorBufferQueue.clear();
221 } 198 }
222 199
223 void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) { 200 void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) {
224 if (m_filterQuality != filterQuality) { 201 if (m_filterQuality != filterQuality) {
225 m_filterQuality = filterQuality; 202 m_filterQuality = filterQuality;
226 if (m_layer) 203 if (m_layer)
227 m_layer->setNearestNeighbor(filterQuality == kNone_SkFilterQuality); 204 m_layer->setNearestNeighbor(filterQuality == kNone_SkFilterQuality);
228 } 205 }
229 } 206 }
230 207
231 bool DrawingBuffer::requiresAlphaChannelToBePreserved() { 208 bool DrawingBuffer::requiresAlphaChannelToBePreserved() {
232 return !m_drawFramebufferBinding && 209 DrawingBufferRestoreState restoreState;
210 m_stateTracker->GetDrawingBufferRestoreState(&restoreState);
211 return !restoreState.drawFramebufferBinding &&
233 defaultBufferRequiresAlphaChannelToBePreserved(); 212 defaultBufferRequiresAlphaChannelToBePreserved();
234 } 213 }
235 214
236 bool DrawingBuffer::defaultBufferRequiresAlphaChannelToBePreserved() { 215 bool DrawingBuffer::defaultBufferRequiresAlphaChannelToBePreserved() {
237 if (wantExplicitResolve()) { 216 if (wantExplicitResolve()) {
238 return !m_wantAlphaChannel && 217 return !m_wantAlphaChannel &&
239 getMultisampledRenderbufferFormat() == GL_RGBA8_OES; 218 getMultisampledRenderbufferFormat() == GL_RGBA8_OES;
240 } 219 }
241 220
242 bool rgbEmulation = 221 bool rgbEmulation =
(...skipping 15 matching lines...) Expand all
258 DCHECK(recycled.size == m_size); 237 DCHECK(recycled.size == m_size);
259 return std::move(recycled.bitmap); 238 return std::move(recycled.bitmap);
260 } 239 }
261 240
262 return Platform::current()->allocateSharedBitmap(m_size); 241 return Platform::current()->allocateSharedBitmap(m_size);
263 } 242 }
264 243
265 bool DrawingBuffer::PrepareTextureMailbox( 244 bool DrawingBuffer::PrepareTextureMailbox(
266 cc::TextureMailbox* outMailbox, 245 cc::TextureMailbox* outMailbox,
267 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) { 246 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
247 ScopedStateRestorer scopedStateRestorer(this);
268 bool forceGpuResult = false; 248 bool forceGpuResult = false;
269 return prepareTextureMailboxInternal(outMailbox, outReleaseCallback, 249 return prepareTextureMailboxInternal(outMailbox, outReleaseCallback,
270 forceGpuResult); 250 forceGpuResult);
271 } 251 }
272 252
273 bool DrawingBuffer::prepareTextureMailboxInternal( 253 bool DrawingBuffer::prepareTextureMailboxInternal(
274 cc::TextureMailbox* outMailbox, 254 cc::TextureMailbox* outMailbox,
275 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback, 255 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback,
276 bool forceGpuResult) { 256 bool forceGpuResult) {
277 if (m_destructionInProgress) { 257 if (m_destructionInProgress) {
(...skipping 14 matching lines...) Expand all
292 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) 272 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
293 return false; 273 return false;
294 274
295 TRACE_EVENT0("blink,rail", "DrawingBuffer::prepareMailbox"); 275 TRACE_EVENT0("blink,rail", "DrawingBuffer::prepareMailbox");
296 276
297 if (m_newMailboxCallback) 277 if (m_newMailboxCallback)
298 (*m_newMailboxCallback)(); 278 (*m_newMailboxCallback)();
299 279
300 // Resolve the multisampled buffer into m_backColorBuffer texture. 280 // Resolve the multisampled buffer into m_backColorBuffer texture.
301 if (m_antiAliasingMode != None) 281 if (m_antiAliasingMode != None)
302 commit(); 282 resolveMultisampleFramebufferInternal();
303 283
304 if (m_softwareRendering && !forceGpuResult) { 284 if (m_softwareRendering && !forceGpuResult) {
305 std::unique_ptr<cc::SharedBitmap> bitmap = createOrRecycleBitmap(); 285 return finishPrepareTextureMailboxSoftware(outMailbox, outReleaseCallback);
306 if (!bitmap) 286 } else {
307 return false; 287 return finishPrepareTextureMailboxGpu(outMailbox, outReleaseCallback);
288 }
289 }
290
291 bool DrawingBuffer::finishPrepareTextureMailboxSoftware(
292 cc::TextureMailbox* outMailbox,
293 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
294 std::unique_ptr<cc::SharedBitmap> bitmap = createOrRecycleBitmap();
295 if (!bitmap)
296 return false;
297
298 // Read the framebuffer into |bitmap|.
299 {
308 unsigned char* pixels = bitmap->pixels(); 300 unsigned char* pixels = bitmap->pixels();
309 DCHECK(pixels); 301 DCHECK(pixels);
310
311 bool needPremultiply = m_wantAlphaChannel && !m_premultipliedAlpha; 302 bool needPremultiply = m_wantAlphaChannel && !m_premultipliedAlpha;
312 WebGLImageConversion::AlphaOp op = 303 WebGLImageConversion::AlphaOp op =
313 needPremultiply ? WebGLImageConversion::AlphaDoPremultiply 304 needPremultiply ? WebGLImageConversion::AlphaDoPremultiply
314 : WebGLImageConversion::AlphaDoNothing; 305 : WebGLImageConversion::AlphaDoNothing;
315 readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSkia, 306 readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSkia,
316 op); 307 op);
317
318 *outMailbox = cc::TextureMailbox(bitmap.get(), m_size);
319
320 // This holds a ref on the DrawingBuffer that will keep it alive until the
321 // mailbox is released (and while the release callback is running). It also
322 // owns the SharedBitmap.
323 auto func = WTF::bind(&DrawingBuffer::softwareMailboxReleased,
324 RefPtr<DrawingBuffer>(this),
325 WTF::passed(std::move(bitmap)), m_size);
326 *outReleaseCallback = cc::SingleReleaseCallback::Create(
327 convertToBaseCallback(std::move(func)));
328 return true;
329 } 308 }
330 309
310 *outMailbox = cc::TextureMailbox(bitmap.get(), m_size);
311
312 // This holds a ref on the DrawingBuffer that will keep it alive until the
313 // mailbox is released (and while the release callback is running). It also
314 // owns the SharedBitmap.
315 auto func = WTF::bind(&DrawingBuffer::mailboxReleasedSoftware,
316 RefPtr<DrawingBuffer>(this),
317 WTF::passed(std::move(bitmap)), m_size);
318 *outReleaseCallback =
319 cc::SingleReleaseCallback::Create(convertToBaseCallback(std::move(func)));
320 return true;
321 }
322
323 bool DrawingBuffer::finishPrepareTextureMailboxGpu(
324 cc::TextureMailbox* outMailbox,
325 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
331 if (m_webGLVersion > WebGL1) { 326 if (m_webGLVersion > WebGL1) {
327 m_stateRestorer->setPixelUnpackBufferBindingDirty();
332 m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 328 m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
333 } 329 }
334 330
335 // We must restore the texture binding since creating new textures, 331 // Specify the buffer that we will put in the mailbox.
336 // consuming and producing mailboxes changes it. 332 RefPtr<ColorBuffer> colorBufferForMailbox;
337 ScopedTextureUnit0BindingRestorer restorer(m_gl, m_activeTextureUnit,
338 m_texture2DBinding);
339
340 // First try to recycle an old buffer.
341 RefPtr<ColorBuffer> colorBufferForMailbox = takeRecycledMailbox();
342
343 // No buffer available to recycle, create a new one.
344 if (!colorBufferForMailbox)
345 colorBufferForMailbox = createTextureAndAllocateMemory(m_size);
346
347 if (m_preserveDrawingBuffer == Discard) { 333 if (m_preserveDrawingBuffer == Discard) {
348 std::swap(colorBufferForMailbox, m_backColorBuffer); 334 // If we can discard the backbuffer, send the old backbuffer directly
335 // into the mailbox, and allocate (or recycle) a new backbuffer.
336 colorBufferForMailbox = m_backColorBuffer;
337 m_backColorBuffer = createOrRecycleColorBuffer();
349 attachColorBufferToReadFramebuffer(); 338 attachColorBufferToReadFramebuffer();
350 339
340 // Explicitly specify that m_fbo (which is now bound to the just-allocated
341 // m_backColorBuffer) is not initialized, to save GPU memory bandwidth for
342 // tile-based GPU architectures.
351 if (m_discardFramebufferSupported) { 343 if (m_discardFramebufferSupported) {
352 // Explicitly discard the framebuffer to save GPU memory bandwidth for
353 // tile-based GPU arch.
354 const GLenum attachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, 344 const GLenum attachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
355 GL_STENCIL_ATTACHMENT}; 345 GL_STENCIL_ATTACHMENT};
346 m_stateRestorer->setFramebufferBindingDirty();
356 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 347 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
357 m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments); 348 m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments);
358 } 349 }
359 } else { 350 } else {
351 // If we can't discard the backbuffer, create (or recycle) a buffer to put
352 // in the mailbox, and copy backbuffer's contents there.
353 colorBufferForMailbox = createOrRecycleColorBuffer();
360 m_gl->CopySubTextureCHROMIUM( 354 m_gl->CopySubTextureCHROMIUM(
361 m_backColorBuffer->textureId, colorBufferForMailbox->textureId, 0, 0, 0, 355 m_backColorBuffer->textureId, colorBufferForMailbox->textureId, 0, 0, 0,
362 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE); 356 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE);
363 } 357 }
364 358
365 restoreFramebufferBindings(); 359 // Put colorBufferForMailbox into its mailbox, and populate its
366 restorePixelUnpackBufferBindings(); 360 // produceSyncToken with that point.
361 {
362 m_gl->ProduceTextureDirectCHROMIUM(colorBufferForMailbox->textureId,
363 colorBufferForMailbox->parameters.target,
364 colorBufferForMailbox->mailbox.name);
365 const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM();
366 #if OS(MACOSX)
367 m_gl->DescheduleUntilFinishedCHROMIUM();
368 #endif
369 m_gl->Flush();
370 m_gl->GenSyncTokenCHROMIUM(
371 fenceSync, colorBufferForMailbox->produceSyncToken.GetData());
372 }
373
374 // Populate the output mailbox and callback.
375 {
376 bool isOverlayCandidate = colorBufferForMailbox->imageId != 0;
377 bool secureOutputOnly = false;
378 *outMailbox = cc::TextureMailbox(
379 colorBufferForMailbox->mailbox, colorBufferForMailbox->produceSyncToken,
380 colorBufferForMailbox->parameters.target, gfx::Size(m_size),
381 isOverlayCandidate, secureOutputOnly);
382
383 // This holds a ref on the DrawingBuffer that will keep it alive until the
384 // mailbox is released (and while the release callback is running).
385 auto func = WTF::bind(&DrawingBuffer::mailboxReleasedGpu,
386 RefPtr<DrawingBuffer>(this), colorBufferForMailbox);
387 *outReleaseCallback = cc::SingleReleaseCallback::Create(
388 convertToBaseCallback(std::move(func)));
389 }
390
391 // Point |m_frontColorBuffer| to the buffer that we are now presenting.
392 m_frontColorBuffer = colorBufferForMailbox;
393
367 m_contentsChanged = false; 394 m_contentsChanged = false;
368
369 m_gl->ProduceTextureDirectCHROMIUM(colorBufferForMailbox->textureId,
370 colorBufferForMailbox->parameters.target,
371 colorBufferForMailbox->mailbox.name);
372 const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM();
373 #if OS(MACOSX)
374 m_gl->DescheduleUntilFinishedCHROMIUM();
375 #endif
376 m_gl->Flush();
377 gpu::SyncToken syncToken;
378 m_gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData());
379
380 bool isOverlayCandidate = colorBufferForMailbox->imageId != 0;
381 bool secureOutputOnly = false;
382 *outMailbox = cc::TextureMailbox(colorBufferForMailbox->mailbox, syncToken,
383 colorBufferForMailbox->parameters.target,
384 gfx::Size(m_size.width(), m_size.height()),
385 isOverlayCandidate, secureOutputOnly);
386
387 // This holds a ref on the DrawingBuffer that will keep it alive until the
388 // mailbox is released (and while the release callback is running).
389 auto func = WTF::bind(&DrawingBuffer::gpuMailboxReleased,
390 RefPtr<DrawingBuffer>(this), colorBufferForMailbox);
391 *outReleaseCallback =
392 cc::SingleReleaseCallback::Create(convertToBaseCallback(std::move(func)));
393
394 // Point |m_frontColorBuffer| to the buffer that we are presenting, and
395 // update its sync token.
396 colorBufferForMailbox->produceSyncToken = syncToken;
397 m_frontColorBuffer = colorBufferForMailbox;
398 setBufferClearNeeded(true); 395 setBufferClearNeeded(true);
399 return true; 396 return true;
400 } 397 }
401 398
402 void DrawingBuffer::gpuMailboxReleased(RefPtr<ColorBuffer> colorBuffer, 399 void DrawingBuffer::mailboxReleasedGpu(RefPtr<ColorBuffer> colorBuffer,
403 const gpu::SyncToken& syncToken, 400 const gpu::SyncToken& syncToken,
404 bool lostResource) { 401 bool lostResource) {
405 // If the mailbox has been returned by the compositor then it is no 402 // If the mailbox has been returned by the compositor then it is no
406 // longer being presented, and so is no longer the front buffer. 403 // longer being presented, and so is no longer the front buffer.
407 if (colorBuffer == m_frontColorBuffer) 404 if (colorBuffer == m_frontColorBuffer)
408 m_frontColorBuffer = nullptr; 405 m_frontColorBuffer = nullptr;
409 406
410 // Update the SyncToken to ensure that we will wait for it even if we 407 // Update the SyncToken to ensure that we will wait for it even if we
411 // immediately destroy this buffer. 408 // immediately destroy this buffer.
412 colorBuffer->receiveSyncToken = syncToken; 409 colorBuffer->receiveSyncToken = syncToken;
413 410
414 if (m_destructionInProgress || colorBuffer->size != m_size || 411 if (m_destructionInProgress || colorBuffer->size != m_size ||
415 m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR || lostResource || 412 m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR || lostResource ||
416 m_isHidden) { 413 m_isHidden) {
417 return; 414 return;
418 } 415 }
419 416
420 // Creation of image backed mailboxes is very expensive, so be less 417 // Creation of image backed mailboxes is very expensive, so be less
421 // aggressive about pruning them. Pruning is done in FIFO order. 418 // aggressive about pruning them. Pruning is done in FIFO order.
422 size_t cacheLimit = 1; 419 size_t cacheLimit = 1;
423 if (shouldUseChromiumImage()) 420 if (shouldUseChromiumImage())
424 cacheLimit = 4; 421 cacheLimit = 4;
425 while (m_recycledMailboxQueue.size() >= cacheLimit) 422 while (m_recycledColorBufferQueue.size() >= cacheLimit)
426 m_recycledMailboxQueue.takeLast(); 423 m_recycledColorBufferQueue.takeLast();
427 424
428 m_recycledMailboxQueue.prepend(colorBuffer); 425 m_recycledColorBufferQueue.prepend(colorBuffer);
429 } 426 }
430 427
431 void DrawingBuffer::softwareMailboxReleased( 428 void DrawingBuffer::mailboxReleasedSoftware(
432 std::unique_ptr<cc::SharedBitmap> bitmap, 429 std::unique_ptr<cc::SharedBitmap> bitmap,
433 const IntSize& size, 430 const IntSize& size,
434 const gpu::SyncToken& syncToken, 431 const gpu::SyncToken& syncToken,
435 bool lostResource) { 432 bool lostResource) {
436 DCHECK(!syncToken.HasData()); // No sync tokens for software resources. 433 DCHECK(!syncToken.HasData()); // No sync tokens for software resources.
437 if (m_destructionInProgress || lostResource || m_isHidden || size != m_size) 434 if (m_destructionInProgress || lostResource || m_isHidden || size != m_size)
438 return; // Just delete the bitmap. 435 return; // Just delete the bitmap.
439 436
440 RecycledBitmap recycled = {std::move(bitmap), m_size}; 437 RecycledBitmap recycled = {std::move(bitmap), m_size};
441 m_recycledBitmaps.append(std::move(recycled)); 438 m_recycledBitmaps.append(std::move(recycled));
442 } 439 }
443 440
444 PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() { 441 PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() {
442 ScopedStateRestorer scopedStateRestorer(this);
443
445 // This can be null if the context is lost before the first call to 444 // This can be null if the context is lost before the first call to
446 // grContext(). 445 // grContext().
447 GrContext* grContext = m_contextProvider->grContext(); 446 GrContext* grContext = m_contextProvider->grContext();
448 447
449 cc::TextureMailbox textureMailbox; 448 cc::TextureMailbox textureMailbox;
450 std::unique_ptr<cc::SingleReleaseCallback> releaseCallback; 449 std::unique_ptr<cc::SingleReleaseCallback> releaseCallback;
451 bool success = false; 450 bool success = false;
452 if (grContext) { 451 if (grContext) {
453 bool forceGpuResult = true; 452 bool forceGpuResult = true;
454 success = prepareTextureMailboxInternal(&textureMailbox, &releaseCallback, 453 success = prepareTextureMailboxInternal(&textureMailbox, &releaseCallback,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 // DrawingBuffer's context anyways. 506 // DrawingBuffer's context anyways.
508 const auto& skImageSyncToken = textureMailbox.sync_token(); 507 const auto& skImageSyncToken = textureMailbox.sync_token();
509 508
510 // TODO(xidachen): Create a small pool of recycled textures from 509 // TODO(xidachen): Create a small pool of recycled textures from
511 // ImageBitmapRenderingContext's transferFromImageBitmap, and try to use them 510 // ImageBitmapRenderingContext's transferFromImageBitmap, and try to use them
512 // in DrawingBuffer. 511 // in DrawingBuffer.
513 return AcceleratedStaticBitmapImage::createFromWebGLContextImage( 512 return AcceleratedStaticBitmapImage::createFromWebGLContextImage(
514 std::move(skImage), skImageMailbox, skImageSyncToken); 513 std::move(skImage), skImageMailbox, skImageSyncToken);
515 } 514 }
516 515
517 DrawingBuffer::TextureParameters 516 DrawingBuffer::ColorBufferParameters
518 DrawingBuffer::chromiumImageTextureParameters() { 517 DrawingBuffer::gpuMemoryBufferColorBufferParameters() {
519 #if OS(MACOSX) 518 #if OS(MACOSX)
520 // A CHROMIUM_image backed texture requires a specialized set of parameters 519 // A CHROMIUM_image backed texture requires a specialized set of parameters
521 // on OSX. 520 // on OSX.
522 TextureParameters parameters; 521 ColorBufferParameters parameters;
523 parameters.target = GC3D_TEXTURE_RECTANGLE_ARB; 522 parameters.target = GC3D_TEXTURE_RECTANGLE_ARB;
524 523
525 if (m_wantAlphaChannel) { 524 if (m_wantAlphaChannel) {
526 parameters.creationInternalColorFormat = GL_RGBA; 525 parameters.creationInternalColorFormat = GL_RGBA;
527 parameters.internalColorFormat = GL_RGBA; 526 parameters.internalColorFormat = GL_RGBA;
528 } else if (contextProvider() 527 } else if (contextProvider()
529 ->getCapabilities() 528 ->getCapabilities()
530 .chromium_image_rgb_emulation) { 529 .chromium_image_rgb_emulation) {
531 parameters.creationInternalColorFormat = GL_RGB; 530 parameters.creationInternalColorFormat = GL_RGB;
532 parameters.internalColorFormat = GL_RGBA; 531 parameters.internalColorFormat = GL_RGBA;
533 } else { 532 } else {
534 GLenum format = 533 GLenum format =
535 defaultBufferRequiresAlphaChannelToBePreserved() ? GL_RGBA : GL_RGB; 534 defaultBufferRequiresAlphaChannelToBePreserved() ? GL_RGBA : GL_RGB;
536 parameters.creationInternalColorFormat = format; 535 parameters.creationInternalColorFormat = format;
537 parameters.internalColorFormat = format; 536 parameters.internalColorFormat = format;
538 } 537 }
539 538
540 // Unused when CHROMIUM_image is being used. 539 // Unused when CHROMIUM_image is being used.
541 parameters.colorFormat = 0; 540 parameters.colorFormat = 0;
542 return parameters; 541 return parameters;
543 #else 542 #else
544 return defaultTextureParameters(); 543 return textureColorBufferParameters();
545 #endif 544 #endif
546 } 545 }
547 546
548 DrawingBuffer::TextureParameters DrawingBuffer::defaultTextureParameters() { 547 DrawingBuffer::ColorBufferParameters
549 TextureParameters parameters; 548 DrawingBuffer::textureColorBufferParameters() {
549 ColorBufferParameters parameters;
550 parameters.target = GL_TEXTURE_2D; 550 parameters.target = GL_TEXTURE_2D;
551 if (m_wantAlphaChannel) { 551 if (m_wantAlphaChannel) {
552 parameters.internalColorFormat = GL_RGBA; 552 parameters.internalColorFormat = GL_RGBA;
553 parameters.creationInternalColorFormat = GL_RGBA; 553 parameters.creationInternalColorFormat = GL_RGBA;
554 parameters.colorFormat = GL_RGBA; 554 parameters.colorFormat = GL_RGBA;
555 } else if (contextProvider() 555 } else if (contextProvider()
556 ->getCapabilities() 556 ->getCapabilities()
557 .emulate_rgb_buffer_with_rgba) { 557 .emulate_rgb_buffer_with_rgba) {
558 parameters.internalColorFormat = GL_RGBA; 558 parameters.internalColorFormat = GL_RGBA;
559 parameters.creationInternalColorFormat = GL_RGBA; 559 parameters.creationInternalColorFormat = GL_RGBA;
560 parameters.colorFormat = GL_RGBA; 560 parameters.colorFormat = GL_RGBA;
561 } else { 561 } else {
562 GLenum format = 562 GLenum format =
563 defaultBufferRequiresAlphaChannelToBePreserved() ? GL_RGBA : GL_RGB; 563 defaultBufferRequiresAlphaChannelToBePreserved() ? GL_RGBA : GL_RGB;
564 parameters.creationInternalColorFormat = format; 564 parameters.creationInternalColorFormat = format;
565 parameters.internalColorFormat = format; 565 parameters.internalColorFormat = format;
566 parameters.colorFormat = format; 566 parameters.colorFormat = format;
567 } 567 }
568 return parameters; 568 return parameters;
569 } 569 }
570 570
571 PassRefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::takeRecycledMailbox() { 571 PassRefPtr<DrawingBuffer::ColorBuffer>
572 if (m_recycledMailboxQueue.isEmpty()) 572 DrawingBuffer::createOrRecycleColorBuffer() {
573 return nullptr; 573 if (!m_recycledColorBufferQueue.isEmpty()) {
574 574 RefPtr<ColorBuffer> recycled = m_recycledColorBufferQueue.takeLast();
575 RefPtr<ColorBuffer> recycled = m_recycledMailboxQueue.takeLast(); 575 if (recycled->receiveSyncToken.HasData())
576 DCHECK(recycled->size == m_size); 576 m_gl->WaitSyncTokenCHROMIUM(recycled->receiveSyncToken.GetData());
577 if (recycled->receiveSyncToken.HasData()) 577 DCHECK(recycled->size == m_size);
578 m_gl->WaitSyncTokenCHROMIUM(recycled->receiveSyncToken.GetData()); 578 return recycled;
579 return recycled; 579 }
580 return createColorBuffer(m_size);
580 } 581 }
581 582
582 DrawingBuffer::ColorBuffer::ColorBuffer(DrawingBuffer* drawingBuffer, 583 DrawingBuffer::ColorBuffer::ColorBuffer(DrawingBuffer* drawingBuffer,
583 const TextureParameters& parameters, 584 const ColorBufferParameters& parameters,
584 const IntSize& size) 585 const IntSize& size,
585 : drawingBuffer(drawingBuffer), parameters(parameters), size(size) { 586 GLuint textureId,
587 GLuint imageId)
588 : drawingBuffer(drawingBuffer),
589 parameters(parameters),
590 size(size),
591 textureId(textureId),
592 imageId(imageId) {
586 drawingBuffer->contextGL()->GenMailboxCHROMIUM(mailbox.name); 593 drawingBuffer->contextGL()->GenMailboxCHROMIUM(mailbox.name);
587 } 594 }
588 595
589 DrawingBuffer::ColorBuffer::~ColorBuffer() { 596 DrawingBuffer::ColorBuffer::~ColorBuffer() {
590 gpu::gles2::GLES2Interface* gl = drawingBuffer->contextGL(); 597 gpu::gles2::GLES2Interface* gl = drawingBuffer->m_gl;
591 if (receiveSyncToken.HasData()) 598 if (receiveSyncToken.HasData())
592 gl->WaitSyncTokenCHROMIUM(receiveSyncToken.GetConstData()); 599 gl->WaitSyncTokenCHROMIUM(receiveSyncToken.GetConstData());
593 if (imageId) { 600 if (imageId) {
594 gl->BindTexture(parameters.target, textureId); 601 gl->BindTexture(parameters.target, textureId);
595 gl->ReleaseTexImage2DCHROMIUM(parameters.target, imageId); 602 gl->ReleaseTexImage2DCHROMIUM(parameters.target, imageId);
596 gl->DestroyImageCHROMIUM(imageId); 603 gl->DestroyImageCHROMIUM(imageId);
604 switch (parameters.target) {
605 case GL_TEXTURE_2D:
606 // Restore the texture binding for GL_TEXTURE_2D, since the client will
607 // expect the previous state.
608 if (drawingBuffer->m_stateTracker) {
609 DrawingBufferRestoreState restoreState;
610 drawingBuffer->m_stateTracker->GetDrawingBufferRestoreState(
611 &restoreState);
612 gl->BindTexture(GL_TEXTURE_2D, restoreState.activeTexture2DBinding);
613 }
614 break;
615 case GC3D_TEXTURE_RECTANGLE_ARB:
616 // Rectangle textures aren't exposed to WebGL, so don't bother
617 // restoring this state (there is no meaningful way to restore it).
618 break;
619 default:
620 NOTREACHED();
621 break;
622 }
597 } 623 }
598 gl->DeleteTextures(1, &textureId); 624 gl->DeleteTextures(1, &textureId);
599 } 625 }
600 626
601 bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) { 627 bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
628 ScopedStateRestorer scopedStateRestorer(this);
629
602 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { 630 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
603 // Need to try to restore the context again later. 631 // Need to try to restore the context again later.
604 return false; 632 return false;
605 } 633 }
606 634
607 m_gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); 635 m_gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
608 636
609 int maxSampleCount = 0; 637 int maxSampleCount = 0;
610 m_antiAliasingMode = None; 638 m_antiAliasingMode = None;
611 if (useMultisampling) { 639 if (useMultisampling) {
(...skipping 11 matching lines...) Expand all
623 // The Linux ATI bot fails 651 // The Linux ATI bot fails
624 // WebglConformance.conformance_textures_misc_tex_image_webgl, so use storage 652 // WebglConformance.conformance_textures_misc_tex_image_webgl, so use storage
625 // textures only if ScreenSpaceAntialiasing is enabled, because 653 // textures only if ScreenSpaceAntialiasing is enabled, because
626 // ScreenSpaceAntialiasing is much faster with storage textures. 654 // ScreenSpaceAntialiasing is much faster with storage textures.
627 m_storageTextureSupported = 655 m_storageTextureSupported =
628 (m_webGLVersion > WebGL1 || 656 (m_webGLVersion > WebGL1 ||
629 m_extensionsUtil->supportsExtension("GL_EXT_texture_storage")) && 657 m_extensionsUtil->supportsExtension("GL_EXT_texture_storage")) &&
630 m_antiAliasingMode == ScreenSpaceAntialiasing; 658 m_antiAliasingMode == ScreenSpaceAntialiasing;
631 m_sampleCount = std::min(4, maxSampleCount); 659 m_sampleCount = std::min(4, maxSampleCount);
632 660
661 m_stateRestorer->setFramebufferBindingDirty();
633 m_gl->GenFramebuffers(1, &m_fbo); 662 m_gl->GenFramebuffers(1, &m_fbo);
634 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 663 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
635 if (wantExplicitResolve()) { 664 if (wantExplicitResolve()) {
636 m_gl->GenFramebuffers(1, &m_multisampleFBO); 665 m_gl->GenFramebuffers(1, &m_multisampleFBO);
637 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 666 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
638 m_gl->GenRenderbuffers(1, &m_multisampleRenderbuffer); 667 m_gl->GenRenderbuffers(1, &m_multisampleRenderbuffer);
639 } 668 }
640 if (!reset(size)) 669 if (!resizeFramebufferInternal(size))
641 return false; 670 return false;
642 671
643 if (m_depthStencilBuffer) { 672 if (m_depthStencilBuffer) {
644 DCHECK(wantDepthOrStencil()); 673 DCHECK(wantDepthOrStencil());
645 m_hasImplicitStencilBuffer = !m_wantStencil; 674 m_hasImplicitStencilBuffer = !m_wantStencil;
646 } 675 }
647 676
648 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { 677 if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
649 // It's possible that the drawing buffer allocation provokes a context loss, 678 // It's possible that the drawing buffer allocation provokes a context loss,
650 // so check again just in case. http://crbug.com/512302 679 // so check again just in case. http://crbug.com/512302
651 return false; 680 return false;
652 } 681 }
653 682
654 return true; 683 return true;
655 } 684 }
656 685
657 bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl, 686 bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl,
658 GLuint texture, 687 GLuint texture,
659 GLenum internalFormat, 688 GLenum internalFormat,
660 GLenum destType, 689 GLenum destType,
661 GLint level, 690 GLint level,
662 bool premultiplyAlpha, 691 bool premultiplyAlpha,
663 bool flipY, 692 bool flipY,
664 SourceDrawingBuffer sourceBuffer) { 693 SourceDrawingBuffer sourceBuffer) {
694 ScopedStateRestorer scopedStateRestorer(this);
695
665 if (m_contentsChanged) { 696 if (m_contentsChanged) {
666 if (m_antiAliasingMode != None) { 697 if (m_antiAliasingMode != None)
667 commit(); 698 resolveMultisampleFramebufferInternal();
668 restoreFramebufferBindings();
669 }
670 m_gl->Flush(); 699 m_gl->Flush();
671 } 700 }
672 701
673 // Assume that the destination target is GL_TEXTURE_2D. 702 // Assume that the destination target is GL_TEXTURE_2D.
674 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM( 703 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(
675 GL_TEXTURE_2D, internalFormat, destType, level)) 704 GL_TEXTURE_2D, internalFormat, destType, level))
676 return false; 705 return false;
677 706
678 // Contexts may be in a different share group. We must transfer the texture 707 // Contexts may be in a different share group. We must transfer the texture
679 // through a mailbox first. 708 // through a mailbox first.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM(); 744 const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM();
716 745
717 gl->Flush(); 746 gl->Flush();
718 gpu::SyncToken syncToken; 747 gpu::SyncToken syncToken;
719 gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData()); 748 gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData());
720 m_gl->WaitSyncTokenCHROMIUM(syncToken.GetData()); 749 m_gl->WaitSyncTokenCHROMIUM(syncToken.GetData());
721 750
722 return true; 751 return true;
723 } 752 }
724 753
725 GLuint DrawingBuffer::framebuffer() const {
726 return m_fbo;
727 }
728
729 WebLayer* DrawingBuffer::platformLayer() { 754 WebLayer* DrawingBuffer::platformLayer() {
730 if (!m_layer) { 755 if (!m_layer) {
731 m_layer = wrapUnique( 756 m_layer = wrapUnique(
732 Platform::current()->compositorSupport()->createExternalTextureLayer( 757 Platform::current()->compositorSupport()->createExternalTextureLayer(
733 this)); 758 this));
734 759
735 m_layer->setOpaque(!m_wantAlphaChannel); 760 m_layer->setOpaque(!m_wantAlphaChannel);
736 m_layer->setBlendBackgroundColor(m_wantAlphaChannel); 761 m_layer->setBlendBackgroundColor(m_wantAlphaChannel);
737 m_layer->setPremultipliedAlpha(m_premultipliedAlpha); 762 m_layer->setPremultipliedAlpha(m_premultipliedAlpha);
738 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality); 763 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
739 GraphicsLayer::registerContentsLayer(m_layer->layer()); 764 GraphicsLayer::registerContentsLayer(m_layer->layer());
740 } 765 }
741 766
742 return m_layer->layer(); 767 return m_layer->layer();
743 } 768 }
744 769
745 void DrawingBuffer::clearPlatformLayer() { 770 void DrawingBuffer::clearPlatformLayer() {
746 if (m_layer) 771 if (m_layer)
747 m_layer->clearTexture(); 772 m_layer->clearTexture();
748 773
749 m_gl->Flush(); 774 m_gl->Flush();
750 } 775 }
751 776
752 void DrawingBuffer::beginDestruction() { 777 void DrawingBuffer::beginDestruction() {
753 ASSERT(!m_destructionInProgress); 778 ASSERT(!m_destructionInProgress);
754 m_destructionInProgress = true; 779 m_destructionInProgress = true;
755 780
756 clearPlatformLayer(); 781 clearPlatformLayer();
757 m_recycledMailboxQueue.clear(); 782 m_recycledColorBufferQueue.clear();
758 783
759 if (m_multisampleFBO) 784 if (m_multisampleFBO)
760 m_gl->DeleteFramebuffers(1, &m_multisampleFBO); 785 m_gl->DeleteFramebuffers(1, &m_multisampleFBO);
761 786
762 if (m_fbo) 787 if (m_fbo)
763 m_gl->DeleteFramebuffers(1, &m_fbo); 788 m_gl->DeleteFramebuffers(1, &m_fbo);
764 789
765 if (m_multisampleRenderbuffer) 790 if (m_multisampleRenderbuffer)
766 m_gl->DeleteRenderbuffers(1, &m_multisampleRenderbuffer); 791 m_gl->DeleteRenderbuffers(1, &m_multisampleRenderbuffer);
767 792
768 if (m_depthStencilBuffer) 793 if (m_depthStencilBuffer)
769 m_gl->DeleteRenderbuffers(1, &m_depthStencilBuffer); 794 m_gl->DeleteRenderbuffers(1, &m_depthStencilBuffer);
770 795
771 m_size = IntSize(); 796 m_size = IntSize();
772 797
773 m_backColorBuffer = nullptr; 798 m_backColorBuffer = nullptr;
774 m_frontColorBuffer = nullptr; 799 m_frontColorBuffer = nullptr;
775 m_multisampleRenderbuffer = 0; 800 m_multisampleRenderbuffer = 0;
776 m_depthStencilBuffer = 0; 801 m_depthStencilBuffer = 0;
777 m_multisampleFBO = 0; 802 m_multisampleFBO = 0;
778 m_fbo = 0; 803 m_fbo = 0;
779 804
780 if (m_layer) 805 if (m_layer)
781 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); 806 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
782 }
783 807
784 GLuint DrawingBuffer::createColorTexture(const TextureParameters& parameters) { 808 m_stateTracker = nullptr;
785 GLuint offscreenColorTexture;
786 m_gl->GenTextures(1, &offscreenColorTexture);
787 m_gl->BindTexture(parameters.target, offscreenColorTexture);
788 m_gl->TexParameteri(parameters.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
789 m_gl->TexParameteri(parameters.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
790 m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
791 m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
792 return offscreenColorTexture;
793 } 809 }
794 810
795 bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) { 811 bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
796 // Recreate m_backColorBuffer. 812 // Recreate m_backColorBuffer.
797 m_backColorBuffer = createTextureAndAllocateMemory(size); 813 m_backColorBuffer = createColorBuffer(size);
798 814
799 attachColorBufferToReadFramebuffer(); 815 attachColorBufferToReadFramebuffer();
800 816
801 if (wantExplicitResolve()) { 817 if (wantExplicitResolve()) {
818 m_stateRestorer->setFramebufferBindingDirty();
819 m_stateRestorer->setRenderbufferBindingDirty();
802 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 820 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
803 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_multisampleRenderbuffer); 821 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_multisampleRenderbuffer);
804 m_gl->RenderbufferStorageMultisampleCHROMIUM( 822 m_gl->RenderbufferStorageMultisampleCHROMIUM(
805 GL_RENDERBUFFER, m_sampleCount, getMultisampledRenderbufferFormat(), 823 GL_RENDERBUFFER, m_sampleCount, getMultisampledRenderbufferFormat(),
806 size.width(), size.height()); 824 size.width(), size.height());
807 825
808 if (m_gl->GetError() == GL_OUT_OF_MEMORY) 826 if (m_gl->GetError() == GL_OUT_OF_MEMORY)
809 return false; 827 return false;
810 828
811 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 829 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
812 GL_RENDERBUFFER, m_multisampleRenderbuffer); 830 GL_RENDERBUFFER, m_multisampleRenderbuffer);
813 } 831 }
814 832
815 if (wantDepthOrStencil()) { 833 if (wantDepthOrStencil()) {
834 m_stateRestorer->setFramebufferBindingDirty();
835 m_stateRestorer->setRenderbufferBindingDirty();
816 m_gl->BindFramebuffer(GL_FRAMEBUFFER, 836 m_gl->BindFramebuffer(GL_FRAMEBUFFER,
817 m_multisampleFBO ? m_multisampleFBO : m_fbo); 837 m_multisampleFBO ? m_multisampleFBO : m_fbo);
818 if (!m_depthStencilBuffer) 838 if (!m_depthStencilBuffer)
819 m_gl->GenRenderbuffers(1, &m_depthStencilBuffer); 839 m_gl->GenRenderbuffers(1, &m_depthStencilBuffer);
820 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); 840 m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
821 if (m_antiAliasingMode == MSAAImplicitResolve) { 841 if (m_antiAliasingMode == MSAAImplicitResolve) {
822 m_gl->RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, 842 m_gl->RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount,
823 GL_DEPTH24_STENCIL8_OES, 843 GL_DEPTH24_STENCIL8_OES,
824 size.width(), size.height()); 844 size.width(), size.height());
825 } else if (m_antiAliasingMode == MSAAExplicitResolve) { 845 } else if (m_antiAliasingMode == MSAAExplicitResolve) {
826 m_gl->RenderbufferStorageMultisampleCHROMIUM( 846 m_gl->RenderbufferStorageMultisampleCHROMIUM(
827 GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), 847 GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(),
828 size.height()); 848 size.height());
829 } else { 849 } else {
830 m_gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, 850 m_gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
831 size.width(), size.height()); 851 size.width(), size.height());
832 } 852 }
833 // For ES 2.0 contexts DEPTH_STENCIL is not available natively, so we 853 // For ES 2.0 contexts DEPTH_STENCIL is not available natively, so we
834 // emulate 854 // emulate
835 // it at the command buffer level for WebGL contexts. 855 // it at the command buffer level for WebGL contexts.
836 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 856 m_gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
837 GL_RENDERBUFFER, m_depthStencilBuffer); 857 GL_RENDERBUFFER, m_depthStencilBuffer);
838 m_gl->BindRenderbuffer(GL_RENDERBUFFER, 0); 858 m_gl->BindRenderbuffer(GL_RENDERBUFFER, 0);
839 } 859 }
840 860
841 if (wantExplicitResolve()) { 861 if (wantExplicitResolve()) {
862 m_stateRestorer->setFramebufferBindingDirty();
842 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 863 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
843 if (m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 864 if (m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
844 return false; 865 return false;
845 } 866 }
846 867
868 m_stateRestorer->setFramebufferBindingDirty();
847 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 869 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
848 return m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) == 870 return m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
849 GL_FRAMEBUFFER_COMPLETE; 871 GL_FRAMEBUFFER_COMPLETE;
850 } 872 }
851 873
852 void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) { 874 void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) {
875 ScopedStateRestorer scopedStateRestorer(this);
876 clearFramebuffersInternal(clearMask);
877 }
878
879 void DrawingBuffer::clearFramebuffersInternal(GLbitfield clearMask) {
880 m_stateRestorer->setFramebufferBindingDirty();
853 // We will clear the multisample FBO, but we also need to clear the 881 // We will clear the multisample FBO, but we also need to clear the
854 // non-multisampled buffer. 882 // non-multisampled buffer.
855 if (m_multisampleFBO) { 883 if (m_multisampleFBO) {
856 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 884 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
857 m_gl->Clear(GL_COLOR_BUFFER_BIT); 885 m_gl->Clear(GL_COLOR_BUFFER_BIT);
858 } 886 }
859 887
860 m_gl->BindFramebuffer(GL_FRAMEBUFFER, 888 m_gl->BindFramebuffer(GL_FRAMEBUFFER,
861 m_multisampleFBO ? m_multisampleFBO : m_fbo); 889 m_multisampleFBO ? m_multisampleFBO : m_fbo);
862 m_gl->Clear(clearMask); 890 m_gl->Clear(clearMask);
863 } 891 }
864 892
865 IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize, 893 IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize,
866 const IntSize& curSize, 894 const IntSize& curSize,
867 int maxTextureSize) { 895 int maxTextureSize) {
868 IntSize adjustedSize = desiredSize; 896 IntSize adjustedSize = desiredSize;
869 897
870 // Clamp if the desired size is greater than the maximum texture size for the 898 // Clamp if the desired size is greater than the maximum texture size for the
871 // device. 899 // device.
872 if (adjustedSize.height() > maxTextureSize) 900 if (adjustedSize.height() > maxTextureSize)
873 adjustedSize.setHeight(maxTextureSize); 901 adjustedSize.setHeight(maxTextureSize);
874 902
875 if (adjustedSize.width() > maxTextureSize) 903 if (adjustedSize.width() > maxTextureSize)
876 adjustedSize.setWidth(maxTextureSize); 904 adjustedSize.setWidth(maxTextureSize);
877 905
878 return adjustedSize; 906 return adjustedSize;
879 } 907 }
880 908
881 bool DrawingBuffer::reset(const IntSize& newSize) { 909 bool DrawingBuffer::resize(const IntSize& newSize) {
910 ScopedStateRestorer scopedStateRestorer(this);
911 return resizeFramebufferInternal(newSize);
912 }
913
914 bool DrawingBuffer::resizeFramebufferInternal(const IntSize& newSize) {
882 CHECK(!newSize.isEmpty()); 915 CHECK(!newSize.isEmpty());
883 IntSize adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize); 916 IntSize adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize);
884 if (adjustedSize.isEmpty()) 917 if (adjustedSize.isEmpty())
885 return false; 918 return false;
886 919
887 if (adjustedSize != m_size) { 920 if (adjustedSize != m_size) {
888 do { 921 do {
889 if (!resizeDefaultFramebuffer(adjustedSize)) { 922 if (!resizeDefaultFramebuffer(adjustedSize)) {
890 adjustedSize.scale(s_resourceAdjustedRatio); 923 adjustedSize.scale(s_resourceAdjustedRatio);
891 continue; 924 continue;
892 } 925 }
893 break; 926 break;
894 } while (!adjustedSize.isEmpty()); 927 } while (!adjustedSize.isEmpty());
895 928
896 m_size = adjustedSize; 929 m_size = adjustedSize;
897 // Free all mailboxes, because they are now of the wrong size. Only the 930 // Free all mailboxes, because they are now of the wrong size. Only the
898 // first call in this loop has any effect. 931 // first call in this loop has any effect.
899 m_recycledMailboxQueue.clear(); 932 m_recycledColorBufferQueue.clear();
900 m_recycledBitmaps.clear(); 933 m_recycledBitmaps.clear();
901 934
902 if (adjustedSize.isEmpty()) 935 if (adjustedSize.isEmpty())
903 return false; 936 return false;
904 } 937 }
905 938
939 m_stateRestorer->setClearStateDirty();
906 m_gl->Disable(GL_SCISSOR_TEST); 940 m_gl->Disable(GL_SCISSOR_TEST);
907 m_gl->ClearColor(0, 0, 0, 941 m_gl->ClearColor(0, 0, 0,
908 defaultBufferRequiresAlphaChannelToBePreserved() ? 1 : 0); 942 defaultBufferRequiresAlphaChannelToBePreserved() ? 1 : 0);
909 m_gl->ColorMask(true, true, true, true); 943 m_gl->ColorMask(true, true, true, true);
910 944
911 GLbitfield clearMask = GL_COLOR_BUFFER_BIT; 945 GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
912 if (!!m_depthStencilBuffer) { 946 if (!!m_depthStencilBuffer) {
913 m_gl->ClearDepthf(1.0f); 947 m_gl->ClearDepthf(1.0f);
914 clearMask |= GL_DEPTH_BUFFER_BIT; 948 clearMask |= GL_DEPTH_BUFFER_BIT;
915 m_gl->DepthMask(true); 949 m_gl->DepthMask(true);
916 } 950 }
917 if (!!m_depthStencilBuffer) { 951 if (!!m_depthStencilBuffer) {
918 m_gl->ClearStencil(0); 952 m_gl->ClearStencil(0);
919 clearMask |= GL_STENCIL_BUFFER_BIT; 953 clearMask |= GL_STENCIL_BUFFER_BIT;
920 m_gl->StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF); 954 m_gl->StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
921 } 955 }
922 956
923 clearFramebuffers(clearMask); 957 clearFramebuffersInternal(clearMask);
924 return true; 958 return true;
925 } 959 }
926 960
927 void DrawingBuffer::commit() { 961 void DrawingBuffer::resolveAndBindForReadAndDraw() {
962 {
963 ScopedStateRestorer scopedStateRestorer(this);
964 resolveMultisampleFramebufferInternal();
965 }
966 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
967 }
968
969 void DrawingBuffer::resolveMultisampleFramebufferInternal() {
970 m_stateRestorer->setFramebufferBindingDirty();
928 if (wantExplicitResolve() && !m_contentsChangeCommitted) { 971 if (wantExplicitResolve() && !m_contentsChangeCommitted) {
972 m_stateRestorer->setClearStateDirty();
929 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO); 973 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO);
930 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo); 974 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo);
931 975 m_gl->Disable(GL_SCISSOR_TEST);
932 if (m_scissorEnabled)
933 m_gl->Disable(GL_SCISSOR_TEST);
934 976
935 int width = m_size.width(); 977 int width = m_size.width();
936 int height = m_size.height(); 978 int height = m_size.height();
937 // Use NEAREST, because there is no scale performed during the blit. 979 // Use NEAREST, because there is no scale performed during the blit.
938 GLuint filter = GL_NEAREST; 980 GLuint filter = GL_NEAREST;
939 981
940 m_gl->BlitFramebufferCHROMIUM(0, 0, width, height, 0, 0, width, height, 982 m_gl->BlitFramebufferCHROMIUM(0, 0, width, height, 0, 0, width, height,
941 GL_COLOR_BUFFER_BIT, filter); 983 GL_COLOR_BUFFER_BIT, filter);
942 984
943 // On old AMD GPUs on OS X, glColorMask doesn't work correctly for 985 // On old AMD GPUs on OS X, glColorMask doesn't work correctly for
944 // multisampled renderbuffers and the alpha channel can be overwritten. 986 // multisampled renderbuffers and the alpha channel can be overwritten.
945 // Clear the alpha channel of |m_fbo|. 987 // Clear the alpha channel of |m_fbo|.
946 if (defaultBufferRequiresAlphaChannelToBePreserved() && 988 if (defaultBufferRequiresAlphaChannelToBePreserved() &&
947 contextProvider() 989 contextProvider()
948 ->getCapabilities() 990 ->getCapabilities()
949 .disable_multisampling_color_mask_usage) { 991 .disable_multisampling_color_mask_usage) {
950 m_gl->ClearColor(0, 0, 0, 1); 992 m_gl->ClearColor(0, 0, 0, 1);
951 m_gl->ColorMask(false, false, false, true); 993 m_gl->ColorMask(false, false, false, true);
952 m_gl->Clear(GL_COLOR_BUFFER_BIT);
953
954 m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
955 m_clearColor[3]);
956 m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
957 m_colorMask[3]);
958 } 994 }
959
960 if (m_scissorEnabled)
961 m_gl->Enable(GL_SCISSOR_TEST);
962 } 995 }
963 996
964 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 997 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
965 if (m_antiAliasingMode == ScreenSpaceAntialiasing) { 998 if (m_antiAliasingMode == ScreenSpaceAntialiasing)
966 m_gl->ApplyScreenSpaceAntialiasingCHROMIUM(); 999 m_gl->ApplyScreenSpaceAntialiasingCHROMIUM();
967 }
968 m_contentsChangeCommitted = true; 1000 m_contentsChangeCommitted = true;
969 } 1001 }
970 1002
971 void DrawingBuffer::restorePixelUnpackBufferBindings() {
972 if (m_webGLVersion > WebGL1) {
973 m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixelUnpackBufferBinding);
974 }
975 }
976
977 void DrawingBuffer::restoreFramebufferBindings() { 1003 void DrawingBuffer::restoreFramebufferBindings() {
978 if (m_drawFramebufferBinding && m_readFramebufferBinding) { 1004 DrawingBufferRestoreState restoreState;
979 if (m_drawFramebufferBinding == m_readFramebufferBinding) { 1005 m_stateRestorer->setFramebufferBindingDirty();
980 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_readFramebufferBinding);
981 } else {
982 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding);
983 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding);
984 }
985 return;
986 }
987 if (!m_drawFramebufferBinding && !m_readFramebufferBinding) {
988 bind(GL_FRAMEBUFFER);
989 return;
990 }
991 if (!m_drawFramebufferBinding) {
992 bind(GL_DRAW_FRAMEBUFFER);
993 m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding);
994 } else {
995 bind(GL_READ_FRAMEBUFFER);
996 m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding);
997 }
998 } 1006 }
999 1007
1000 bool DrawingBuffer::multisample() const { 1008 bool DrawingBuffer::multisample() const {
1001 return m_antiAliasingMode != None; 1009 return m_antiAliasingMode != None;
1002 } 1010 }
1003 1011
1004 void DrawingBuffer::bind(GLenum target) { 1012 void DrawingBuffer::bind(GLenum target) {
1005 m_gl->BindFramebuffer(target, 1013 m_gl->BindFramebuffer(target,
1006 wantExplicitResolve() ? m_multisampleFBO : m_fbo); 1014 wantExplicitResolve() ? m_multisampleFBO : m_fbo);
1007 } 1015 }
1008 1016
1009 void DrawingBuffer::setPackAlignment(GLint param) {
1010 m_packAlignment = param;
1011 }
1012
1013 bool DrawingBuffer::paintRenderingResultsToImageData( 1017 bool DrawingBuffer::paintRenderingResultsToImageData(
1014 int& width, 1018 int& width,
1015 int& height, 1019 int& height,
1016 SourceDrawingBuffer sourceBuffer, 1020 SourceDrawingBuffer sourceBuffer,
1017 WTF::ArrayBufferContents& contents) { 1021 WTF::ArrayBufferContents& contents) {
1022 ScopedStateRestorer scopedStateRestorer(this);
1023
1018 ASSERT(!m_premultipliedAlpha); 1024 ASSERT(!m_premultipliedAlpha);
1019 width = size().width(); 1025 width = size().width();
1020 height = size().height(); 1026 height = size().height();
1021 1027
1022 CheckedNumeric<int> dataSize = 4; 1028 CheckedNumeric<int> dataSize = 4;
1023 dataSize *= width; 1029 dataSize *= width;
1024 dataSize *= height; 1030 dataSize *= height;
1025 if (!dataSize.IsValid()) 1031 if (!dataSize.IsValid())
1026 return false; 1032 return false;
1027 1033
1028 WTF::ArrayBufferContents pixels(width * height, 4, 1034 WTF::ArrayBufferContents pixels(width * height, 4,
1029 WTF::ArrayBufferContents::NotShared, 1035 WTF::ArrayBufferContents::NotShared,
1030 WTF::ArrayBufferContents::DontInitialize); 1036 WTF::ArrayBufferContents::DontInitialize);
1031 1037
1032 GLuint fbo = 0; 1038 GLuint fbo = 0;
1039 m_stateRestorer->setFramebufferBindingDirty();
1033 if (sourceBuffer == FrontBuffer && m_frontColorBuffer) { 1040 if (sourceBuffer == FrontBuffer && m_frontColorBuffer) {
1034 m_gl->GenFramebuffers(1, &fbo); 1041 m_gl->GenFramebuffers(1, &fbo);
1035 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo); 1042 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
1036 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 1043 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1037 m_frontColorBuffer->parameters.target, 1044 m_frontColorBuffer->parameters.target,
1038 m_frontColorBuffer->textureId, 0); 1045 m_frontColorBuffer->textureId, 0);
1039 } else { 1046 } else {
1040 m_gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer()); 1047 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
1041 } 1048 }
1042 1049
1043 readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height, 1050 readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height,
1044 ReadbackRGBA, WebGLImageConversion::AlphaDoNothing); 1051 ReadbackRGBA, WebGLImageConversion::AlphaDoNothing);
1045 flipVertically(static_cast<uint8_t*>(pixels.data()), width, height); 1052 flipVertically(static_cast<uint8_t*>(pixels.data()), width, height);
1046 1053
1047 if (fbo) { 1054 if (fbo) {
1048 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 1055 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1049 m_frontColorBuffer->parameters.target, 0, 0); 1056 m_frontColorBuffer->parameters.target, 0, 0);
1050 m_gl->DeleteFramebuffers(1, &fbo); 1057 m_gl->DeleteFramebuffers(1, &fbo);
1051 } 1058 }
1052 1059
1053 restoreFramebufferBindings();
1054
1055 pixels.transfer(contents); 1060 pixels.transfer(contents);
1056 return true; 1061 return true;
1057 } 1062 }
1058 1063
1059 void DrawingBuffer::readBackFramebuffer(unsigned char* pixels, 1064 void DrawingBuffer::readBackFramebuffer(unsigned char* pixels,
1060 int width, 1065 int width,
1061 int height, 1066 int height,
1062 ReadbackOrder readbackOrder, 1067 ReadbackOrder readbackOrder,
1063 WebGLImageConversion::AlphaOp op) { 1068 WebGLImageConversion::AlphaOp op) {
1064 if (m_packAlignment > 4) 1069 m_stateRestorer->setPixelPackAlignmentDirty();
1065 m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1); 1070 m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
1066 m_gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 1071 m_gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1067 if (m_packAlignment > 4)
1068 m_gl->PixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
1069 1072
1070 size_t bufferSize = 4 * width * height; 1073 size_t bufferSize = 4 * width * height;
1071 1074
1072 if (readbackOrder == ReadbackSkia) { 1075 if (readbackOrder == ReadbackSkia) {
1073 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT 1076 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
1074 // Swizzle red and blue channels to match SkBitmap's byte ordering. 1077 // Swizzle red and blue channels to match SkBitmap's byte ordering.
1075 // TODO(kbr): expose GL_BGRA as extension. 1078 // TODO(kbr): expose GL_BGRA as extension.
1076 for (size_t i = 0; i < bufferSize; i += 4) { 1079 for (size_t i = 0; i < bufferSize; i += 4) {
1077 std::swap(pixels[i], pixels[i + 2]); 1080 std::swap(pixels[i], pixels[i + 2]);
1078 } 1081 }
1079 #endif 1082 #endif
1080 } 1083 }
1081 1084
1082 if (op == WebGLImageConversion::AlphaDoPremultiply) { 1085 if (op == WebGLImageConversion::AlphaDoPremultiply) {
1083 for (size_t i = 0; i < bufferSize; i += 4) { 1086 for (size_t i = 0; i < bufferSize; i += 4) {
1084 pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); 1087 pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
1085 pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); 1088 pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
1086 pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); 1089 pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
1087 } 1090 }
1088 } else if (op != WebGLImageConversion::AlphaDoNothing) { 1091 } else if (op != WebGLImageConversion::AlphaDoNothing) {
1089 ASSERT_NOT_REACHED(); 1092 ASSERT_NOT_REACHED();
1090 } 1093 }
1091 } 1094 }
1092 1095
1093 void DrawingBuffer::flipVertically(uint8_t* framebuffer, 1096 void DrawingBuffer::flipVertically(uint8_t* framebuffer,
1094 int width, 1097 int width,
1095 int height) { 1098 int height) {
1096 m_scanline.resize(width * 4); 1099 std::vector<uint8_t> scanline(width * 4);
1097 uint8_t* scanline = &m_scanline[0];
1098 unsigned rowBytes = width * 4; 1100 unsigned rowBytes = width * 4;
1099 unsigned count = height / 2; 1101 unsigned count = height / 2;
1100 for (unsigned i = 0; i < count; i++) { 1102 for (unsigned i = 0; i < count; i++) {
1101 uint8_t* rowA = framebuffer + i * rowBytes; 1103 uint8_t* rowA = framebuffer + i * rowBytes;
1102 uint8_t* rowB = framebuffer + (height - i - 1) * rowBytes; 1104 uint8_t* rowB = framebuffer + (height - i - 1) * rowBytes;
1103 memcpy(scanline, rowB, rowBytes); 1105 memcpy(scanline.data(), rowB, rowBytes);
1104 memcpy(rowB, rowA, rowBytes); 1106 memcpy(rowB, rowA, rowBytes);
1105 memcpy(rowA, scanline, rowBytes); 1107 memcpy(rowA, scanline.data(), rowBytes);
1106 } 1108 }
1107 } 1109 }
1108 1110
1109 void DrawingBuffer::allocateConditionallyImmutableTexture(GLenum target, 1111 RefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::createColorBuffer(
1110 GLenum internalformat, 1112 const IntSize& size) {
1111 GLsizei width, 1113 m_stateRestorer->setFramebufferBindingDirty();
1112 GLsizei height, 1114 m_stateRestorer->setTextureBindingDirty();
1113 GLint border, 1115
1114 GLenum format, 1116 // Select the Parameters for the texture object. Allocate the backing
1115 GLenum type) { 1117 // GpuMemoryBuffer and GLImage, if one is going to be used.
1116 if (m_storageTextureSupported) { 1118 ColorBufferParameters parameters;
1117 GLenum internalStorageFormat = GL_NONE; 1119 GLuint imageId = 0;
1118 if (internalformat == GL_RGB) { 1120 if (shouldUseChromiumImage()) {
1119 internalStorageFormat = GL_RGB8; 1121 parameters = gpuMemoryBufferColorBufferParameters();
1120 } else if (internalformat == GL_RGBA) { 1122 imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(
1121 internalStorageFormat = GL_RGBA8; 1123 size.width(), size.height(), parameters.creationInternalColorFormat,
1122 } else { 1124 GC3D_SCANOUT_CHROMIUM);
1123 NOTREACHED(); 1125 } else {
1124 } 1126 parameters = textureColorBufferParameters();
1125 m_gl->TexStorage2DEXT(GL_TEXTURE_2D, 1, internalStorageFormat, width,
1126 height);
1127 return;
1128 } 1127 }
1129 m_gl->TexImage2D(target, 0, internalformat, width, height, border, format,
1130 type, 0);
1131 }
1132 1128
1133 void DrawingBuffer::clearChromiumImageAlpha(const ColorBuffer& info) { 1129 // Allocate the texture for this object.
1134 if (m_wantAlphaChannel) 1130 GLuint textureId = 0;
1135 return; 1131 {
1136 if (!contextProvider()->getCapabilities().chromium_image_rgb_emulation) 1132 m_gl->GenTextures(1, &textureId);
1137 return; 1133 m_gl->BindTexture(parameters.target, textureId);
1134 m_gl->TexParameteri(parameters.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1135 m_gl->TexParameteri(parameters.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1136 m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1137 m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1138 }
1138 1139
1139 GLuint fbo = 0; 1140 // If this is GpuMemoryBuffer-backed, then bind the texture to the
1140 m_gl->GenFramebuffers(1, &fbo); 1141 // GpuMemoryBuffer's GLImage. Otherwise, allocate ordinary texture storage.
1141 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
1142 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1143 info.parameters.target, info.textureId, 0);
1144 m_gl->ClearColor(0, 0, 0, 1);
1145 m_gl->ColorMask(false, false, false, true);
1146 m_gl->Clear(GL_COLOR_BUFFER_BIT);
1147 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1148 info.parameters.target, 0, 0);
1149 m_gl->DeleteFramebuffers(1, &fbo);
1150 restoreFramebufferBindings();
1151 m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
1152 m_clearColor[3]);
1153 m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
1154 m_colorMask[3]);
1155 }
1156
1157 RefPtr<DrawingBuffer::ColorBuffer>
1158 DrawingBuffer::createTextureAndAllocateMemory(const IntSize& size) {
1159 if (!shouldUseChromiumImage())
1160 return createDefaultTextureAndAllocateMemory(size);
1161
1162 TextureParameters parameters = chromiumImageTextureParameters();
1163 GLuint imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(
1164 size.width(), size.height(), parameters.creationInternalColorFormat,
1165 GC3D_SCANOUT_CHROMIUM);
1166 GLuint textureId = createColorTexture(parameters);
1167 if (imageId) { 1142 if (imageId) {
1168 m_gl->BindTexImage2DCHROMIUM(parameters.target, imageId); 1143 m_gl->BindTexImage2DCHROMIUM(parameters.target, imageId);
1144 } else {
1145 if (m_storageTextureSupported) {
1146 GLenum internalStorageFormat = GL_NONE;
1147 if (parameters.creationInternalColorFormat == GL_RGB) {
1148 internalStorageFormat = GL_RGB8;
1149 } else if (parameters.creationInternalColorFormat == GL_RGBA) {
1150 internalStorageFormat = GL_RGBA8;
1151 } else {
1152 NOTREACHED();
1153 }
1154 m_gl->TexStorage2DEXT(GL_TEXTURE_2D, 1, internalStorageFormat,
1155 size.width(), size.height());
1156 } else {
1157 m_gl->TexImage2D(parameters.target, 0,
1158 parameters.creationInternalColorFormat, size.width(),
1159 size.height(), 0, parameters.colorFormat,
1160 GL_UNSIGNED_BYTE, 0);
1161 }
1169 } 1162 }
1170 1163
1171 RefPtr<ColorBuffer> info(adoptRef(new ColorBuffer(this, parameters, size))); 1164 // Clear the alpha channel if this is RGB emulated.
1172 info->textureId = textureId; 1165 if (imageId && !m_wantAlphaChannel &&
1173 info->imageId = imageId; 1166 contextProvider()->getCapabilities().chromium_image_rgb_emulation) {
1174 clearChromiumImageAlpha(*info); 1167 GLuint fbo = 0;
1175 return info;
1176 }
1177 1168
1178 RefPtr<DrawingBuffer::ColorBuffer> 1169 m_stateRestorer->setClearStateDirty();
1179 DrawingBuffer::createDefaultTextureAndAllocateMemory(const IntSize& size) { 1170 m_gl->GenFramebuffers(1, &fbo);
1180 TextureParameters parameters = defaultTextureParameters(); 1171 m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
1181 RefPtr<ColorBuffer> info(adoptRef(new ColorBuffer(this, parameters, size))); 1172 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1182 info->textureId = createColorTexture(parameters); 1173 parameters.target, textureId, 0);
1183 allocateConditionallyImmutableTexture( 1174 m_gl->ClearColor(0, 0, 0, 1);
1184 parameters.target, parameters.creationInternalColorFormat, size.width(), 1175 m_gl->ColorMask(false, false, false, true);
1185 size.height(), 0, parameters.colorFormat, GL_UNSIGNED_BYTE); 1176 m_gl->Clear(GL_COLOR_BUFFER_BIT);
1186 return info; 1177 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1178 parameters.target, 0, 0);
1179 m_gl->DeleteFramebuffers(1, &fbo);
1180 }
1181
1182 return adoptRef(new ColorBuffer(this, parameters, size, textureId, imageId));
1187 } 1183 }
1188 1184
1189 void DrawingBuffer::attachColorBufferToReadFramebuffer() { 1185 void DrawingBuffer::attachColorBufferToReadFramebuffer() {
1186 m_stateRestorer->setFramebufferBindingDirty();
1187 m_stateRestorer->setTextureBindingDirty();
1188
1190 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); 1189 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
1191 1190
1192 GLenum target = m_backColorBuffer->parameters.target; 1191 GLenum target = m_backColorBuffer->parameters.target;
1193 GLenum id = m_backColorBuffer->textureId; 1192 GLenum id = m_backColorBuffer->textureId;
1194 1193
1195 m_gl->BindTexture(target, id); 1194 m_gl->BindTexture(target, id);
1196 1195
1197 if (m_antiAliasingMode == MSAAImplicitResolve) 1196 if (m_antiAliasingMode == MSAAImplicitResolve)
1198 m_gl->FramebufferTexture2DMultisampleEXT( 1197 m_gl->FramebufferTexture2DMultisampleEXT(
1199 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id, 0, m_sampleCount); 1198 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id, 0, m_sampleCount);
1200 else 1199 else
1201 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id, 1200 m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id,
1202 0); 1201 0);
1203
1204 restoreTextureBindings();
1205 restoreFramebufferBindings();
1206 } 1202 }
1207 1203
1208 bool DrawingBuffer::wantExplicitResolve() { 1204 bool DrawingBuffer::wantExplicitResolve() {
1209 return m_antiAliasingMode == MSAAExplicitResolve; 1205 return m_antiAliasingMode == MSAAExplicitResolve;
1210 } 1206 }
1211 1207
1212 bool DrawingBuffer::wantDepthOrStencil() { 1208 bool DrawingBuffer::wantDepthOrStencil() {
1213 return m_wantDepth || m_wantStencil; 1209 return m_wantDepth || m_wantStencil;
1214 } 1210 }
1215 1211
1216 GLenum DrawingBuffer::getMultisampledRenderbufferFormat() { 1212 GLenum DrawingBuffer::getMultisampledRenderbufferFormat() {
1217 DCHECK(wantExplicitResolve()); 1213 DCHECK(wantExplicitResolve());
1218 if (m_wantAlphaChannel) 1214 if (m_wantAlphaChannel)
1219 return GL_RGBA8_OES; 1215 return GL_RGBA8_OES;
1220 if (shouldUseChromiumImage() && 1216 if (shouldUseChromiumImage() &&
1221 contextProvider()->getCapabilities().chromium_image_rgb_emulation) 1217 contextProvider()->getCapabilities().chromium_image_rgb_emulation)
1222 return GL_RGBA8_OES; 1218 return GL_RGBA8_OES;
1223 if (contextProvider() 1219 if (contextProvider()
1224 ->getCapabilities() 1220 ->getCapabilities()
1225 .disable_webgl_rgb_multisampling_usage) 1221 .disable_webgl_rgb_multisampling_usage)
1226 return GL_RGBA8_OES; 1222 return GL_RGBA8_OES;
1227 return GL_RGB8_OES; 1223 return GL_RGB8_OES;
1228 } 1224 }
1229 1225
1230 void DrawingBuffer::restoreTextureBindings() { 1226 DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer(
1231 // This class potentially modifies the bindings for GL_TEXTURE_2D and 1227 DrawingBuffer* drawingBuffer)
1232 // GL_TEXTURE_RECTANGLE. Only GL_TEXTURE_2D needs to be restored since 1228 : m_drawingBuffer(drawingBuffer) {
1233 // the public interface for WebGL does not support GL_TEXTURE_RECTANGLE. 1229 DCHECK(!m_drawingBuffer->m_stateRestorer);
1234 m_gl->BindTexture(GL_TEXTURE_2D, m_texture2DBinding); 1230 m_drawingBuffer->m_stateRestorer = this;
1231 }
1232
1233 DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() {
1234 m_drawingBuffer->m_stateRestorer = nullptr;
1235 if (!m_drawingBuffer->m_stateTracker)
1236 return;
1237
1238 gpu::gles2::GLES2Interface* gl = m_drawingBuffer->m_gl;
1239 DrawingBufferRestoreState restoreState;
1240 m_drawingBuffer->m_stateTracker->GetDrawingBufferRestoreState(&restoreState);
1241
1242 if (m_clearStateDirty) {
1243 if (restoreState.scissorEnabled)
1244 gl->Enable(GL_SCISSOR_TEST);
1245 else
1246 gl->Disable(GL_SCISSOR_TEST);
1247 gl->ClearColor(restoreState.clearColor[0], restoreState.clearColor[1],
1248 restoreState.clearColor[2], restoreState.clearColor[3]);
1249 gl->ClearDepthf(restoreState.clearDepth);
1250 gl->ClearStencil(restoreState.clearStencil);
1251
1252 gl->ColorMask(restoreState.colorMask[0], restoreState.colorMask[1],
1253 restoreState.colorMask[2], restoreState.colorMask[3]);
1254 gl->DepthMask(restoreState.depthMask);
1255 gl->StencilMaskSeparate(GL_FRONT, restoreState.stencilMask);
1256 }
1257 if (m_pixelPackAlignmentDirty)
1258 gl->PixelStorei(GL_PACK_ALIGNMENT, restoreState.packAlignment);
1259 if (m_textureBindingDirty)
1260 gl->BindTexture(GL_TEXTURE_2D, restoreState.activeTexture2DBinding);
1261 if (m_renderbufferBindingDirty)
1262 gl->BindRenderbuffer(GL_RENDERBUFFER, restoreState.renderbufferBinding);
1263 if (m_framebufferBindingDirty) {
1264 if (restoreState.drawFramebufferBinding ==
1265 restoreState.readFramebufferBinding) {
1266 gl->BindFramebuffer(GL_FRAMEBUFFER, restoreState.drawFramebufferBinding);
1267 } else {
1268 gl->BindFramebuffer(GL_READ_FRAMEBUFFER,
1269 restoreState.readFramebufferBinding);
1270 gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER,
1271 restoreState.drawFramebufferBinding);
1272 }
1273 }
1274 if (m_pixelUnpackBufferBindingDirty) {
1275 gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER,
1276 restoreState.pixelUnpackBufferBinding);
1277 }
1235 } 1278 }
1236 1279
1237 bool DrawingBuffer::shouldUseChromiumImage() { 1280 bool DrawingBuffer::shouldUseChromiumImage() {
1238 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() && 1281 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() &&
1239 m_chromiumImageUsage == AllowChromiumImage; 1282 m_chromiumImageUsage == AllowChromiumImage;
1240 } 1283 }
1241 1284
1242 } // namespace blink 1285 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698