// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/browser/gpu/gpu_surface_tracker.h" #if defined(OS_ANDROID) #include #endif // defined(OS_ANDROID) #include "base/logging.h" #if defined(TOOLKIT_GTK) #include "base/bind.h" #include "content/public/browser/browser_thread.h" #include "ui/gfx/gtk_native_view_id_manager.h" #endif // defined(TOOLKIT_GTK) namespace content { namespace { #if defined(TOOLKIT_GTK) void ReleasePermanentXIDDispatcher( const gfx::PluginWindowHandle& surface) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); manager->ReleasePermanentXID(surface); } // Implementation of SurfaceRef that allows GTK to ref and unref the // surface with the GtkNativeViewManager. class SurfaceRefPluginWindow : public GpuSurfaceTracker::SurfaceRef { public: SurfaceRefPluginWindow(const gfx::PluginWindowHandle& surface_ref); private: virtual ~SurfaceRefPluginWindow(); gfx::PluginWindowHandle surface_; }; SurfaceRefPluginWindow::SurfaceRefPluginWindow( const gfx::PluginWindowHandle& surface) : surface_(surface) { if (surface_ != gfx::kNullPluginWindow) { GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); if (!manager->AddRefPermanentXID(surface_)) { LOG(ERROR) << "Surface " << surface << " cannot be referenced."; } } } SurfaceRefPluginWindow::~SurfaceRefPluginWindow() { if (surface_ != gfx::kNullPluginWindow) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&ReleasePermanentXIDDispatcher, surface_)); } } #endif // defined(TOOLKIT_GTK) } // anonymous GpuSurfaceTracker::GpuSurfaceTracker() : next_surface_id_(1) { GpuSurfaceLookup::InitInstance(this); } GpuSurfaceTracker::~GpuSurfaceTracker() { GpuSurfaceLookup::InitInstance(NULL); } GpuSurfaceTracker* GpuSurfaceTracker::GetInstance() { return Singleton::get(); } int GpuSurfaceTracker::AddSurfaceForRenderer(int renderer_id, int render_widget_id) { base::AutoLock lock(lock_); int surface_id = next_surface_id_++; surface_map_[surface_id] = SurfaceInfo(renderer_id, render_widget_id, gfx::kNullAcceleratedWidget, gfx::GLSurfaceHandle(), NULL); return surface_id; } int GpuSurfaceTracker::LookupSurfaceForRenderer(int renderer_id, int render_widget_id) { base::AutoLock lock(lock_); for (SurfaceMap::iterator it = surface_map_.begin(); it != surface_map_.end(); ++it) { const SurfaceInfo& info = it->second; if (info.renderer_id == renderer_id && info.render_widget_id == render_widget_id) { return it->first; } } return 0; } int GpuSurfaceTracker::AddSurfaceForNativeWidget( gfx::AcceleratedWidget widget) { base::AutoLock lock(lock_); int surface_id = next_surface_id_++; surface_map_[surface_id] = SurfaceInfo(0, 0, widget, gfx::GLSurfaceHandle(), NULL); return surface_id; } void GpuSurfaceTracker::RemoveSurface(int surface_id) { base::AutoLock lock(lock_); DCHECK(surface_map_.find(surface_id) != surface_map_.end()); surface_map_.erase(surface_id); } bool GpuSurfaceTracker::GetRenderWidgetIDForSurface(int surface_id, int* renderer_id, int* render_widget_id) { base::AutoLock lock(lock_); SurfaceMap::iterator it = surface_map_.find(surface_id); if (it == surface_map_.end()) return false; const SurfaceInfo& info = it->second; if (!info.handle.is_transport()) return false; *renderer_id = info.renderer_id; *render_widget_id = info.render_widget_id; return true; } void GpuSurfaceTracker::SetSurfaceHandle(int surface_id, const gfx::GLSurfaceHandle& handle) { base::AutoLock lock(lock_); DCHECK(surface_map_.find(surface_id) != surface_map_.end()); SurfaceInfo& info = surface_map_[surface_id]; info.handle = handle; #if defined(TOOLKIT_GTK) info.surface_ref = new SurfaceRefPluginWindow(handle.handle); #endif // defined(TOOLKIT_GTK) } gfx::GLSurfaceHandle GpuSurfaceTracker::GetSurfaceHandle(int surface_id) { base::AutoLock lock(lock_); SurfaceMap::iterator it = surface_map_.find(surface_id); if (it == surface_map_.end()) return gfx::GLSurfaceHandle(); return it->second.handle; } gfx::AcceleratedWidget GpuSurfaceTracker::AcquireNativeWidget(int surface_id) { base::AutoLock lock(lock_); SurfaceMap::iterator it = surface_map_.find(surface_id); if (it == surface_map_.end()) return gfx::kNullAcceleratedWidget; #if defined(OS_ANDROID) if (it->second.native_widget != gfx::kNullAcceleratedWidget) ANativeWindow_acquire(it->second.native_widget); #endif // defined(OS_ANDROID) return it->second.native_widget; } void GpuSurfaceTracker::SetNativeWidget( int surface_id, gfx::AcceleratedWidget widget, SurfaceRef* surface_ref) { base::AutoLock lock(lock_); SurfaceMap::iterator it = surface_map_.find(surface_id); DCHECK(it != surface_map_.end()); SurfaceInfo& info = it->second; info.native_widget = widget; info.surface_ref = surface_ref; } std::size_t GpuSurfaceTracker::GetSurfaceCount() { base::AutoLock lock(lock_); return surface_map_.size(); } GpuSurfaceTracker::SurfaceInfo::SurfaceInfo() : renderer_id(0), render_widget_id(0), native_widget(gfx::kNullAcceleratedWidget) { } GpuSurfaceTracker::SurfaceInfo::SurfaceInfo( int renderer_id, int render_widget_id, const gfx::AcceleratedWidget& native_widget, const gfx::GLSurfaceHandle& handle, const scoped_refptr& surface_ref) : renderer_id(renderer_id), render_widget_id(render_widget_id), native_widget(native_widget), handle(handle), surface_ref(surface_ref) { } GpuSurfaceTracker::SurfaceInfo::~SurfaceInfo() { } } // namespace content