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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/mac/scoped_nsautorelease_pool.h" | 8 #include "base/mac/scoped_nsautorelease_pool.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/stringize_macros.h" | 10 #include "base/strings/stringize_macros.h" |
11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
12 #include "ui/gl/gl_context.h" | 12 #include "ui/gl/gl_context.h" |
13 #include "ui/gl/gl_context_stub_with_extensions.h" | 13 #include "ui/gl/gl_context_stub_with_extensions.h" |
14 #include "ui/gl/gl_implementation.h" | 14 #include "ui/gl/gl_implementation.h" |
15 #include "ui/gl/gl_surface.h" | 15 #include "ui/gl/gl_surface.h" |
16 | 16 |
17 #if defined(OS_WIN) | |
18 #include <windows.h> | |
19 #endif | |
20 | |
17 #if defined(USE_X11) | 21 #if defined(USE_X11) |
18 #include "ui/gfx/x/x11_types.h" | 22 #include "ui/gfx/x/x11_types.h" |
19 #endif | 23 #endif |
20 | 24 |
21 #ifdef GL_VARIANT_GLX | 25 #ifdef GL_VARIANT_GLX |
22 typedef GLXWindow NativeWindowType; | 26 typedef GLXWindow NativeWindowType; |
23 struct XFreeDeleter { | 27 struct XFreeDeleter { |
24 void operator()(void* x) const { ::XFree(x); } | 28 void operator()(void* x) const { ::XFree(x); } |
25 }; | 29 }; |
26 #else // EGL | 30 #else // EGL |
(...skipping 30 matching lines...) Expand all Loading... | |
57 #if defined(GL_VARIANT_GLX) | 61 #if defined(GL_VARIANT_GLX) |
58 gfx::kGLImplementationDesktopGL; | 62 gfx::kGLImplementationDesktopGL; |
59 #elif defined(GL_VARIANT_EGL) | 63 #elif defined(GL_VARIANT_EGL) |
60 gfx::kGLImplementationEGLGLES2; | 64 gfx::kGLImplementationEGLGLES2; |
61 #else | 65 #else |
62 -1; | 66 -1; |
63 #error "Unknown GL implementation." | 67 #error "Unknown GL implementation." |
64 #endif | 68 #endif |
65 | 69 |
66 RenderingHelper::RenderingHelper() { | 70 RenderingHelper::RenderingHelper() { |
71 #if defined(GL_VARIANT_EGL) | |
72 gl_surface_ = EGL_NO_SURFACE; | |
73 #endif | |
74 | |
75 #if defined(OS_WIN) | |
76 window_ = NULL; | |
77 #else | |
78 x_window_ = (Window)0; | |
79 #endif | |
80 | |
67 Clear(); | 81 Clear(); |
68 } | 82 } |
69 | 83 |
70 RenderingHelper::~RenderingHelper() { | 84 RenderingHelper::~RenderingHelper() { |
71 CHECK_EQ(window_dimensions_.size(), 0U) << | 85 CHECK_EQ(frame_dimensions_.size(), 0U) |
72 "Must call UnInitialize before dtor."; | 86 << "Must call UnInitialize before dtor."; |
73 Clear(); | 87 Clear(); |
74 } | 88 } |
75 | 89 |
76 void RenderingHelper::MakeCurrent(int window_id) { | |
77 #if GL_VARIANT_GLX | |
78 if (window_id < 0) { | |
79 CHECK(glXMakeContextCurrent(x_display_, GLX_NONE, GLX_NONE, NULL)); | |
80 } else { | |
81 CHECK(glXMakeContextCurrent( | |
82 x_display_, x_windows_[window_id], x_windows_[window_id], gl_context_)); | |
83 } | |
84 #else // EGL | |
85 if (window_id < 0) { | |
86 CHECK(eglMakeCurrent(gl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, | |
87 EGL_NO_CONTEXT)) << eglGetError(); | |
88 } else { | |
89 CHECK(eglMakeCurrent(gl_display_, gl_surfaces_[window_id], | |
90 gl_surfaces_[window_id], gl_context_)) | |
91 << eglGetError(); | |
92 } | |
93 #endif | |
94 } | |
95 | |
96 void RenderingHelper::Initialize(const RenderingHelperParams& params, | 90 void RenderingHelper::Initialize(const RenderingHelperParams& params, |
97 base::WaitableEvent* done) { | 91 base::WaitableEvent* done) { |
98 // Use window_dimensions_.size() != 0 as a proxy for the class having already | 92 // Use frame_dimensions_.size() != 0 as a proxy for the class having already |
99 // been Initialize()'d, and UnInitialize() before continuing. | 93 // been Initialize()'d, and UnInitialize() before continuing. |
100 if (window_dimensions_.size()) { | 94 if (frame_dimensions_.size()) { |
101 base::WaitableEvent done(false, false); | 95 base::WaitableEvent done(false, false); |
102 UnInitialize(&done); | 96 UnInitialize(&done); |
103 done.Wait(); | 97 done.Wait(); |
104 } | 98 } |
105 | 99 |
100 // TODO(owenlin): pass fps from params | |
101 frame_duration_ = base::TimeDelta::FromSeconds(1) / 60; | |
102 | |
106 gfx::InitializeStaticGLBindings(kGLImplementation); | 103 gfx::InitializeStaticGLBindings(kGLImplementation); |
107 scoped_refptr<gfx::GLContextStubWithExtensions> stub_context( | 104 scoped_refptr<gfx::GLContextStubWithExtensions> stub_context( |
108 new gfx::GLContextStubWithExtensions()); | 105 new gfx::GLContextStubWithExtensions()); |
109 | 106 |
110 CHECK_GT(params.window_dimensions.size(), 0U); | 107 CHECK_GT(params.window_dimensions.size(), 0U); |
111 CHECK_EQ(params.frame_dimensions.size(), params.window_dimensions.size()); | 108 CHECK_EQ(params.frame_dimensions.size(), params.window_dimensions.size()); |
112 window_dimensions_ = params.window_dimensions; | |
113 frame_dimensions_ = params.frame_dimensions; | 109 frame_dimensions_ = params.frame_dimensions; |
114 render_as_thumbnails_ = params.render_as_thumbnails; | 110 render_as_thumbnails_ = params.render_as_thumbnails; |
115 message_loop_ = base::MessageLoop::current(); | 111 message_loop_ = base::MessageLoop::current(); |
116 CHECK_GT(params.num_windows, 0); | 112 CHECK_GT(params.num_windows, 0); |
117 | 113 |
114 gfx::Size window_size; | |
115 | |
118 #if GL_VARIANT_GLX | 116 #if GL_VARIANT_GLX |
119 x_display_ = gfx::GetXDisplay(); | 117 x_display_ = gfx::GetXDisplay(); |
120 CHECK(x_display_); | 118 CHECK(x_display_); |
121 CHECK(glXQueryVersion(x_display_, NULL, NULL)); | 119 CHECK(glXQueryVersion(x_display_, NULL, NULL)); |
122 const int fbconfig_attr[] = { | 120 const int fbconfig_attr[] = { |
123 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, | 121 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, |
124 GLX_RENDER_TYPE, GLX_RGBA_BIT, | 122 GLX_RENDER_TYPE, GLX_RGBA_BIT, |
125 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, | 123 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, |
126 GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE, | 124 GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE, |
127 GLX_DOUBLEBUFFER, True, | 125 GLX_DOUBLEBUFFER, True, |
128 GL_NONE, | 126 GL_NONE, |
129 }; | 127 }; |
130 int num_fbconfigs; | 128 int num_fbconfigs; |
131 scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs( | 129 scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs( |
132 glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr, | 130 glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr, |
133 &num_fbconfigs)); | 131 &num_fbconfigs)); |
134 CHECK(glx_fb_configs.get()); | 132 CHECK(glx_fb_configs.get()); |
135 CHECK_GT(num_fbconfigs, 0); | 133 CHECK_GT(num_fbconfigs, 0); |
136 x_visual_ = glXGetVisualFromFBConfig(x_display_, glx_fb_configs.get()[0]); | 134 x_visual_ = glXGetVisualFromFBConfig(x_display_, glx_fb_configs.get()[0]); |
137 CHECK(x_visual_); | 135 CHECK(x_visual_); |
138 gl_context_ = glXCreateContext(x_display_, x_visual_, 0, true); | 136 gl_context_ = glXCreateContext(x_display_, x_visual_, 0, true); |
139 CHECK(gl_context_); | 137 CHECK(gl_context_); |
140 stub_context->AddExtensionsString( | 138 stub_context->AddExtensionsString( |
141 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); | 139 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); |
142 stub_context->SetGLVersionString( | 140 stub_context->SetGLVersionString( |
143 reinterpret_cast<const char*>(glGetString(GL_VERSION))); | 141 reinterpret_cast<const char*>(glGetString(GL_VERSION))); |
144 | 142 |
143 Screen* screen = DefaultScreenOfDisplay(x_display_); | |
144 window_size = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); | |
145 #else // EGL | 145 #else // EGL |
146 EGLNativeDisplayType native_display; | 146 EGLNativeDisplayType native_display; |
147 | 147 |
148 #if defined(OS_WIN) | 148 #if defined(OS_WIN) |
149 native_display = EGL_DEFAULT_DISPLAY; | 149 native_display = EGL_DEFAULT_DISPLAY; |
150 window_size = | |
151 gfx::Size(GetSystemMetrics(SM_CXSREEN), GetSystemMetrics(SM_CY_SCREEN)); | |
150 #else | 152 #else |
151 x_display_ = gfx::GetXDisplay(); | 153 x_display_ = gfx::GetXDisplay(); |
152 CHECK(x_display_); | 154 CHECK(x_display_); |
153 native_display = x_display_; | 155 native_display = x_display_; |
156 | |
157 Screen* screen = DefaultScreenOfDisplay(x_display_); | |
158 window_size = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen)); | |
154 #endif | 159 #endif |
155 | |
156 gl_display_ = eglGetDisplay(native_display); | 160 gl_display_ = eglGetDisplay(native_display); |
157 CHECK(gl_display_); | 161 CHECK(gl_display_); |
158 CHECK(eglInitialize(gl_display_, NULL, NULL)) << glGetError(); | 162 CHECK(eglInitialize(gl_display_, NULL, NULL)) << glGetError(); |
159 | 163 |
160 static EGLint rgba8888[] = { | 164 static EGLint rgba8888[] = { |
161 EGL_RED_SIZE, 8, | 165 EGL_RED_SIZE, 8, |
162 EGL_GREEN_SIZE, 8, | 166 EGL_GREEN_SIZE, 8, |
163 EGL_BLUE_SIZE, 8, | 167 EGL_BLUE_SIZE, 8, |
164 EGL_ALPHA_SIZE, 8, | 168 EGL_ALPHA_SIZE, 8, |
165 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | 169 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
166 EGL_NONE, | 170 EGL_NONE, |
167 }; | 171 }; |
168 EGLConfig egl_config; | 172 EGLConfig egl_config; |
169 int num_configs; | 173 int num_configs; |
170 CHECK(eglChooseConfig(gl_display_, rgba8888, &egl_config, 1, &num_configs)) | 174 CHECK(eglChooseConfig(gl_display_, rgba8888, &egl_config, 1, &num_configs)) |
171 << eglGetError(); | 175 << eglGetError(); |
172 CHECK_GE(num_configs, 1); | 176 CHECK_GE(num_configs, 1); |
173 static EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; | 177 static EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; |
174 gl_context_ = eglCreateContext( | 178 gl_context_ = eglCreateContext( |
175 gl_display_, egl_config, EGL_NO_CONTEXT, context_attribs); | 179 gl_display_, egl_config, EGL_NO_CONTEXT, context_attribs); |
176 CHECK_NE(gl_context_, EGL_NO_CONTEXT) << eglGetError(); | 180 CHECK_NE(gl_context_, EGL_NO_CONTEXT) << eglGetError(); |
177 stub_context->AddExtensionsString( | 181 stub_context->AddExtensionsString( |
178 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); | 182 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); |
179 stub_context->AddExtensionsString( | 183 stub_context->AddExtensionsString( |
180 eglQueryString(gl_display_, EGL_EXTENSIONS)); | 184 eglQueryString(gl_display_, EGL_EXTENSIONS)); |
181 stub_context->SetGLVersionString( | 185 stub_context->SetGLVersionString( |
182 reinterpret_cast<const char*>(glGetString(GL_VERSION))); | 186 reinterpret_cast<const char*>(glGetString(GL_VERSION))); |
183 #endif | 187 #endif |
184 | 188 |
185 // Per-window/surface X11 & EGL initialization. | 189 // Per-window/surface X11 & EGL initialization. |
Pawel Osciak
2014/05/27 06:21:49
CHECK(texture_ids_.empty());
CHECK(texture_targets
| |
186 for (int i = 0; i < params.num_windows; ++i) { | 190 for (int i = 0; i < params.num_windows; ++i) { |
187 // Arrange X windows whimsically, with some padding. | 191 // Arrange X windows whimsically, with some padding. |
188 int j = i % window_dimensions_.size(); | 192 int j = i % params.window_dimensions.size(); |
189 int width = window_dimensions_[j].width(); | 193 int width = params.window_dimensions[j].width(); |
190 int height = window_dimensions_[j].height(); | 194 int height = params.window_dimensions[j].height(); |
191 CHECK_GT(width, 0); | 195 CHECK_GT(width, 0); |
192 CHECK_GT(height, 0); | 196 CHECK_GT(height, 0); |
193 int top_left_x = (width + 20) * (i % 4); | 197 int top_left_x = (width + 20) * (i % 4); |
194 int top_left_y = (height + 12) * (i % 3); | 198 int top_left_y = (height + 12) * (i % 3); |
199 render_areas_.push_back(gfx::Rect(top_left_x, top_left_y, width, height)); | |
200 | |
201 // Initialize to an invalid texture id: 0 to indicate no texture | |
202 // for rendering. | |
203 texture_ids_.push_back(0); | |
Pawel Osciak
2014/05/27 06:21:49
You could achieve the same by saying outside of th
Owen Lin
2014/05/27 07:33:51
Thanks.
| |
204 texture_targets_.push_back(0); | |
205 } | |
195 | 206 |
196 #if defined(OS_WIN) | 207 #if defined(OS_WIN) |
197 NativeWindowType window = | 208 window_ = CreateWindowEx(0, |
198 CreateWindowEx(0, L"Static", L"VideoDecodeAcceleratorTest", | 209 L"Static", |
199 WS_OVERLAPPEDWINDOW | WS_VISIBLE, top_left_x, | 210 L"VideoDecodeAcceleratorTest", |
200 top_left_y, width, height, NULL, NULL, NULL, | 211 WS_OVERLAPPEDWINDOW | WS_VISIBLE, |
201 NULL); | 212 0, |
202 CHECK(window != NULL); | 213 0, |
203 windows_.push_back(window); | 214 window_size.width(), |
215 window_size.height(), | |
216 NULL, | |
217 NULL, | |
218 NULL, | |
219 NULL); | |
220 CHECK(window_ != NULL); | |
204 #else | 221 #else |
205 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_)); | 222 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_)); |
206 | 223 |
207 #if defined(GL_VARIANT_GLX) | 224 #if defined(GL_VARIANT_GLX) |
208 CHECK_EQ(depth, x_visual_->depth); | 225 CHECK_EQ(depth, x_visual_->depth); |
209 #endif | 226 #endif |
210 | 227 |
211 XSetWindowAttributes window_attributes; | 228 XSetWindowAttributes window_attributes; |
212 window_attributes.background_pixel = | 229 window_attributes.background_pixel = |
213 BlackPixel(x_display_, DefaultScreen(x_display_)); | 230 BlackPixel(x_display_, DefaultScreen(x_display_)); |
214 window_attributes.override_redirect = true; | 231 window_attributes.override_redirect = true; |
215 | 232 |
216 NativeWindowType window = XCreateWindow( | 233 x_window_ = XCreateWindow(x_display_, |
217 x_display_, DefaultRootWindow(x_display_), | 234 DefaultRootWindow(x_display_), |
218 top_left_x, top_left_y, width, height, | 235 0, |
219 0 /* border width */, | 236 0, |
220 depth, CopyFromParent /* class */, CopyFromParent /* visual */, | 237 window_size.width(), |
221 (CWBackPixel | CWOverrideRedirect), &window_attributes); | 238 window_size.height(), |
222 XStoreName(x_display_, window, "VideoDecodeAcceleratorTest"); | 239 0 /* border width */, |
223 XSelectInput(x_display_, window, ExposureMask); | 240 depth, |
224 XMapWindow(x_display_, window); | 241 CopyFromParent /* class */, |
225 x_windows_.push_back(window); | 242 CopyFromParent /* visual */, |
243 (CWBackPixel | CWOverrideRedirect), | |
244 &window_attributes); | |
245 XStoreName(x_display_, x_window_, "VideoDecodeAcceleratorTest"); | |
246 XSelectInput(x_display_, x_window_, ExposureMask); | |
247 XMapWindow(x_display_, x_window_); | |
226 #endif | 248 #endif |
227 | 249 |
228 #if GL_VARIANT_EGL | 250 #if GL_VARIANT_EGL |
229 EGLSurface egl_surface = | 251 gl_surface_ = |
230 eglCreateWindowSurface(gl_display_, egl_config, window, NULL); | 252 eglCreateWindowSurface(gl_display_, egl_config, x_window_, NULL); |
231 gl_surfaces_.push_back(egl_surface); | 253 CHECK_NE(gl_surface_, EGL_NO_SURFACE); |
232 CHECK_NE(egl_surface, EGL_NO_SURFACE); | |
233 #endif | 254 #endif |
234 MakeCurrent(i); | 255 |
235 } | 256 #if GL_VARIANT_GLX |
257 CHECK(glXMakeContextCurrent(x_display_, x_window_, x_window_, gl_context_)); | |
258 #else // EGL | |
259 CHECK(eglMakeCurrent(gl_display_, gl_surface_, gl_surface_, gl_context_)) | |
260 << eglGetError(); | |
261 #endif | |
236 | 262 |
237 // Must be done after a context is made current. | 263 // Must be done after a context is made current. |
238 gfx::InitializeDynamicGLBindings(kGLImplementation, stub_context.get()); | 264 gfx::InitializeDynamicGLBindings(kGLImplementation, stub_context.get()); |
239 | 265 |
240 if (render_as_thumbnails_) { | 266 if (render_as_thumbnails_) { |
241 CHECK_EQ(window_dimensions_.size(), 1U); | 267 CHECK_EQ(frame_dimensions_.size(), 1U); |
242 | 268 |
243 GLint max_texture_size; | 269 GLint max_texture_size; |
244 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); | 270 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); |
245 CHECK_GE(max_texture_size, params.thumbnails_page_size.width()); | 271 CHECK_GE(max_texture_size, params.thumbnails_page_size.width()); |
246 CHECK_GE(max_texture_size, params.thumbnails_page_size.height()); | 272 CHECK_GE(max_texture_size, params.thumbnails_page_size.height()); |
247 | 273 |
248 thumbnails_fbo_size_ = params.thumbnails_page_size; | 274 thumbnails_fbo_size_ = params.thumbnails_page_size; |
249 thumbnail_size_ = params.thumbnail_size; | 275 thumbnail_size_ = params.thumbnail_size; |
250 | 276 |
251 glGenFramebuffersEXT(1, &thumbnails_fbo_id_); | 277 glGenFramebuffersEXT(1, &thumbnails_fbo_id_); |
(...skipping 18 matching lines...) Expand all Loading... | |
270 GL_COLOR_ATTACHMENT0, | 296 GL_COLOR_ATTACHMENT0, |
271 GL_TEXTURE_2D, | 297 GL_TEXTURE_2D, |
272 thumbnails_texture_id_, | 298 thumbnails_texture_id_, |
273 0); | 299 0); |
274 | 300 |
275 GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 301 GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
276 CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << fb_status; | 302 CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << fb_status; |
277 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | 303 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
278 glClear(GL_COLOR_BUFFER_BIT); | 304 glClear(GL_COLOR_BUFFER_BIT); |
279 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | 305 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
306 | |
307 // In render_as_thumbnails_ mode, we render the FBO content on the | |
308 // screen instead of the decoded textures. | |
309 texture_targets_[0] = GL_TEXTURE_2D; | |
310 texture_ids_[0] = thumbnails_texture_id_; | |
280 } | 311 } |
281 | 312 |
282 // These vertices and texture coords. map (0,0) in the texture to the | 313 // These vertices and texture coords. map (0,0) in the texture to the |
283 // bottom left of the viewport. Since we get the video frames with the | 314 // bottom left of the viewport. Since we get the video frames with the |
284 // the top left at (0,0) we need to flip the texture y coordinate | 315 // the top left at (0,0) we need to flip the texture y coordinate |
285 // in the vertex shader for this to be rendered the right way up. | 316 // in the vertex shader for this to be rendered the right way up. |
286 // In the case of thumbnail rendering we use the same vertex shader | 317 // In the case of thumbnail rendering we use the same vertex shader |
287 // to render the FBO the screen, where we do not want this flipping. | 318 // to render the FBO the screen, where we do not want this flipping. |
288 static const float kVertices[] = | 319 static const float kVertices[] = |
289 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, }; | 320 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, }; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 GLint tex_external = glGetUniformLocation(program_, "tex_external"); | 379 GLint tex_external = glGetUniformLocation(program_, "tex_external"); |
349 if (tex_external != -1) { | 380 if (tex_external != -1) { |
350 glUniform1i(tex_external, 1); | 381 glUniform1i(tex_external, 1); |
351 } | 382 } |
352 int pos_location = glGetAttribLocation(program_, "in_pos"); | 383 int pos_location = glGetAttribLocation(program_, "in_pos"); |
353 glEnableVertexAttribArray(pos_location); | 384 glEnableVertexAttribArray(pos_location); |
354 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); | 385 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); |
355 int tc_location = glGetAttribLocation(program_, "in_tc"); | 386 int tc_location = glGetAttribLocation(program_, "in_tc"); |
356 glEnableVertexAttribArray(tc_location); | 387 glEnableVertexAttribArray(tc_location); |
357 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords); | 388 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords); |
389 | |
390 render_timer_.Start( | |
391 FROM_HERE, frame_duration_, this, &RenderingHelper::RenderContent); | |
358 done->Signal(); | 392 done->Signal(); |
359 } | 393 } |
360 | 394 |
361 void RenderingHelper::UnInitialize(base::WaitableEvent* done) { | 395 void RenderingHelper::UnInitialize(base::WaitableEvent* done) { |
362 CHECK_EQ(base::MessageLoop::current(), message_loop_); | 396 CHECK_EQ(base::MessageLoop::current(), message_loop_); |
397 render_timer_.Stop(); | |
363 if (render_as_thumbnails_) { | 398 if (render_as_thumbnails_) { |
364 glDeleteTextures(1, &thumbnails_texture_id_); | 399 glDeleteTextures(1, &thumbnails_texture_id_); |
365 glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_); | 400 glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_); |
366 } | 401 } |
367 #if GL_VARIANT_GLX | 402 #if GL_VARIANT_GLX |
368 | 403 |
369 glXDestroyContext(x_display_, gl_context_); | 404 glXDestroyContext(x_display_, gl_context_); |
370 #else // EGL | 405 #else // EGL |
371 MakeCurrent(-1); | |
372 CHECK(eglDestroyContext(gl_display_, gl_context_)); | 406 CHECK(eglDestroyContext(gl_display_, gl_context_)); |
373 for (size_t i = 0; i < gl_surfaces_.size(); ++i) | 407 CHECK(eglDestroySurface(gl_display_, gl_surface_)); |
374 CHECK(eglDestroySurface(gl_display_, gl_surfaces_[i])); | |
375 CHECK(eglTerminate(gl_display_)); | 408 CHECK(eglTerminate(gl_display_)); |
376 #endif | 409 #endif |
377 gfx::ClearGLBindings(); | 410 gfx::ClearGLBindings(); |
378 Clear(); | 411 Clear(); |
379 done->Signal(); | 412 done->Signal(); |
380 } | 413 } |
381 | 414 |
382 void RenderingHelper::CreateTexture(int window_id, | 415 void RenderingHelper::CreateTexture(int window_id, |
383 uint32 texture_target, | 416 uint32 texture_target, |
384 uint32* texture_id, | 417 uint32* texture_id, |
385 base::WaitableEvent* done) { | 418 base::WaitableEvent* done) { |
386 if (base::MessageLoop::current() != message_loop_) { | 419 if (base::MessageLoop::current() != message_loop_) { |
387 message_loop_->PostTask( | 420 message_loop_->PostTask( |
388 FROM_HERE, | 421 FROM_HERE, |
389 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), | 422 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), |
390 window_id, texture_target, texture_id, done)); | 423 window_id, texture_target, texture_id, done)); |
391 return; | 424 return; |
392 } | 425 } |
393 MakeCurrent(window_id); | |
394 glGenTextures(1, texture_id); | 426 glGenTextures(1, texture_id); |
395 glBindTexture(texture_target, *texture_id); | 427 glBindTexture(texture_target, *texture_id); |
396 int dimensions_id = window_id % frame_dimensions_.size(); | 428 int dimensions_id = window_id % frame_dimensions_.size(); |
397 if (texture_target == GL_TEXTURE_2D) { | 429 if (texture_target == GL_TEXTURE_2D) { |
398 glTexImage2D(GL_TEXTURE_2D, | 430 glTexImage2D(GL_TEXTURE_2D, |
399 0, | 431 0, |
400 GL_RGBA, | 432 GL_RGBA, |
401 frame_dimensions_[dimensions_id].width(), | 433 frame_dimensions_[dimensions_id].width(), |
402 frame_dimensions_[dimensions_id].height(), | 434 frame_dimensions_[dimensions_id].height(), |
403 0, | 435 0, |
404 GL_RGBA, | 436 GL_RGBA, |
405 GL_UNSIGNED_BYTE, | 437 GL_UNSIGNED_BYTE, |
406 NULL); | 438 NULL); |
407 } | 439 } |
408 glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 440 glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
409 glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 441 glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
410 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. | 442 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. |
411 glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 443 glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
412 glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 444 glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
413 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 445 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
414 CHECK(texture_id_to_surface_index_.insert( | 446 CHECK(texture_id_to_surface_index_.insert( |
415 std::make_pair(*texture_id, window_id)).second); | 447 std::make_pair(*texture_id, window_id)).second); |
416 done->Signal(); | 448 done->Signal(); |
417 } | 449 } |
418 | 450 |
419 void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) { | 451 void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) { |
420 CHECK_EQ(base::MessageLoop::current(), message_loop_); | 452 CHECK_EQ(base::MessageLoop::current(), message_loop_); |
421 size_t window_id = texture_id_to_surface_index_[texture_id]; | 453 if (texture_id == 0) |
422 MakeCurrent(window_id); | 454 return; |
423 | |
424 int dimensions_id = window_id % window_dimensions_.size(); | |
425 int width = window_dimensions_[dimensions_id].width(); | |
426 int height = window_dimensions_[dimensions_id].height(); | |
427 | 455 |
428 if (render_as_thumbnails_) { | 456 if (render_as_thumbnails_) { |
429 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_); | 457 const int width = thumbnail_size_.width(); |
430 const int thumbnails_in_row = | 458 const int height = thumbnail_size_.height(); |
431 thumbnails_fbo_size_.width() / thumbnail_size_.width(); | 459 const int thumbnails_in_row = thumbnails_fbo_size_.width() / width; |
432 const int thumbnails_in_column = | 460 const int thumbnails_in_column = thumbnails_fbo_size_.height() / height; |
433 thumbnails_fbo_size_.height() / thumbnail_size_.height(); | |
434 const int row = (frame_count_ / thumbnails_in_row) % thumbnails_in_column; | 461 const int row = (frame_count_ / thumbnails_in_row) % thumbnails_in_column; |
435 const int col = frame_count_ % thumbnails_in_row; | 462 const int col = frame_count_ % thumbnails_in_row; |
436 const int x = col * thumbnail_size_.width(); | |
437 const int y = row * thumbnail_size_.height(); | |
438 | 463 |
439 glViewport(x, y, thumbnail_size_.width(), thumbnail_size_.height()); | 464 gfx::Rect area(col * width, row * height, width, height); |
440 glScissor(x, y, thumbnail_size_.width(), thumbnail_size_.height()); | 465 |
441 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0); | 466 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0); |
467 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_); | |
468 DrawTexture(area, texture_target, texture_id); | |
469 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | |
470 ++frame_count_; | |
442 } else { | 471 } else { |
443 glViewport(0, 0, width, height); | 472 size_t window_id = texture_id_to_surface_index_[texture_id]; |
444 glScissor(0, 0, width, height); | 473 texture_targets_[window_id] = texture_target; |
445 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); | 474 texture_ids_[window_id] = texture_id; |
Pawel Osciak
2014/05/27 06:21:49
It looks to me that RenderTexture() used to be syn
Owen Lin
2014/05/27 07:33:51
Ah, you are right. There is problem in this code.
Pawel Osciak
2014/05/28 05:45:52
Hm, I guess merging is probably better once we lgt
| |
446 } | 475 } |
476 } | |
477 | |
478 void RenderingHelper::DrawTexture(const gfx::Rect& area, | |
479 uint32 texture_target, | |
480 uint32 texture_id) { | |
481 glViewport(area.x(), area.y(), area.width(), area.height()); | |
482 glScissor(area.x(), area.y(), area.width(), area.height()); | |
447 | 483 |
448 // Unbound texture samplers default to (0, 0, 0, 1). Use this fact to switch | 484 // Unbound texture samplers default to (0, 0, 0, 1). Use this fact to switch |
449 // between GL_TEXTURE_2D and GL_TEXTURE_EXTERNAL_OES as appopriate. | 485 // between GL_TEXTURE_2D and GL_TEXTURE_EXTERNAL_OES as appopriate. |
450 if (texture_target == GL_TEXTURE_2D) { | 486 if (texture_target == GL_TEXTURE_2D) { |
451 glActiveTexture(GL_TEXTURE0 + 0); | 487 glActiveTexture(GL_TEXTURE0 + 0); |
452 glBindTexture(GL_TEXTURE_2D, texture_id); | 488 glBindTexture(GL_TEXTURE_2D, texture_id); |
453 glActiveTexture(GL_TEXTURE0 + 1); | 489 glActiveTexture(GL_TEXTURE0 + 1); |
454 glBindTexture(texture_target, 0); | 490 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); |
455 } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) { | 491 } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) { |
456 glActiveTexture(GL_TEXTURE0 + 0); | 492 glActiveTexture(GL_TEXTURE0 + 0); |
457 glBindTexture(GL_TEXTURE_2D, 0); | 493 glBindTexture(GL_TEXTURE_2D, 0); |
458 glActiveTexture(GL_TEXTURE0 + 1); | 494 glActiveTexture(GL_TEXTURE0 + 1); |
459 glBindTexture(texture_target, texture_id); | 495 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id); |
460 } | 496 } |
497 | |
461 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 498 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
462 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 499 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
463 | |
464 ++frame_count_; | |
465 | |
466 if (render_as_thumbnails_) { | |
467 // Copy from FBO to screen | |
468 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); | |
469 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | |
470 glViewport(0, 0, width, height); | |
471 glScissor(0, 0, width, height); | |
472 glActiveTexture(GL_TEXTURE0 + 0); | |
473 glBindTexture(GL_TEXTURE_2D, thumbnails_texture_id_); | |
474 glActiveTexture(GL_TEXTURE0 + 1); | |
475 glBindTexture(texture_target, 0); | |
476 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
477 } | |
478 | |
479 #if GL_VARIANT_GLX | |
480 glXSwapBuffers(x_display_, x_windows_[window_id]); | |
481 #else // EGL | |
482 eglSwapBuffers(gl_display_, gl_surfaces_[window_id]); | |
483 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); | |
484 #endif | |
485 } | 500 } |
486 | 501 |
487 void RenderingHelper::DeleteTexture(uint32 texture_id) { | 502 void RenderingHelper::DeleteTexture(uint32 texture_id) { |
488 glDeleteTextures(1, &texture_id); | 503 glDeleteTextures(1, &texture_id); |
489 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 504 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
490 } | 505 } |
491 | 506 |
492 NativeContextType RenderingHelper::GetGLContext() { return gl_context_; } | 507 NativeContextType RenderingHelper::GetGLContext() { return gl_context_; } |
493 | 508 |
494 void* RenderingHelper::GetGLDisplay() { | 509 void* RenderingHelper::GetGLDisplay() { |
495 #if GL_VARIANT_GLX | 510 #if GL_VARIANT_GLX |
496 return x_display_; | 511 return x_display_; |
497 #else // EGL | 512 #else // EGL |
498 return gl_display_; | 513 return gl_display_; |
499 #endif | 514 #endif |
500 } | 515 } |
501 | 516 |
502 void RenderingHelper::Clear() { | 517 void RenderingHelper::Clear() { |
503 window_dimensions_.clear(); | |
504 frame_dimensions_.clear(); | 518 frame_dimensions_.clear(); |
505 texture_id_to_surface_index_.clear(); | 519 texture_id_to_surface_index_.clear(); |
506 message_loop_ = NULL; | 520 message_loop_ = NULL; |
507 gl_context_ = NULL; | 521 gl_context_ = NULL; |
508 #if GL_VARIANT_EGL | 522 #if GL_VARIANT_EGL |
509 gl_display_ = EGL_NO_DISPLAY; | 523 gl_display_ = EGL_NO_DISPLAY; |
510 gl_surfaces_.clear(); | 524 gl_surface_ = EGL_NO_SURFACE; |
511 #endif | 525 #endif |
512 render_as_thumbnails_ = false; | 526 render_as_thumbnails_ = false; |
513 frame_count_ = 0; | 527 frame_count_ = 0; |
514 thumbnails_fbo_id_ = 0; | 528 thumbnails_fbo_id_ = 0; |
515 thumbnails_texture_id_ = 0; | 529 thumbnails_texture_id_ = 0; |
516 | 530 |
517 #if defined(OS_WIN) | 531 #if defined(OS_WIN) |
518 for (size_t i = 0; i < windows_.size(); ++i) { | 532 if (window_) { |
519 DestroyWindow(windows_[i]); | 533 DestroyWindow(window_); |
534 window_ = NULL; | |
520 } | 535 } |
521 windows_.clear(); | |
522 #else | 536 #else |
523 // Destroy resources acquired in Initialize, in reverse-acquisition order. | 537 // Destroy resources acquired in Initialize, in reverse-acquisition order. |
524 for (size_t i = 0; i < x_windows_.size(); ++i) { | 538 if (x_window_) { |
525 CHECK(XUnmapWindow(x_display_, x_windows_[i])); | 539 CHECK(XUnmapWindow(x_display_, x_window_)); |
526 CHECK(XDestroyWindow(x_display_, x_windows_[i])); | 540 CHECK(XDestroyWindow(x_display_, x_window_)); |
541 x_window_ = (Window)0; | |
527 } | 542 } |
528 // Mimic newly created object. | 543 // Mimic newly created object. |
529 x_display_ = NULL; | 544 x_display_ = NULL; |
530 x_windows_.clear(); | |
531 #endif | 545 #endif |
532 } | 546 } |
533 | 547 |
534 void RenderingHelper::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb, | 548 void RenderingHelper::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb, |
535 bool* alpha_solid, | 549 bool* alpha_solid, |
536 base::WaitableEvent* done) { | 550 base::WaitableEvent* done) { |
537 CHECK(render_as_thumbnails_); | 551 CHECK(render_as_thumbnails_); |
538 | 552 |
539 const size_t num_pixels = thumbnails_fbo_size_.GetArea(); | 553 const size_t num_pixels = thumbnails_fbo_size_.GetArea(); |
540 std::vector<unsigned char> rgba; | 554 std::vector<unsigned char> rgba; |
(...skipping 19 matching lines...) Expand all Loading... | |
560 *rgb_ptr++ = *rgba_ptr++; | 574 *rgb_ptr++ = *rgba_ptr++; |
561 *rgb_ptr++ = *rgba_ptr++; | 575 *rgb_ptr++ = *rgba_ptr++; |
562 solid = solid && (*rgba_ptr == 0xff); | 576 solid = solid && (*rgba_ptr == 0xff); |
563 rgba_ptr++; | 577 rgba_ptr++; |
564 } | 578 } |
565 *alpha_solid = solid; | 579 *alpha_solid = solid; |
566 | 580 |
567 done->Signal(); | 581 done->Signal(); |
568 } | 582 } |
569 | 583 |
584 void RenderingHelper::RenderContent() { | |
585 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); | |
586 for (size_t i = 0; i < render_areas_.size(); ++i) { | |
587 DrawTexture(render_areas_[i], texture_targets_[i], texture_ids_[i]); | |
588 } | |
589 | |
590 #if GL_VARIANT_GLX | |
591 glXSwapBuffers(x_display_, x_window_); | |
592 #else // EGL | |
593 eglSwapBuffers(gl_display_, gl_surface_); | |
594 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); | |
595 #endif | |
596 } | |
570 } // namespace content | 597 } // namespace content |
OLD | NEW |