1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/gpu/gpu_surface_tracker.h" 6 7 #if defined(OS_ANDROID) 8 #include <android/native_window_jni.h> 9 #endif // defined(OS_ANDROID) 10 11 #include "base/logging.h" 12 13 #if defined(TOOLKIT_GTK) 14 #include "base/bind.h" 15 #include "content/public/browser/browser_thread.h" 16 #include "ui/gfx/gtk_native_view_id_manager.h" 17 #endif // defined(TOOLKIT_GTK) 18 19 namespace content { 20 21 namespace { 22 #if defined(TOOLKIT_GTK) 23 24 void ReleasePermanentXIDDispatcher( 25 const gfx::PluginWindowHandle& surface) { 26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 27 28 GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); 29 manager->ReleasePermanentXID(surface); 30 } 31 32 // Implementation of SurfaceRef that allows GTK to ref and unref the 33 // surface with the GtkNativeViewManager. 34 class SurfaceRefPluginWindow : public GpuSurfaceTracker::SurfaceRef { 35 public: 36 SurfaceRefPluginWindow(const gfx::PluginWindowHandle& surface_ref); 37 private: 38 virtual ~SurfaceRefPluginWindow(); 39 gfx::PluginWindowHandle surface_; 40 }; 41 42 SurfaceRefPluginWindow::SurfaceRefPluginWindow( 43 const gfx::PluginWindowHandle& surface) 44 : surface_(surface) { 45 if (surface_ != gfx::kNullPluginWindow) { 46 GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); 47 if (!manager->AddRefPermanentXID(surface_)) { 48 LOG(ERROR) << "Surface " << surface << " cannot be referenced."; 49 } 50 } 51 } 52 53 SurfaceRefPluginWindow::~SurfaceRefPluginWindow() { 54 if (surface_ != gfx::kNullPluginWindow) { 55 BrowserThread::PostTask(BrowserThread::UI, 56 FROM_HERE, 57 base::Bind(&ReleasePermanentXIDDispatcher, 58 surface_)); 59 } 60 } 61 #endif // defined(TOOLKIT_GTK) 62 } // anonymous 63 64 GpuSurfaceTracker::GpuSurfaceTracker() 65 : next_surface_id_(1) { 66 GpuSurfaceLookup::InitInstance(this); 67 } 68 69 GpuSurfaceTracker::~GpuSurfaceTracker() { 70 GpuSurfaceLookup::InitInstance(NULL); 71 } 72 73 GpuSurfaceTracker* GpuSurfaceTracker::GetInstance() { 74 return Singleton<GpuSurfaceTracker>::get(); 75 } 76 77 int GpuSurfaceTracker::AddSurfaceForRenderer(int renderer_id, 78 int render_widget_id) { 79 base::AutoLock lock(lock_); 80 int surface_id = next_surface_id_++; 81 surface_map_[surface_id] = 82 SurfaceInfo(renderer_id, render_widget_id, gfx::kNullAcceleratedWidget, 83 gfx::GLSurfaceHandle(), NULL); 84 return surface_id; 85 } 86 87 int GpuSurfaceTracker::LookupSurfaceForRenderer(int renderer_id, 88 int render_widget_id) { 89 base::AutoLock lock(lock_); 90 for (SurfaceMap::iterator it = surface_map_.begin(); it != surface_map_.end(); 91 ++it) { 92 const SurfaceInfo& info = it->second; 93 if (info.renderer_id == renderer_id && 94 info.render_widget_id == render_widget_id) { 95 return it->first; 96 } 97 } 98 return 0; 99 } 100 101 int GpuSurfaceTracker::AddSurfaceForNativeWidget( 102 gfx::AcceleratedWidget widget) { 103 base::AutoLock lock(lock_); 104 int surface_id = next_surface_id_++; 105 surface_map_[surface_id] = 106 SurfaceInfo(0, 0, widget, gfx::GLSurfaceHandle(), NULL); 107 return surface_id; 108 } 109 110 void GpuSurfaceTracker::RemoveSurface(int surface_id) { 111 base::AutoLock lock(lock_); 112 DCHECK(surface_map_.find(surface_id) != surface_map_.end()); 113 surface_map_.erase(surface_id); 114 } 115 116 bool GpuSurfaceTracker::GetRenderWidgetIDForSurface(int surface_id, 117 int* renderer_id, 118 int* render_widget_id) { 119 base::AutoLock lock(lock_); 120 SurfaceMap::iterator it = surface_map_.find(surface_id); 121 if (it == surface_map_.end()) 122 return false; 123 const SurfaceInfo& info = it->second; 124 if (!info.handle.is_transport()) 125 return false; 126 *renderer_id = info.renderer_id; 127 *render_widget_id = info.render_widget_id; 128 return true; 129 } 130 131 void GpuSurfaceTracker::SetSurfaceHandle(int surface_id, 132 const gfx::GLSurfaceHandle& handle) { 133 base::AutoLock lock(lock_); 134 DCHECK(surface_map_.find(surface_id) != surface_map_.end()); 135 SurfaceInfo& info = surface_map_[surface_id]; 136 info.handle = handle; 137 #if defined(TOOLKIT_GTK) 138 info.surface_ref = new SurfaceRefPluginWindow(handle.handle); 139 #endif // defined(TOOLKIT_GTK) 140 } 141 142 gfx::GLSurfaceHandle GpuSurfaceTracker::GetSurfaceHandle(int surface_id) { 143 base::AutoLock lock(lock_); 144 SurfaceMap::iterator it = surface_map_.find(surface_id); 145 if (it == surface_map_.end()) 146 return gfx::GLSurfaceHandle(); 147 return it->second.handle; 148 } 149 150 gfx::AcceleratedWidget GpuSurfaceTracker::AcquireNativeWidget(int surface_id) { 151 base::AutoLock lock(lock_); 152 SurfaceMap::iterator it = surface_map_.find(surface_id); 153 if (it == surface_map_.end()) 154 return gfx::kNullAcceleratedWidget; 155 156 #if defined(OS_ANDROID) 157 if (it->second.native_widget != gfx::kNullAcceleratedWidget) 158 ANativeWindow_acquire(it->second.native_widget); 159 #endif // defined(OS_ANDROID) 160 161 return it->second.native_widget; 162 } 163 164 void GpuSurfaceTracker::SetNativeWidget( 165 int surface_id, gfx::AcceleratedWidget widget, 166 SurfaceRef* surface_ref) { 167 base::AutoLock lock(lock_); 168 SurfaceMap::iterator it = surface_map_.find(surface_id); 169 DCHECK(it != surface_map_.end()); 170 SurfaceInfo& info = it->second; 171 info.native_widget = widget; 172 info.surface_ref = surface_ref; 173 } 174 175 std::size_t GpuSurfaceTracker::GetSurfaceCount() { 176 base::AutoLock lock(lock_); 177 return surface_map_.size(); 178 } 179 180 GpuSurfaceTracker::SurfaceInfo::SurfaceInfo() 181 : renderer_id(0), 182 render_widget_id(0), 183 native_widget(gfx::kNullAcceleratedWidget) { } 184 185 GpuSurfaceTracker::SurfaceInfo::SurfaceInfo( 186 int renderer_id, 187 int render_widget_id, 188 const gfx::AcceleratedWidget& native_widget, 189 const gfx::GLSurfaceHandle& handle, 190 const scoped_refptr<SurfaceRef>& surface_ref) 191 : renderer_id(renderer_id), 192 render_widget_id(render_widget_id), 193 native_widget(native_widget), 194 handle(handle), 195 surface_ref(surface_ref) { } 196 197 GpuSurfaceTracker::SurfaceInfo::~SurfaceInfo() { } 198 199 200 } // namespace content 201