OLD | NEW |
1 // Copyright 2010 The Chromium Authors. All rights reserved. | 1 // Copyright 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/output/gl_renderer.h" | 5 #include "cc/output/gl_renderer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; | 289 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; |
290 // Only the Skia GPU backend uses the stencil buffer. No need to clear it | 290 // Only the Skia GPU backend uses the stencil buffer. No need to clear it |
291 // otherwise. | 291 // otherwise. |
292 if (CanUseSkiaGPUBackend()) | 292 if (CanUseSkiaGPUBackend()) |
293 clear_bits |= GL_STENCIL_BUFFER_BIT; | 293 clear_bits |= GL_STENCIL_BUFFER_BIT; |
294 context_->clear(clear_bits); | 294 context_->clear(clear_bits); |
295 } | 295 } |
296 } | 296 } |
297 | 297 |
298 void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { | 298 void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { |
299 // FIXME: Remove this once backbuffer is automatically recreated on first use | 299 // TODO(hubbe): Remove this once backbuffer is automatically recreated |
| 300 // on first use. |
300 EnsureBackbuffer(); | 301 EnsureBackbuffer(); |
301 | 302 |
302 if (client_->DeviceViewport().IsEmpty()) | 303 if (client_->DeviceViewport().IsEmpty()) |
303 return; | 304 return; |
304 | 305 |
305 TRACE_EVENT0("cc", "GLRenderer::DrawLayers"); | 306 TRACE_EVENT0("cc", "GLRenderer::DrawLayers"); |
306 | 307 |
307 MakeContextCurrent(); | 308 MakeContextCurrent(); |
308 | 309 |
309 ReinitializeGLState(); | 310 ReinitializeGLState(); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 // quad since the destination texture has bounds matching the quad's content. | 580 // quad since the destination texture has bounds matching the quad's content. |
580 // 5. Draw the background texture for the contents using the same transform as | 581 // 5. Draw the background texture for the contents using the same transform as |
581 // used to draw the contents itself. This is done without blending to replace | 582 // used to draw the contents itself. This is done without blending to replace |
582 // the current background pixels with the new filtered background. | 583 // the current background pixels with the new filtered background. |
583 // 6. Draw the contents of the quad over drop of the new background with | 584 // 6. Draw the contents of the quad over drop of the new background with |
584 // blending, as per usual. The filtered background pixels will show through | 585 // blending, as per usual. The filtered background pixels will show through |
585 // any non-opaque pixels in this draws. | 586 // any non-opaque pixels in this draws. |
586 // | 587 // |
587 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. | 588 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. |
588 | 589 |
589 // FIXME: When this algorithm changes, update | 590 // TODO(hubbe): When this algorithm changes, update |
590 // LayerTreeHost::PrioritizeTextures() accordingly. | 591 // LayerTreeHost::PrioritizeTextures() accordingly. |
591 | 592 |
592 FilterOperations filters = | 593 FilterOperations filters = |
593 RenderSurfaceFilters::Optimize(quad->background_filters); | 594 RenderSurfaceFilters::Optimize(quad->background_filters); |
594 DCHECK(!filters.IsEmpty()); | 595 DCHECK(!filters.IsEmpty()); |
595 | 596 |
596 // FIXME: We only allow background filters on an opaque render surface because | 597 // TODO(hubbe): We only allow background filters on an opaque render surface |
597 // other surfaces may contain translucent pixels, and the contents behind | 598 // because other surfaces may contain translucent pixels, and the contents |
598 // those translucent pixels wouldn't have the filter applied. | 599 // behind those translucent pixels wouldn't have the filter applied. |
599 if (frame->current_render_pass->has_transparent_background) | 600 if (frame->current_render_pass->has_transparent_background) |
600 return scoped_ptr<ScopedResource>(); | 601 return scoped_ptr<ScopedResource>(); |
601 DCHECK(!frame->current_texture); | 602 DCHECK(!frame->current_texture); |
602 | 603 |
603 // FIXME: Do a single readback for both the surface and replica and cache the | 604 // TODO(hubbe): Do a single readback for both the surface and replica and |
604 // filtered results (once filter textures are not reused). | 605 // cache the filtered results (once filter textures are not reused). |
605 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( | 606 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( |
606 contents_device_transform, SharedGeometryQuad().BoundingBox())); | 607 contents_device_transform, SharedGeometryQuad().BoundingBox())); |
607 | 608 |
608 int top, right, bottom, left; | 609 int top, right, bottom, left; |
609 filters.GetOutsets(&top, &right, &bottom, &left); | 610 filters.GetOutsets(&top, &right, &bottom, &left); |
610 window_rect.Inset(-left, -top, -right, -bottom); | 611 window_rect.Inset(-left, -top, -right, -bottom); |
611 | 612 |
612 window_rect.Intersect( | 613 window_rect.Intersect( |
613 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); | 614 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); |
614 | 615 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 background_texture = DrawBackgroundFilters( | 716 background_texture = DrawBackgroundFilters( |
716 frame, | 717 frame, |
717 quad, | 718 quad, |
718 contents_device_transform, | 719 contents_device_transform, |
719 contents_device_transform_inverse); | 720 contents_device_transform_inverse); |
720 | 721 |
721 if (disable_blending) | 722 if (disable_blending) |
722 SetBlendEnabled(true); | 723 SetBlendEnabled(true); |
723 } | 724 } |
724 | 725 |
725 // FIXME: Cache this value so that we don't have to do it for both the surface | 726 // TODO(hubbe): Cache this value so that we don't have to do it for both the |
726 // and its replica. Apply filters to the contents texture. | 727 // surface and its replica. Apply filters to the contents texture. |
727 SkBitmap filter_bitmap; | 728 SkBitmap filter_bitmap; |
728 SkScalar color_matrix[20]; | 729 SkScalar color_matrix[20]; |
729 bool use_color_matrix = false; | 730 bool use_color_matrix = false; |
730 if (quad->filter) { | 731 if (quad->filter) { |
731 SkColorFilter* cf; | 732 SkColorFilter* cf; |
732 if ((quad->filter->asColorFilter(&cf)) && cf->asColorMatrix(color_matrix) && | 733 if ((quad->filter->asColorFilter(&cf)) && cf->asColorMatrix(color_matrix) && |
733 !quad->filter->getInput(0)) { | 734 !quad->filter->getInput(0)) { |
734 // We have a single color matrix as a filter; apply it locally | 735 // We have a single color matrix as a filter; apply it locally |
735 // in the compositor. | 736 // in the compositor. |
736 use_color_matrix = true; | 737 use_color_matrix = true; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 } | 788 } |
788 | 789 |
789 scoped_ptr<ResourceProvider::ScopedReadLockGL> mask_resource_lock; | 790 scoped_ptr<ResourceProvider::ScopedReadLockGL> mask_resource_lock; |
790 unsigned mask_texture_id = 0; | 791 unsigned mask_texture_id = 0; |
791 if (quad->mask_resource_id) { | 792 if (quad->mask_resource_id) { |
792 mask_resource_lock.reset(new ResourceProvider::ScopedReadLockGL( | 793 mask_resource_lock.reset(new ResourceProvider::ScopedReadLockGL( |
793 resource_provider_, quad->mask_resource_id)); | 794 resource_provider_, quad->mask_resource_id)); |
794 mask_texture_id = mask_resource_lock->texture_id(); | 795 mask_texture_id = mask_resource_lock->texture_id(); |
795 } | 796 } |
796 | 797 |
797 // FIXME: use the background_texture and blend the background in with this | 798 // TODO(hubbe): use the background_texture and blend the background |
798 // draw instead of having a separate copy of the background texture. | 799 // in with this draw instead of having a separate copy of the background |
| 800 // texture. |
799 | 801 |
800 scoped_ptr<ResourceProvider::ScopedReadLockGL> contents_resource_lock; | 802 scoped_ptr<ResourceProvider::ScopedReadLockGL> contents_resource_lock; |
801 if (filter_bitmap.getTexture()) { | 803 if (filter_bitmap.getTexture()) { |
802 GrTexture* texture = | 804 GrTexture* texture = |
803 reinterpret_cast<GrTexture*>(filter_bitmap.getTexture()); | 805 reinterpret_cast<GrTexture*>(filter_bitmap.getTexture()); |
804 Context()->bindTexture(GL_TEXTURE_2D, texture->getTextureHandle()); | 806 Context()->bindTexture(GL_TEXTURE_2D, texture->getTextureHandle()); |
805 } else { | 807 } else { |
806 contents_resource_lock = make_scoped_ptr( | 808 contents_resource_lock = make_scoped_ptr( |
807 new ResourceProvider::ScopedSamplerGL(resource_provider_, | 809 new ResourceProvider::ScopedSamplerGL(resource_provider_, |
808 contents_texture->id(), | 810 contents_texture->id(), |
(...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2303 } | 2305 } |
2304 | 2306 |
2305 unsigned buffer = context_->createBuffer(); | 2307 unsigned buffer = context_->createBuffer(); |
2306 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 2308 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
2307 buffer)); | 2309 buffer)); |
2308 GLC(context_, context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 2310 GLC(context_, context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
2309 4 * window_rect.size().GetArea(), | 2311 4 * window_rect.size().GetArea(), |
2310 NULL, | 2312 NULL, |
2311 GL_STREAM_READ)); | 2313 GL_STREAM_READ)); |
2312 | 2314 |
| 2315 WebKit::WebGLId query = 0; |
| 2316 if (is_async) { |
| 2317 query = context_->createQueryEXT(); |
| 2318 GLC(context_, context_->beginQueryEXT( |
| 2319 GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM, |
| 2320 query)); |
| 2321 } |
| 2322 |
2313 GLC(context_, | 2323 GLC(context_, |
2314 context_->readPixels(window_rect.x(), | 2324 context_->readPixels(window_rect.x(), |
2315 window_rect.y(), | 2325 window_rect.y(), |
2316 window_rect.width(), | 2326 window_rect.width(), |
2317 window_rect.height(), | 2327 window_rect.height(), |
2318 GL_RGBA, | 2328 GL_RGBA, |
2319 GL_UNSIGNED_BYTE, | 2329 GL_UNSIGNED_BYTE, |
2320 NULL)); | 2330 NULL)); |
2321 | 2331 |
2322 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 2332 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
2323 0)); | 2333 0)); |
2324 | 2334 |
2325 if (do_workaround) { | 2335 if (do_workaround) { |
2326 // Clean up. | 2336 // Clean up. |
2327 GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0)); | 2337 GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0)); |
2328 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0)); | 2338 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0)); |
2329 GLC(context_, context_->deleteFramebuffer(temporary_fbo)); | 2339 GLC(context_, context_->deleteFramebuffer(temporary_fbo)); |
2330 GLC(context_, context_->deleteTexture(temporary_texture)); | 2340 GLC(context_, context_->deleteTexture(temporary_texture)); |
2331 } | 2341 } |
2332 | 2342 |
2333 base::Closure finished_callback = | 2343 base::Closure finished_callback = |
2334 base::Bind(&GLRenderer::FinishedReadback, | 2344 base::Bind(&GLRenderer::FinishedReadback, |
2335 base::Unretained(this), | 2345 base::Unretained(this), |
2336 cleanup_callback, | 2346 cleanup_callback, |
2337 buffer, | 2347 buffer, |
| 2348 query, |
2338 dest_pixels, | 2349 dest_pixels, |
2339 window_rect.size()); | 2350 window_rect.size()); |
2340 // Save the finished_callback so it can be cancelled. | 2351 // Save the finished_callback so it can be cancelled. |
2341 pending_async_read_pixels_.front()->finished_read_pixels_callback.Reset( | 2352 pending_async_read_pixels_.front()->finished_read_pixels_callback.Reset( |
2342 finished_callback); | 2353 finished_callback); |
2343 | 2354 |
2344 // Save the buffer to verify the callbacks happen in the expected order. | 2355 // Save the buffer to verify the callbacks happen in the expected order. |
2345 pending_async_read_pixels_.front()->buffer = buffer; | 2356 pending_async_read_pixels_.front()->buffer = buffer; |
2346 | 2357 |
2347 if (is_async) { | 2358 if (is_async) { |
2348 unsigned sync_point = context_->insertSyncPoint(); | 2359 GLC(context_, context_->endQueryEXT( |
2349 SyncPointHelper::SignalSyncPoint( | 2360 GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM)); |
| 2361 SyncPointHelper::SignalQuery( |
2350 context_, | 2362 context_, |
2351 sync_point, | 2363 query, |
2352 finished_callback); | 2364 finished_callback); |
2353 } else { | 2365 } else { |
2354 resource_provider_->Finish(); | 2366 resource_provider_->Finish(); |
2355 finished_callback.Run(); | 2367 finished_callback.Run(); |
2356 } | 2368 } |
2357 | 2369 |
2358 EnforceMemoryPolicy(); | 2370 EnforceMemoryPolicy(); |
2359 } | 2371 } |
2360 | 2372 |
2361 void GLRenderer::FinishedReadback( | 2373 void GLRenderer::FinishedReadback( |
2362 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, | 2374 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, |
2363 unsigned source_buffer, | 2375 unsigned source_buffer, |
| 2376 unsigned query, |
2364 uint8* dest_pixels, | 2377 uint8* dest_pixels, |
2365 gfx::Size size) { | 2378 gfx::Size size) { |
2366 DCHECK(!pending_async_read_pixels_.empty()); | 2379 DCHECK(!pending_async_read_pixels_.empty()); |
2367 | 2380 |
| 2381 if (query != 0) { |
| 2382 GLC(context_, context_->deleteQueryEXT(query)); |
| 2383 } |
| 2384 |
2368 PendingAsyncReadPixels* current_read = pending_async_read_pixels_.back(); | 2385 PendingAsyncReadPixels* current_read = pending_async_read_pixels_.back(); |
2369 // Make sure we service the readbacks in order. | 2386 // Make sure we service the readbacks in order. |
2370 DCHECK_EQ(source_buffer, current_read->buffer); | 2387 DCHECK_EQ(source_buffer, current_read->buffer); |
2371 | 2388 |
2372 uint8* src_pixels = NULL; | 2389 uint8* src_pixels = NULL; |
2373 | 2390 |
2374 if (source_buffer != 0) { | 2391 if (source_buffer != 0) { |
2375 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 2392 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
2376 source_buffer)); | 2393 source_buffer)); |
2377 src_pixels = static_cast<uint8*>( | 2394 src_pixels = static_cast<uint8*>( |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3037 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas | 3054 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas |
3038 // implementation. | 3055 // implementation. |
3039 return gr_context_ && context_->getContextAttributes().stencil; | 3056 return gr_context_ && context_->getContextAttributes().stencil; |
3040 } | 3057 } |
3041 | 3058 |
3042 bool GLRenderer::IsContextLost() { | 3059 bool GLRenderer::IsContextLost() { |
3043 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); | 3060 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); |
3044 } | 3061 } |
3045 | 3062 |
3046 } // namespace cc | 3063 } // namespace cc |
OLD | NEW |