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> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/string_util.h" | 15 #include "base/string_util.h" |
16 #include "base/strings/string_split.h" | 16 #include "base/strings/string_split.h" |
17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
18 #include "cc/base/math_util.h" | 18 #include "cc/base/math_util.h" |
19 #include "cc/layers/video_layer_impl.h" | 19 #include "cc/layers/video_layer_impl.h" |
20 #include "cc/output/compositor_frame.h" | 20 #include "cc/output/compositor_frame.h" |
21 #include "cc/output/compositor_frame_metadata.h" | 21 #include "cc/output/compositor_frame_metadata.h" |
22 #include "cc/output/context_provider.h" | 22 #include "cc/output/context_provider.h" |
| 23 #include "cc/output/copy_output_request.h" |
23 #include "cc/output/geometry_binding.h" | 24 #include "cc/output/geometry_binding.h" |
24 #include "cc/output/gl_frame_data.h" | 25 #include "cc/output/gl_frame_data.h" |
25 #include "cc/output/output_surface.h" | 26 #include "cc/output/output_surface.h" |
26 #include "cc/output/render_surface_filters.h" | 27 #include "cc/output/render_surface_filters.h" |
27 #include "cc/quads/picture_draw_quad.h" | 28 #include "cc/quads/picture_draw_quad.h" |
28 #include "cc/quads/render_pass.h" | 29 #include "cc/quads/render_pass.h" |
29 #include "cc/quads/stream_video_draw_quad.h" | 30 #include "cc/quads/stream_video_draw_quad.h" |
30 #include "cc/quads/texture_draw_quad.h" | 31 #include "cc/quads/texture_draw_quad.h" |
31 #include "cc/resources/layer_quad.h" | 32 #include "cc/resources/layer_quad.h" |
32 #include "cc/resources/priority_calculator.h" | 33 #include "cc/resources/priority_calculator.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 | 88 |
88 // Smallest unit that impact anti-aliasing output. We use this to | 89 // Smallest unit that impact anti-aliasing output. We use this to |
89 // determine when anti-aliasing is unnecessary. | 90 // determine when anti-aliasing is unnecessary. |
90 const float kAntiAliasingEpsilon = 1.0f / 1024.0f; | 91 const float kAntiAliasingEpsilon = 1.0f / 1024.0f; |
91 | 92 |
92 } // anonymous namespace | 93 } // anonymous namespace |
93 | 94 |
94 struct GLRenderer::PendingAsyncReadPixels { | 95 struct GLRenderer::PendingAsyncReadPixels { |
95 PendingAsyncReadPixels() : buffer(0) {} | 96 PendingAsyncReadPixels() : buffer(0) {} |
96 | 97 |
97 CopyRenderPassCallback copy_callback; | 98 scoped_ptr<CopyOutputRequest> copy_request; |
98 base::CancelableClosure finished_read_pixels_callback; | 99 base::CancelableClosure finished_read_pixels_callback; |
99 unsigned buffer; | 100 unsigned buffer; |
100 | 101 |
101 private: | 102 private: |
102 DISALLOW_COPY_AND_ASSIGN(PendingAsyncReadPixels); | 103 DISALLOW_COPY_AND_ASSIGN(PendingAsyncReadPixels); |
103 }; | 104 }; |
104 | 105 |
105 scoped_ptr<GLRenderer> GLRenderer::Create(RendererClient* client, | 106 scoped_ptr<GLRenderer> GLRenderer::Create(RendererClient* client, |
106 OutputSurface* output_surface, | 107 OutputSurface* output_surface, |
107 ResourceProvider* resource_provider, | 108 ResourceProvider* resource_provider, |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 return; | 217 return; |
217 | 218 |
218 gr_context_ = skia::AdoptRef(GrContext::Create( | 219 gr_context_ = skia::AdoptRef(GrContext::Create( |
219 kOpenGL_GrBackend, | 220 kOpenGL_GrBackend, |
220 reinterpret_cast<GrBackendContext>(interface.get()))); | 221 reinterpret_cast<GrBackendContext>(interface.get()))); |
221 ReinitializeGrCanvas(); | 222 ReinitializeGrCanvas(); |
222 } | 223 } |
223 | 224 |
224 GLRenderer::~GLRenderer() { | 225 GLRenderer::~GLRenderer() { |
225 while (!pending_async_read_pixels_.empty()) { | 226 while (!pending_async_read_pixels_.empty()) { |
226 pending_async_read_pixels_.back()->finished_read_pixels_callback.Cancel(); | 227 PendingAsyncReadPixels* pending_read = pending_async_read_pixels_.back(); |
227 pending_async_read_pixels_.back()->copy_callback.Run( | 228 pending_read->finished_read_pixels_callback.Cancel(); |
228 scoped_ptr<SkBitmap>()); | |
229 pending_async_read_pixels_.pop_back(); | 229 pending_async_read_pixels_.pop_back(); |
230 } | 230 } |
231 | 231 |
232 context_->setMemoryAllocationChangedCallbackCHROMIUM(NULL); | 232 context_->setMemoryAllocationChangedCallbackCHROMIUM(NULL); |
233 CleanupSharedObjects(); | 233 CleanupSharedObjects(); |
234 } | 234 } |
235 | 235 |
236 const RendererCapabilities& GLRenderer::Capabilities() const { | 236 const RendererCapabilities& GLRenderer::Capabilities() const { |
237 return capabilities_; | 237 return capabilities_; |
238 } | 238 } |
(...skipping 1623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1862 if (!is_scissor_enabled_) | 1862 if (!is_scissor_enabled_) |
1863 return; | 1863 return; |
1864 | 1864 |
1865 FlushTextureQuadCache(); | 1865 FlushTextureQuadCache(); |
1866 GLC(context_, context_->disable(GL_SCISSOR_TEST)); | 1866 GLC(context_, context_->disable(GL_SCISSOR_TEST)); |
1867 is_scissor_enabled_ = false; | 1867 is_scissor_enabled_ = false; |
1868 } | 1868 } |
1869 | 1869 |
1870 void GLRenderer::CopyCurrentRenderPassToBitmap( | 1870 void GLRenderer::CopyCurrentRenderPassToBitmap( |
1871 DrawingFrame* frame, | 1871 DrawingFrame* frame, |
1872 const CopyRenderPassCallback& callback) { | 1872 scoped_ptr<CopyOutputRequest> request) { |
1873 GetFramebufferPixelsAsync(frame->current_render_pass->output_rect, | 1873 GetFramebufferPixelsAsync(frame->current_render_pass->output_rect, |
1874 frame->flipped_y, | 1874 frame->flipped_y, |
1875 callback); | 1875 request.Pass()); |
1876 } | 1876 } |
1877 | 1877 |
1878 void GLRenderer::ToGLMatrix(float* gl_matrix, const gfx::Transform& transform) { | 1878 void GLRenderer::ToGLMatrix(float* gl_matrix, const gfx::Transform& transform) { |
1879 transform.matrix().asColMajorf(gl_matrix); | 1879 transform.matrix().asColMajorf(gl_matrix); |
1880 } | 1880 } |
1881 | 1881 |
1882 void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad, int quad_location) { | 1882 void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad, int quad_location) { |
1883 if (quad_location == -1) | 1883 if (quad_location == -1) |
1884 return; | 1884 return; |
1885 | 1885 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2084 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), | 2084 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), |
2085 pending_read.Pass()); | 2085 pending_read.Pass()); |
2086 | 2086 |
2087 // This is a syncronous call since the callback is null. | 2087 // This is a syncronous call since the callback is null. |
2088 DoGetFramebufferPixels(static_cast<uint8*>(pixels), | 2088 DoGetFramebufferPixels(static_cast<uint8*>(pixels), |
2089 rect, | 2089 rect, |
2090 flipped_y, | 2090 flipped_y, |
2091 AsyncGetFramebufferPixelsCleanupCallback()); | 2091 AsyncGetFramebufferPixelsCleanupCallback()); |
2092 } | 2092 } |
2093 | 2093 |
2094 void GLRenderer::GetFramebufferPixelsAsync(gfx::Rect rect, | 2094 void GLRenderer::GetFramebufferPixelsAsync( |
2095 bool flipped_y, | 2095 gfx::Rect rect, bool flipped_y, scoped_ptr<CopyOutputRequest> request) { |
2096 CopyRenderPassCallback callback) { | 2096 DCHECK(!request->IsEmpty()); |
2097 if (callback.is_null()) | 2097 if (request->IsEmpty()) |
2098 return; | 2098 return; |
2099 if (rect.IsEmpty()) { | 2099 if (rect.IsEmpty()) |
2100 callback.Run(scoped_ptr<SkBitmap>()); | |
2101 return; | 2100 return; |
2102 } | |
2103 | 2101 |
2104 scoped_ptr<SkBitmap> bitmap(new SkBitmap); | 2102 scoped_ptr<SkBitmap> bitmap(new SkBitmap); |
2105 bitmap->setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); | 2103 bitmap->setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); |
2106 bitmap->allocPixels(); | 2104 bitmap->allocPixels(); |
2107 | 2105 |
2108 scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap)); | 2106 scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap)); |
2109 | 2107 |
2110 // Save a pointer to the pixels, the bitmap is owned by the cleanup_callback. | 2108 // Save a pointer to the pixels, the bitmap is owned by the cleanup_callback. |
2111 uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); | 2109 uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); |
2112 | 2110 |
2113 AsyncGetFramebufferPixelsCleanupCallback cleanup_callback = base::Bind( | 2111 AsyncGetFramebufferPixelsCleanupCallback cleanup_callback = base::Bind( |
2114 &GLRenderer::PassOnSkBitmap, | 2112 &GLRenderer::PassOnSkBitmap, |
2115 base::Unretained(this), | 2113 base::Unretained(this), |
2116 base::Passed(&bitmap), | 2114 base::Passed(&bitmap), |
2117 base::Passed(&lock), | 2115 base::Passed(&lock)); |
2118 callback); | |
2119 | 2116 |
2120 scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels); | 2117 scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels); |
2121 pending_read->copy_callback = callback; | 2118 pending_read->copy_request = request.Pass(); |
2122 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), | 2119 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), |
2123 pending_read.Pass()); | 2120 pending_read.Pass()); |
2124 | 2121 |
2125 // This is an asyncronous call since the callback is not null. | 2122 // This is an asyncronous call since the callback is not null. |
2126 DoGetFramebufferPixels(pixels, rect, flipped_y, cleanup_callback); | 2123 DoGetFramebufferPixels(pixels, rect, flipped_y, cleanup_callback); |
2127 } | 2124 } |
2128 | 2125 |
2129 void GLRenderer::DoGetFramebufferPixels( | 2126 void GLRenderer::DoGetFramebufferPixels( |
2130 uint8* dest_pixels, | 2127 uint8* dest_pixels, |
2131 gfx::Rect rect, | 2128 gfx::Rect rect, |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2246 EnforceMemoryPolicy(); | 2243 EnforceMemoryPolicy(); |
2247 } | 2244 } |
2248 | 2245 |
2249 void GLRenderer::FinishedReadback( | 2246 void GLRenderer::FinishedReadback( |
2250 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, | 2247 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, |
2251 unsigned source_buffer, | 2248 unsigned source_buffer, |
2252 uint8* dest_pixels, | 2249 uint8* dest_pixels, |
2253 gfx::Size size, | 2250 gfx::Size size, |
2254 bool flipped_y) { | 2251 bool flipped_y) { |
2255 DCHECK(!pending_async_read_pixels_.empty()); | 2252 DCHECK(!pending_async_read_pixels_.empty()); |
2256 DCHECK_EQ(source_buffer, pending_async_read_pixels_.back()->buffer); | 2253 |
| 2254 PendingAsyncReadPixels* current_read = pending_async_read_pixels_.back(); |
| 2255 // Make sure we service the readbacks in order. |
| 2256 DCHECK_EQ(source_buffer, current_read->buffer); |
2257 | 2257 |
2258 uint8* src_pixels = NULL; | 2258 uint8* src_pixels = NULL; |
2259 | 2259 |
2260 if (source_buffer != 0) { | 2260 if (source_buffer != 0) { |
2261 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 2261 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
2262 source_buffer)); | 2262 source_buffer)); |
2263 src_pixels = static_cast<uint8*>( | 2263 src_pixels = static_cast<uint8*>( |
2264 context_->mapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 2264 context_->mapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
2265 GL_READ_ONLY)); | 2265 GL_READ_ONLY)); |
2266 | 2266 |
(...skipping 18 matching lines...) Expand all Loading... |
2285 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM)); | 2285 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM)); |
2286 } | 2286 } |
2287 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 2287 GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
2288 0)); | 2288 0)); |
2289 GLC(context_, context_->deleteBuffer(source_buffer)); | 2289 GLC(context_, context_->deleteBuffer(source_buffer)); |
2290 } | 2290 } |
2291 | 2291 |
2292 // TODO(danakj): This can go away when synchronous readback is no more and its | 2292 // TODO(danakj): This can go away when synchronous readback is no more and its |
2293 // contents can just move here. | 2293 // contents can just move here. |
2294 if (!cleanup_callback.is_null()) | 2294 if (!cleanup_callback.is_null()) |
2295 cleanup_callback.Run(src_pixels != NULL); | 2295 cleanup_callback.Run(current_read->copy_request.Pass(), src_pixels != NULL); |
2296 | 2296 |
2297 pending_async_read_pixels_.pop_back(); | 2297 pending_async_read_pixels_.pop_back(); |
2298 } | 2298 } |
2299 | 2299 |
2300 void GLRenderer::PassOnSkBitmap( | 2300 void GLRenderer::PassOnSkBitmap( |
2301 scoped_ptr<SkBitmap> bitmap, | 2301 scoped_ptr<SkBitmap> bitmap, |
2302 scoped_ptr<SkAutoLockPixels> lock, | 2302 scoped_ptr<SkAutoLockPixels> lock, |
2303 const CopyRenderPassCallback& callback, | 2303 scoped_ptr<CopyOutputRequest> request, |
2304 bool success) { | 2304 bool success) { |
2305 DCHECK(callback.Equals(pending_async_read_pixels_.back()->copy_callback)); | 2305 DCHECK(request->HasBitmapRequest()); |
2306 | 2306 |
2307 lock.reset(); | 2307 lock.reset(); |
2308 if (success) | 2308 if (success) |
2309 callback.Run(bitmap.Pass()); | 2309 request->SendBitmapResult(bitmap.Pass()); |
2310 else | |
2311 callback.Run(scoped_ptr<SkBitmap>()); | |
2312 } | 2310 } |
2313 | 2311 |
2314 bool GLRenderer::GetFramebufferTexture(ScopedResource* texture, | 2312 bool GLRenderer::GetFramebufferTexture(ScopedResource* texture, |
2315 gfx::Rect device_rect) { | 2313 gfx::Rect device_rect) { |
2316 DCHECK(!texture->id() || (texture->size() == device_rect.size() && | 2314 DCHECK(!texture->id() || (texture->size() == device_rect.size() && |
2317 texture->format() == GL_RGB)); | 2315 texture->format() == GL_RGB)); |
2318 | 2316 |
2319 if (!texture->id() && !texture->Allocate(device_rect.size(), | 2317 if (!texture->id() && !texture->Allocate(device_rect.size(), |
2320 GL_RGB, | 2318 GL_RGB, |
2321 ResourceProvider::TextureUsageAny)) | 2319 ResourceProvider::TextureUsageAny)) |
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2908 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas | 2906 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas |
2909 // implementation. | 2907 // implementation. |
2910 return gr_context_ && context_->getContextAttributes().stencil; | 2908 return gr_context_ && context_->getContextAttributes().stencil; |
2911 } | 2909 } |
2912 | 2910 |
2913 bool GLRenderer::IsContextLost() { | 2911 bool GLRenderer::IsContextLost() { |
2914 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); | 2912 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); |
2915 } | 2913 } |
2916 | 2914 |
2917 } // namespace cc | 2915 } // namespace cc |
OLD | NEW |