| 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 |