Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(507)

Side by Side Diff: chrome/renderer/render_process.cc

Issue 21485: Bitmap transport (Closed)
Patch Set: Fix some mac crashes Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <windows.h> 8 #include <windows.h>
9 #include <objidl.h> 9 #include <objidl.h>
10 #include <mlang.h> 10 #include <mlang.h>
11 #endif 11 #endif
12 12
13 #include "chrome/renderer/render_process.h" 13 #include "chrome/renderer/render_process.h"
14 14
15 #include "base/basictypes.h" 15 #include "base/basictypes.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/compiler_specific.h" 17 #include "base/compiler_specific.h"
18 #include "base/message_loop.h" 18 #include "base/message_loop.h"
19 #include "base/histogram.h" 19 #include "base/histogram.h"
20 #include "base/path_service.h" 20 #include "base/path_service.h"
21 #include "base/sys_info.h" 21 #include "base/sys_info.h"
22 #include "chrome/browser/net/dns_global.h" // TODO(jar): DNS calls should be re nderer specific, not including browser. 22 #include "chrome/browser/net/dns_global.h" // TODO(jar): DNS calls should be re nderer specific, not including browser.
23 #include "chrome/common/chrome_switches.h" 23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/chrome_paths.h" 24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/ipc_channel.h" 25 #include "chrome/common/ipc_channel.h"
26 #include "chrome/common/ipc_message_utils.h" 26 #include "chrome/common/ipc_message_utils.h"
27 #include "chrome/common/render_messages.h" 27 #include "chrome/common/render_messages.h"
28 #include "chrome/common/transport_dib.h"
28 #include "chrome/renderer/render_view.h" 29 #include "chrome/renderer/render_view.h"
29 #include "webkit/glue/webkit_glue.h" 30 #include "webkit/glue/webkit_glue.h"
30 31
31 //----------------------------------------------------------------------------- 32 //-----------------------------------------------------------------------------
32 33
33 bool RenderProcess::load_plugins_in_process_ = false; 34 bool RenderProcess::load_plugins_in_process_ = false;
34 35
35 //----------------------------------------------------------------------------- 36 //-----------------------------------------------------------------------------
36 37
37 RenderProcess::RenderProcess(const std::wstring& channel_name) 38 RenderProcess::RenderProcess(const std::wstring& channel_name)
38 : render_thread_(channel_name), 39 : render_thread_(channel_name),
39 ALLOW_THIS_IN_INITIALIZER_LIST(clearer_factory_(this)) { 40 ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_(
41 base::TimeDelta::FromSeconds(5),
42 this, &RenderProcess::ClearTransportDIBCache)),
43 sequence_number_(0) {
40 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) 44 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i)
41 shared_mem_cache_[i] = NULL; 45 shared_mem_cache_[i] = NULL;
42 } 46 }
43 47
44 RenderProcess::~RenderProcess() { 48 RenderProcess::~RenderProcess() {
45 // We need to stop the RenderThread as the clearer_factory_ 49 // We need to stop the RenderThread as the clearer_factory_
46 // member could be in use while the object itself is destroyed, 50 // member could be in use while the object itself is destroyed,
47 // as a result of the containing RenderProcess object being destroyed. 51 // as a result of the containing RenderProcess object being destroyed.
48 // This race condition causes a crash when the renderer process is shutting 52 // This race condition causes a crash when the renderer process is shutting
49 // down. 53 // down.
50 render_thread_.Stop(); 54 render_thread_.Stop();
51 ClearSharedMemCache(); 55 ClearTransportDIBCache();
52 } 56 }
53 57
54 // static 58 // static
55 bool RenderProcess::GlobalInit(const std::wstring &channel_name) { 59 bool RenderProcess::GlobalInit(const std::wstring &channel_name) {
56 #if defined(OS_WIN) 60 #if defined(OS_WIN)
57 // HACK: See http://b/issue?id=1024307 for rationale. 61 // HACK: See http://b/issue?id=1024307 for rationale.
58 if (GetModuleHandle(L"LPK.DLL") == NULL) { 62 if (GetModuleHandle(L"LPK.DLL") == NULL) {
59 // Makes sure lpk.dll is loaded by gdi32 to make sure ExtTextOut() works 63 // Makes sure lpk.dll is loaded by gdi32 to make sure ExtTextOut() works
60 // when buffering into a EMF buffer for printing. 64 // when buffering into a EMF buffer for printing.
61 typedef BOOL (__stdcall *GdiInitializeLanguagePack)(int LoadedShapingDLLs); 65 typedef BOOL (__stdcall *GdiInitializeLanguagePack)(int LoadedShapingDLLs);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 // static 121 // static
118 void RenderProcess::GlobalCleanup() { 122 void RenderProcess::GlobalCleanup() {
119 ChildProcess::GlobalCleanup(); 123 ChildProcess::GlobalCleanup();
120 } 124 }
121 125
122 // static 126 // static
123 bool RenderProcess::ShouldLoadPluginsInProcess() { 127 bool RenderProcess::ShouldLoadPluginsInProcess() {
124 return load_plugins_in_process_; 128 return load_plugins_in_process_;
125 } 129 }
126 130
131 // -----------------------------------------------------------------------------
132 // Platform specific code for dealing with bitmap transport...
133
134 // -----------------------------------------------------------------------------
135 // Create a platform canvas object which renders into the given transport
136 // memory.
137 // -----------------------------------------------------------------------------
138 static skia::PlatformCanvas* CanvasFromTransportDIB(
139 TransportDIB* dib, const gfx::Rect& rect) {
140 #if defined(OS_WIN)
141 return new skia::PlatformCanvas(rect.width(), rect.height(), true,
142 dib->handle());
143 #elif defined(OS_LINUX) || defined(OS_MACOSX)
144 return new skia::PlatformCanvas(rect.width(), rect.height(), true,
145 reinterpret_cast<uint8_t*>(dib->memory()));
146 #endif
147 }
148
149 TransportDIB* RenderProcess::CreateTransportDIB(size_t size) {
150 #if defined(OS_WIN) || defined(OS_LINUX)
151 // Windows and Linux create transport DIBs inside the renderer
152 return TransportDIB::Create(size, sequence_number_++);
153 #elif defined(OS_MACOSX) // defined(OS_WIN) || defined(OS_LINUX)
154 // Mac creates transport DIBs in the browser, so we need to do a sync IPC to
155 // get one.
156 IPC::Maybe<TransportDIB::Handle> mhandle;
157 IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, &mhandle);
158 if (!render_thread_.Send(msg))
159 return NULL;
160 if (!mhandle.valid)
161 return NULL;
162 return TransportDIB::Map(mhandle.value);
163 #endif // defined(OS_MACOSX)
164 }
165
166 void RenderProcess::FreeTransportDIB(TransportDIB* dib) {
167 if (!dib)
168 return;
169
170 #if defined(OS_MACOSX)
171 // On Mac we need to tell the browser that it can drop a reference to the
172 // shared memory.
173 IPC::Message* msg = new ViewHostMsg_FreeTransportDIB(dib->id());
174 render_thread_.Send(msg);
175 #endif
176
177 delete dib;
178 }
179
180 // -----------------------------------------------------------------------------
181
182
127 // static 183 // static
128 base::SharedMemory* RenderProcess::AllocSharedMemory(size_t size) { 184 skia::PlatformCanvas* RenderProcess::GetDrawingCanvas(
129 self()->clearer_factory_.RevokeAll(); 185 TransportDIB** memory, const gfx::Rect& rect) {
186 const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width());
187 const size_t size = stride * rect.height();
130 188
131 base::SharedMemory* mem = self()->GetSharedMemFromCache(size); 189 if (!self()->GetTransportDIBFromCache(memory, size)) {
132 if (mem) 190 *memory = self()->CreateTransportDIB(size);
133 return mem; 191 if (!*memory)
134 192 return false;
135 // Round-up size to allocation granularity
136 size_t allocation_granularity = base::SysInfo::VMAllocationGranularity();
137 size = size / allocation_granularity + 1;
138 size = size * allocation_granularity;
139
140 mem = new base::SharedMemory();
141 if (!mem)
142 return NULL;
143 if (!mem->Create(L"", false, true, size)) {
144 delete mem;
145 return NULL;
146 } 193 }
147 194
148 return mem; 195 return CanvasFromTransportDIB(*memory, rect);
149 } 196 }
150 197
151 // static 198 // static
152 void RenderProcess::FreeSharedMemory(base::SharedMemory* mem) { 199 void RenderProcess::ReleaseTransportDIB(TransportDIB* mem) {
153 if (self()->PutSharedMemInCache(mem)) { 200 if (self()->PutSharedMemInCache(mem)) {
154 self()->ScheduleCacheClearer(); 201 self()->shared_mem_cache_cleaner_.Reset();
155 return; 202 return;
156 } 203 }
157 DeleteSharedMem(mem); 204
205 self()->FreeTransportDIB(mem);
158 } 206 }
159 207
160 // static 208 bool RenderProcess::GetTransportDIBFromCache(TransportDIB** mem,
161 void RenderProcess::DeleteSharedMem(base::SharedMemory* mem) { 209 size_t size) {
162 delete mem;
163 }
164
165 base::SharedMemory* RenderProcess::GetSharedMemFromCache(size_t size) {
166 // look for a cached object that is suitable for the requested size. 210 // look for a cached object that is suitable for the requested size.
167 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) { 211 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
168 base::SharedMemory* mem = shared_mem_cache_[i]; 212 if (shared_mem_cache_[i] &&
169 if (mem && mem->max_size() >= size) { 213 size <= shared_mem_cache_[i]->size()) {
214 *mem = shared_mem_cache_[i];
170 shared_mem_cache_[i] = NULL; 215 shared_mem_cache_[i] = NULL;
171 return mem;
172 }
173 }
174 return NULL;
175 }
176
177 bool RenderProcess::PutSharedMemInCache(base::SharedMemory* mem) {
178 // simple algorithm:
179 // - look for an empty slot to store mem, or
180 // - if full, then replace any existing cache entry that is smaller than the
181 // given shared memory object.
182 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
183 if (!shared_mem_cache_[i]) {
184 shared_mem_cache_[i] = mem;
185 return true; 216 return true;
186 } 217 }
187 } 218 }
188 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) { 219
189 base::SharedMemory* cached_mem = shared_mem_cache_[i];
190 if (cached_mem->max_size() < mem->max_size()) {
191 shared_mem_cache_[i] = mem;
192 DeleteSharedMem(cached_mem);
193 return true;
194 }
195 }
196 return false; 220 return false;
197 } 221 }
198 222
199 void RenderProcess::ClearSharedMemCache() { 223 int RenderProcess::FindFreeCacheSlot(size_t size) {
224 // simple algorithm:
225 // - look for an empty slot to store mem, or
226 // - if full, then replace smallest entry which is smaller than |size|
227 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
228 if (shared_mem_cache_[i] == NULL)
229 return i;
230 }
231
232 size_t smallest_size = size;
233 int smallest_index = -1;
234
235 for (size_t i = 1; i < arraysize(shared_mem_cache_); ++i) {
236 const size_t entry_size = shared_mem_cache_[i]->size();
237 if (entry_size < smallest_size) {
238 smallest_size = entry_size;
239 smallest_index = i;
240 }
241 }
242
243 if (smallest_index != -1) {
244 FreeTransportDIB(shared_mem_cache_[smallest_index]);
245 shared_mem_cache_[smallest_index] = NULL;
246 }
247
248 return smallest_index;
249 }
250
251 bool RenderProcess::PutSharedMemInCache(TransportDIB* mem) {
252 const int slot = FindFreeCacheSlot(mem->size());
253 if (slot == -1)
254 return false;
255
256 shared_mem_cache_[slot] = mem;
257 return true;
258 }
259
260 void RenderProcess::ClearTransportDIBCache() {
200 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) { 261 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
201 if (shared_mem_cache_[i]) { 262 if (shared_mem_cache_[i]) {
202 DeleteSharedMem(shared_mem_cache_[i]); 263 FreeTransportDIB(shared_mem_cache_[i]);
203 shared_mem_cache_[i] = NULL; 264 shared_mem_cache_[i] = NULL;
204 } 265 }
205 } 266 }
206 } 267 }
207 268
208 void RenderProcess::ScheduleCacheClearer() {
209 // If we already have a deferred clearer, then revoke it so we effectively
210 // delay cache clearing until idle for our desired interval.
211 clearer_factory_.RevokeAll();
212
213 MessageLoop::current()->PostDelayedTask(FROM_HERE,
214 clearer_factory_.NewRunnableMethod(&RenderProcess::ClearSharedMemCache),
215 5000 /* 5 seconds */);
216 }
217
218 void RenderProcess::Cleanup() { 269 void RenderProcess::Cleanup() {
219 // TODO(port) 270 // TODO(port)
220 // Try and limit what we pull in for our non-Win unit test bundle 271 // Try and limit what we pull in for our non-Win unit test bundle
221 #ifndef NDEBUG 272 #ifndef NDEBUG
222 // log important leaked objects 273 // log important leaked objects
223 webkit_glue::CheckForLeaks(); 274 webkit_glue::CheckForLeaks();
224 #endif 275 #endif
225 } 276 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698