OLD | NEW |
| (Empty) |
1 // Copyright 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 "cc/resource_provider.h" | |
6 | |
7 #include <limits.h> | |
8 | |
9 #include "base/debug/alias.h" | |
10 #include "base/hash_tables.h" | |
11 #include "base/stl_util.h" | |
12 #include "base/string_util.h" | |
13 #include "base/strings/string_split.h" | |
14 #include "cc/output/gl_renderer.h" // For the GLC() macro. | |
15 #include "cc/platform_color.h" | |
16 #include "cc/texture_uploader.h" | |
17 #include "cc/transferable_resource.h" | |
18 #include "gpu/GLES2/gl2extchromium.h" | |
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3
D.h" | |
20 #include "third_party/khronos/GLES2/gl2.h" | |
21 #include "third_party/khronos/GLES2/gl2ext.h" | |
22 #include "ui/gfx/rect.h" | |
23 #include "ui/gfx/vector2d.h" | |
24 | |
25 using WebKit::WebGraphicsContext3D; | |
26 | |
27 namespace cc { | |
28 | |
29 static GLenum TextureToStorageFormat(GLenum texture_format) { | |
30 GLenum storage_format = GL_RGBA8_OES; | |
31 switch (texture_format) { | |
32 case GL_RGBA: | |
33 break; | |
34 case GL_BGRA_EXT: | |
35 storage_format = GL_BGRA8_EXT; | |
36 break; | |
37 default: | |
38 NOTREACHED(); | |
39 break; | |
40 } | |
41 | |
42 return storage_format; | |
43 } | |
44 | |
45 static bool IsTextureFormatSupportedForStorage(GLenum format) { | |
46 return (format == GL_RGBA || format == GL_BGRA_EXT); | |
47 } | |
48 | |
49 static unsigned CreateTextureId(WebGraphicsContext3D* context3d) { | |
50 unsigned texture_id = 0; | |
51 GLC(context3d, texture_id = context3d->createTexture()); | |
52 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id)); | |
53 GLC(context3d, context3d->texParameteri( | |
54 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
55 GLC(context3d, context3d->texParameteri( | |
56 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
57 GLC(context3d, context3d->texParameteri( | |
58 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); | |
59 GLC(context3d, context3d->texParameteri( | |
60 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); | |
61 return texture_id; | |
62 } | |
63 | |
64 ResourceProvider::Resource::Resource() | |
65 : gl_id(0), | |
66 gl_pixel_buffer_id(0), | |
67 gl_upload_query_id(0), | |
68 pixels(NULL), | |
69 pixel_buffer(NULL), | |
70 lock_for_read_count(0), | |
71 locked_for_write(false), | |
72 external(false), | |
73 exported(false), | |
74 marked_for_deletion(false), | |
75 pending_set_pixels(false), | |
76 set_pixels_completion_forced(false), | |
77 allocated(false), | |
78 enable_read_lock_fences(false), | |
79 read_lock_fence(NULL), | |
80 size(), | |
81 format(0), | |
82 filter(0), | |
83 type(static_cast<ResourceType>(0)) {} | |
84 | |
85 ResourceProvider::Resource::~Resource() {} | |
86 | |
87 ResourceProvider::Resource::Resource( | |
88 unsigned texture_id, gfx::Size size, GLenum format, GLenum filter) | |
89 : gl_id(texture_id), | |
90 gl_pixel_buffer_id(0), | |
91 gl_upload_query_id(0), | |
92 pixels(NULL), | |
93 pixel_buffer(NULL), | |
94 lock_for_read_count(0), | |
95 locked_for_write(false), | |
96 external(false), | |
97 exported(false), | |
98 marked_for_deletion(false), | |
99 pending_set_pixels(false), | |
100 set_pixels_completion_forced(false), | |
101 allocated(false), | |
102 enable_read_lock_fences(false), | |
103 read_lock_fence(NULL), | |
104 size(size), | |
105 format(format), | |
106 filter(filter), | |
107 type(GLTexture) {} | |
108 | |
109 ResourceProvider::Resource::Resource( | |
110 uint8_t* pixels, gfx::Size size, GLenum format, GLenum filter) | |
111 : gl_id(0), | |
112 gl_pixel_buffer_id(0), | |
113 gl_upload_query_id(0), | |
114 pixels(pixels), | |
115 pixel_buffer(NULL), | |
116 lock_for_read_count(0), | |
117 locked_for_write(false), | |
118 external(false), | |
119 exported(false), | |
120 marked_for_deletion(false), | |
121 pending_set_pixels(false), | |
122 set_pixels_completion_forced(false), | |
123 allocated(false), | |
124 enable_read_lock_fences(false), | |
125 read_lock_fence(NULL), | |
126 size(size), | |
127 format(format), | |
128 filter(filter), | |
129 type(Bitmap) {} | |
130 | |
131 ResourceProvider::Child::Child() {} | |
132 | |
133 ResourceProvider::Child::~Child() {} | |
134 | |
135 scoped_ptr<ResourceProvider> ResourceProvider::Create( | |
136 OutputSurface* output_surface) { | |
137 scoped_ptr<ResourceProvider> resource_provider( | |
138 new ResourceProvider(output_surface)); | |
139 if (!resource_provider->Initialize()) | |
140 return scoped_ptr<ResourceProvider>(); | |
141 return resource_provider.Pass(); | |
142 } | |
143 | |
144 ResourceProvider::~ResourceProvider() { | |
145 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
146 if (!context3d || !context3d->makeContextCurrent()) | |
147 return; | |
148 texture_uploader_.reset(); | |
149 texture_copier_.reset(); | |
150 } | |
151 | |
152 WebGraphicsContext3D* ResourceProvider::GraphicsContext3D() { | |
153 DCHECK(thread_checker_.CalledOnValidThread()); | |
154 return output_surface_->context3d(); | |
155 } | |
156 | |
157 bool ResourceProvider::InUseByConsumer(ResourceId id) { | |
158 DCHECK(thread_checker_.CalledOnValidThread()); | |
159 ResourceMap::iterator it = resources_.find(id); | |
160 CHECK(it != resources_.end()); | |
161 Resource* resource = &it->second; | |
162 return !!resource->lock_for_read_count || resource->exported; | |
163 } | |
164 | |
165 ResourceProvider::ResourceId ResourceProvider::CreateResource( | |
166 gfx::Size size, GLenum format, TextureUsageHint hint) { | |
167 switch (default_resource_type_) { | |
168 case GLTexture: | |
169 return CreateGLTexture( | |
170 size, format, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, hint); | |
171 case Bitmap: | |
172 DCHECK(format == GL_RGBA); | |
173 return CreateBitmap(size); | |
174 } | |
175 | |
176 LOG(FATAL) << "Invalid default resource type."; | |
177 return 0; | |
178 } | |
179 | |
180 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource( | |
181 gfx::Size size, GLenum format, TextureUsageHint hint) { | |
182 switch (default_resource_type_) { | |
183 case GLTexture: | |
184 return CreateGLTexture( | |
185 size, format, GL_TEXTURE_POOL_MANAGED_CHROMIUM, hint); | |
186 case Bitmap: | |
187 DCHECK(format == GL_RGBA); | |
188 return CreateBitmap(size); | |
189 } | |
190 | |
191 LOG(FATAL) << "Invalid default resource type."; | |
192 return 0; | |
193 } | |
194 | |
195 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture( | |
196 gfx::Size size, GLenum format, GLenum texture_pool, TextureUsageHint hint) { | |
197 DCHECK_LE(size.width(), max_texture_size_); | |
198 DCHECK_LE(size.height(), max_texture_size_); | |
199 | |
200 DCHECK(thread_checker_.CalledOnValidThread()); | |
201 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
202 DCHECK(context3d); | |
203 | |
204 // Create and set texture properties. Allocation is delayed until needed. | |
205 unsigned texture_id = CreateTextureId(context3d); | |
206 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, | |
207 GL_TEXTURE_POOL_CHROMIUM, | |
208 texture_pool)); | |
209 if (use_texture_usage_hint_ && hint == TextureUsageFramebuffer) { | |
210 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, | |
211 GL_TEXTURE_USAGE_ANGLE, | |
212 GL_FRAMEBUFFER_ATTACHMENT_ANGLE)); | |
213 } | |
214 | |
215 ResourceId id = next_id_++; | |
216 Resource resource(texture_id, size, format, GL_LINEAR); | |
217 resource.allocated = false; | |
218 resources_[id] = resource; | |
219 return id; | |
220 } | |
221 | |
222 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) { | |
223 DCHECK(thread_checker_.CalledOnValidThread()); | |
224 | |
225 uint8_t* pixels = new uint8_t[size.width() * size.height() * 4]; | |
226 | |
227 ResourceId id = next_id_++; | |
228 Resource resource(pixels, size, GL_RGBA, GL_LINEAR); | |
229 resource.allocated = true; | |
230 resources_[id] = resource; | |
231 return id; | |
232 } | |
233 | |
234 ResourceProvider::ResourceId ResourceProvider:: | |
235 CreateResourceFromExternalTexture(unsigned texture_id) { | |
236 DCHECK(thread_checker_.CalledOnValidThread()); | |
237 | |
238 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
239 DCHECK(context3d); | |
240 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id)); | |
241 GLC(context3d, context3d->texParameteri( | |
242 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
243 GLC(context3d, context3d->texParameteri( | |
244 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
245 GLC(context3d, context3d->texParameteri( | |
246 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); | |
247 GLC(context3d, context3d->texParameteri( | |
248 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); | |
249 | |
250 ResourceId id = next_id_++; | |
251 Resource resource(texture_id, gfx::Size(), 0, GL_LINEAR); | |
252 resource.external = true; | |
253 resource.allocated = true; | |
254 resources_[id] = resource; | |
255 return id; | |
256 } | |
257 | |
258 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( | |
259 const TextureMailbox& mailbox) { | |
260 DCHECK(thread_checker_.CalledOnValidThread()); | |
261 // Just store the information. Mailbox will be consumed in LockForRead(). | |
262 ResourceId id = next_id_++; | |
263 unsigned texture_id = 0; | |
264 Resource resource(texture_id, gfx::Size(), 0, GL_LINEAR); | |
265 resource.external = true; | |
266 resource.allocated = true; | |
267 resource.mailbox = mailbox; | |
268 resources_[id] = resource; | |
269 return id; | |
270 } | |
271 | |
272 void ResourceProvider::DeleteResource(ResourceId id) { | |
273 DCHECK(thread_checker_.CalledOnValidThread()); | |
274 ResourceMap::iterator it = resources_.find(id); | |
275 CHECK(it != resources_.end()); | |
276 Resource* resource = &it->second; | |
277 DCHECK(!resource->lock_for_read_count); | |
278 DCHECK(!resource->marked_for_deletion); | |
279 DCHECK(resource->pending_set_pixels || !resource->locked_for_write); | |
280 | |
281 if (resource->exported) { | |
282 resource->marked_for_deletion = true; | |
283 return; | |
284 } else { | |
285 DeleteResourceInternal(it); | |
286 } | |
287 } | |
288 | |
289 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it) { | |
290 Resource* resource = &it->second; | |
291 if (resource->gl_id && !resource->external) { | |
292 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
293 DCHECK(context3d); | |
294 GLC(context3d, context3d->deleteTexture(resource->gl_id)); | |
295 } | |
296 if (resource->gl_upload_query_id) { | |
297 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
298 DCHECK(context3d); | |
299 GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id)); | |
300 } | |
301 if (resource->gl_pixel_buffer_id) { | |
302 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
303 DCHECK(context3d); | |
304 GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id)); | |
305 } | |
306 if (!resource->mailbox.IsEmpty() && resource->external) { | |
307 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
308 DCHECK(context3d); | |
309 unsigned sync_point = resource->mailbox.sync_point(); | |
310 if (resource->gl_id) { | |
311 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); | |
312 GLC(context3d, context3d->produceTextureCHROMIUM( | |
313 GL_TEXTURE_2D, resource->mailbox.data())); | |
314 GLC(context3d, context3d->deleteTexture(resource->gl_id)); | |
315 sync_point = context3d->insertSyncPoint(); | |
316 } | |
317 resource->mailbox.RunReleaseCallback(sync_point); | |
318 } | |
319 if (resource->pixels) | |
320 delete[] resource->pixels; | |
321 if (resource->pixel_buffer) | |
322 delete[] resource->pixel_buffer; | |
323 | |
324 resources_.erase(it); | |
325 } | |
326 | |
327 ResourceProvider::ResourceType ResourceProvider::GetResourceType( | |
328 ResourceId id) { | |
329 ResourceMap::iterator it = resources_.find(id); | |
330 CHECK(it != resources_.end()); | |
331 Resource* resource = &it->second; | |
332 return resource->type; | |
333 } | |
334 | |
335 void ResourceProvider::SetPixels(ResourceId id, | |
336 const uint8_t* image, | |
337 gfx::Rect image_rect, | |
338 gfx::Rect source_rect, | |
339 gfx::Vector2d dest_offset) { | |
340 DCHECK(thread_checker_.CalledOnValidThread()); | |
341 ResourceMap::iterator it = resources_.find(id); | |
342 CHECK(it != resources_.end()); | |
343 Resource* resource = &it->second; | |
344 DCHECK(!resource->locked_for_write); | |
345 DCHECK(!resource->lock_for_read_count); | |
346 DCHECK(!resource->external); | |
347 DCHECK(!resource->exported); | |
348 DCHECK(ReadLockFenceHasPassed(resource)); | |
349 LazyAllocate(resource); | |
350 | |
351 if (resource->gl_id) { | |
352 DCHECK(!resource->pending_set_pixels); | |
353 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
354 DCHECK(context3d); | |
355 DCHECK(texture_uploader_.get()); | |
356 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id); | |
357 texture_uploader_->Upload(image, | |
358 image_rect, | |
359 source_rect, | |
360 dest_offset, | |
361 resource->format, | |
362 resource->size); | |
363 } | |
364 | |
365 if (resource->pixels) { | |
366 DCHECK(resource->allocated); | |
367 DCHECK(resource->format == GL_RGBA); | |
368 SkBitmap src_full; | |
369 src_full.setConfig( | |
370 SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height()); | |
371 src_full.setPixels(const_cast<uint8_t*>(image)); | |
372 SkBitmap src_subset; | |
373 SkIRect sk_source_rect = SkIRect::MakeXYWH(source_rect.x(), | |
374 source_rect.y(), | |
375 source_rect.width(), | |
376 source_rect.height()); | |
377 sk_source_rect.offset(-image_rect.x(), -image_rect.y()); | |
378 src_full.extractSubset(&src_subset, sk_source_rect); | |
379 | |
380 ScopedWriteLockSoftware lock(this, id); | |
381 SkCanvas* dest = lock.sk_canvas(); | |
382 dest->writePixels(src_subset, dest_offset.x(), dest_offset.y()); | |
383 } | |
384 } | |
385 | |
386 size_t ResourceProvider::NumBlockingUploads() { | |
387 if (!texture_uploader_) | |
388 return 0; | |
389 | |
390 return texture_uploader_->NumBlockingUploads(); | |
391 } | |
392 | |
393 void ResourceProvider::MarkPendingUploadsAsNonBlocking() { | |
394 if (!texture_uploader_) | |
395 return; | |
396 | |
397 texture_uploader_->MarkPendingUploadsAsNonBlocking(); | |
398 } | |
399 | |
400 double ResourceProvider::EstimatedUploadsPerSecond() { | |
401 if (!texture_uploader_) | |
402 return 0.0; | |
403 | |
404 return texture_uploader_->EstimatedTexturesPerSecond(); | |
405 } | |
406 | |
407 void ResourceProvider::FlushUploads() { | |
408 if (!texture_uploader_) | |
409 return; | |
410 | |
411 texture_uploader_->Flush(); | |
412 } | |
413 | |
414 void ResourceProvider::ReleaseCachedData() { | |
415 if (!texture_uploader_) | |
416 return; | |
417 | |
418 texture_uploader_->ReleaseCachedQueries(); | |
419 } | |
420 | |
421 void ResourceProvider::Flush() { | |
422 DCHECK(thread_checker_.CalledOnValidThread()); | |
423 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
424 if (context3d) | |
425 context3d->flush(); | |
426 } | |
427 | |
428 bool ResourceProvider::ShallowFlushIfSupported() { | |
429 DCHECK(thread_checker_.CalledOnValidThread()); | |
430 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
431 if (!context3d || !use_shallow_flush_) | |
432 return false; | |
433 | |
434 context3d->shallowFlushCHROMIUM(); | |
435 return true; | |
436 } | |
437 | |
438 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) { | |
439 DCHECK(thread_checker_.CalledOnValidThread()); | |
440 ResourceMap::iterator it = resources_.find(id); | |
441 CHECK(it != resources_.end()); | |
442 Resource* resource = &it->second; | |
443 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced); | |
444 DCHECK(!resource->exported); | |
445 // Uninitialized! Call SetPixels or LockForWrite first. | |
446 DCHECK(resource->allocated); | |
447 | |
448 if (!resource->gl_id && resource->external && !resource->mailbox.IsEmpty()) { | |
449 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
450 DCHECK(context3d); | |
451 if (resource->mailbox.sync_point()) { | |
452 GLC(context3d, context3d->waitSyncPoint(resource->mailbox.sync_point())); | |
453 resource->mailbox.ResetSyncPoint(); | |
454 } | |
455 resource->gl_id = context3d->createTexture(); | |
456 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); | |
457 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, | |
458 resource->mailbox.data())); | |
459 } | |
460 | |
461 resource->lock_for_read_count++; | |
462 if (resource->enable_read_lock_fences) | |
463 resource->read_lock_fence = current_read_lock_fence_; | |
464 | |
465 return resource; | |
466 } | |
467 | |
468 void ResourceProvider::UnlockForRead(ResourceId id) { | |
469 DCHECK(thread_checker_.CalledOnValidThread()); | |
470 ResourceMap::iterator it = resources_.find(id); | |
471 CHECK(it != resources_.end()); | |
472 Resource* resource = &it->second; | |
473 DCHECK(resource->lock_for_read_count > 0); | |
474 DCHECK(!resource->exported); | |
475 resource->lock_for_read_count--; | |
476 } | |
477 | |
478 const ResourceProvider::Resource* ResourceProvider::LockForWrite( | |
479 ResourceId id) { | |
480 DCHECK(thread_checker_.CalledOnValidThread()); | |
481 ResourceMap::iterator it = resources_.find(id); | |
482 CHECK(it != resources_.end()); | |
483 Resource* resource = &it->second; | |
484 DCHECK(!resource->locked_for_write); | |
485 DCHECK(!resource->lock_for_read_count); | |
486 DCHECK(!resource->exported); | |
487 DCHECK(!resource->external); | |
488 DCHECK(ReadLockFenceHasPassed(resource)); | |
489 LazyAllocate(resource); | |
490 | |
491 resource->locked_for_write = true; | |
492 return resource; | |
493 } | |
494 | |
495 bool ResourceProvider::CanLockForWrite(ResourceId id) { | |
496 DCHECK(thread_checker_.CalledOnValidThread()); | |
497 ResourceMap::iterator it = resources_.find(id); | |
498 CHECK(it != resources_.end()); | |
499 Resource* resource = &it->second; | |
500 return !resource->locked_for_write && | |
501 !resource->lock_for_read_count && | |
502 !resource->exported && | |
503 !resource->external && | |
504 ReadLockFenceHasPassed(resource); | |
505 } | |
506 | |
507 void ResourceProvider::UnlockForWrite(ResourceId id) { | |
508 DCHECK(thread_checker_.CalledOnValidThread()); | |
509 ResourceMap::iterator it = resources_.find(id); | |
510 CHECK(it != resources_.end()); | |
511 Resource* resource = &it->second; | |
512 DCHECK(resource->locked_for_write); | |
513 DCHECK(!resource->exported); | |
514 DCHECK(!resource->external); | |
515 resource->locked_for_write = false; | |
516 } | |
517 | |
518 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( | |
519 ResourceProvider* resource_provider, | |
520 ResourceProvider::ResourceId resource_id) | |
521 : resource_provider_(resource_provider), | |
522 resource_id_(resource_id), | |
523 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) { | |
524 DCHECK(texture_id_); | |
525 } | |
526 | |
527 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { | |
528 resource_provider_->UnlockForRead(resource_id_); | |
529 } | |
530 | |
531 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( | |
532 ResourceProvider* resource_provider, | |
533 ResourceProvider::ResourceId resource_id, | |
534 GLenum target, | |
535 GLenum filter) | |
536 : ScopedReadLockGL(resource_provider, resource_id) { | |
537 resource_provider->BindForSampling(resource_id, target, filter); | |
538 } | |
539 | |
540 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( | |
541 ResourceProvider* resource_provider, | |
542 ResourceProvider::ResourceId resource_id) | |
543 : resource_provider_(resource_provider), | |
544 resource_id_(resource_id), | |
545 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) { | |
546 DCHECK(texture_id_); | |
547 } | |
548 | |
549 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { | |
550 resource_provider_->UnlockForWrite(resource_id_); | |
551 } | |
552 | |
553 void ResourceProvider::PopulateSkBitmapWithResource( | |
554 SkBitmap* sk_bitmap, const Resource* resource) { | |
555 DCHECK(resource->pixels); | |
556 DCHECK(resource->format == GL_RGBA); | |
557 sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config, | |
558 resource->size.width(), | |
559 resource->size.height()); | |
560 sk_bitmap->setPixels(resource->pixels); | |
561 } | |
562 | |
563 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware( | |
564 ResourceProvider* resource_provider, | |
565 ResourceProvider::ResourceId resource_id) | |
566 : resource_provider_(resource_provider), | |
567 resource_id_(resource_id) { | |
568 ResourceProvider::PopulateSkBitmapWithResource( | |
569 &sk_bitmap_, resource_provider->LockForRead(resource_id)); | |
570 } | |
571 | |
572 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() { | |
573 resource_provider_->UnlockForRead(resource_id_); | |
574 } | |
575 | |
576 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( | |
577 ResourceProvider* resource_provider, | |
578 ResourceProvider::ResourceId resource_id) | |
579 : resource_provider_(resource_provider), | |
580 resource_id_(resource_id) { | |
581 ResourceProvider::PopulateSkBitmapWithResource( | |
582 &sk_bitmap_, resource_provider->LockForWrite(resource_id)); | |
583 sk_canvas_.reset(new SkCanvas(sk_bitmap_)); | |
584 } | |
585 | |
586 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { | |
587 resource_provider_->UnlockForWrite(resource_id_); | |
588 } | |
589 | |
590 ResourceProvider::ResourceProvider(OutputSurface* output_surface) | |
591 : output_surface_(output_surface), | |
592 next_id_(1), | |
593 next_child_(1), | |
594 default_resource_type_(GLTexture), | |
595 use_texture_storage_ext_(false), | |
596 use_texture_usage_hint_(false), | |
597 use_shallow_flush_(false), | |
598 max_texture_size_(0), | |
599 best_texture_format_(0) {} | |
600 | |
601 bool ResourceProvider::Initialize() { | |
602 DCHECK(thread_checker_.CalledOnValidThread()); | |
603 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
604 if (!context3d) { | |
605 max_texture_size_ = INT_MAX / 2; | |
606 best_texture_format_ = GL_RGBA; | |
607 return true; | |
608 } | |
609 if (!context3d->makeContextCurrent()) | |
610 return false; | |
611 | |
612 std::string extensions_string = | |
613 UTF16ToASCII(context3d->getString(GL_EXTENSIONS)); | |
614 std::vector<std::string> extensions; | |
615 base::SplitString(extensions_string, ' ', &extensions); | |
616 bool use_map_sub = false; | |
617 bool use_bind_uniform = false; | |
618 bool use_bgra = false; | |
619 for (size_t i = 0; i < extensions.size(); ++i) { | |
620 if (extensions[i] == "GL_EXT_texture_storage") | |
621 use_texture_storage_ext_ = true; | |
622 else if (extensions[i] == "GL_ANGLE_texture_usage") | |
623 use_texture_usage_hint_ = true; | |
624 else if (extensions[i] == "GL_CHROMIUM_map_sub") | |
625 use_map_sub = true; | |
626 else if (extensions[i] == "GL_CHROMIUM_shallow_flush") | |
627 use_shallow_flush_ = true; | |
628 else if (extensions[i] == "GL_CHROMIUM_bind_uniform_location") | |
629 use_bind_uniform = true; | |
630 else if (extensions[i] == "GL_EXT_texture_format_BGRA8888") | |
631 use_bgra = true; | |
632 } | |
633 | |
634 texture_copier_ = | |
635 AcceleratedTextureCopier::Create(context3d, use_bind_uniform); | |
636 | |
637 texture_uploader_ = | |
638 TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_); | |
639 GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE, | |
640 &max_texture_size_)); | |
641 best_texture_format_ = | |
642 PlatformColor::BestTextureFormat(context3d, use_bgra); | |
643 return true; | |
644 } | |
645 | |
646 int ResourceProvider::CreateChild() { | |
647 DCHECK(thread_checker_.CalledOnValidThread()); | |
648 Child child_info; | |
649 int child = next_child_++; | |
650 children_[child] = child_info; | |
651 return child; | |
652 } | |
653 | |
654 void ResourceProvider::DestroyChild(int child_id) { | |
655 DCHECK(thread_checker_.CalledOnValidThread()); | |
656 ChildMap::iterator it = children_.find(child_id); | |
657 DCHECK(it != children_.end()); | |
658 Child& child = it->second; | |
659 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin(); | |
660 child_it != child.child_to_parent_map.end(); | |
661 ++child_it) | |
662 DeleteResource(child_it->second); | |
663 children_.erase(it); | |
664 } | |
665 | |
666 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap( | |
667 int child) const { | |
668 DCHECK(thread_checker_.CalledOnValidThread()); | |
669 ChildMap::const_iterator it = children_.find(child); | |
670 DCHECK(it != children_.end()); | |
671 return it->second.child_to_parent_map; | |
672 } | |
673 | |
674 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources, | |
675 TransferableResourceArray* list) { | |
676 DCHECK(thread_checker_.CalledOnValidThread()); | |
677 list->clear(); | |
678 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
679 if (!context3d || !context3d->makeContextCurrent()) { | |
680 // FIXME: Implement this path for software compositing. | |
681 return; | |
682 } | |
683 bool need_sync_point = false; | |
684 for (ResourceIdArray::const_iterator it = resources.begin(); | |
685 it != resources.end(); | |
686 ++it) { | |
687 TransferableResource resource; | |
688 if (TransferResource(context3d, *it, &resource)) { | |
689 if (!resource.sync_point) | |
690 need_sync_point = true; | |
691 resources_.find(*it)->second.exported = true; | |
692 list->push_back(resource); | |
693 } | |
694 } | |
695 if (need_sync_point) { | |
696 unsigned int sync_point = context3d->insertSyncPoint(); | |
697 for (TransferableResourceArray::iterator it = list->begin(); | |
698 it != list->end(); | |
699 ++it) { | |
700 if (!it->sync_point) | |
701 it->sync_point = sync_point; | |
702 } | |
703 } | |
704 } | |
705 | |
706 void ResourceProvider::PrepareSendToChild(int child, | |
707 const ResourceIdArray& resources, | |
708 TransferableResourceArray* list) { | |
709 DCHECK(thread_checker_.CalledOnValidThread()); | |
710 list->clear(); | |
711 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
712 if (!context3d || !context3d->makeContextCurrent()) { | |
713 // FIXME: Implement this path for software compositing. | |
714 return; | |
715 } | |
716 Child& child_info = children_.find(child)->second; | |
717 bool need_sync_point = false; | |
718 for (ResourceIdArray::const_iterator it = resources.begin(); | |
719 it != resources.end(); | |
720 ++it) { | |
721 TransferableResource resource; | |
722 if (!TransferResource(context3d, *it, &resource)) | |
723 NOTREACHED(); | |
724 if (!resource.sync_point) | |
725 need_sync_point = true; | |
726 DCHECK(child_info.parent_to_child_map.find(*it) != | |
727 child_info.parent_to_child_map.end()); | |
728 resource.id = child_info.parent_to_child_map[*it]; | |
729 child_info.parent_to_child_map.erase(*it); | |
730 child_info.child_to_parent_map.erase(resource.id); | |
731 list->push_back(resource); | |
732 DeleteResource(*it); | |
733 } | |
734 if (need_sync_point) { | |
735 unsigned int sync_point = context3d->insertSyncPoint(); | |
736 for (TransferableResourceArray::iterator it = list->begin(); | |
737 it != list->end(); | |
738 ++it) { | |
739 if (!it->sync_point) | |
740 it->sync_point = sync_point; | |
741 } | |
742 } | |
743 } | |
744 | |
745 void ResourceProvider::ReceiveFromChild( | |
746 int child, const TransferableResourceArray& resources) { | |
747 DCHECK(thread_checker_.CalledOnValidThread()); | |
748 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
749 if (!context3d || !context3d->makeContextCurrent()) { | |
750 // FIXME: Implement this path for software compositing. | |
751 return; | |
752 } | |
753 Child& child_info = children_.find(child)->second; | |
754 for (TransferableResourceArray::const_iterator it = resources.begin(); | |
755 it != resources.end(); | |
756 ++it) { | |
757 unsigned texture_id; | |
758 // NOTE: If the parent is a browser and the child a renderer, the parent | |
759 // is not supposed to have its context wait, because that could induce | |
760 // deadlocks and/or security issues. The caller is responsible for | |
761 // waiting asynchronously, and resetting sync_point before calling this. | |
762 // However if the parent is a renderer (e.g. browser tag), it may be ok | |
763 // (and is simpler) to wait. | |
764 if (it->sync_point) | |
765 GLC(context3d, context3d->waitSyncPoint(it->sync_point)); | |
766 GLC(context3d, texture_id = context3d->createTexture()); | |
767 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id)); | |
768 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, | |
769 it->mailbox.name)); | |
770 ResourceId id = next_id_++; | |
771 Resource resource(texture_id, it->size, it->format, it->filter); | |
772 resource.mailbox.SetName(it->mailbox); | |
773 // Don't allocate a texture for a child. | |
774 resource.allocated = true; | |
775 resources_[id] = resource; | |
776 child_info.parent_to_child_map[id] = it->id; | |
777 child_info.child_to_parent_map[it->id] = id; | |
778 } | |
779 } | |
780 | |
781 void ResourceProvider::ReceiveFromParent( | |
782 const TransferableResourceArray& resources) { | |
783 DCHECK(thread_checker_.CalledOnValidThread()); | |
784 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
785 if (!context3d || !context3d->makeContextCurrent()) { | |
786 // FIXME: Implement this path for software compositing. | |
787 return; | |
788 } | |
789 for (TransferableResourceArray::const_iterator it = resources.begin(); | |
790 it != resources.end(); | |
791 ++it) { | |
792 ResourceMap::iterator map_iterator = resources_.find(it->id); | |
793 DCHECK(map_iterator != resources_.end()); | |
794 Resource* resource = &map_iterator->second; | |
795 DCHECK(resource->exported); | |
796 resource->exported = false; | |
797 resource->filter = it->filter; | |
798 DCHECK(resource->mailbox.Equals(it->mailbox)); | |
799 if (resource->gl_id) { | |
800 if (it->sync_point) | |
801 GLC(context3d, context3d->waitSyncPoint(it->sync_point)); | |
802 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); | |
803 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, | |
804 it->mailbox.name)); | |
805 } else { | |
806 resource->mailbox = TextureMailbox(resource->mailbox.name(), | |
807 resource->mailbox.callback(), | |
808 it->sync_point); | |
809 } | |
810 if (resource->marked_for_deletion) | |
811 DeleteResourceInternal(map_iterator); | |
812 } | |
813 } | |
814 | |
815 bool ResourceProvider::TransferResource(WebGraphicsContext3D* context, | |
816 ResourceId id, | |
817 TransferableResource* resource) { | |
818 DCHECK(thread_checker_.CalledOnValidThread()); | |
819 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
820 ResourceMap::iterator it = resources_.find(id); | |
821 CHECK(it != resources_.end()); | |
822 Resource* source = &it->second; | |
823 DCHECK(!source->locked_for_write); | |
824 DCHECK(!source->lock_for_read_count); | |
825 DCHECK(!source->external || (source->external && !source->mailbox.IsEmpty())); | |
826 DCHECK(source->allocated); | |
827 if (source->exported) | |
828 return false; | |
829 resource->id = id; | |
830 resource->format = source->format; | |
831 resource->filter = source->filter; | |
832 resource->size = source->size; | |
833 | |
834 if (source->mailbox.IsEmpty()) { | |
835 GLC(context3d, context3d->genMailboxCHROMIUM(resource->mailbox.name)); | |
836 source->mailbox.SetName(resource->mailbox); | |
837 } else { | |
838 resource->mailbox = source->mailbox.name(); | |
839 } | |
840 | |
841 if (source->gl_id) { | |
842 GLC(context, context->bindTexture(GL_TEXTURE_2D, source->gl_id)); | |
843 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, | |
844 resource->mailbox.name)); | |
845 } else { | |
846 resource->sync_point = source->mailbox.sync_point(); | |
847 source->mailbox.ResetSyncPoint(); | |
848 } | |
849 return true; | |
850 } | |
851 | |
852 void ResourceProvider::AcquirePixelBuffer(ResourceId id) { | |
853 DCHECK(thread_checker_.CalledOnValidThread()); | |
854 ResourceMap::iterator it = resources_.find(id); | |
855 CHECK(it != resources_.end()); | |
856 Resource* resource = &it->second; | |
857 DCHECK(!resource->external); | |
858 DCHECK(!resource->exported); | |
859 | |
860 if (resource->gl_id) { | |
861 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
862 DCHECK(context3d); | |
863 if (!resource->gl_pixel_buffer_id) | |
864 resource->gl_pixel_buffer_id = context3d->createBuffer(); | |
865 context3d->bindBuffer( | |
866 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
867 resource->gl_pixel_buffer_id); | |
868 context3d->bufferData( | |
869 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
870 resource->size.width() * resource->size.height() * 4, | |
871 NULL, | |
872 GL_DYNAMIC_DRAW); | |
873 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
874 } | |
875 | |
876 if (resource->pixels) { | |
877 if (resource->pixel_buffer) | |
878 return; | |
879 | |
880 resource->pixel_buffer = new uint8_t[ | |
881 resource->size.width() * resource->size.height() * 4]; | |
882 } | |
883 } | |
884 | |
885 void ResourceProvider::ReleasePixelBuffer(ResourceId id) { | |
886 DCHECK(thread_checker_.CalledOnValidThread()); | |
887 ResourceMap::iterator it = resources_.find(id); | |
888 CHECK(it != resources_.end()); | |
889 Resource* resource = &it->second; | |
890 DCHECK(!resource->external); | |
891 DCHECK(!resource->exported); | |
892 | |
893 if (resource->gl_id) { | |
894 DCHECK(resource->gl_pixel_buffer_id); | |
895 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
896 DCHECK(context3d); | |
897 context3d->bindBuffer( | |
898 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
899 resource->gl_pixel_buffer_id); | |
900 context3d->bufferData( | |
901 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
902 0, | |
903 NULL, | |
904 GL_DYNAMIC_DRAW); | |
905 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
906 } | |
907 | |
908 if (resource->pixels) { | |
909 if (!resource->pixel_buffer) | |
910 return; | |
911 delete[] resource->pixel_buffer; | |
912 resource->pixel_buffer = NULL; | |
913 } | |
914 } | |
915 | |
916 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) { | |
917 DCHECK(thread_checker_.CalledOnValidThread()); | |
918 ResourceMap::iterator it = resources_.find(id); | |
919 CHECK(it != resources_.end()); | |
920 Resource* resource = &it->second; | |
921 DCHECK(!resource->external); | |
922 DCHECK(!resource->exported); | |
923 | |
924 if (resource->gl_id) { | |
925 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
926 DCHECK(context3d); | |
927 DCHECK(resource->gl_pixel_buffer_id); | |
928 context3d->bindBuffer( | |
929 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
930 resource->gl_pixel_buffer_id); | |
931 uint8_t* image = static_cast<uint8_t*>( | |
932 context3d->mapBufferCHROMIUM( | |
933 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY)); | |
934 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
935 DCHECK(image); | |
936 return image; | |
937 } | |
938 | |
939 if (resource->pixels) | |
940 return resource->pixel_buffer; | |
941 | |
942 return NULL; | |
943 } | |
944 | |
945 void ResourceProvider::UnmapPixelBuffer(ResourceId id) { | |
946 DCHECK(thread_checker_.CalledOnValidThread()); | |
947 ResourceMap::iterator it = resources_.find(id); | |
948 CHECK(it != resources_.end()); | |
949 Resource* resource = &it->second; | |
950 DCHECK(!resource->external); | |
951 DCHECK(!resource->exported); | |
952 | |
953 if (resource->gl_id) { | |
954 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
955 DCHECK(context3d); | |
956 DCHECK(resource->gl_pixel_buffer_id); | |
957 context3d->bindBuffer( | |
958 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
959 resource->gl_pixel_buffer_id); | |
960 context3d->unmapBufferCHROMIUM( | |
961 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM); | |
962 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
963 } | |
964 } | |
965 | |
966 void ResourceProvider::SetPixelsFromBuffer(ResourceId id) { | |
967 DCHECK(thread_checker_.CalledOnValidThread()); | |
968 ResourceMap::iterator it = resources_.find(id); | |
969 CHECK(it != resources_.end()); | |
970 Resource* resource = &it->second; | |
971 DCHECK(!resource->locked_for_write); | |
972 DCHECK(!resource->lock_for_read_count); | |
973 DCHECK(!resource->external); | |
974 DCHECK(!resource->exported); | |
975 DCHECK(ReadLockFenceHasPassed(resource)); | |
976 LazyAllocate(resource); | |
977 | |
978 if (resource->gl_id) { | |
979 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
980 DCHECK(context3d); | |
981 DCHECK(resource->gl_pixel_buffer_id); | |
982 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id); | |
983 context3d->bindBuffer( | |
984 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
985 resource->gl_pixel_buffer_id); | |
986 context3d->texSubImage2D(GL_TEXTURE_2D, | |
987 0, /* level */ | |
988 0, /* x */ | |
989 0, /* y */ | |
990 resource->size.width(), | |
991 resource->size.height(), | |
992 resource->format, | |
993 GL_UNSIGNED_BYTE, | |
994 NULL); | |
995 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
996 } | |
997 | |
998 if (resource->pixels) { | |
999 DCHECK(resource->pixel_buffer); | |
1000 DCHECK(resource->format == GL_RGBA); | |
1001 SkBitmap src; | |
1002 src.setConfig(SkBitmap::kARGB_8888_Config, | |
1003 resource->size.width(), | |
1004 resource->size.height()); | |
1005 src.setPixels(resource->pixel_buffer); | |
1006 | |
1007 ScopedWriteLockSoftware lock(this, id); | |
1008 SkCanvas* dest = lock.sk_canvas(); | |
1009 dest->writePixels(src, 0, 0); | |
1010 } | |
1011 } | |
1012 | |
1013 void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id, | |
1014 GLenum target, GLenum filter) { | |
1015 DCHECK(thread_checker_.CalledOnValidThread()); | |
1016 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
1017 ResourceMap::iterator it = resources_.find(resource_id); | |
1018 DCHECK(it != resources_.end()); | |
1019 Resource* resource = &it->second; | |
1020 DCHECK(resource->lock_for_read_count); | |
1021 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced); | |
1022 | |
1023 GLC(context3d, context3d->bindTexture(target, resource->gl_id)); | |
1024 if (filter != resource->filter) { | |
1025 GLC(context3d, context3d->texParameteri(target, | |
1026 GL_TEXTURE_MIN_FILTER, | |
1027 filter)); | |
1028 GLC(context3d, context3d->texParameteri(target, | |
1029 GL_TEXTURE_MAG_FILTER, | |
1030 filter)); | |
1031 resource->filter = filter; | |
1032 } | |
1033 } | |
1034 | |
1035 void ResourceProvider::BeginSetPixels(ResourceId id) { | |
1036 DCHECK(thread_checker_.CalledOnValidThread()); | |
1037 ResourceMap::iterator it = resources_.find(id); | |
1038 CHECK(it != resources_.end()); | |
1039 Resource* resource = &it->second; | |
1040 DCHECK(!resource->pending_set_pixels); | |
1041 DCHECK(resource->gl_id || resource->allocated); | |
1042 DCHECK(ReadLockFenceHasPassed(resource)); | |
1043 | |
1044 bool allocate = !resource->allocated; | |
1045 resource->allocated = true; | |
1046 LockForWrite(id); | |
1047 | |
1048 if (resource->gl_id) { | |
1049 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
1050 DCHECK(context3d); | |
1051 DCHECK(resource->gl_pixel_buffer_id); | |
1052 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id); | |
1053 context3d->bindBuffer( | |
1054 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, | |
1055 resource->gl_pixel_buffer_id); | |
1056 if (!resource->gl_upload_query_id) | |
1057 resource->gl_upload_query_id = context3d->createQueryEXT(); | |
1058 context3d->beginQueryEXT( | |
1059 GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM, | |
1060 resource->gl_upload_query_id); | |
1061 if (allocate) { | |
1062 context3d->asyncTexImage2DCHROMIUM(GL_TEXTURE_2D, | |
1063 0, /* level */ | |
1064 resource->format, | |
1065 resource->size.width(), | |
1066 resource->size.height(), | |
1067 0, /* border */ | |
1068 resource->format, | |
1069 GL_UNSIGNED_BYTE, | |
1070 NULL); | |
1071 } else { | |
1072 context3d->asyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D, | |
1073 0, /* level */ | |
1074 0, /* x */ | |
1075 0, /* y */ | |
1076 resource->size.width(), | |
1077 resource->size.height(), | |
1078 resource->format, | |
1079 GL_UNSIGNED_BYTE, | |
1080 NULL); | |
1081 } | |
1082 context3d->endQueryEXT(GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM); | |
1083 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
1084 } | |
1085 | |
1086 if (resource->pixels) | |
1087 SetPixelsFromBuffer(id); | |
1088 | |
1089 resource->pending_set_pixels = true; | |
1090 resource->set_pixels_completion_forced = false; | |
1091 } | |
1092 | |
1093 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) { | |
1094 DCHECK(thread_checker_.CalledOnValidThread()); | |
1095 ResourceMap::iterator it = resources_.find(id); | |
1096 CHECK(it != resources_.end()); | |
1097 Resource* resource = &it->second; | |
1098 DCHECK(resource->locked_for_write); | |
1099 DCHECK(resource->pending_set_pixels); | |
1100 DCHECK(!resource->set_pixels_completion_forced); | |
1101 | |
1102 if (resource->gl_id) { | |
1103 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
1104 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); | |
1105 GLC(context3d, context3d->waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)); | |
1106 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, 0)); | |
1107 } | |
1108 | |
1109 resource->set_pixels_completion_forced = true; | |
1110 } | |
1111 | |
1112 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) { | |
1113 DCHECK(thread_checker_.CalledOnValidThread()); | |
1114 ResourceMap::iterator it = resources_.find(id); | |
1115 CHECK(it != resources_.end()); | |
1116 Resource* resource = &it->second; | |
1117 DCHECK(resource->locked_for_write); | |
1118 DCHECK(resource->pending_set_pixels); | |
1119 | |
1120 if (resource->gl_id) { | |
1121 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
1122 DCHECK(context3d); | |
1123 DCHECK(resource->gl_upload_query_id); | |
1124 unsigned complete = 1; | |
1125 context3d->getQueryObjectuivEXT( | |
1126 resource->gl_upload_query_id, | |
1127 GL_QUERY_RESULT_AVAILABLE_EXT, | |
1128 &complete); | |
1129 if (!complete) | |
1130 return false; | |
1131 } | |
1132 | |
1133 resource->pending_set_pixels = false; | |
1134 UnlockForWrite(id); | |
1135 | |
1136 return true; | |
1137 } | |
1138 | |
1139 void ResourceProvider::AbortSetPixels(ResourceId id) { | |
1140 DCHECK(thread_checker_.CalledOnValidThread()); | |
1141 ResourceMap::iterator it = resources_.find(id); | |
1142 CHECK(it != resources_.end()); | |
1143 Resource* resource = &it->second; | |
1144 DCHECK(resource->locked_for_write); | |
1145 DCHECK(resource->pending_set_pixels); | |
1146 | |
1147 if (resource->gl_id) { | |
1148 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
1149 DCHECK(context3d); | |
1150 DCHECK(resource->gl_upload_query_id); | |
1151 // CHROMIUM_async_pixel_transfers currently doesn't have a way to | |
1152 // abort an upload. The best we can do is delete the query and | |
1153 // the texture. | |
1154 context3d->deleteQueryEXT(resource->gl_upload_query_id); | |
1155 resource->gl_upload_query_id = 0; | |
1156 context3d->deleteTexture(resource->gl_id); | |
1157 resource->gl_id = CreateTextureId(context3d); | |
1158 resource->allocated = false; | |
1159 } | |
1160 | |
1161 resource->pending_set_pixels = false; | |
1162 UnlockForWrite(id); | |
1163 } | |
1164 | |
1165 void ResourceProvider::AllocateForTesting(ResourceId id) { | |
1166 ResourceMap::iterator it = resources_.find(id); | |
1167 CHECK(it != resources_.end()); | |
1168 Resource* resource = &it->second; | |
1169 LazyAllocate(resource); | |
1170 } | |
1171 | |
1172 void ResourceProvider::LazyAllocate(Resource* resource) { | |
1173 DCHECK(resource); | |
1174 DCHECK(resource->gl_id || resource->allocated); | |
1175 | |
1176 if (resource->allocated || !resource->gl_id) | |
1177 return; | |
1178 resource->allocated = true; | |
1179 WebGraphicsContext3D* context3d = output_surface_->context3d(); | |
1180 gfx::Size& size = resource->size; | |
1181 GLenum format = resource->format; | |
1182 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); | |
1183 if (use_texture_storage_ext_ && IsTextureFormatSupportedForStorage(format)) { | |
1184 GLenum storage_format = TextureToStorageFormat(format); | |
1185 GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, | |
1186 1, | |
1187 storage_format, | |
1188 size.width(), | |
1189 size.height())); | |
1190 } else | |
1191 GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, | |
1192 0, | |
1193 format, | |
1194 size.width(), | |
1195 size.height(), | |
1196 0, | |
1197 format, | |
1198 GL_UNSIGNED_BYTE, | |
1199 NULL)); | |
1200 } | |
1201 | |
1202 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id, | |
1203 bool enable) { | |
1204 DCHECK(thread_checker_.CalledOnValidThread()); | |
1205 ResourceMap::iterator it = resources_.find(id); | |
1206 CHECK(it != resources_.end()); | |
1207 Resource* resource = &it->second; | |
1208 resource->enable_read_lock_fences = enable; | |
1209 } | |
1210 | |
1211 } // namespace cc | |
OLD | NEW |