Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 "wm/gpu/foreign_window_texture_factory.h" | |
| 6 | |
| 7 #include "base/lazy_instance.h" | |
| 8 #include "base/observer_list.h" | |
| 9 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" | |
| 10 #include "content/common/gpu/client/gl_helper.h" | |
| 11 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3 D.h" | |
| 12 #include "third_party/khronos/GLES2/gl2.h" | |
| 13 #include "ui/compositor/compositor_setup.h" | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 class DefaultGpuChannelHostFactory : public content::GpuChannelHostFactory { | |
| 18 public: | |
| 19 DefaultGpuChannelHostFactory() {} | |
| 20 | |
| 21 virtual bool IsMainThread() OVERRIDE { | |
| 22 return false; | |
| 23 } | |
| 24 virtual bool IsIOThread() OVERRIDE { | |
| 25 return false; | |
| 26 } | |
| 27 virtual MessageLoop* GetMainLoop() OVERRIDE { | |
| 28 return NULL; | |
| 29 } | |
| 30 virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE { | |
| 31 return NULL; | |
| 32 } | |
| 33 virtual base::WaitableEvent* GetShutDownEvent() OVERRIDE { return NULL; } | |
| 34 virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory( | |
| 35 size_t size) OVERRIDE { | |
| 36 return scoped_ptr<base::SharedMemory>(); | |
| 37 } | |
| 38 virtual int32 CreateViewCommandBuffer( | |
| 39 int32 surface_id, | |
| 40 const GPUCreateCommandBufferConfig& init_params) OVERRIDE { | |
| 41 return 0; | |
| 42 } | |
| 43 virtual content::GpuChannelHost* EstablishGpuChannelSync( | |
| 44 content::CauseForGpuLaunch) OVERRIDE { | |
| 45 return NULL; | |
| 46 } | |
| 47 virtual void CreateImage( | |
| 48 gfx::PluginWindowHandle window, | |
| 49 int32 image_id, | |
| 50 const CreateImageCallback& callback) OVERRIDE { | |
| 51 callback.Run(gfx::Size()); | |
| 52 } | |
| 53 virtual void DeleteImage(int32 image_id, int32 sync_point) OVERRIDE {} | |
| 54 }; | |
| 55 | |
| 56 base::LazyInstance<DefaultGpuChannelHostFactory> g_default_factory = | |
| 57 LAZY_INSTANCE_INITIALIZER; | |
| 58 | |
| 59 } // namespace | |
| 60 | |
| 61 namespace wm { | |
| 62 | |
| 63 // static | |
| 64 ForeignWindowTextureFactory* ForeignWindowTextureFactory::instance_ = NULL; | |
| 65 | |
| 66 ForeignWindowTexture::ForeignWindowTexture( | |
| 67 content::GpuChannelHostFactory* factory, | |
| 68 WebKit::WebGraphicsContext3D* host_context, | |
| 69 bool flipped, | |
| 70 const gfx::Size& size, | |
| 71 float device_scale_factor, | |
| 72 int32 image_id) : ui::Texture(flipped, size, device_scale_factor), | |
|
danakj
2013/02/21 01:33:15
shouldn't : be on next line?
reveman
2013/02/22 01:26:44
Done.
| |
| 73 factory_(factory), | |
| 74 host_context_(host_context), | |
| 75 image_id_(image_id), | |
| 76 texture_id_(0), | |
| 77 contents_changed_(true) { | |
| 78 ForeignWindowTextureFactory::GetInstance()->AddObserver(this); | |
| 79 } | |
| 80 | |
| 81 ForeignWindowTexture::~ForeignWindowTexture() { | |
| 82 ForeignWindowTextureFactory::GetInstance()->RemoveObserver(this); | |
| 83 if (texture_id_) | |
| 84 host_context_->deleteTexture(texture_id_); | |
| 85 if (image_id_ && !host_context_->isContextLost()) { | |
| 86 factory_->DeleteImage(image_id_, | |
| 87 texture_id_ ? host_context_->insertSyncPoint() : 0); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 unsigned int ForeignWindowTexture::PrepareTexture() { | |
| 92 if (contents_changed_) { | |
| 93 unsigned texture_id = texture_id_; | |
| 94 | |
| 95 if (!texture_id) | |
| 96 texture_id = host_context_->createTexture(); | |
| 97 | |
| 98 host_context_->bindTexture(GL_TEXTURE_2D, texture_id); | |
| 99 if (texture_id_) | |
| 100 host_context_->releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_); | |
| 101 host_context_->bindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_); | |
| 102 host_context_->bindTexture(GL_TEXTURE_2D, 0); | |
| 103 host_context_->flush(); | |
| 104 | |
| 105 texture_id_ = texture_id; | |
| 106 contents_changed_ = false; | |
| 107 } | |
| 108 | |
| 109 return texture_id_; | |
| 110 } | |
| 111 | |
| 112 WebKit::WebGraphicsContext3D* ForeignWindowTexture::HostContext3D() { | |
| 113 DCHECK(host_context_); // This should never be called after lost context. | |
| 114 return host_context_; | |
| 115 } | |
| 116 | |
| 117 void ForeignWindowTexture::OnLostResources() { | |
| 118 if (texture_id_) { | |
| 119 host_context_->deleteTexture(texture_id_); | |
|
danakj
2013/02/21 01:33:15
is there some benefit to doing this when it's lost
reveman
2013/02/22 01:26:44
I think it's good accounting.
| |
| 120 texture_id_ = 0; | |
| 121 } | |
| 122 contents_changed_ = false; | |
| 123 image_id_ = 0; | |
| 124 host_context_ = NULL; | |
| 125 } | |
| 126 | |
| 127 void ForeignWindowTexture::OnContentsChanged() { | |
| 128 if (image_id_) | |
| 129 contents_changed_ = true; | |
| 130 } | |
| 131 | |
| 132 ForeignWindowTextureFactory::ForeignWindowTextureFactory( | |
| 133 content::GpuChannelHostFactory* factory) : factory_(factory) { | |
| 134 DCHECK(factory); | |
| 135 DCHECK(content::ImageTransportFactory::GetInstance()); | |
| 136 content::ImageTransportFactory::GetInstance()->AddObserver(this); | |
| 137 } | |
| 138 | |
| 139 ForeignWindowTextureFactory::~ForeignWindowTextureFactory() { | |
| 140 content::ImageTransportFactory::GetInstance()->RemoveObserver(this); | |
| 141 } | |
| 142 | |
| 143 void ForeignWindowTextureFactory::OnLostResources() { | |
| 144 content::ImageTransportFactory* transport_factory = | |
| 145 content::ImageTransportFactory::GetInstance(); | |
| 146 // Make sure a new gpu channel is established before any calls to | |
| 147 // CreateTextureForForeignWindow() are made. | |
| 148 WebKit::WebGraphicsContext3D* context = | |
| 149 transport_factory->GetGLHelper()->context(); | |
| 150 CHECK(context); | |
| 151 | |
| 152 FOR_EACH_OBSERVER(ForeignWindowTextureFactoryObserver, | |
| 153 observer_list_, | |
| 154 OnLostResources()); | |
| 155 } | |
| 156 | |
| 157 void ForeignWindowTextureFactory::CreateTextureForForeignWindow( | |
| 158 gfx::PluginWindowHandle window, | |
| 159 bool flipped, | |
| 160 float device_scale_factor, | |
| 161 const CreateTextureCallback& callback) { | |
| 162 DCHECK(window); | |
| 163 | |
| 164 int32 image_id = GenerateImageID(); | |
| 165 factory_->CreateImage( | |
| 166 window, | |
| 167 image_id, | |
| 168 base::Bind(&ForeignWindowTextureFactory::OnImageCreated, | |
| 169 base::Unretained(this), | |
| 170 callback, | |
| 171 flipped, | |
| 172 device_scale_factor, | |
| 173 image_id)); | |
| 174 } | |
| 175 | |
| 176 void ForeignWindowTextureFactory::AddObserver( | |
| 177 ForeignWindowTextureFactoryObserver* observer) { | |
| 178 observer_list_.AddObserver(observer); | |
| 179 } | |
| 180 | |
| 181 void ForeignWindowTextureFactory::RemoveObserver( | |
| 182 ForeignWindowTextureFactoryObserver* observer) { | |
| 183 observer_list_.RemoveObserver(observer); | |
| 184 } | |
| 185 | |
| 186 int ForeignWindowTextureFactory::GenerateImageID() { | |
| 187 static unsigned int image_id = 0; | |
| 188 return ++image_id; | |
| 189 } | |
| 190 | |
| 191 void ForeignWindowTextureFactory::OnImageCreated( | |
| 192 const CreateTextureCallback& callback, | |
| 193 bool flipped, | |
| 194 float device_scale_factor, | |
| 195 int32 image_id, | |
| 196 const gfx::Size size) { | |
| 197 if (size.IsEmpty()) { | |
| 198 callback.Run(NULL); | |
| 199 return; | |
| 200 } | |
| 201 | |
| 202 content::ImageTransportFactory* transport_factory = | |
| 203 content::ImageTransportFactory::GetInstance(); | |
| 204 scoped_refptr<ForeignWindowTexture> texture( | |
| 205 new ForeignWindowTexture(factory_, | |
| 206 transport_factory->GetGLHelper()->context(), | |
| 207 flipped, | |
| 208 size, | |
| 209 device_scale_factor, | |
| 210 image_id)); | |
| 211 | |
| 212 callback.Run(texture); | |
| 213 } | |
| 214 | |
| 215 // static | |
| 216 void ForeignWindowTextureFactory::Initialize() { | |
| 217 CHECK(!instance_); | |
| 218 if (ui::IsTestCompositorEnabled()) { | |
| 219 instance_ = new ForeignWindowTextureFactory(&g_default_factory.Get()); | |
| 220 } else { | |
| 221 instance_ = new ForeignWindowTextureFactory( | |
| 222 content::BrowserGpuChannelHostFactory::instance()); | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 // static | |
| 227 void ForeignWindowTextureFactory::Terminate() { | |
| 228 CHECK(instance_); | |
| 229 delete instance_; | |
| 230 instance_ = NULL; | |
| 231 } | |
| 232 | |
| 233 // static | |
| 234 ForeignWindowTextureFactory* ForeignWindowTextureFactory::GetInstance() { | |
| 235 DCHECK(instance_); | |
| 236 return instance_; | |
| 237 } | |
| 238 | |
| 239 } // namespace wm | |
| OLD | NEW |