Index: content/common/gpu/media/rendering_helper.cc |
diff --git a/content/common/gpu/media/rendering_helper.cc b/content/common/gpu/media/rendering_helper.cc |
index 6abe8c5ca4dda93ac3032d70dee4deae488a1872..2b1f1dd4751755f4d35a17adca380758917621c4 100644 |
--- a/content/common/gpu/media/rendering_helper.cc |
+++ b/content/common/gpu/media/rendering_helper.cc |
@@ -4,6 +4,10 @@ |
#include "content/common/gpu/media/rendering_helper.h" |
+#include <algorithm> |
+#include <numeric> |
+#include <vector> |
+ |
#include "base/bind.h" |
#include "base/mac/scoped_nsautorelease_pool.h" |
#include "base/message_loop/message_loop.h" |
@@ -79,16 +83,15 @@ RenderingHelper::RenderingHelper() { |
} |
RenderingHelper::~RenderingHelper() { |
- CHECK_EQ(frame_dimensions_.size(), 0U) |
- << "Must call UnInitialize before dtor."; |
+ CHECK_EQ(clients_.size(), 0U) << "Must call UnInitialize before dtor."; |
Clear(); |
} |
void RenderingHelper::Initialize(const RenderingHelperParams& params, |
base::WaitableEvent* done) { |
- // Use frame_dimensions_.size() != 0 as a proxy for the class having already |
- // been Initialize()'d, and UnInitialize() before continuing. |
- if (frame_dimensions_.size()) { |
+ // Use cients_.size() != 0 as a proxy for the class having already been |
+ // Initialize()'d, and UnInitialize() before continuing. |
+ if (clients_.size()) { |
base::WaitableEvent done(false, false); |
UnInitialize(&done); |
done.Wait(); |
@@ -102,14 +105,8 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, |
scoped_refptr<gfx::GLContextStubWithExtensions> stub_context( |
new gfx::GLContextStubWithExtensions()); |
- CHECK_GT(params.window_dimensions.size(), 0U); |
- CHECK_EQ(params.frame_dimensions.size(), params.window_dimensions.size()); |
- frame_dimensions_ = params.frame_dimensions; |
render_as_thumbnails_ = params.render_as_thumbnails; |
message_loop_ = base::MessageLoop::current(); |
- CHECK_GT(params.num_windows, 0); |
- |
- gfx::Size window_size; |
#if GL_VARIANT_GLX |
x_display_ = gfx::GetXDisplay(); |
@@ -139,13 +136,13 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, |
reinterpret_cast<const char*>(glGetString(GL_VERSION))); |
Screen* screen = DefaultScreenOfDisplay(x_display_); |
- window_size = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); |
+ screen_size_ = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); |
#else // EGL |
EGLNativeDisplayType native_display; |
#if defined(OS_WIN) |
native_display = EGL_DEFAULT_DISPLAY; |
- window_size = |
+ screen_size_ = |
gfx::Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); |
#else |
x_display_ = gfx::GetXDisplay(); |
@@ -153,7 +150,7 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, |
native_display = x_display_; |
Screen* screen = DefaultScreenOfDisplay(x_display_); |
- window_size = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); |
+ screen_size_ = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); |
#endif |
gl_display_ = eglGetDisplay(native_display); |
CHECK(gl_display_); |
@@ -184,18 +181,8 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, |
reinterpret_cast<const char*>(glGetString(GL_VERSION))); |
#endif |
clients_ = params.clients; |
- // Per-window/surface X11 & EGL initialization. |
- for (int i = 0; i < params.num_windows; ++i) { |
- // Arrange X windows whimsically, with some padding. |
- int j = i % params.window_dimensions.size(); |
- int width = params.window_dimensions[j].width(); |
- int height = params.window_dimensions[j].height(); |
- CHECK_GT(width, 0); |
- CHECK_GT(height, 0); |
- int top_left_x = (width + 20) * (i % 4); |
- int top_left_y = (height + 12) * (i % 3); |
- render_areas_.push_back(gfx::Rect(top_left_x, top_left_y, width, height)); |
- } |
+ CHECK_GT(clients_.size(), 0U); |
+ LayoutRenderingAreas(); |
#if defined(OS_WIN) |
window_ = CreateWindowEx(0, |
@@ -204,8 +191,8 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, |
WS_OVERLAPPEDWINDOW | WS_VISIBLE, |
0, |
0, |
- window_size.width(), |
- window_size.height(), |
+ screen_size_.width(), |
+ screen_size_.height(), |
NULL, |
NULL, |
NULL, |
@@ -227,8 +214,8 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, |
DefaultRootWindow(x_display_), |
0, |
0, |
- window_size.width(), |
- window_size.height(), |
+ screen_size_.width(), |
+ screen_size_.height(), |
0 /* border width */, |
depth, |
CopyFromParent /* class */, |
@@ -262,7 +249,7 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, |
gfx::InitializeDynamicGLBindings(kGLImplementation, stub_context.get()); |
if (render_as_thumbnails_) { |
- CHECK_EQ(frame_dimensions_.size(), 1U); |
+ CHECK_EQ(clients_.size(), 1U); |
GLint max_texture_size; |
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); |
@@ -407,26 +394,28 @@ void RenderingHelper::UnInitialize(base::WaitableEvent* done) { |
done->Signal(); |
} |
-void RenderingHelper::CreateTexture(int window_id, |
- uint32 texture_target, |
+void RenderingHelper::CreateTexture(uint32 texture_target, |
uint32* texture_id, |
+ const gfx::Size& size, |
base::WaitableEvent* done) { |
if (base::MessageLoop::current() != message_loop_) { |
- message_loop_->PostTask( |
- FROM_HERE, |
- base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), |
- window_id, texture_target, texture_id, done)); |
+ message_loop_->PostTask(FROM_HERE, |
+ base::Bind(&RenderingHelper::CreateTexture, |
+ base::Unretained(this), |
+ texture_target, |
+ texture_id, |
+ size, |
+ done)); |
return; |
} |
glGenTextures(1, texture_id); |
glBindTexture(texture_target, *texture_id); |
- int dimensions_id = window_id % frame_dimensions_.size(); |
if (texture_target == GL_TEXTURE_2D) { |
glTexImage2D(GL_TEXTURE_2D, |
0, |
GL_RGBA, |
- frame_dimensions_[dimensions_id].width(), |
- frame_dimensions_[dimensions_id].height(), |
+ size.width(), |
+ size.height(), |
0, |
GL_RGBA, |
GL_UNSIGNED_BYTE, |
@@ -438,8 +427,6 @@ void RenderingHelper::CreateTexture(int window_id, |
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
- CHECK(texture_id_to_surface_index_.insert( |
- std::make_pair(*texture_id, window_id)).second); |
done->Signal(); |
} |
@@ -504,8 +491,7 @@ void* RenderingHelper::GetGLDisplay() { |
} |
void RenderingHelper::Clear() { |
- frame_dimensions_.clear(); |
- texture_id_to_surface_index_.clear(); |
+ clients_.clear(); |
message_loop_ = NULL; |
gl_context_ = NULL; |
#if GL_VARIANT_EGL |
@@ -594,4 +580,58 @@ void RenderingHelper::RenderContent() { |
CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); |
#endif |
} |
+ |
+// Helper function for the LayoutRenderingAreas(). The |lengths| are the |
+// heights(widths) of the rows(columns). It scales the elements in |
+// |lengths| proportionally so that the sum of them equal to |total_length|. |
+// It also outputs the coordinates of the rows(columns) to |offsets|. |
+static void ScaleAndCalculateOffsets(std::vector<int>* lengths, |
+ std::vector<int>* offsets, |
+ int total_length) { |
+ int sum = std::accumulate(lengths->begin(), lengths->end(), 0); |
+ for (size_t i = 0; i < lengths->size(); ++i) { |
+ lengths->at(i) = lengths->at(i) * total_length / sum; |
+ offsets->at(i) = (i == 0) ? 0 : offsets->at(i - 1) + lengths->at(i - 1); |
+ } |
+} |
+ |
+void RenderingHelper::LayoutRenderingAreas() { |
+ // Find the number of colums and rows. |
+ // The smallest n * n or n * (n + 1) > number of clients. |
+ size_t cols = sqrt(clients_.size() - 1) + 1; |
+ size_t rows = (clients_.size() + cols - 1) / cols; |
+ |
+ // Find the widths and heights of the grid. |
+ std::vector<int> widths(cols); |
+ std::vector<int> heights(rows); |
+ std::vector<int> offset_x(cols); |
+ std::vector<int> offset_y(rows); |
+ |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ const gfx::Size& window_size = clients_[i]->GetWindowSize(); |
+ widths[i % cols] = std::max(widths[i % cols], window_size.width()); |
+ heights[i / cols] = std::max(heights[i / cols], window_size.height()); |
+ } |
+ |
+ ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width()); |
+ ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height()); |
+ |
+ // Put each render_area_ in the center of each cell. |
+ render_areas_.clear(); |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ const gfx::Size& window_size = clients_[i]->GetWindowSize(); |
+ float scale = |
+ std::min(static_cast<float>(widths[i % cols]) / window_size.width(), |
+ static_cast<float>(heights[i / cols]) / window_size.height()); |
+ |
+ // Don't scale up the texture. |
+ scale = std::min(1.0f, scale); |
+ |
+ size_t w = scale * window_size.width(); |
+ size_t h = scale * window_size.height(); |
+ size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2; |
+ size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2; |
+ render_areas_.push_back(gfx::Rect(x, y, w, h)); |
+ } |
+} |
} // namespace content |