| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |