OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/common/gpu/media/rendering_helper.h" | 5 #include "content/common/gpu/media/rendering_helper.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 #include <numeric> |
| 9 #include <vector> |
| 10 |
7 #include "base/bind.h" | 11 #include "base/bind.h" |
8 #include "base/mac/scoped_nsautorelease_pool.h" | 12 #include "base/mac/scoped_nsautorelease_pool.h" |
9 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/stringize_macros.h" | 14 #include "base/strings/stringize_macros.h" |
11 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
12 #include "ui/gl/gl_context.h" | 16 #include "ui/gl/gl_context.h" |
13 #include "ui/gl/gl_context_stub_with_extensions.h" | 17 #include "ui/gl/gl_context_stub_with_extensions.h" |
14 #include "ui/gl/gl_implementation.h" | 18 #include "ui/gl/gl_implementation.h" |
15 #include "ui/gl/gl_surface.h" | 19 #include "ui/gl/gl_surface.h" |
16 | 20 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 #if defined(OS_WIN) | 76 #if defined(OS_WIN) |
73 window_ = NULL; | 77 window_ = NULL; |
74 #else | 78 #else |
75 x_window_ = (Window)0; | 79 x_window_ = (Window)0; |
76 #endif | 80 #endif |
77 | 81 |
78 Clear(); | 82 Clear(); |
79 } | 83 } |
80 | 84 |
81 RenderingHelper::~RenderingHelper() { | 85 RenderingHelper::~RenderingHelper() { |
82 CHECK_EQ(frame_dimensions_.size(), 0U) | 86 CHECK_EQ(clients_.size(), 0U) << "Must call UnInitialize before dtor."; |
83 << "Must call UnInitialize before dtor."; | |
84 Clear(); | 87 Clear(); |
85 } | 88 } |
86 | 89 |
87 void RenderingHelper::Initialize(const RenderingHelperParams& params, | 90 void RenderingHelper::Initialize(const RenderingHelperParams& params, |
88 base::WaitableEvent* done) { | 91 base::WaitableEvent* done) { |
89 // Use frame_dimensions_.size() != 0 as a proxy for the class having already | 92 // Use cients_.size() != 0 as a proxy for the class having already been |
90 // been Initialize()'d, and UnInitialize() before continuing. | 93 // Initialize()'d, and UnInitialize() before continuing. |
91 if (frame_dimensions_.size()) { | 94 if (clients_.size()) { |
92 base::WaitableEvent done(false, false); | 95 base::WaitableEvent done(false, false); |
93 UnInitialize(&done); | 96 UnInitialize(&done); |
94 done.Wait(); | 97 done.Wait(); |
95 } | 98 } |
96 | 99 |
97 frame_duration_ = params.rendering_fps > 0 | 100 frame_duration_ = params.rendering_fps > 0 |
98 ? base::TimeDelta::FromSeconds(1) / params.rendering_fps | 101 ? base::TimeDelta::FromSeconds(1) / params.rendering_fps |
99 : base::TimeDelta(); | 102 : base::TimeDelta(); |
100 | 103 |
101 gfx::InitializeStaticGLBindings(kGLImplementation); | 104 gfx::InitializeStaticGLBindings(kGLImplementation); |
102 scoped_refptr<gfx::GLContextStubWithExtensions> stub_context( | 105 scoped_refptr<gfx::GLContextStubWithExtensions> stub_context( |
103 new gfx::GLContextStubWithExtensions()); | 106 new gfx::GLContextStubWithExtensions()); |
104 | 107 |
105 CHECK_GT(params.window_dimensions.size(), 0U); | |
106 CHECK_EQ(params.frame_dimensions.size(), params.window_dimensions.size()); | |
107 frame_dimensions_ = params.frame_dimensions; | |
108 render_as_thumbnails_ = params.render_as_thumbnails; | 108 render_as_thumbnails_ = params.render_as_thumbnails; |
109 message_loop_ = base::MessageLoop::current(); | 109 message_loop_ = base::MessageLoop::current(); |
110 CHECK_GT(params.num_windows, 0); | |
111 | |
112 gfx::Size window_size; | |
113 | 110 |
114 #if GL_VARIANT_GLX | 111 #if GL_VARIANT_GLX |
115 x_display_ = gfx::GetXDisplay(); | 112 x_display_ = gfx::GetXDisplay(); |
116 CHECK(x_display_); | 113 CHECK(x_display_); |
117 CHECK(glXQueryVersion(x_display_, NULL, NULL)); | 114 CHECK(glXQueryVersion(x_display_, NULL, NULL)); |
118 const int fbconfig_attr[] = { | 115 const int fbconfig_attr[] = { |
119 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, | 116 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, |
120 GLX_RENDER_TYPE, GLX_RGBA_BIT, | 117 GLX_RENDER_TYPE, GLX_RGBA_BIT, |
121 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, | 118 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, |
122 GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE, | 119 GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE, |
123 GLX_DOUBLEBUFFER, True, | 120 GLX_DOUBLEBUFFER, True, |
124 GL_NONE, | 121 GL_NONE, |
125 }; | 122 }; |
126 int num_fbconfigs; | 123 int num_fbconfigs; |
127 scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs( | 124 scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs( |
128 glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr, | 125 glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr, |
129 &num_fbconfigs)); | 126 &num_fbconfigs)); |
130 CHECK(glx_fb_configs.get()); | 127 CHECK(glx_fb_configs.get()); |
131 CHECK_GT(num_fbconfigs, 0); | 128 CHECK_GT(num_fbconfigs, 0); |
132 x_visual_ = glXGetVisualFromFBConfig(x_display_, glx_fb_configs.get()[0]); | 129 x_visual_ = glXGetVisualFromFBConfig(x_display_, glx_fb_configs.get()[0]); |
133 CHECK(x_visual_); | 130 CHECK(x_visual_); |
134 gl_context_ = glXCreateContext(x_display_, x_visual_, 0, true); | 131 gl_context_ = glXCreateContext(x_display_, x_visual_, 0, true); |
135 CHECK(gl_context_); | 132 CHECK(gl_context_); |
136 stub_context->AddExtensionsString( | 133 stub_context->AddExtensionsString( |
137 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); | 134 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); |
138 stub_context->SetGLVersionString( | 135 stub_context->SetGLVersionString( |
139 reinterpret_cast<const char*>(glGetString(GL_VERSION))); | 136 reinterpret_cast<const char*>(glGetString(GL_VERSION))); |
140 | 137 |
141 Screen* screen = DefaultScreenOfDisplay(x_display_); | 138 Screen* screen = DefaultScreenOfDisplay(x_display_); |
142 window_size = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); | 139 screen_size_ = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); |
143 #else // EGL | 140 #else // EGL |
144 EGLNativeDisplayType native_display; | 141 EGLNativeDisplayType native_display; |
145 | 142 |
146 #if defined(OS_WIN) | 143 #if defined(OS_WIN) |
147 native_display = EGL_DEFAULT_DISPLAY; | 144 native_display = EGL_DEFAULT_DISPLAY; |
148 window_size = | 145 screen_size_ = |
149 gfx::Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); | 146 gfx::Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); |
150 #else | 147 #else |
151 x_display_ = gfx::GetXDisplay(); | 148 x_display_ = gfx::GetXDisplay(); |
152 CHECK(x_display_); | 149 CHECK(x_display_); |
153 native_display = x_display_; | 150 native_display = x_display_; |
154 | 151 |
155 Screen* screen = DefaultScreenOfDisplay(x_display_); | 152 Screen* screen = DefaultScreenOfDisplay(x_display_); |
156 window_size = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); | 153 screen_size_ = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); |
157 #endif | 154 #endif |
158 gl_display_ = eglGetDisplay(native_display); | 155 gl_display_ = eglGetDisplay(native_display); |
159 CHECK(gl_display_); | 156 CHECK(gl_display_); |
160 CHECK(eglInitialize(gl_display_, NULL, NULL)) << glGetError(); | 157 CHECK(eglInitialize(gl_display_, NULL, NULL)) << glGetError(); |
161 | 158 |
162 static EGLint rgba8888[] = { | 159 static EGLint rgba8888[] = { |
163 EGL_RED_SIZE, 8, | 160 EGL_RED_SIZE, 8, |
164 EGL_GREEN_SIZE, 8, | 161 EGL_GREEN_SIZE, 8, |
165 EGL_BLUE_SIZE, 8, | 162 EGL_BLUE_SIZE, 8, |
166 EGL_ALPHA_SIZE, 8, | 163 EGL_ALPHA_SIZE, 8, |
(...skipping 10 matching lines...) Expand all Loading... |
177 gl_display_, egl_config, EGL_NO_CONTEXT, context_attribs); | 174 gl_display_, egl_config, EGL_NO_CONTEXT, context_attribs); |
178 CHECK_NE(gl_context_, EGL_NO_CONTEXT) << eglGetError(); | 175 CHECK_NE(gl_context_, EGL_NO_CONTEXT) << eglGetError(); |
179 stub_context->AddExtensionsString( | 176 stub_context->AddExtensionsString( |
180 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); | 177 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); |
181 stub_context->AddExtensionsString( | 178 stub_context->AddExtensionsString( |
182 eglQueryString(gl_display_, EGL_EXTENSIONS)); | 179 eglQueryString(gl_display_, EGL_EXTENSIONS)); |
183 stub_context->SetGLVersionString( | 180 stub_context->SetGLVersionString( |
184 reinterpret_cast<const char*>(glGetString(GL_VERSION))); | 181 reinterpret_cast<const char*>(glGetString(GL_VERSION))); |
185 #endif | 182 #endif |
186 clients_ = params.clients; | 183 clients_ = params.clients; |
187 // Per-window/surface X11 & EGL initialization. | 184 CHECK_GT(clients_.size(), 0U); |
188 for (int i = 0; i < params.num_windows; ++i) { | 185 LayoutRenderingAreas(); |
189 // Arrange X windows whimsically, with some padding. | |
190 int j = i % params.window_dimensions.size(); | |
191 int width = params.window_dimensions[j].width(); | |
192 int height = params.window_dimensions[j].height(); | |
193 CHECK_GT(width, 0); | |
194 CHECK_GT(height, 0); | |
195 int top_left_x = (width + 20) * (i % 4); | |
196 int top_left_y = (height + 12) * (i % 3); | |
197 render_areas_.push_back(gfx::Rect(top_left_x, top_left_y, width, height)); | |
198 } | |
199 | 186 |
200 #if defined(OS_WIN) | 187 #if defined(OS_WIN) |
201 window_ = CreateWindowEx(0, | 188 window_ = CreateWindowEx(0, |
202 L"Static", | 189 L"Static", |
203 L"VideoDecodeAcceleratorTest", | 190 L"VideoDecodeAcceleratorTest", |
204 WS_OVERLAPPEDWINDOW | WS_VISIBLE, | 191 WS_OVERLAPPEDWINDOW | WS_VISIBLE, |
205 0, | 192 0, |
206 0, | 193 0, |
207 window_size.width(), | 194 screen_size_.width(), |
208 window_size.height(), | 195 screen_size_.height(), |
209 NULL, | 196 NULL, |
210 NULL, | 197 NULL, |
211 NULL, | 198 NULL, |
212 NULL); | 199 NULL); |
213 CHECK(window_ != NULL); | 200 CHECK(window_ != NULL); |
214 #else | 201 #else |
215 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_)); | 202 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_)); |
216 | 203 |
217 #if defined(GL_VARIANT_GLX) | 204 #if defined(GL_VARIANT_GLX) |
218 CHECK_EQ(depth, x_visual_->depth); | 205 CHECK_EQ(depth, x_visual_->depth); |
219 #endif | 206 #endif |
220 | 207 |
221 XSetWindowAttributes window_attributes; | 208 XSetWindowAttributes window_attributes; |
222 window_attributes.background_pixel = | 209 window_attributes.background_pixel = |
223 BlackPixel(x_display_, DefaultScreen(x_display_)); | 210 BlackPixel(x_display_, DefaultScreen(x_display_)); |
224 window_attributes.override_redirect = true; | 211 window_attributes.override_redirect = true; |
225 | 212 |
226 x_window_ = XCreateWindow(x_display_, | 213 x_window_ = XCreateWindow(x_display_, |
227 DefaultRootWindow(x_display_), | 214 DefaultRootWindow(x_display_), |
228 0, | 215 0, |
229 0, | 216 0, |
230 window_size.width(), | 217 screen_size_.width(), |
231 window_size.height(), | 218 screen_size_.height(), |
232 0 /* border width */, | 219 0 /* border width */, |
233 depth, | 220 depth, |
234 CopyFromParent /* class */, | 221 CopyFromParent /* class */, |
235 CopyFromParent /* visual */, | 222 CopyFromParent /* visual */, |
236 (CWBackPixel | CWOverrideRedirect), | 223 (CWBackPixel | CWOverrideRedirect), |
237 &window_attributes); | 224 &window_attributes); |
238 XStoreName(x_display_, x_window_, "VideoDecodeAcceleratorTest"); | 225 XStoreName(x_display_, x_window_, "VideoDecodeAcceleratorTest"); |
239 XSelectInput(x_display_, x_window_, ExposureMask); | 226 XSelectInput(x_display_, x_window_, ExposureMask); |
240 XMapWindow(x_display_, x_window_); | 227 XMapWindow(x_display_, x_window_); |
241 #endif | 228 #endif |
(...skipping 13 matching lines...) Expand all Loading... |
255 CHECK(glXMakeContextCurrent(x_display_, x_window_, x_window_, gl_context_)); | 242 CHECK(glXMakeContextCurrent(x_display_, x_window_, x_window_, gl_context_)); |
256 #else // EGL | 243 #else // EGL |
257 CHECK(eglMakeCurrent(gl_display_, gl_surface_, gl_surface_, gl_context_)) | 244 CHECK(eglMakeCurrent(gl_display_, gl_surface_, gl_surface_, gl_context_)) |
258 << eglGetError(); | 245 << eglGetError(); |
259 #endif | 246 #endif |
260 | 247 |
261 // Must be done after a context is made current. | 248 // Must be done after a context is made current. |
262 gfx::InitializeDynamicGLBindings(kGLImplementation, stub_context.get()); | 249 gfx::InitializeDynamicGLBindings(kGLImplementation, stub_context.get()); |
263 | 250 |
264 if (render_as_thumbnails_) { | 251 if (render_as_thumbnails_) { |
265 CHECK_EQ(frame_dimensions_.size(), 1U); | 252 CHECK_EQ(clients_.size(), 1U); |
266 | 253 |
267 GLint max_texture_size; | 254 GLint max_texture_size; |
268 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); | 255 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); |
269 CHECK_GE(max_texture_size, params.thumbnails_page_size.width()); | 256 CHECK_GE(max_texture_size, params.thumbnails_page_size.width()); |
270 CHECK_GE(max_texture_size, params.thumbnails_page_size.height()); | 257 CHECK_GE(max_texture_size, params.thumbnails_page_size.height()); |
271 | 258 |
272 thumbnails_fbo_size_ = params.thumbnails_page_size; | 259 thumbnails_fbo_size_ = params.thumbnails_page_size; |
273 thumbnail_size_ = params.thumbnail_size; | 260 thumbnail_size_ = params.thumbnail_size; |
274 | 261 |
275 glGenFramebuffersEXT(1, &thumbnails_fbo_id_); | 262 glGenFramebuffersEXT(1, &thumbnails_fbo_id_); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 #else // EGL | 387 #else // EGL |
401 CHECK(eglDestroyContext(gl_display_, gl_context_)); | 388 CHECK(eglDestroyContext(gl_display_, gl_context_)); |
402 CHECK(eglDestroySurface(gl_display_, gl_surface_)); | 389 CHECK(eglDestroySurface(gl_display_, gl_surface_)); |
403 CHECK(eglTerminate(gl_display_)); | 390 CHECK(eglTerminate(gl_display_)); |
404 #endif | 391 #endif |
405 gfx::ClearGLBindings(); | 392 gfx::ClearGLBindings(); |
406 Clear(); | 393 Clear(); |
407 done->Signal(); | 394 done->Signal(); |
408 } | 395 } |
409 | 396 |
410 void RenderingHelper::CreateTexture(int window_id, | 397 void RenderingHelper::CreateTexture(uint32 texture_target, |
411 uint32 texture_target, | |
412 uint32* texture_id, | 398 uint32* texture_id, |
| 399 const gfx::Size& size, |
413 base::WaitableEvent* done) { | 400 base::WaitableEvent* done) { |
414 if (base::MessageLoop::current() != message_loop_) { | 401 if (base::MessageLoop::current() != message_loop_) { |
415 message_loop_->PostTask( | 402 message_loop_->PostTask(FROM_HERE, |
416 FROM_HERE, | 403 base::Bind(&RenderingHelper::CreateTexture, |
417 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), | 404 base::Unretained(this), |
418 window_id, texture_target, texture_id, done)); | 405 texture_target, |
| 406 texture_id, |
| 407 size, |
| 408 done)); |
419 return; | 409 return; |
420 } | 410 } |
421 glGenTextures(1, texture_id); | 411 glGenTextures(1, texture_id); |
422 glBindTexture(texture_target, *texture_id); | 412 glBindTexture(texture_target, *texture_id); |
423 int dimensions_id = window_id % frame_dimensions_.size(); | |
424 if (texture_target == GL_TEXTURE_2D) { | 413 if (texture_target == GL_TEXTURE_2D) { |
425 glTexImage2D(GL_TEXTURE_2D, | 414 glTexImage2D(GL_TEXTURE_2D, |
426 0, | 415 0, |
427 GL_RGBA, | 416 GL_RGBA, |
428 frame_dimensions_[dimensions_id].width(), | 417 size.width(), |
429 frame_dimensions_[dimensions_id].height(), | 418 size.height(), |
430 0, | 419 0, |
431 GL_RGBA, | 420 GL_RGBA, |
432 GL_UNSIGNED_BYTE, | 421 GL_UNSIGNED_BYTE, |
433 NULL); | 422 NULL); |
434 } | 423 } |
435 glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 424 glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
436 glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 425 glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
437 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. | 426 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. |
438 glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 427 glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
439 glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 428 glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
440 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 429 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
441 CHECK(texture_id_to_surface_index_.insert( | |
442 std::make_pair(*texture_id, window_id)).second); | |
443 done->Signal(); | 430 done->Signal(); |
444 } | 431 } |
445 | 432 |
446 // Helper function to set GL viewport. | 433 // Helper function to set GL viewport. |
447 static inline void GLSetViewPort(const gfx::Rect& area) { | 434 static inline void GLSetViewPort(const gfx::Rect& area) { |
448 glViewport(area.x(), area.y(), area.width(), area.height()); | 435 glViewport(area.x(), area.y(), area.width(), area.height()); |
449 glScissor(area.x(), area.y(), area.width(), area.height()); | 436 glScissor(area.x(), area.y(), area.width(), area.height()); |
450 } | 437 } |
451 | 438 |
452 void RenderingHelper::RenderThumbnail(uint32 texture_target, | 439 void RenderingHelper::RenderThumbnail(uint32 texture_target, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 | 484 |
498 void* RenderingHelper::GetGLDisplay() { | 485 void* RenderingHelper::GetGLDisplay() { |
499 #if GL_VARIANT_GLX | 486 #if GL_VARIANT_GLX |
500 return x_display_; | 487 return x_display_; |
501 #else // EGL | 488 #else // EGL |
502 return gl_display_; | 489 return gl_display_; |
503 #endif | 490 #endif |
504 } | 491 } |
505 | 492 |
506 void RenderingHelper::Clear() { | 493 void RenderingHelper::Clear() { |
507 frame_dimensions_.clear(); | 494 clients_.clear(); |
508 texture_id_to_surface_index_.clear(); | |
509 message_loop_ = NULL; | 495 message_loop_ = NULL; |
510 gl_context_ = NULL; | 496 gl_context_ = NULL; |
511 #if GL_VARIANT_EGL | 497 #if GL_VARIANT_EGL |
512 gl_display_ = EGL_NO_DISPLAY; | 498 gl_display_ = EGL_NO_DISPLAY; |
513 gl_surface_ = EGL_NO_SURFACE; | 499 gl_surface_ = EGL_NO_SURFACE; |
514 #endif | 500 #endif |
515 render_as_thumbnails_ = false; | 501 render_as_thumbnails_ = false; |
516 frame_count_ = 0; | 502 frame_count_ = 0; |
517 thumbnails_fbo_id_ = 0; | 503 thumbnails_fbo_id_ = 0; |
518 thumbnails_texture_id_ = 0; | 504 thumbnails_texture_id_ = 0; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 } | 573 } |
588 } | 574 } |
589 | 575 |
590 #if GL_VARIANT_GLX | 576 #if GL_VARIANT_GLX |
591 glXSwapBuffers(x_display_, x_window_); | 577 glXSwapBuffers(x_display_, x_window_); |
592 #else // EGL | 578 #else // EGL |
593 eglSwapBuffers(gl_display_, gl_surface_); | 579 eglSwapBuffers(gl_display_, gl_surface_); |
594 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); | 580 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); |
595 #endif | 581 #endif |
596 } | 582 } |
| 583 |
| 584 // Helper function for the LayoutRenderingAreas(). The |lengths| are the |
| 585 // heights(widths) of the rows(columns). It scales the elements in |
| 586 // |lengths| proportionally so that the sum of them equal to |total_length|. |
| 587 // It also outputs the coordinates of the rows(columns) to |offsets|. |
| 588 static void ScaleAndCalculateOffsets(std::vector<int>* lengths, |
| 589 std::vector<int>* offsets, |
| 590 int total_length) { |
| 591 int sum = std::accumulate(lengths->begin(), lengths->end(), 0); |
| 592 for (size_t i = 0; i < lengths->size(); ++i) { |
| 593 lengths->at(i) = lengths->at(i) * total_length / sum; |
| 594 offsets->at(i) = (i == 0) ? 0 : offsets->at(i - 1) + lengths->at(i - 1); |
| 595 } |
| 596 } |
| 597 |
| 598 void RenderingHelper::LayoutRenderingAreas() { |
| 599 // Find the number of colums and rows. |
| 600 // The smallest n * n or n * (n + 1) > number of clients. |
| 601 size_t cols = sqrt(clients_.size() - 1) + 1; |
| 602 size_t rows = (clients_.size() + cols - 1) / cols; |
| 603 |
| 604 // Find the widths and heights of the grid. |
| 605 std::vector<int> widths(cols); |
| 606 std::vector<int> heights(rows); |
| 607 std::vector<int> offset_x(cols); |
| 608 std::vector<int> offset_y(rows); |
| 609 |
| 610 for (size_t i = 0; i < clients_.size(); ++i) { |
| 611 const gfx::Size& window_size = clients_[i]->GetWindowSize(); |
| 612 widths[i % cols] = std::max(widths[i % cols], window_size.width()); |
| 613 heights[i / cols] = std::max(heights[i / cols], window_size.height()); |
| 614 } |
| 615 |
| 616 ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width()); |
| 617 ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height()); |
| 618 |
| 619 // Put each render_area_ in the center of each cell. |
| 620 render_areas_.clear(); |
| 621 for (size_t i = 0; i < clients_.size(); ++i) { |
| 622 const gfx::Size& window_size = clients_[i]->GetWindowSize(); |
| 623 float scale = |
| 624 std::min(static_cast<float>(widths[i % cols]) / window_size.width(), |
| 625 static_cast<float>(heights[i / cols]) / window_size.height()); |
| 626 |
| 627 // Don't scale up the texture. |
| 628 scale = std::min(1.0f, scale); |
| 629 |
| 630 size_t w = scale * window_size.width(); |
| 631 size_t h = scale * window_size.height(); |
| 632 size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2; |
| 633 size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2; |
| 634 render_areas_.push_back(gfx::Rect(x, y, w, h)); |
| 635 } |
| 636 } |
597 } // namespace content | 637 } // namespace content |
OLD | NEW |