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