1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // A class to emulate GLES2 over command buffers. 6 7 #include "gpu/command_buffer/client/gles2_implementation.h" 8 9 #include <GLES2/gl2ext.h> 10 #include <GLES2/gl2extchromium.h> 11 #include <algorithm> 12 #include <limits> 13 #include <map> 14 #include <queue> 15 #include <set> 16 #include <sstream> 17 #include <string> 18 #include "base/bind.h" 19 #include "gpu/command_buffer/client/buffer_tracker.h" 20 #include "gpu/command_buffer/client/gpu_control.h" 21 #include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h" 22 #include "gpu/command_buffer/client/program_info_manager.h" 23 #include "gpu/command_buffer/client/query_tracker.h" 24 #include "gpu/command_buffer/client/transfer_buffer.h" 25 #include "gpu/command_buffer/client/vertex_array_object_manager.h" 26 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 27 #include "gpu/command_buffer/common/trace_event.h" 28 #include "ui/gfx/gpu_memory_buffer.h" 29 30 #if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 31 #define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS 32 #endif 33 34 #if defined(GPU_CLIENT_DEBUG) 35 #include "base/command_line.h" 36 #include "ui/gl/gl_switches.h" 37 #endif 38 39 namespace gpu { 40 namespace gles2 { 41 42 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint. 43 static GLuint ToGLuint(const void* ptr) { 44 return static_cast<GLuint>(reinterpret_cast<size_t>(ptr)); 45 } 46 47 #if !defined(_MSC_VER) 48 const size_t GLES2Implementation::kMaxSizeOfSimpleResult; 49 const unsigned int GLES2Implementation::kStartingOffset; 50 #endif 51 52 GLES2Implementation::GLStaticState::GLStaticState() { 53 } 54 55 GLES2Implementation::GLStaticState::~GLStaticState() { 56 } 57 58 GLES2Implementation::GLStaticState::IntState::IntState() 59 : max_combined_texture_image_units(0), 60 max_cube_map_texture_size(0), 61 max_fragment_uniform_vectors(0), 62 max_renderbuffer_size(0), 63 max_texture_image_units(0), 64 max_texture_size(0), 65 max_varying_vectors(0), 66 max_vertex_attribs(0), 67 max_vertex_texture_image_units(0), 68 max_vertex_uniform_vectors(0), 69 num_compressed_texture_formats(0), 70 num_shader_binary_formats(0), 71 bind_generates_resource_chromium(0) {} 72 73 GLES2Implementation::SingleThreadChecker::SingleThreadChecker( 74 GLES2Implementation* gles2_implementation) 75 : gles2_implementation_(gles2_implementation) { 76 CHECK_EQ(0, gles2_implementation_->use_count_); 77 ++gles2_implementation_->use_count_; 78 } 79 80 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() { 81 --gles2_implementation_->use_count_; 82 CHECK_EQ(0, gles2_implementation_->use_count_); 83 } 84 85 GLES2Implementation::GLES2Implementation( 86 GLES2CmdHelper* helper, 87 ShareGroup* share_group, 88 TransferBufferInterface* transfer_buffer, 89 bool bind_generates_resource, 90 bool lose_context_when_out_of_memory, 91 GpuControl* gpu_control) 92 : helper_(helper), 93 transfer_buffer_(transfer_buffer), 94 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus), 95 chromium_framebuffer_multisample_(kUnknownExtensionStatus), 96 pack_alignment_(4), 97 unpack_alignment_(4), 98 unpack_flip_y_(false), 99 unpack_row_length_(0), 100 unpack_skip_rows_(0), 101 unpack_skip_pixels_(0), 102 pack_reverse_row_order_(false), 103 active_texture_unit_(0), 104 bound_framebuffer_(0), 105 bound_read_framebuffer_(0), 106 bound_renderbuffer_(0), 107 current_program_(0), 108 bound_array_buffer_id_(0), 109 bound_pixel_pack_transfer_buffer_id_(0), 110 bound_pixel_unpack_transfer_buffer_id_(0), 111 async_upload_token_(0), 112 async_upload_sync_(NULL), 113 async_upload_sync_shm_id_(0), 114 async_upload_sync_shm_offset_(0), 115 error_bits_(0), 116 debug_(false), 117 lose_context_when_out_of_memory_(lose_context_when_out_of_memory), 118 use_count_(0), 119 error_message_callback_(NULL), 120 gpu_control_(gpu_control), 121 capabilities_(gpu_control->GetCapabilities()), 122 weak_ptr_factory_(this) { 123 DCHECK(helper); 124 DCHECK(transfer_buffer); 125 DCHECK(gpu_control); 126 127 std::stringstream ss; 128 ss << std::hex << this; 129 this_in_hex_ = ss.str(); 130 131 GPU_CLIENT_LOG_CODE_BLOCK({ 132 debug_ = CommandLine::ForCurrentProcess()->HasSwitch( 133 switches::kEnableGPUClientLogging); 134 }); 135 136 share_group_ = 137 (share_group ? share_group : new ShareGroup(bind_generates_resource)); 138 DCHECK(share_group_->bind_generates_resource() == bind_generates_resource); 139 140 memset(&reserved_ids_, 0, sizeof(reserved_ids_)); 141 } 142 143 bool GLES2Implementation::Initialize( 144 unsigned int starting_transfer_buffer_size, 145 unsigned int min_transfer_buffer_size, 146 unsigned int max_transfer_buffer_size, 147 unsigned int mapped_memory_limit) { 148 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize"); 149 DCHECK_GE(starting_transfer_buffer_size, min_transfer_buffer_size); 150 DCHECK_LE(starting_transfer_buffer_size, max_transfer_buffer_size); 151 DCHECK_GE(min_transfer_buffer_size, kStartingOffset); 152 153 if (!transfer_buffer_->Initialize( 154 starting_transfer_buffer_size, 155 kStartingOffset, 156 min_transfer_buffer_size, 157 max_transfer_buffer_size, 158 kAlignment, 159 kSizeToFlush)) { 160 return false; 161 } 162 163 mapped_memory_.reset( 164 new MappedMemoryManager( 165 helper_, 166 base::Bind(&GLES2Implementation::PollAsyncUploads, 167 // The mapped memory manager is owned by |this| here, and 168 // since its destroyed before before we destroy ourselves 169 // we don't need extra safety measures for this closure. 170 base::Unretained(this)), 171 mapped_memory_limit)); 172 173 unsigned chunk_size = 2 * 1024 * 1024; 174 if (mapped_memory_limit != kNoLimit) { 175 // Use smaller chunks if the client is very memory conscientious. 176 chunk_size = std::min(mapped_memory_limit / 4, chunk_size); 177 } 178 mapped_memory_->set_chunk_size_multiple(chunk_size); 179 180 if (!QueryAndCacheStaticState()) 181 return false; 182 183 util_.set_num_compressed_texture_formats( 184 static_state_.int_state.num_compressed_texture_formats); 185 util_.set_num_shader_binary_formats( 186 static_state_.int_state.num_shader_binary_formats); 187 188 texture_units_.reset( 189 new TextureUnit[ 190 static_state_.int_state.max_combined_texture_image_units]); 191 192 query_tracker_.reset(new QueryTracker(mapped_memory_.get())); 193 buffer_tracker_.reset(new BufferTracker(mapped_memory_.get())); 194 gpu_memory_buffer_tracker_.reset(new GpuMemoryBufferTracker(gpu_control_)); 195 196 query_id_allocator_.reset(new IdAllocator()); 197 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 198 GetIdHandler(id_namespaces::kBuffers)->MakeIds( 199 this, kClientSideArrayId, arraysize(reserved_ids_), &reserved_ids_[0]); 200 #endif 201 202 vertex_array_object_manager_.reset(new VertexArrayObjectManager( 203 static_state_.int_state.max_vertex_attribs, 204 reserved_ids_[0], 205 reserved_ids_[1])); 206 207 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same 208 // on Client & Service. 209 if (static_state_.int_state.bind_generates_resource_chromium != 210 (share_group_->bind_generates_resource() ? 1 : 0)) { 211 SetGLError(GL_INVALID_OPERATION, 212 "Initialize", 213 "Service bind_generates_resource mismatch."); 214 return false; 215 } 216 217 return true; 218 } 219 220 bool GLES2Implementation::QueryAndCacheStaticState() { 221 TRACE_EVENT0("gpu", "GLES2Implementation::QueryAndCacheStaticState"); 222 // Setup query for multiple GetIntegerv's 223 static const GLenum pnames[] = { 224 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 225 GL_MAX_CUBE_MAP_TEXTURE_SIZE, 226 GL_MAX_FRAGMENT_UNIFORM_VECTORS, 227 GL_MAX_RENDERBUFFER_SIZE, 228 GL_MAX_TEXTURE_IMAGE_UNITS, 229 GL_MAX_TEXTURE_SIZE, 230 GL_MAX_VARYING_VECTORS, 231 GL_MAX_VERTEX_ATTRIBS, 232 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, 233 GL_MAX_VERTEX_UNIFORM_VECTORS, 234 GL_NUM_COMPRESSED_TEXTURE_FORMATS, 235 GL_NUM_SHADER_BINARY_FORMATS, 236 GL_BIND_GENERATES_RESOURCE_CHROMIUM, 237 }; 238 239 GetMultipleIntegervState integerv_state( 240 pnames, arraysize(pnames), 241 &static_state_.int_state.max_combined_texture_image_units, 242 sizeof(static_state_.int_state)); 243 if (!GetMultipleIntegervSetup(&integerv_state)) { 244 return false; 245 } 246 247 // Setup query for multiple GetShaderPrecisionFormat's 248 static const GLenum precision_params[][2] = { 249 { GL_VERTEX_SHADER, GL_LOW_INT }, 250 { GL_VERTEX_SHADER, GL_MEDIUM_INT }, 251 { GL_VERTEX_SHADER, GL_HIGH_INT }, 252 { GL_VERTEX_SHADER, GL_LOW_FLOAT }, 253 { GL_VERTEX_SHADER, GL_MEDIUM_FLOAT }, 254 { GL_VERTEX_SHADER, GL_HIGH_FLOAT }, 255 { GL_FRAGMENT_SHADER, GL_LOW_INT }, 256 { GL_FRAGMENT_SHADER, GL_MEDIUM_INT }, 257 { GL_FRAGMENT_SHADER, GL_HIGH_INT }, 258 { GL_FRAGMENT_SHADER, GL_LOW_FLOAT }, 259 { GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT }, 260 { GL_FRAGMENT_SHADER, GL_HIGH_FLOAT }, 261 }; 262 263 GetAllShaderPrecisionFormatsState precision_state( 264 precision_params, arraysize(precision_params)); 265 GetAllShaderPrecisionFormatsSetup(&precision_state); 266 267 // Allocate and partition transfer buffer for all requests 268 void* buffer = transfer_buffer_->Alloc( 269 integerv_state.transfer_buffer_size_needed + 270 precision_state.transfer_buffer_size_needed); 271 if (!buffer) { 272 SetGLError(GL_OUT_OF_MEMORY, "QueryAndCacheStaticState", 273 "Transfer buffer allocation failed."); 274 return false; 275 } 276 integerv_state.buffer = buffer; 277 precision_state.results_buffer = 278 static_cast<char*>(buffer) + integerv_state.transfer_buffer_size_needed; 279 280 // Make all the requests and wait once for all the results. 281 GetMultipleIntegervRequest(&integerv_state); 282 GetAllShaderPrecisionFormatsRequest(&precision_state); 283 WaitForCmd(); 284 GetMultipleIntegervOnCompleted(&integerv_state); 285 GetAllShaderPrecisionFormatsOnCompleted(&precision_state); 286 287 // TODO(gman): We should be able to free without a token. 288 transfer_buffer_->FreePendingToken(buffer, helper_->InsertToken()); 289 CheckGLError(); 290 291 return true; 292 } 293 294 GLES2Implementation::~GLES2Implementation() { 295 // Make sure the queries are finished otherwise we'll delete the 296 // shared memory (mapped_memory_) which will free the memory used 297 // by the queries. The GPU process when validating that memory is still 298 // shared will fail and abort (ie, it will stop running). 299 WaitForCmd(); 300 query_tracker_.reset(); 301 302 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 303 DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]); 304 #endif 305 306 // Release any per-context data in share group. 307 share_group_->FreeContext(this); 308 309 buffer_tracker_.reset(); 310 311 FreeAllAsyncUploadBuffers(); 312 313 if (async_upload_sync_) { 314 mapped_memory_->Free(async_upload_sync_); 315 async_upload_sync_ = NULL; 316 } 317 318 // Make sure the commands make it the service. 319 WaitForCmd(); 320 } 321 322 GLES2CmdHelper* GLES2Implementation::helper() const { 323 return helper_; 324 } 325 326 IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const { 327 return share_group_->GetIdHandler(namespace_id); 328 } 329 330 IdAllocatorInterface* GLES2Implementation::GetIdAllocator( 331 int namespace_id) const { 332 if (namespace_id == id_namespaces::kQueries) 333 return query_id_allocator_.get(); 334 NOTREACHED(); 335 return NULL; 336 } 337 338 void* GLES2Implementation::GetResultBuffer() { 339 return transfer_buffer_->GetResultBuffer(); 340 } 341 342 int32 GLES2Implementation::GetResultShmId() { 343 return transfer_buffer_->GetShmId(); 344 } 345 346 uint32 GLES2Implementation::GetResultShmOffset() { 347 return transfer_buffer_->GetResultOffset(); 348 } 349 350 void GLES2Implementation::FreeUnusedSharedMemory() { 351 mapped_memory_->FreeUnused(); 352 } 353 354 void GLES2Implementation::FreeEverything() { 355 FreeAllAsyncUploadBuffers(); 356 WaitForCmd(); 357 query_tracker_->Shrink(); 358 FreeUnusedSharedMemory(); 359 transfer_buffer_->Free(); 360 helper_->FreeRingBuffer(); 361 } 362 363 void GLES2Implementation::RunIfContextNotLost(const base::Closure& callback) { 364 if (!helper_->IsContextLost()) 365 callback.Run(); 366 } 367 368 void GLES2Implementation::SignalSyncPoint(uint32 sync_point, 369 const base::Closure& callback) { 370 gpu_control_->SignalSyncPoint( 371 sync_point, 372 base::Bind(&GLES2Implementation::RunIfContextNotLost, 373 weak_ptr_factory_.GetWeakPtr(), 374 callback)); 375 } 376 377 void GLES2Implementation::SignalQuery(uint32 query, 378 const base::Closure& callback) { 379 // Flush previously entered commands to ensure ordering with any 380 // glBeginQueryEXT() calls that may have been put into the context. 381 ShallowFlushCHROMIUM(); 382 gpu_control_->SignalQuery( 383 query, 384 base::Bind(&GLES2Implementation::RunIfContextNotLost, 385 weak_ptr_factory_.GetWeakPtr(), 386 callback)); 387 } 388 389 void GLES2Implementation::SetSurfaceVisible(bool visible) { 390 TRACE_EVENT1( 391 "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible); 392 // TODO(piman): This probably should be ShallowFlushCHROMIUM(). 393 Flush(); 394 gpu_control_->SetSurfaceVisible(visible); 395 if (!visible) 396 FreeEverything(); 397 } 398 399 void GLES2Implementation::WaitForCmd() { 400 TRACE_EVENT0("gpu", "GLES2::WaitForCmd"); 401 helper_->CommandBufferHelper::Finish(); 402 } 403 404 bool GLES2Implementation::IsExtensionAvailable(const char* ext) { 405 const char* extensions = 406 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS)); 407 if (!extensions) 408 return false; 409 410 int length = strlen(ext); 411 while (true) { 412 int n = strcspn(extensions, " "); 413 if (n == length && 0 == strncmp(ext, extensions, length)) { 414 return true; 415 } 416 if ('\0' == extensions[n]) { 417 return false; 418 } 419 extensions += n + 1; 420 } 421 } 422 423 bool GLES2Implementation::IsExtensionAvailableHelper( 424 const char* extension, ExtensionStatus* status) { 425 switch (*status) { 426 case kAvailableExtensionStatus: 427 return true; 428 case kUnavailableExtensionStatus: 429 return false; 430 default: { 431 bool available = IsExtensionAvailable(extension); 432 *status = available ? kAvailableExtensionStatus : 433 kUnavailableExtensionStatus; 434 return available; 435 } 436 } 437 } 438 439 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() { 440 return IsExtensionAvailableHelper( 441 "GL_ANGLE_pack_reverse_row_order", 442 &angle_pack_reverse_row_order_status_); 443 } 444 445 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() { 446 return IsExtensionAvailableHelper( 447 "GL_CHROMIUM_framebuffer_multisample", 448 &chromium_framebuffer_multisample_); 449 } 450 451 const std::string& GLES2Implementation::GetLogPrefix() const { 452 const std::string& prefix(debug_marker_manager_.GetMarker()); 453 return prefix.empty() ? this_in_hex_ : prefix; 454 } 455 456 GLenum GLES2Implementation::GetError() { 457 GPU_CLIENT_SINGLE_THREAD_CHECK(); 458 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()"); 459 GLenum err = GetGLError(); 460 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err)); 461 return err; 462 } 463 464 GLenum GLES2Implementation::GetClientSideGLError() { 465 if (error_bits_ == 0) { 466 return GL_NO_ERROR; 467 } 468 469 GLenum error = GL_NO_ERROR; 470 for (uint32 mask = 1; mask != 0; mask = mask << 1) { 471 if ((error_bits_ & mask) != 0) { 472 error = GLES2Util::GLErrorBitToGLError(mask); 473 break; 474 } 475 } 476 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error); 477 return error; 478 } 479 480 GLenum GLES2Implementation::GetGLError() { 481 TRACE_EVENT0("gpu", "GLES2::GetGLError"); 482 // Check the GL error first, then our wrapped error. 483 typedef cmds::GetError::Result Result; 484 Result* result = GetResultAs<Result*>(); 485 // If we couldn't allocate a result the context is lost. 486 if (!result) { 487 return GL_NO_ERROR; 488 } 489 *result = GL_NO_ERROR; 490 helper_->GetError(GetResultShmId(), GetResultShmOffset()); 491 WaitForCmd(); 492 GLenum error = *result; 493 if (error == GL_NO_ERROR) { 494 error = GetClientSideGLError(); 495 } else { 496 // There was an error, clear the corresponding wrapped error. 497 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error); 498 } 499 return error; 500 } 501 502 #if defined(GL_CLIENT_FAIL_GL_ERRORS) 503 void GLES2Implementation::FailGLError(GLenum error) { 504 if (error != GL_NO_ERROR) { 505 NOTREACHED() << "Error"; 506 } 507 } 508 // NOTE: Calling GetGLError overwrites data in the result buffer. 509 void GLES2Implementation::CheckGLError() { 510 FailGLError(GetGLError()); 511 } 512 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS) 513 514 void GLES2Implementation::SetGLError( 515 GLenum error, const char* function_name, const char* msg) { 516 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: " 517 << GLES2Util::GetStringError(error) << ": " 518 << function_name << ": " << msg); 519 FailGLError(error); 520 if (msg) { 521 last_error_ = msg; 522 } 523 if (error_message_callback_) { 524 std::string temp(GLES2Util::GetStringError(error) + " : " + 525 function_name + ": " + (msg ? msg : "")); 526 error_message_callback_->OnErrorMessage(temp.c_str(), 0); 527 } 528 error_bits_ |= GLES2Util::GLErrorToErrorBit(error); 529 530 if (error == GL_OUT_OF_MEMORY && lose_context_when_out_of_memory_) { 531 helper_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, 532 GL_UNKNOWN_CONTEXT_RESET_ARB); 533 } 534 } 535 536 void GLES2Implementation::SetGLErrorInvalidEnum( 537 const char* function_name, GLenum value, const char* label) { 538 SetGLError(GL_INVALID_ENUM, function_name, 539 (std::string(label) + " was " + 540 GLES2Util::GetStringEnum(value)).c_str()); 541 } 542 543 bool GLES2Implementation::GetBucketContents(uint32 bucket_id, 544 std::vector<int8>* data) { 545 TRACE_EVENT0("gpu", "GLES2::GetBucketContents"); 546 DCHECK(data); 547 const uint32 kStartSize = 32 * 1024; 548 ScopedTransferBufferPtr buffer(kStartSize, helper_, transfer_buffer_); 549 if (!buffer.valid()) { 550 return false; 551 } 552 typedef cmd::GetBucketStart::Result Result; 553 Result* result = GetResultAs<Result*>(); 554 if (!result) { 555 return false; 556 } 557 *result = 0; 558 helper_->GetBucketStart( 559 bucket_id, GetResultShmId(), GetResultShmOffset(), 560 buffer.size(), buffer.shm_id(), buffer.offset()); 561 WaitForCmd(); 562 uint32 size = *result; 563 data->resize(size); 564 if (size > 0u) { 565 uint32 offset = 0; 566 while (size) { 567 if (!buffer.valid()) { 568 buffer.Reset(size); 569 if (!buffer.valid()) { 570 return false; 571 } 572 helper_->GetBucketData( 573 bucket_id, offset, buffer.size(), buffer.shm_id(), buffer.offset()); 574 WaitForCmd(); 575 } 576 uint32 size_to_copy = std::min(size, buffer.size()); 577 memcpy(&(*data)[offset], buffer.address(), size_to_copy); 578 offset += size_to_copy; 579 size -= size_to_copy; 580 buffer.Release(); 581 } 582 // Free the bucket. This is not required but it does free up the memory. 583 // and we don't have to wait for the result so from the client's perspective 584 // it's cheap. 585 helper_->SetBucketSize(bucket_id, 0); 586 } 587 return true; 588 } 589 590 void GLES2Implementation::SetBucketContents( 591 uint32 bucket_id, const void* data, size_t size) { 592 DCHECK(data); 593 helper_->SetBucketSize(bucket_id, size); 594 if (size > 0u) { 595 uint32 offset = 0; 596 while (size) { 597 ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); 598 if (!buffer.valid()) { 599 return; 600 } 601 memcpy(buffer.address(), static_cast<const int8*>(data) + offset, 602 buffer.size()); 603 helper_->SetBucketData( 604 bucket_id, offset, buffer.size(), buffer.shm_id(), buffer.offset()); 605 offset += buffer.size(); 606 size -= buffer.size(); 607 } 608 } 609 } 610 611 void GLES2Implementation::SetBucketAsCString( 612 uint32 bucket_id, const char* str) { 613 // NOTE: strings are passed NULL terminated. That means the empty 614 // string will have a size of 1 and no-string will have a size of 0 615 if (str) { 616 SetBucketContents(bucket_id, str, strlen(str) + 1); 617 } else { 618 helper_->SetBucketSize(bucket_id, 0); 619 } 620 } 621 622 bool GLES2Implementation::GetBucketAsString( 623 uint32 bucket_id, std::string* str) { 624 DCHECK(str); 625 std::vector<int8> data; 626 // NOTE: strings are passed NULL terminated. That means the empty 627 // string will have a size of 1 and no-string will have a size of 0 628 if (!GetBucketContents(bucket_id, &data)) { 629 return false; 630 } 631 if (data.empty()) { 632 return false; 633 } 634 str->assign(&data[0], &data[0] + data.size() - 1); 635 return true; 636 } 637 638 void GLES2Implementation::SetBucketAsString( 639 uint32 bucket_id, const std::string& str) { 640 // NOTE: strings are passed NULL terminated. That means the empty 641 // string will have a size of 1 and no-string will have a size of 0 642 SetBucketContents(bucket_id, str.c_str(), str.size() + 1); 643 } 644 645 void GLES2Implementation::Disable(GLenum cap) { 646 GPU_CLIENT_SINGLE_THREAD_CHECK(); 647 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable(" 648 << GLES2Util::GetStringCapability(cap) << ")"); 649 bool changed = false; 650 if (!state_.SetCapabilityState(cap, false, &changed) || changed) { 651 helper_->Disable(cap); 652 } 653 CheckGLError(); 654 } 655 656 void GLES2Implementation::Enable(GLenum cap) { 657 GPU_CLIENT_SINGLE_THREAD_CHECK(); 658 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable(" 659 << GLES2Util::GetStringCapability(cap) << ")"); 660 bool changed = false; 661 if (!state_.SetCapabilityState(cap, true, &changed) || changed) { 662 helper_->Enable(cap); 663 } 664 CheckGLError(); 665 } 666 667 GLboolean GLES2Implementation::IsEnabled(GLenum cap) { 668 GPU_CLIENT_SINGLE_THREAD_CHECK(); 669 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled(" 670 << GLES2Util::GetStringCapability(cap) << ")"); 671 bool state = false; 672 if (!state_.GetEnabled(cap, &state)) { 673 typedef cmds::IsEnabled::Result Result; 674 Result* result = GetResultAs<Result*>(); 675 if (!result) { 676 return GL_FALSE; 677 } 678 *result = 0; 679 helper_->IsEnabled(cap, GetResultShmId(), GetResultShmOffset()); 680 WaitForCmd(); 681 state = (*result) != 0; 682 } 683 684 GPU_CLIENT_LOG("returned " << state); 685 CheckGLError(); 686 return state; 687 } 688 689 bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { 690 switch (pname) { 691 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: 692 *params = static_state_.int_state.max_combined_texture_image_units; 693 return true; 694 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: 695 *params = static_state_.int_state.max_cube_map_texture_size; 696 return true; 697 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: 698 *params = static_state_.int_state.max_fragment_uniform_vectors; 699 return true; 700 case GL_MAX_RENDERBUFFER_SIZE: 701 *params = static_state_.int_state.max_renderbuffer_size; 702 return true; 703 case GL_MAX_TEXTURE_IMAGE_UNITS: 704 *params = static_state_.int_state.max_texture_image_units; 705 return true; 706 case GL_MAX_TEXTURE_SIZE: 707 *params = static_state_.int_state.max_texture_size; 708 return true; 709 case GL_MAX_VARYING_VECTORS: 710 *params = static_state_.int_state.max_varying_vectors; 711 return true; 712 case GL_MAX_VERTEX_ATTRIBS: 713 *params = static_state_.int_state.max_vertex_attribs; 714 return true; 715 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: 716 *params = static_state_.int_state.max_vertex_texture_image_units; 717 return true; 718 case GL_MAX_VERTEX_UNIFORM_VECTORS: 719 *params = static_state_.int_state.max_vertex_uniform_vectors; 720 return true; 721 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: 722 *params = static_state_.int_state.num_compressed_texture_formats; 723 return true; 724 case GL_NUM_SHADER_BINARY_FORMATS: 725 *params = static_state_.int_state.num_shader_binary_formats; 726 return true; 727 case GL_ARRAY_BUFFER_BINDING: 728 if (share_group_->bind_generates_resource()) { 729 *params = bound_array_buffer_id_; 730 return true; 731 } 732 return false; 733 case GL_ELEMENT_ARRAY_BUFFER_BINDING: 734 if (share_group_->bind_generates_resource()) { 735 *params = 736 vertex_array_object_manager_->bound_element_array_buffer(); 737 return true; 738 } 739 return false; 740 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM: 741 *params = bound_pixel_pack_transfer_buffer_id_; 742 return true; 743 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM: 744 *params = bound_pixel_unpack_transfer_buffer_id_; 745 return true; 746 case GL_ACTIVE_TEXTURE: 747 *params = active_texture_unit_ + GL_TEXTURE0; 748 return true; 749 case GL_TEXTURE_BINDING_2D: 750 if (share_group_->bind_generates_resource()) { 751 *params = texture_units_[active_texture_unit_].bound_texture_2d; 752 return true; 753 } 754 return false; 755 case GL_TEXTURE_BINDING_CUBE_MAP: 756 if (share_group_->bind_generates_resource()) { 757 *params = texture_units_[active_texture_unit_].bound_texture_cube_map; 758 return true; 759 } 760 return false; 761 case GL_TEXTURE_BINDING_EXTERNAL_OES: 762 if (share_group_->bind_generates_resource()) { 763 *params = 764 texture_units_[active_texture_unit_].bound_texture_external_oes; 765 return true; 766 } 767 return false; 768 case GL_FRAMEBUFFER_BINDING: 769 if (share_group_->bind_generates_resource()) { 770 *params = bound_framebuffer_; 771 return true; 772 } 773 return false; 774 case GL_READ_FRAMEBUFFER_BINDING: 775 if (IsChromiumFramebufferMultisampleAvailable() && 776 share_group_->bind_generates_resource()) { 777 *params = bound_read_framebuffer_; 778 return true; 779 } 780 return false; 781 case GL_RENDERBUFFER_BINDING: 782 if (share_group_->bind_generates_resource()) { 783 *params = bound_renderbuffer_; 784 return true; 785 } 786 return false; 787 default: 788 return false; 789 } 790 } 791 792 bool GLES2Implementation::GetBooleanvHelper(GLenum pname, GLboolean* params) { 793 // TODO(gman): Make this handle pnames that return more than 1 value. 794 GLint value; 795 if (!GetHelper(pname, &value)) { 796 return false; 797 } 798 *params = static_cast<GLboolean>(value); 799 return true; 800 } 801 802 bool GLES2Implementation::GetFloatvHelper(GLenum pname, GLfloat* params) { 803 // TODO(gman): Make this handle pnames that return more than 1 value. 804 GLint value; 805 if (!GetHelper(pname, &value)) { 806 return false; 807 } 808 *params = static_cast<GLfloat>(value); 809 return true; 810 } 811 812 bool GLES2Implementation::GetIntegervHelper(GLenum pname, GLint* params) { 813 return GetHelper(pname, params); 814 } 815 816 GLuint GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper( 817 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) { 818 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result; 819 Result* result = GetResultAs<Result*>(); 820 if (!result) { 821 return 0; 822 } 823 *result = 0; 824 helper_->GetMaxValueInBufferCHROMIUM( 825 buffer_id, count, type, offset, GetResultShmId(), GetResultShmOffset()); 826 WaitForCmd(); 827 return *result; 828 } 829 830 GLuint GLES2Implementation::GetMaxValueInBufferCHROMIUM( 831 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) { 832 GPU_CLIENT_SINGLE_THREAD_CHECK(); 833 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM(" 834 << buffer_id << ", " << count << ", " 835 << GLES2Util::GetStringGetMaxIndexType(type) 836 << ", " << offset << ")"); 837 GLuint result = GetMaxValueInBufferCHROMIUMHelper( 838 buffer_id, count, type, offset); 839 GPU_CLIENT_LOG("returned " << result); 840 CheckGLError(); 841 return result; 842 } 843 844 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore) { 845 if (restore) { 846 RestoreArrayBuffer(restore); 847 // Restore the element array binding. 848 // We only need to restore it if it wasn't a client side array. 849 if (vertex_array_object_manager_->bound_element_array_buffer() == 0) { 850 helper_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 851 } 852 } 853 } 854 855 void GLES2Implementation::RestoreArrayBuffer(bool restore) { 856 if (restore) { 857 // Restore the user's current binding. 858 helper_->BindBuffer(GL_ARRAY_BUFFER, bound_array_buffer_id_); 859 } 860 } 861 862 void GLES2Implementation::DrawElements( 863 GLenum mode, GLsizei count, GLenum type, const void* indices) { 864 GPU_CLIENT_SINGLE_THREAD_CHECK(); 865 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements(" 866 << GLES2Util::GetStringDrawMode(mode) << ", " 867 << count << ", " 868 << GLES2Util::GetStringIndexType(type) << ", " 869 << static_cast<const void*>(indices) << ")"); 870 if (count < 0) { 871 SetGLError(GL_INVALID_VALUE, "glDrawElements", "count less than 0."); 872 return; 873 } 874 if (count == 0) { 875 return; 876 } 877 if (vertex_array_object_manager_->bound_element_array_buffer() != 0 && 878 !ValidateOffset("glDrawElements", reinterpret_cast<GLintptr>(indices))) { 879 return; 880 } 881 GLuint offset = 0; 882 bool simulated = false; 883 if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers( 884 "glDrawElements", this, helper_, count, type, 0, indices, 885 &offset, &simulated)) { 886 return; 887 } 888 helper_->DrawElements(mode, count, type, offset); 889 RestoreElementAndArrayBuffers(simulated); 890 CheckGLError(); 891 } 892 893 void GLES2Implementation::Flush() { 894 GPU_CLIENT_SINGLE_THREAD_CHECK(); 895 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()"); 896 // Insert the cmd to call glFlush 897 helper_->Flush(); 898 // Flush our command buffer 899 // (tell the service to execute up to the flush cmd.) 900 helper_->CommandBufferHelper::Flush(); 901 } 902 903 void GLES2Implementation::ShallowFlushCHROMIUM() { 904 GPU_CLIENT_SINGLE_THREAD_CHECK(); 905 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()"); 906 // Flush our command buffer 907 // (tell the service to execute up to the flush cmd.) 908 helper_->CommandBufferHelper::Flush(); 909 // TODO(piman): Add the FreeEverything() logic here. 910 } 911 912 void GLES2Implementation::Finish() { 913 GPU_CLIENT_SINGLE_THREAD_CHECK(); 914 FinishHelper(); 915 } 916 917 void GLES2Implementation::ShallowFinishCHROMIUM() { 918 GPU_CLIENT_SINGLE_THREAD_CHECK(); 919 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM"); 920 // Flush our command buffer (tell the service to execute up to the flush cmd 921 // and don't return until it completes). 922 helper_->CommandBufferHelper::Finish(); 923 } 924 925 void GLES2Implementation::FinishHelper() { 926 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()"); 927 TRACE_EVENT0("gpu", "GLES2::Finish"); 928 // Insert the cmd to call glFinish 929 helper_->Finish(); 930 // Finish our command buffer 931 // (tell the service to execute up to the Finish cmd and wait for it to 932 // execute.) 933 helper_->CommandBufferHelper::Finish(); 934 } 935 936 void GLES2Implementation::SwapBuffers() { 937 GPU_CLIENT_SINGLE_THREAD_CHECK(); 938 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()"); 939 // TODO(piman): Strictly speaking we'd want to insert the token after the 940 // swap, but the state update with the updated token might not have happened 941 // by the time the SwapBuffer callback gets called, forcing us to synchronize 942 // with the GPU process more than needed. So instead, make it happen before. 943 // All it means is that we could be slightly looser on the kMaxSwapBuffers 944 // semantics if the client doesn't use the callback mechanism, and by chance 945 // the scheduler yields between the InsertToken and the SwapBuffers. 946 swap_buffers_tokens_.push(helper_->InsertToken()); 947 helper_->SwapBuffers(); 948 helper_->CommandBufferHelper::Flush(); 949 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to 950 // compensate for TODO above. 951 if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) { 952 helper_->WaitForToken(swap_buffers_tokens_.front()); 953 swap_buffers_tokens_.pop(); 954 } 955 } 956 957 void GLES2Implementation::GenSharedIdsCHROMIUM( 958 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) { 959 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenSharedIdsCHROMIUM(" 960 << namespace_id << ", " << id_offset << ", " << n << ", " << 961 static_cast<void*>(ids) << ")"); 962 TRACE_EVENT0("gpu", "GLES2::GenSharedIdsCHROMIUM"); 963 GLsizei num = n; 964 GLuint* dst = ids; 965 while (num) { 966 ScopedTransferBufferArray<GLint> id_buffer(num, helper_, transfer_buffer_); 967 if (!id_buffer.valid()) { 968 return; 969 } 970 helper_->GenSharedIdsCHROMIUM( 971 namespace_id, id_offset, id_buffer.num_elements(), 972 id_buffer.shm_id(), id_buffer.offset()); 973 WaitForCmd(); 974 memcpy(dst, id_buffer.address(), sizeof(*dst) * id_buffer.num_elements()); 975 num -= id_buffer.num_elements(); 976 dst += id_buffer.num_elements(); 977 } 978 GPU_CLIENT_LOG_CODE_BLOCK({ 979 for (GLsizei i = 0; i < n; ++i) { 980 GPU_CLIENT_LOG(" " << i << ": " << namespace_id << ", " << ids[i]); 981 } 982 }); 983 } 984 985 void GLES2Implementation::DeleteSharedIdsCHROMIUM( 986 GLuint namespace_id, GLsizei n, const GLuint* ids) { 987 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSharedIdsCHROMIUM(" 988 << namespace_id << ", " << n << ", " 989 << static_cast<const void*>(ids) << ")"); 990 GPU_CLIENT_LOG_CODE_BLOCK({ 991 for (GLsizei i = 0; i < n; ++i) { 992 GPU_CLIENT_LOG(" " << i << ": " << namespace_id << ", " << ids[i]); 993 } 994 }); 995 TRACE_EVENT0("gpu", "GLES2::DeleteSharedIdsCHROMIUM"); 996 while (n) { 997 ScopedTransferBufferArray<GLint> id_buffer(n, helper_, transfer_buffer_); 998 if (!id_buffer.valid()) { 999 return; 1000 } 1001 memcpy(id_buffer.address(), ids, sizeof(*ids) * id_buffer.num_elements()); 1002 helper_->DeleteSharedIdsCHROMIUM( 1003 namespace_id, id_buffer.num_elements(), 1004 id_buffer.shm_id(), id_buffer.offset()); 1005 WaitForCmd(); 1006 n -= id_buffer.num_elements(); 1007 ids += id_buffer.num_elements(); 1008 } 1009 } 1010 1011 void GLES2Implementation::RegisterSharedIdsCHROMIUM( 1012 GLuint namespace_id, GLsizei n, const GLuint* ids) { 1013 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRegisterSharedIdsCHROMIUM(" 1014 << namespace_id << ", " << n << ", " 1015 << static_cast<const void*>(ids) << ")"); 1016 GPU_CLIENT_LOG_CODE_BLOCK({ 1017 for (GLsizei i = 0; i < n; ++i) { 1018 GPU_CLIENT_LOG(" " << i << ": " << namespace_id << ", " << ids[i]); 1019 } 1020 }); 1021 TRACE_EVENT0("gpu", "GLES2::RegisterSharedIdsCHROMIUM"); 1022 while (n) { 1023 ScopedTransferBufferArray<GLint> id_buffer(n, helper_, transfer_buffer_); 1024 if (!id_buffer.valid()) { 1025 return; 1026 } 1027 memcpy(id_buffer.address(), ids, sizeof(*ids) * id_buffer.num_elements()); 1028 helper_->RegisterSharedIdsCHROMIUM( 1029 namespace_id, id_buffer.num_elements(), 1030 id_buffer.shm_id(), id_buffer.offset()); 1031 WaitForCmd(); 1032 n -= id_buffer.num_elements(); 1033 ids += id_buffer.num_elements(); 1034 } 1035 } 1036 1037 void GLES2Implementation::BindAttribLocation( 1038 GLuint program, GLuint index, const char* name) { 1039 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1040 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation(" 1041 << program << ", " << index << ", " << name << ")"); 1042 SetBucketAsString(kResultBucketId, name); 1043 helper_->BindAttribLocationBucket(program, index, kResultBucketId); 1044 helper_->SetBucketSize(kResultBucketId, 0); 1045 CheckGLError(); 1046 } 1047 1048 void GLES2Implementation::BindUniformLocationCHROMIUM( 1049 GLuint program, GLint location, const char* name) { 1050 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1051 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM(" 1052 << program << ", " << location << ", " << name << ")"); 1053 SetBucketAsString(kResultBucketId, name); 1054 helper_->BindUniformLocationCHROMIUMBucket( 1055 program, location, kResultBucketId); 1056 helper_->SetBucketSize(kResultBucketId, 0); 1057 CheckGLError(); 1058 } 1059 1060 void GLES2Implementation::GetVertexAttribPointerv( 1061 GLuint index, GLenum pname, void** ptr) { 1062 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1063 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer(" 1064 << index << ", " << GLES2Util::GetStringVertexPointer(pname) << ", " 1065 << static_cast<void*>(ptr) << ")"); 1066 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results = 1); 1067 if (!vertex_array_object_manager_->GetAttribPointer(index, pname, ptr)) { 1068 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv"); 1069 typedef cmds::GetVertexAttribPointerv::Result Result; 1070 Result* result = GetResultAs<Result*>(); 1071 if (!result) { 1072 return; 1073 } 1074 result->SetNumResults(0); 1075 helper_->GetVertexAttribPointerv( 1076 index, pname, GetResultShmId(), GetResultShmOffset()); 1077 WaitForCmd(); 1078 result->CopyResult(ptr); 1079 GPU_CLIENT_LOG_CODE_BLOCK(num_results = result->GetNumResults()); 1080 } 1081 GPU_CLIENT_LOG_CODE_BLOCK({ 1082 for (int32 i = 0; i < num_results; ++i) { 1083 GPU_CLIENT_LOG(" " << i << ": " << ptr[i]); 1084 } 1085 }); 1086 CheckGLError(); 1087 } 1088 1089 bool GLES2Implementation::DeleteProgramHelper(GLuint program) { 1090 if (!GetIdHandler(id_namespaces::kProgramsAndShaders)->FreeIds( 1091 this, 1, &program, &GLES2Implementation::DeleteProgramStub)) { 1092 SetGLError( 1093 GL_INVALID_VALUE, 1094 "glDeleteProgram", "id not created by this context."); 1095 return false; 1096 } 1097 if (program == current_program_) { 1098 current_program_ = 0; 1099 } 1100 return true; 1101 } 1102 1103 void GLES2Implementation::DeleteProgramStub( 1104 GLsizei n, const GLuint* programs) { 1105 DCHECK_EQ(1, n); 1106 share_group_->program_info_manager()->DeleteInfo(programs[0]); 1107 helper_->DeleteProgram(programs[0]); 1108 } 1109 1110 bool GLES2Implementation::DeleteShaderHelper(GLuint shader) { 1111 if (!GetIdHandler(id_namespaces::kProgramsAndShaders)->FreeIds( 1112 this, 1, &shader, &GLES2Implementation::DeleteShaderStub)) { 1113 SetGLError( 1114 GL_INVALID_VALUE, 1115 "glDeleteShader", "id not created by this context."); 1116 return false; 1117 } 1118 return true; 1119 } 1120 1121 void GLES2Implementation::DeleteShaderStub( 1122 GLsizei n, const GLuint* shaders) { 1123 DCHECK_EQ(1, n); 1124 share_group_->program_info_manager()->DeleteInfo(shaders[0]); 1125 helper_->DeleteShader(shaders[0]); 1126 } 1127 1128 1129 GLint GLES2Implementation::GetAttribLocationHelper( 1130 GLuint program, const char* name) { 1131 typedef cmds::GetAttribLocation::Result Result; 1132 Result* result = GetResultAs<Result*>(); 1133 if (!result) { 1134 return -1; 1135 } 1136 *result = -1; 1137 SetBucketAsCString(kResultBucketId, name); 1138 helper_->GetAttribLocation( 1139 program, kResultBucketId, GetResultShmId(), GetResultShmOffset()); 1140 WaitForCmd(); 1141 helper_->SetBucketSize(kResultBucketId, 0); 1142 return *result; 1143 } 1144 1145 GLint GLES2Implementation::GetAttribLocation( 1146 GLuint program, const char* name) { 1147 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1148 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program 1149 << ", " << name << ")"); 1150 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation"); 1151 GLint loc = share_group_->program_info_manager()->GetAttribLocation( 1152 this, program, name); 1153 GPU_CLIENT_LOG("returned " << loc); 1154 CheckGLError(); 1155 return loc; 1156 } 1157 1158 GLint GLES2Implementation::GetUniformLocationHelper( 1159 GLuint program, const char* name) { 1160 typedef cmds::GetUniformLocation::Result Result; 1161 Result* result = GetResultAs<Result*>(); 1162 if (!result) { 1163 return -1; 1164 } 1165 *result = -1; 1166 SetBucketAsCString(kResultBucketId, name); 1167 helper_->GetUniformLocation(program, kResultBucketId, 1168 GetResultShmId(), GetResultShmOffset()); 1169 WaitForCmd(); 1170 helper_->SetBucketSize(kResultBucketId, 0); 1171 return *result; 1172 } 1173 1174 GLint GLES2Implementation::GetUniformLocation( 1175 GLuint program, const char* name) { 1176 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1177 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program 1178 << ", " << name << ")"); 1179 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation"); 1180 GLint loc = share_group_->program_info_manager()->GetUniformLocation( 1181 this, program, name); 1182 GPU_CLIENT_LOG("returned " << loc); 1183 CheckGLError(); 1184 return loc; 1185 } 1186 1187 bool GLES2Implementation::GetProgramivHelper( 1188 GLuint program, GLenum pname, GLint* params) { 1189 bool got_value = share_group_->program_info_manager()->GetProgramiv( 1190 this, program, pname, params); 1191 GPU_CLIENT_LOG_CODE_BLOCK({ 1192 if (got_value) { 1193 GPU_CLIENT_LOG(" 0: " << *params); 1194 } 1195 }); 1196 return got_value; 1197 } 1198 1199 void GLES2Implementation::LinkProgram(GLuint program) { 1200 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1201 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program << ")"); 1202 helper_->LinkProgram(program); 1203 share_group_->program_info_manager()->CreateInfo(program); 1204 CheckGLError(); 1205 } 1206 1207 void GLES2Implementation::ShaderBinary( 1208 GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, 1209 GLsizei length) { 1210 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1211 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n << ", " 1212 << static_cast<const void*>(shaders) << ", " 1213 << GLES2Util::GetStringEnum(binaryformat) << ", " 1214 << static_cast<const void*>(binary) << ", " 1215 << length << ")"); 1216 if (n < 0) { 1217 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "n < 0."); 1218 return; 1219 } 1220 if (length < 0) { 1221 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "length < 0."); 1222 return; 1223 } 1224 // TODO(gman): ShaderBinary should use buckets. 1225 unsigned int shader_id_size = n * sizeof(*shaders); 1226 ScopedTransferBufferArray<GLint> buffer( 1227 shader_id_size + length, helper_, transfer_buffer_); 1228 if (!buffer.valid() || buffer.num_elements() != shader_id_size + length) { 1229 SetGLError(GL_OUT_OF_MEMORY, "glShaderBinary", "out of memory."); 1230 return; 1231 } 1232 void* shader_ids = buffer.elements(); 1233 void* shader_data = buffer.elements() + shader_id_size; 1234 memcpy(shader_ids, shaders, shader_id_size); 1235 memcpy(shader_data, binary, length); 1236 helper_->ShaderBinary( 1237 n, 1238 buffer.shm_id(), 1239 buffer.offset(), 1240 binaryformat, 1241 buffer.shm_id(), 1242 buffer.offset() + shader_id_size, 1243 length); 1244 CheckGLError(); 1245 } 1246 1247 void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { 1248 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1249 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei(" 1250 << GLES2Util::GetStringPixelStore(pname) << ", " 1251 << param << ")"); 1252 switch (pname) { 1253 case GL_PACK_ALIGNMENT: 1254 pack_alignment_ = param; 1255 break; 1256 case GL_UNPACK_ALIGNMENT: 1257 unpack_alignment_ = param; 1258 break; 1259 case GL_UNPACK_ROW_LENGTH_EXT: 1260 unpack_row_length_ = param; 1261 return; 1262 case GL_UNPACK_SKIP_ROWS_EXT: 1263 unpack_skip_rows_ = param; 1264 return; 1265 case GL_UNPACK_SKIP_PIXELS_EXT: 1266 unpack_skip_pixels_ = param; 1267 return; 1268 case GL_UNPACK_FLIP_Y_CHROMIUM: 1269 unpack_flip_y_ = (param != 0); 1270 break; 1271 case GL_PACK_REVERSE_ROW_ORDER_ANGLE: 1272 pack_reverse_row_order_ = 1273 IsAnglePackReverseRowOrderAvailable() ? (param != 0) : false; 1274 break; 1275 default: 1276 break; 1277 } 1278 helper_->PixelStorei(pname, param); 1279 CheckGLError(); 1280 } 1281 1282 void GLES2Implementation::VertexAttribPointer( 1283 GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, 1284 const void* ptr) { 1285 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1286 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer(" 1287 << index << ", " 1288 << size << ", " 1289 << GLES2Util::GetStringVertexAttribType(type) << ", " 1290 << GLES2Util::GetStringBool(normalized) << ", " 1291 << stride << ", " 1292 << static_cast<const void*>(ptr) << ")"); 1293 // Record the info on the client side. 1294 if (!vertex_array_object_manager_->SetAttribPointer( 1295 bound_array_buffer_id_, index, size, type, normalized, stride, ptr)) { 1296 SetGLError(GL_INVALID_OPERATION, "glVertexAttribPointer", 1297 "client side arrays are not allowed in vertex array objects."); 1298 return; 1299 } 1300 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 1301 if (bound_array_buffer_id_ != 0) { 1302 // Only report NON client side buffers to the service. 1303 if (!ValidateOffset("glVertexAttribPointer", 1304 reinterpret_cast<GLintptr>(ptr))) { 1305 return; 1306 } 1307 helper_->VertexAttribPointer(index, size, type, normalized, stride, 1308 ToGLuint(ptr)); 1309 } 1310 #else // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 1311 if (!ValidateOffset("glVertexAttribPointer", 1312 reinterpret_cast<GLintptr>(ptr))) { 1313 return; 1314 } 1315 helper_->VertexAttribPointer(index, size, type, normalized, stride, 1316 ToGLuint(ptr)); 1317 #endif // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 1318 CheckGLError(); 1319 } 1320 1321 void GLES2Implementation::VertexAttribDivisorANGLE( 1322 GLuint index, GLuint divisor) { 1323 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1324 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE(" 1325 << index << ", " 1326 << divisor << ") "); 1327 // Record the info on the client side. 1328 vertex_array_object_manager_->SetAttribDivisor(index, divisor); 1329 helper_->VertexAttribDivisorANGLE(index, divisor); 1330 CheckGLError(); 1331 } 1332 1333 void GLES2Implementation::ShaderSource( 1334 GLuint shader, 1335 GLsizei count, 1336 const GLchar* const* source, 1337 const GLint* length) { 1338 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1339 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderSource(" 1340 << shader << ", " << count << ", " 1341 << static_cast<const void*>(source) << ", " 1342 << static_cast<const void*>(length) << ")"); 1343 GPU_CLIENT_LOG_CODE_BLOCK({ 1344 for (GLsizei ii = 0; ii < count; ++ii) { 1345 if (source[ii]) { 1346 if (length && length[ii] >= 0) { 1347 std::string str(source[ii], length[ii]); 1348 GPU_CLIENT_LOG(" " << ii << ": ---\n" << str << "\n---"); 1349 } else { 1350 GPU_CLIENT_LOG(" " << ii << ": ---\n" << source[ii] << "\n---"); 1351 } 1352 } else { 1353 GPU_CLIENT_LOG(" " << ii << ": NULL"); 1354 } 1355 } 1356 }); 1357 if (count < 0) { 1358 SetGLError(GL_INVALID_VALUE, "glShaderSource", "count < 0"); 1359 return; 1360 } 1361 if (shader == 0) { 1362 SetGLError(GL_INVALID_VALUE, "glShaderSource", "shader == 0"); 1363 return; 1364 } 1365 1366 // Compute the total size. 1367 uint32 total_size = 1; 1368 for (GLsizei ii = 0; ii < count; ++ii) { 1369 if (source[ii]) { 1370 total_size += (length && length[ii] >= 0) ? 1371 static_cast<size_t>(length[ii]) : strlen(source[ii]); 1372 } 1373 } 1374 1375 // Concatenate all the strings in to a bucket on the service. 1376 helper_->SetBucketSize(kResultBucketId, total_size); 1377 uint32 offset = 0; 1378 for (GLsizei ii = 0; ii <= count; ++ii) { 1379 const char* src = ii < count ? source[ii] : ""; 1380 if (src) { 1381 uint32 size = ii < count ? 1382 (length ? static_cast<size_t>(length[ii]) : strlen(src)) : 1; 1383 while (size) { 1384 ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); 1385 if (!buffer.valid()) { 1386 return; 1387 } 1388 memcpy(buffer.address(), src, buffer.size()); 1389 helper_->SetBucketData(kResultBucketId, offset, buffer.size(), 1390 buffer.shm_id(), buffer.offset()); 1391 offset += buffer.size(); 1392 src += buffer.size(); 1393 size -= buffer.size(); 1394 } 1395 } 1396 } 1397 1398 DCHECK_EQ(total_size, offset); 1399 1400 helper_->ShaderSourceBucket(shader, kResultBucketId); 1401 helper_->SetBucketSize(kResultBucketId, 0); 1402 CheckGLError(); 1403 } 1404 1405 void GLES2Implementation::BufferDataHelper( 1406 GLenum target, GLsizeiptr size, const void* data, GLenum usage) { 1407 if (!ValidateSize("glBufferData", size)) 1408 return; 1409 1410 GLuint buffer_id; 1411 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) { 1412 if (!buffer_id) { 1413 return; 1414 } 1415 1416 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); 1417 if (buffer) 1418 RemoveTransferBuffer(buffer); 1419 1420 // Create new buffer. 1421 buffer = buffer_tracker_->CreateBuffer(buffer_id, size); 1422 DCHECK(buffer); 1423 if (buffer->address() && data) 1424 memcpy(buffer->address(), data, size); 1425 return; 1426 } 1427 1428 if (size == 0) { 1429 return; 1430 } 1431 1432 // If there is no data just send BufferData 1433 if (!data) { 1434 helper_->BufferData(target, size, 0, 0, usage); 1435 return; 1436 } 1437 1438 // See if we can send all at once. 1439 ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); 1440 if (!buffer.valid()) { 1441 return; 1442 } 1443 1444 if (buffer.size() >= static_cast<unsigned int>(size)) { 1445 memcpy(buffer.address(), data, size); 1446 helper_->BufferData( 1447 target, 1448 size, 1449 buffer.shm_id(), 1450 buffer.offset(), 1451 usage); 1452 return; 1453 } 1454 1455 // Make the buffer with BufferData then send via BufferSubData 1456 helper_->BufferData(target, size, 0, 0, usage); 1457 BufferSubDataHelperImpl(target, 0, size, data, &buffer); 1458 CheckGLError(); 1459 } 1460 1461 void GLES2Implementation::BufferData( 1462 GLenum target, GLsizeiptr size, const void* data, GLenum usage) { 1463 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1464 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData(" 1465 << GLES2Util::GetStringBufferTarget(target) << ", " 1466 << size << ", " 1467 << static_cast<const void*>(data) << ", " 1468 << GLES2Util::GetStringBufferUsage(usage) << ")"); 1469 BufferDataHelper(target, size, data, usage); 1470 CheckGLError(); 1471 } 1472 1473 void GLES2Implementation::BufferSubDataHelper( 1474 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { 1475 if (size == 0) { 1476 return; 1477 } 1478 1479 if (!ValidateSize("glBufferSubData", size) || 1480 !ValidateOffset("glBufferSubData", offset)) { 1481 return; 1482 } 1483 1484 GLuint buffer_id; 1485 if (GetBoundPixelTransferBuffer(target, "glBufferSubData", &buffer_id)) { 1486 if (!buffer_id) { 1487 return; 1488 } 1489 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); 1490 if (!buffer) { 1491 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer"); 1492 return; 1493 } 1494 1495 int32 end = 0; 1496 int32 buffer_size = buffer->size(); 1497 if (!SafeAddInt32(offset, size, &end) || end > buffer_size) { 1498 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "out of range"); 1499 return; 1500 } 1501 1502 if (buffer->address() && data) 1503 memcpy(static_cast<uint8*>(buffer->address()) + offset, data, size); 1504 return; 1505 } 1506 1507 ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); 1508 BufferSubDataHelperImpl(target, offset, size, data, &buffer); 1509 } 1510 1511 void GLES2Implementation::BufferSubDataHelperImpl( 1512 GLenum target, GLintptr offset, GLsizeiptr size, const void* data, 1513 ScopedTransferBufferPtr* buffer) { 1514 DCHECK(buffer); 1515 DCHECK_GT(size, 0); 1516 1517 const int8* source = static_cast<const int8*>(data); 1518 while (size) { 1519 if (!buffer->valid() || buffer->size() == 0) { 1520 buffer->Reset(size); 1521 if (!buffer->valid()) { 1522 return; 1523 } 1524 } 1525 memcpy(buffer->address(), source, buffer->size()); 1526 helper_->BufferSubData( 1527 target, offset, buffer->size(), buffer->shm_id(), buffer->offset()); 1528 offset += buffer->size(); 1529 source += buffer->size(); 1530 size -= buffer->size(); 1531 buffer->Release(); 1532 } 1533 } 1534 1535 void GLES2Implementation::BufferSubData( 1536 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { 1537 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1538 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData(" 1539 << GLES2Util::GetStringBufferTarget(target) << ", " 1540 << offset << ", " << size << ", " 1541 << static_cast<const void*>(data) << ")"); 1542 BufferSubDataHelper(target, offset, size, data); 1543 CheckGLError(); 1544 } 1545 1546 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer* buffer) { 1547 int32 token = buffer->last_usage_token(); 1548 uint32 async_token = buffer->last_async_upload_token(); 1549 1550 if (async_token) { 1551 if (HasAsyncUploadTokenPassed(async_token)) { 1552 buffer_tracker_->Free(buffer); 1553 } else { 1554 detached_async_upload_memory_.push_back( 1555 std::make_pair(buffer->address(), async_token)); 1556 buffer_tracker_->Unmanage(buffer); 1557 } 1558 } else if (token) { 1559 if (helper_->HasTokenPassed(token)) 1560 buffer_tracker_->Free(buffer); 1561 else 1562 buffer_tracker_->FreePendingToken(buffer, token); 1563 } else { 1564 buffer_tracker_->Free(buffer); 1565 } 1566 1567 buffer_tracker_->RemoveBuffer(buffer->id()); 1568 } 1569 1570 bool GLES2Implementation::GetBoundPixelTransferBuffer( 1571 GLenum target, 1572 const char* function_name, 1573 GLuint* buffer_id) { 1574 *buffer_id = 0; 1575 1576 switch (target) { 1577 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: 1578 *buffer_id = bound_pixel_pack_transfer_buffer_id_; 1579 break; 1580 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: 1581 *buffer_id = bound_pixel_unpack_transfer_buffer_id_; 1582 break; 1583 default: 1584 // Unknown target 1585 return false; 1586 } 1587 if (!*buffer_id) { 1588 SetGLError(GL_INVALID_OPERATION, function_name, "no buffer bound"); 1589 } 1590 return true; 1591 } 1592 1593 BufferTracker::Buffer* 1594 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid( 1595 GLuint buffer_id, 1596 const char* function_name, 1597 GLuint offset, GLsizei size) { 1598 DCHECK(buffer_id); 1599 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); 1600 if (!buffer) { 1601 SetGLError(GL_INVALID_OPERATION, function_name, "invalid buffer"); 1602 return NULL; 1603 } 1604 if (buffer->mapped()) { 1605 SetGLError(GL_INVALID_OPERATION, function_name, "buffer mapped"); 1606 return NULL; 1607 } 1608 if ((buffer->size() - offset) < static_cast<GLuint>(size)) { 1609 SetGLError(GL_INVALID_VALUE, function_name, "unpack size to large"); 1610 return NULL; 1611 } 1612 return buffer; 1613 } 1614 1615 void GLES2Implementation::CompressedTexImage2D( 1616 GLenum target, GLint level, GLenum internalformat, GLsizei width, 1617 GLsizei height, GLint border, GLsizei image_size, const void* data) { 1618 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1619 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D(" 1620 << GLES2Util::GetStringTextureTarget(target) << ", " 1621 << level << ", " 1622 << GLES2Util::GetStringCompressedTextureFormat(internalformat) << ", " 1623 << width << ", " << height << ", " << border << ", " 1624 << image_size << ", " 1625 << static_cast<const void*>(data) << ")"); 1626 if (width < 0 || height < 0 || level < 0) { 1627 SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", "dimension < 0"); 1628 return; 1629 } 1630 if (border != 0) { 1631 SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", "border != 0"); 1632 return; 1633 } 1634 if (height == 0 || width == 0) { 1635 return; 1636 } 1637 // If there's a pixel unpack buffer bound use it when issuing 1638 // CompressedTexImage2D. 1639 if (bound_pixel_unpack_transfer_buffer_id_) { 1640 GLuint offset = ToGLuint(data); 1641 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1642 bound_pixel_unpack_transfer_buffer_id_, 1643 "glCompressedTexImage2D", offset, image_size); 1644 if (buffer && buffer->shm_id() != -1) { 1645 helper_->CompressedTexImage2D( 1646 target, level, internalformat, width, height, image_size, 1647 buffer->shm_id(), buffer->shm_offset() + offset); 1648 buffer->set_last_usage_token(helper_->InsertToken()); 1649 } 1650 return; 1651 } 1652 SetBucketContents(kResultBucketId, data, image_size); 1653 helper_->CompressedTexImage2DBucket( 1654 target, level, internalformat, width, height, kResultBucketId); 1655 // Free the bucket. This is not required but it does free up the memory. 1656 // and we don't have to wait for the result so from the client's perspective 1657 // it's cheap. 1658 helper_->SetBucketSize(kResultBucketId, 0); 1659 CheckGLError(); 1660 } 1661 1662 void GLES2Implementation::CompressedTexSubImage2D( 1663 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, 1664 GLsizei height, GLenum format, GLsizei image_size, const void* data) { 1665 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1666 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D(" 1667 << GLES2Util::GetStringTextureTarget(target) << ", " 1668 << level << ", " 1669 << xoffset << ", " << yoffset << ", " 1670 << width << ", " << height << ", " 1671 << GLES2Util::GetStringCompressedTextureFormat(format) << ", " 1672 << image_size << ", " 1673 << static_cast<const void*>(data) << ")"); 1674 if (width < 0 || height < 0 || level < 0) { 1675 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "dimension < 0"); 1676 return; 1677 } 1678 // If there's a pixel unpack buffer bound use it when issuing 1679 // CompressedTexSubImage2D. 1680 if (bound_pixel_unpack_transfer_buffer_id_) { 1681 GLuint offset = ToGLuint(data); 1682 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1683 bound_pixel_unpack_transfer_buffer_id_, 1684 "glCompressedTexSubImage2D", offset, image_size); 1685 if (buffer && buffer->shm_id() != -1) { 1686 helper_->CompressedTexSubImage2D( 1687 target, level, xoffset, yoffset, width, height, format, image_size, 1688 buffer->shm_id(), buffer->shm_offset() + offset); 1689 buffer->set_last_usage_token(helper_->InsertToken()); 1690 CheckGLError(); 1691 } 1692 return; 1693 } 1694 SetBucketContents(kResultBucketId, data, image_size); 1695 helper_->CompressedTexSubImage2DBucket( 1696 target, level, xoffset, yoffset, width, height, format, kResultBucketId); 1697 // Free the bucket. This is not required but it does free up the memory. 1698 // and we don't have to wait for the result so from the client's perspective 1699 // it's cheap. 1700 helper_->SetBucketSize(kResultBucketId, 0); 1701 CheckGLError(); 1702 } 1703 1704 namespace { 1705 1706 void CopyRectToBuffer( 1707 const void* pixels, 1708 uint32 height, 1709 uint32 unpadded_row_size, 1710 uint32 pixels_padded_row_size, 1711 bool flip_y, 1712 void* buffer, 1713 uint32 buffer_padded_row_size) { 1714 const int8* source = static_cast<const int8*>(pixels); 1715 int8* dest = static_cast<int8*>(buffer); 1716 if (flip_y || pixels_padded_row_size != buffer_padded_row_size) { 1717 if (flip_y) { 1718 dest += buffer_padded_row_size * (height - 1); 1719 } 1720 // the last row is copied unpadded at the end 1721 for (; height > 1; --height) { 1722 memcpy(dest, source, buffer_padded_row_size); 1723 if (flip_y) { 1724 dest -= buffer_padded_row_size; 1725 } else { 1726 dest += buffer_padded_row_size; 1727 } 1728 source += pixels_padded_row_size; 1729 } 1730 memcpy(dest, source, unpadded_row_size); 1731 } else { 1732 uint32 size = (height - 1) * pixels_padded_row_size + unpadded_row_size; 1733 memcpy(dest, source, size); 1734 } 1735 } 1736 1737 } // anonymous namespace 1738 1739 void GLES2Implementation::TexImage2D( 1740 GLenum target, GLint level, GLint internalformat, GLsizei width, 1741 GLsizei height, GLint border, GLenum format, GLenum type, 1742 const void* pixels) { 1743 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1744 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D(" 1745 << GLES2Util::GetStringTextureTarget(target) << ", " 1746 << level << ", " 1747 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " 1748 << width << ", " << height << ", " << border << ", " 1749 << GLES2Util::GetStringTextureFormat(format) << ", " 1750 << GLES2Util::GetStringPixelType(type) << ", " 1751 << static_cast<const void*>(pixels) << ")"); 1752 if (level < 0 || height < 0 || width < 0) { 1753 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "dimension < 0"); 1754 return; 1755 } 1756 if (border != 0) { 1757 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "border != 0"); 1758 return; 1759 } 1760 uint32 size; 1761 uint32 unpadded_row_size; 1762 uint32 padded_row_size; 1763 if (!GLES2Util::ComputeImageDataSizes( 1764 width, height, format, type, unpack_alignment_, &size, 1765 &unpadded_row_size, &padded_row_size)) { 1766 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large"); 1767 return; 1768 } 1769 1770 // If there's a pixel unpack buffer bound use it when issuing TexImage2D. 1771 if (bound_pixel_unpack_transfer_buffer_id_) { 1772 GLuint offset = ToGLuint(pixels); 1773 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1774 bound_pixel_unpack_transfer_buffer_id_, 1775 "glTexImage2D", offset, size); 1776 if (buffer && buffer->shm_id() != -1) { 1777 helper_->TexImage2D( 1778 target, level, internalformat, width, height, format, type, 1779 buffer->shm_id(), buffer->shm_offset() + offset); 1780 buffer->set_last_usage_token(helper_->InsertToken()); 1781 CheckGLError(); 1782 } 1783 return; 1784 } 1785 1786 // If there's no data just issue TexImage2D 1787 if (!pixels) { 1788 helper_->TexImage2D( 1789 target, level, internalformat, width, height, format, type, 1790 0, 0); 1791 CheckGLError(); 1792 return; 1793 } 1794 1795 // compute the advance bytes per row for the src pixels 1796 uint32 src_padded_row_size; 1797 if (unpack_row_length_ > 0) { 1798 if (!GLES2Util::ComputeImagePaddedRowSize( 1799 unpack_row_length_, format, type, unpack_alignment_, 1800 &src_padded_row_size)) { 1801 SetGLError( 1802 GL_INVALID_VALUE, "glTexImage2D", "unpack row length too large"); 1803 return; 1804 } 1805 } else { 1806 src_padded_row_size = padded_row_size; 1807 } 1808 1809 // advance pixels pointer past the skip rows and skip pixels 1810 pixels = reinterpret_cast<const int8*>(pixels) + 1811 unpack_skip_rows_ * src_padded_row_size; 1812 if (unpack_skip_pixels_) { 1813 uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type); 1814 pixels = reinterpret_cast<const int8*>(pixels) + 1815 unpack_skip_pixels_ * group_size; 1816 } 1817 1818 // Check if we can send it all at once. 1819 ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); 1820 if (!buffer.valid()) { 1821 return; 1822 } 1823 1824 if (buffer.size() >= size) { 1825 CopyRectToBuffer( 1826 pixels, height, unpadded_row_size, src_padded_row_size, unpack_flip_y_, 1827 buffer.address(), padded_row_size); 1828 helper_->TexImage2D( 1829 target, level, internalformat, width, height, format, type, 1830 buffer.shm_id(), buffer.offset()); 1831 CheckGLError(); 1832 return; 1833 } 1834 1835 // No, so send it using TexSubImage2D. 1836 helper_->TexImage2D( 1837 target, level, internalformat, width, height, format, type, 1838 0, 0); 1839 TexSubImage2DImpl( 1840 target, level, 0, 0, width, height, format, type, unpadded_row_size, 1841 pixels, src_padded_row_size, GL_TRUE, &buffer, padded_row_size); 1842 CheckGLError(); 1843 } 1844 1845 void GLES2Implementation::TexSubImage2D( 1846 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, 1847 GLsizei height, GLenum format, GLenum type, const void* pixels) { 1848 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1849 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D(" 1850 << GLES2Util::GetStringTextureTarget(target) << ", " 1851 << level << ", " 1852 << xoffset << ", " << yoffset << ", " 1853 << width << ", " << height << ", " 1854 << GLES2Util::GetStringTextureFormat(format) << ", " 1855 << GLES2Util::GetStringPixelType(type) << ", " 1856 << static_cast<const void*>(pixels) << ")"); 1857 1858 if (level < 0 || height < 0 || width < 0) { 1859 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "dimension < 0"); 1860 return; 1861 } 1862 if (height == 0 || width == 0) { 1863 return; 1864 } 1865 1866 uint32 temp_size; 1867 uint32 unpadded_row_size; 1868 uint32 padded_row_size; 1869 if (!GLES2Util::ComputeImageDataSizes( 1870 width, height, format, type, unpack_alignment_, &temp_size, 1871 &unpadded_row_size, &padded_row_size)) { 1872 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "size to large"); 1873 return; 1874 } 1875 1876 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D. 1877 if (bound_pixel_unpack_transfer_buffer_id_) { 1878 GLuint offset = ToGLuint(pixels); 1879 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1880 bound_pixel_unpack_transfer_buffer_id_, 1881 "glTexSubImage2D", offset, temp_size); 1882 if (buffer && buffer->shm_id() != -1) { 1883 helper_->TexSubImage2D( 1884 target, level, xoffset, yoffset, width, height, format, type, 1885 buffer->shm_id(), buffer->shm_offset() + offset, false); 1886 buffer->set_last_usage_token(helper_->InsertToken()); 1887 CheckGLError(); 1888 } 1889 return; 1890 } 1891 1892 // compute the advance bytes per row for the src pixels 1893 uint32 src_padded_row_size; 1894 if (unpack_row_length_ > 0) { 1895 if (!GLES2Util::ComputeImagePaddedRowSize( 1896 unpack_row_length_, format, type, unpack_alignment_, 1897 &src_padded_row_size)) { 1898 SetGLError( 1899 GL_INVALID_VALUE, "glTexImage2D", "unpack row length too large"); 1900 return; 1901 } 1902 } else { 1903 src_padded_row_size = padded_row_size; 1904 } 1905 1906 // advance pixels pointer past the skip rows and skip pixels 1907 pixels = reinterpret_cast<const int8*>(pixels) + 1908 unpack_skip_rows_ * src_padded_row_size; 1909 if (unpack_skip_pixels_) { 1910 uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type); 1911 pixels = reinterpret_cast<const int8*>(pixels) + 1912 unpack_skip_pixels_ * group_size; 1913 } 1914 1915 ScopedTransferBufferPtr buffer(temp_size, helper_, transfer_buffer_); 1916 TexSubImage2DImpl( 1917 target, level, xoffset, yoffset, width, height, format, type, 1918 unpadded_row_size, pixels, src_padded_row_size, GL_FALSE, &buffer, 1919 padded_row_size); 1920 CheckGLError(); 1921 } 1922 1923 static GLint ComputeNumRowsThatFitInBuffer( 1924 uint32 padded_row_size, uint32 unpadded_row_size, 1925 unsigned int size) { 1926 DCHECK_GE(unpadded_row_size, 0u); 1927 if (padded_row_size == 0) { 1928 return 1; 1929 } 1930 GLint num_rows = size / padded_row_size; 1931 return num_rows + (size - num_rows * padded_row_size) / unpadded_row_size; 1932 } 1933 1934 void GLES2Implementation::TexSubImage2DImpl( 1935 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, 1936 GLsizei height, GLenum format, GLenum type, uint32 unpadded_row_size, 1937 const void* pixels, uint32 pixels_padded_row_size, GLboolean internal, 1938 ScopedTransferBufferPtr* buffer, uint32 buffer_padded_row_size) { 1939 DCHECK(buffer); 1940 DCHECK_GE(level, 0); 1941 DCHECK_GT(height, 0); 1942 DCHECK_GT(width, 0); 1943 1944 const int8* source = reinterpret_cast<const int8*>(pixels); 1945 GLint original_yoffset = yoffset; 1946 // Transfer by rows. 1947 while (height) { 1948 unsigned int desired_size = 1949 buffer_padded_row_size * (height - 1) + unpadded_row_size; 1950 if (!buffer->valid() || buffer->size() == 0) { 1951 buffer->Reset(desired_size); 1952 if (!buffer->valid()) { 1953 return; 1954 } 1955 } 1956 1957 GLint num_rows = ComputeNumRowsThatFitInBuffer( 1958 buffer_padded_row_size, unpadded_row_size, buffer->size()); 1959 num_rows = std::min(num_rows, height); 1960 CopyRectToBuffer( 1961 source, num_rows, unpadded_row_size, pixels_padded_row_size, 1962 unpack_flip_y_, buffer->address(), buffer_padded_row_size); 1963 GLint y = unpack_flip_y_ ? original_yoffset + height - num_rows : yoffset; 1964 helper_->TexSubImage2D( 1965 target, level, xoffset, y, width, num_rows, format, type, 1966 buffer->shm_id(), buffer->offset(), internal); 1967 buffer->Release(); 1968 yoffset += num_rows; 1969 source += num_rows * pixels_padded_row_size; 1970 height -= num_rows; 1971 } 1972 } 1973 1974 bool GLES2Implementation::GetActiveAttribHelper( 1975 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, 1976 GLenum* type, char* name) { 1977 // Clear the bucket so if the command fails nothing will be in it. 1978 helper_->SetBucketSize(kResultBucketId, 0); 1979 typedef cmds::GetActiveAttrib::Result Result; 1980 Result* result = GetResultAs<Result*>(); 1981 if (!result) { 1982 return false; 1983 } 1984 // Set as failed so if the command fails we'll recover. 1985 result->success = false; 1986 helper_->GetActiveAttrib(program, index, kResultBucketId, 1987 GetResultShmId(), GetResultShmOffset()); 1988 WaitForCmd(); 1989 if (result->success) { 1990 if (size) { 1991 *size = result->size; 1992 } 1993 if (type) { 1994 *type = result->type; 1995 } 1996 if (length || name) { 1997 std::vector<int8> str; 1998 GetBucketContents(kResultBucketId, &str); 1999 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1, 2000 std::max(static_cast<size_t>(0), 2001 str.size() - 1)); 2002 if (length) { 2003 *length = max_size; 2004 } 2005 if (name && bufsize > 0) { 2006 memcpy(name, &str[0], max_size); 2007 name[max_size] = '\0'; 2008 } 2009 } 2010 } 2011 return result->success != 0; 2012 } 2013 2014 void GLES2Implementation::GetActiveAttrib( 2015 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, 2016 GLenum* type, char* name) { 2017 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2018 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib(" 2019 << program << ", " << index << ", " << bufsize << ", " 2020 << static_cast<const void*>(length) << ", " 2021 << static_cast<const void*>(size) << ", " 2022 << static_cast<const void*>(type) << ", " 2023 << static_cast<const void*>(name) << ", "); 2024 if (bufsize < 0) { 2025 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib", "bufsize < 0"); 2026 return; 2027 } 2028 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib"); 2029 bool success = share_group_->program_info_manager()->GetActiveAttrib( 2030 this, program, index, bufsize, length, size, type, name); 2031 if (success) { 2032 if (size) { 2033 GPU_CLIENT_LOG(" size: " << *size); 2034 } 2035 if (type) { 2036 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type)); 2037 } 2038 if (name) { 2039 GPU_CLIENT_LOG(" name: " << name); 2040 } 2041 } 2042 CheckGLError(); 2043 } 2044 2045 bool GLES2Implementation::GetActiveUniformHelper( 2046 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, 2047 GLenum* type, char* name) { 2048 // Clear the bucket so if the command fails nothing will be in it. 2049 helper_->SetBucketSize(kResultBucketId, 0); 2050 typedef cmds::GetActiveUniform::Result Result; 2051 Result* result = GetResultAs<Result*>(); 2052 if (!result) { 2053 return false; 2054 } 2055 // Set as failed so if the command fails we'll recover. 2056 result->success = false; 2057 helper_->GetActiveUniform(program, index, kResultBucketId, 2058 GetResultShmId(), GetResultShmOffset()); 2059 WaitForCmd(); 2060 if (result->success) { 2061 if (size) { 2062 *size = result->size; 2063 } 2064 if (type) { 2065 *type = result->type; 2066 } 2067 if (length || name) { 2068 std::vector<int8> str; 2069 GetBucketContents(kResultBucketId, &str); 2070 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1, 2071 std::max(static_cast<size_t>(0), 2072 str.size() - 1)); 2073 if (length) { 2074 *length = max_size; 2075 } 2076 if (name && bufsize > 0) { 2077 memcpy(name, &str[0], max_size); 2078 name[max_size] = '\0'; 2079 } 2080 } 2081 } 2082 return result->success != 0; 2083 } 2084 2085 void GLES2Implementation::GetActiveUniform( 2086 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, 2087 GLenum* type, char* name) { 2088 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2089 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform(" 2090 << program << ", " << index << ", " << bufsize << ", " 2091 << static_cast<const void*>(length) << ", " 2092 << static_cast<const void*>(size) << ", " 2093 << static_cast<const void*>(type) << ", " 2094 << static_cast<const void*>(name) << ", "); 2095 if (bufsize < 0) { 2096 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform", "bufsize < 0"); 2097 return; 2098 } 2099 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform"); 2100 bool success = share_group_->program_info_manager()->GetActiveUniform( 2101 this, program, index, bufsize, length, size, type, name); 2102 if (success) { 2103 if (size) { 2104 GPU_CLIENT_LOG(" size: " << *size); 2105 } 2106 if (type) { 2107 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type)); 2108 } 2109 if (name) { 2110 GPU_CLIENT_LOG(" name: " << name); 2111 } 2112 } 2113 CheckGLError(); 2114 } 2115 2116 void GLES2Implementation::GetAttachedShaders( 2117 GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { 2118 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2119 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders(" 2120 << program << ", " << maxcount << ", " 2121 << static_cast<const void*>(count) << ", " 2122 << static_cast<const void*>(shaders) << ", "); 2123 if (maxcount < 0) { 2124 SetGLError(GL_INVALID_VALUE, "glGetAttachedShaders", "maxcount < 0"); 2125 return; 2126 } 2127 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders"); 2128 typedef cmds::GetAttachedShaders::Result Result; 2129 uint32 size = Result::ComputeSize(maxcount); 2130 Result* result = static_cast<Result*>(transfer_buffer_->Alloc(size)); 2131 if (!result) { 2132 return; 2133 } 2134 result->SetNumResults(0); 2135 helper_->GetAttachedShaders( 2136 program, 2137 transfer_buffer_->GetShmId(), 2138 transfer_buffer_->GetOffset(result), 2139 size); 2140 int32 token = helper_->InsertToken(); 2141 WaitForCmd(); 2142 if (count) { 2143 *count = result->GetNumResults(); 2144 } 2145 result->CopyResult(shaders); 2146 GPU_CLIENT_LOG_CODE_BLOCK({ 2147 for (int32 i = 0; i < result->GetNumResults(); ++i) { 2148 GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); 2149 } 2150 }); 2151 transfer_buffer_->FreePendingToken(result, token); 2152 CheckGLError(); 2153 } 2154 2155 void GLES2Implementation::GetShaderPrecisionFormat( 2156 GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { 2157 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2158 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat(" 2159 << GLES2Util::GetStringShaderType(shadertype) << ", " 2160 << GLES2Util::GetStringShaderPrecision(precisiontype) << ", " 2161 << static_cast<const void*>(range) << ", " 2162 << static_cast<const void*>(precision) << ", "); 2163 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat"); 2164 typedef cmds::GetShaderPrecisionFormat::Result Result; 2165 Result* result = GetResultAs<Result*>(); 2166 if (!result) { 2167 return; 2168 } 2169 2170 GLStaticState::ShaderPrecisionKey key(shadertype, precisiontype); 2171 GLStaticState::ShaderPrecisionMap::iterator i = 2172 static_state_.shader_precisions.find(key); 2173 if (i != static_state_.shader_precisions.end()) { 2174 *result = i->second; 2175 } else { 2176 result->success = false; 2177 helper_->GetShaderPrecisionFormat( 2178 shadertype, precisiontype, GetResultShmId(), GetResultShmOffset()); 2179 WaitForCmd(); 2180 if (result->success) 2181 static_state_.shader_precisions[key] = *result; 2182 } 2183 2184 if (result->success) { 2185 if (range) { 2186 range[0] = result->min_range; 2187 range[1] = result->max_range; 2188 GPU_CLIENT_LOG(" min_range: " << range[0]); 2189 GPU_CLIENT_LOG(" min_range: " << range[1]); 2190 } 2191 if (precision) { 2192 precision[0] = result->precision; 2193 GPU_CLIENT_LOG(" min_range: " << precision[0]); 2194 } 2195 } 2196 CheckGLError(); 2197 } 2198 2199 const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { 2200 const char* result = NULL; 2201 // Clears the bucket so if the command fails nothing will be in it. 2202 helper_->SetBucketSize(kResultBucketId, 0); 2203 helper_->GetString(name, kResultBucketId); 2204 std::string str; 2205 if (GetBucketAsString(kResultBucketId, &str)) { 2206 // Adds extensions implemented on client side only. 2207 switch (name) { 2208 case GL_EXTENSIONS: 2209 str += std::string(str.empty() ? "" : " ") + 2210 "GL_CHROMIUM_flipy " 2211 "GL_EXT_unpack_subimage " 2212 "GL_CHROMIUM_map_sub"; 2213 if (capabilities_.map_image) { 2214 // The first space character is intentional. 2215 str += " GL_CHROMIUM_map_image"; 2216 } 2217 if (capabilities_.future_sync_points) 2218 str += " GL_CHROMIUM_future_sync_point"; 2219 break; 2220 default: 2221 break; 2222 } 2223 2224 // Because of WebGL the extensions can change. We have to cache each unique 2225 // result since we don't know when the client will stop referring to a 2226 // previous one it queries. 2227 GLStringMap::iterator it = gl_strings_.find(name); 2228 if (it == gl_strings_.end()) { 2229 std::set<std::string> strings; 2230 std::pair<GLStringMap::iterator, bool> insert_result = 2231 gl_strings_.insert(std::make_pair(name, strings)); 2232 DCHECK(insert_result.second); 2233 it = insert_result.first; 2234 } 2235 std::set<std::string>& string_set = it->second; 2236 std::set<std::string>::const_iterator sit = string_set.find(str); 2237 if (sit != string_set.end()) { 2238 result = sit->c_str(); 2239 } else { 2240 std::pair<std::set<std::string>::const_iterator, bool> insert_result = 2241 string_set.insert(str); 2242 DCHECK(insert_result.second); 2243 result = insert_result.first->c_str(); 2244 } 2245 } 2246 return reinterpret_cast<const GLubyte*>(result); 2247 } 2248 2249 const GLubyte* GLES2Implementation::GetString(GLenum name) { 2250 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2251 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString(" 2252 << GLES2Util::GetStringStringType(name) << ")"); 2253 TRACE_EVENT0("gpu", "GLES2::GetString"); 2254 const GLubyte* result = GetStringHelper(name); 2255 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result)); 2256 CheckGLError(); 2257 return result; 2258 } 2259 2260 void GLES2Implementation::GetUniformfv( 2261 GLuint program, GLint location, GLfloat* params) { 2262 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2263 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv(" 2264 << program << ", " << location << ", " 2265 << static_cast<const void*>(params) << ")"); 2266 TRACE_EVENT0("gpu", "GLES2::GetUniformfv"); 2267 typedef cmds::GetUniformfv::Result Result; 2268 Result* result = GetResultAs<Result*>(); 2269 if (!result) { 2270 return; 2271 } 2272 result->SetNumResults(0); 2273 helper_->GetUniformfv( 2274 program, location, GetResultShmId(), GetResultShmOffset()); 2275 WaitForCmd(); 2276 result->CopyResult(params); 2277 GPU_CLIENT_LOG_CODE_BLOCK({ 2278 for (int32 i = 0; i < result->GetNumResults(); ++i) { 2279 GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); 2280 } 2281 }); 2282 CheckGLError(); 2283 } 2284 2285 void GLES2Implementation::GetUniformiv( 2286 GLuint program, GLint location, GLint* params) { 2287 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2288 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv(" 2289 << program << ", " << location << ", " 2290 << static_cast<const void*>(params) << ")"); 2291 TRACE_EVENT0("gpu", "GLES2::GetUniformiv"); 2292 typedef cmds::GetUniformiv::Result Result; 2293 Result* result = GetResultAs<Result*>(); 2294 if (!result) { 2295 return; 2296 } 2297 result->SetNumResults(0); 2298 helper_->GetUniformiv( 2299 program, location, GetResultShmId(), GetResultShmOffset()); 2300 WaitForCmd(); 2301 GetResultAs<cmds::GetUniformfv::Result*>()->CopyResult(params); 2302 GPU_CLIENT_LOG_CODE_BLOCK({ 2303 for (int32 i = 0; i < result->GetNumResults(); ++i) { 2304 GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); 2305 } 2306 }); 2307 CheckGLError(); 2308 } 2309 2310 void GLES2Implementation::ReadPixels( 2311 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, 2312 GLenum type, void* pixels) { 2313 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2314 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels(" 2315 << xoffset << ", " << yoffset << ", " 2316 << width << ", " << height << ", " 2317 << GLES2Util::GetStringReadPixelFormat(format) << ", " 2318 << GLES2Util::GetStringPixelType(type) << ", " 2319 << static_cast<const void*>(pixels) << ")"); 2320 if (width < 0 || height < 0) { 2321 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0"); 2322 return; 2323 } 2324 if (width == 0 || height == 0) { 2325 return; 2326 } 2327 2328 // glReadPixel pads the size of each row of pixels by an amount specified by 2329 // glPixelStorei. So, we have to take that into account both in the fact that 2330 // the pixels returned from the ReadPixel command will include that padding 2331 // and that when we copy the results to the user's buffer we need to not 2332 // write those padding bytes but leave them as they are. 2333 2334 TRACE_EVENT0("gpu", "GLES2::ReadPixels"); 2335 typedef cmds::ReadPixels::Result Result; 2336 2337 int8* dest = reinterpret_cast<int8*>(pixels); 2338 uint32 temp_size; 2339 uint32 unpadded_row_size; 2340 uint32 padded_row_size; 2341 if (!GLES2Util::ComputeImageDataSizes( 2342 width, 2, format, type, pack_alignment_, &temp_size, &unpadded_row_size, 2343 &padded_row_size)) { 2344 SetGLError(GL_INVALID_VALUE, "glReadPixels", "size too large."); 2345 return; 2346 } 2347 2348 if (bound_pixel_pack_transfer_buffer_id_) { 2349 GLuint offset = ToGLuint(pixels); 2350 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 2351 bound_pixel_pack_transfer_buffer_id_, 2352 "glReadPixels", offset, padded_row_size * height); 2353 if (buffer && buffer->shm_id() != -1) { 2354 helper_->ReadPixels(xoffset, yoffset, width, height, format, type, 2355 buffer->shm_id(), buffer->shm_offset(), 2356 0, 0, true); 2357 CheckGLError(); 2358 } 2359 return; 2360 } 2361 2362 if (!pixels) { 2363 SetGLError(GL_INVALID_OPERATION, "glReadPixels", "pixels = NULL"); 2364 return; 2365 } 2366 2367 // Transfer by rows. 2368 // The max rows we can transfer. 2369 while (height) { 2370 GLsizei desired_size = padded_row_size * height - 1 + unpadded_row_size; 2371 ScopedTransferBufferPtr buffer(desired_size, helper_, transfer_buffer_); 2372 if (!buffer.valid()) { 2373 return; 2374 } 2375 GLint num_rows = ComputeNumRowsThatFitInBuffer( 2376 padded_row_size, unpadded_row_size, buffer.size()); 2377 num_rows = std::min(num_rows, height); 2378 // NOTE: We must look up the address of the result area AFTER allocation 2379 // of the transfer buffer since the transfer buffer may be reallocated. 2380 Result* result = GetResultAs<Result*>(); 2381 if (!result) { 2382 return; 2383 } 2384 *result = 0; // mark as failed. 2385 helper_->ReadPixels( 2386 xoffset, yoffset, width, num_rows, format, type, 2387 buffer.shm_id(), buffer.offset(), 2388 GetResultShmId(), GetResultShmOffset(), 2389 false); 2390 WaitForCmd(); 2391 if (*result != 0) { 2392 // when doing a y-flip we have to iterate through top-to-bottom chunks 2393 // of the dst. The service side handles reversing the rows within a 2394 // chunk. 2395 int8* rows_dst; 2396 if (pack_reverse_row_order_) { 2397 rows_dst = dest + (height - num_rows) * padded_row_size; 2398 } else { 2399 rows_dst = dest; 2400 } 2401 // We have to copy 1 row at a time to avoid writing pad bytes. 2402 const int8* src = static_cast<const int8*>(buffer.address()); 2403 for (GLint yy = 0; yy < num_rows; ++yy) { 2404 memcpy(rows_dst, src, unpadded_row_size); 2405 rows_dst += padded_row_size; 2406 src += padded_row_size; 2407 } 2408 if (!pack_reverse_row_order_) { 2409 dest = rows_dst; 2410 } 2411 } 2412 // If it was not marked as successful exit. 2413 if (*result == 0) { 2414 return; 2415 } 2416 yoffset += num_rows; 2417 height -= num_rows; 2418 } 2419 CheckGLError(); 2420 } 2421 2422 void GLES2Implementation::ActiveTexture(GLenum texture) { 2423 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2424 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture(" 2425 << GLES2Util::GetStringEnum(texture) << ")"); 2426 GLuint texture_index = texture - GL_TEXTURE0; 2427 if (texture_index >= static_cast<GLuint>( 2428 static_state_.int_state.max_combined_texture_image_units)) { 2429 SetGLErrorInvalidEnum( 2430 "glActiveTexture", texture, "texture"); 2431 return; 2432 } 2433 2434 active_texture_unit_ = texture_index; 2435 helper_->ActiveTexture(texture); 2436 CheckGLError(); 2437 } 2438 2439 void GLES2Implementation::GenBuffersHelper( 2440 GLsizei /* n */, const GLuint* /* buffers */) { 2441 } 2442 2443 void GLES2Implementation::GenFramebuffersHelper( 2444 GLsizei /* n */, const GLuint* /* framebuffers */) { 2445 } 2446 2447 void GLES2Implementation::GenRenderbuffersHelper( 2448 GLsizei /* n */, const GLuint* /* renderbuffers */) { 2449 } 2450 2451 void GLES2Implementation::GenTexturesHelper( 2452 GLsizei /* n */, const GLuint* /* textures */) { 2453 } 2454 2455 void GLES2Implementation::GenVertexArraysOESHelper( 2456 GLsizei n, const GLuint* arrays) { 2457 vertex_array_object_manager_->GenVertexArrays(n, arrays); 2458 } 2459 2460 void GLES2Implementation::GenQueriesEXTHelper( 2461 GLsizei /* n */, const GLuint* /* queries */) { 2462 } 2463 2464 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id 2465 // generates a new resource. On newer versions of OpenGL they don't. The code 2466 // related to binding below will need to change if we switch to the new OpenGL 2467 // model. Specifically it assumes a bind will succeed which is always true in 2468 // the old model but possibly not true in the new model if another context has 2469 // deleted the resource. 2470 2471 bool GLES2Implementation::BindBufferHelper( 2472 GLenum target, GLuint buffer_id) { 2473 // TODO(gman): See note #1 above. 2474 bool changed = false; 2475 switch (target) { 2476 case GL_ARRAY_BUFFER: 2477 if (bound_array_buffer_id_ != buffer_id) { 2478 bound_array_buffer_id_ = buffer_id; 2479 changed = true; 2480 } 2481 break; 2482 case GL_ELEMENT_ARRAY_BUFFER: 2483 changed = vertex_array_object_manager_->BindElementArray(buffer_id); 2484 break; 2485 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: 2486 bound_pixel_pack_transfer_buffer_id_ = buffer_id; 2487 break; 2488 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: 2489 bound_pixel_unpack_transfer_buffer_id_ = buffer_id; 2490 break; 2491 default: 2492 changed = true; 2493 break; 2494 } 2495 // TODO(gman): There's a bug here. If the target is invalid the ID will not be 2496 // used even though it's marked it as used here. 2497 GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer_id); 2498 return changed; 2499 } 2500 2501 bool GLES2Implementation::BindFramebufferHelper( 2502 GLenum target, GLuint framebuffer) { 2503 // TODO(gman): See note #1 above. 2504 bool changed = false; 2505 switch (target) { 2506 case GL_FRAMEBUFFER: 2507 if (bound_framebuffer_ != framebuffer || 2508 bound_read_framebuffer_ != framebuffer) { 2509 bound_framebuffer_ = framebuffer; 2510 bound_read_framebuffer_ = framebuffer; 2511 changed = true; 2512 } 2513 break; 2514 case GL_READ_FRAMEBUFFER: 2515 if (!IsChromiumFramebufferMultisampleAvailable()) { 2516 SetGLErrorInvalidEnum("glBindFramebuffer", target, "target"); 2517 return false; 2518 } 2519 if (bound_read_framebuffer_ != framebuffer) { 2520 bound_read_framebuffer_ = framebuffer; 2521 changed = true; 2522 } 2523 break; 2524 case GL_DRAW_FRAMEBUFFER: 2525 if (!IsChromiumFramebufferMultisampleAvailable()) { 2526 SetGLErrorInvalidEnum("glBindFramebuffer", target, "target"); 2527 return false; 2528 } 2529 if (bound_framebuffer_ != framebuffer) { 2530 bound_framebuffer_ = framebuffer; 2531 changed = true; 2532 } 2533 break; 2534 default: 2535 SetGLErrorInvalidEnum("glBindFramebuffer", target, "target"); 2536 return false; 2537 } 2538 GetIdHandler(id_namespaces::kFramebuffers)->MarkAsUsedForBind(framebuffer); 2539 return changed; 2540 } 2541 2542 bool GLES2Implementation::BindRenderbufferHelper( 2543 GLenum target, GLuint renderbuffer) { 2544 // TODO(gman): See note #1 above. 2545 bool changed = false; 2546 switch (target) { 2547 case GL_RENDERBUFFER: 2548 if (bound_renderbuffer_ != renderbuffer) { 2549 bound_renderbuffer_ = renderbuffer; 2550 changed = true; 2551 } 2552 break; 2553 default: 2554 changed = true; 2555 break; 2556 } 2557 // TODO(gman): There's a bug here. If the target is invalid the ID will not be 2558 // used even though it's marked it as used here. 2559 GetIdHandler(id_namespaces::kRenderbuffers)->MarkAsUsedForBind(renderbuffer); 2560 return changed; 2561 } 2562 2563 bool GLES2Implementation::BindTextureHelper(GLenum target, GLuint texture) { 2564 // TODO(gman): See note #1 above. 2565 // TODO(gman): Change this to false once we figure out why it's failing 2566 // on daisy. 2567 bool changed = true; 2568 TextureUnit& unit = texture_units_[active_texture_unit_]; 2569 switch (target) { 2570 case GL_TEXTURE_2D: 2571 if (unit.bound_texture_2d != texture) { 2572 unit.bound_texture_2d = texture; 2573 changed = true; 2574 } 2575 break; 2576 case GL_TEXTURE_CUBE_MAP: 2577 if (unit.bound_texture_cube_map != texture) { 2578 unit.bound_texture_cube_map = texture; 2579 changed = true; 2580 } 2581 break; 2582 case GL_TEXTURE_EXTERNAL_OES: 2583 if (unit.bound_texture_external_oes != texture) { 2584 unit.bound_texture_external_oes = texture; 2585 changed = true; 2586 } 2587 break; 2588 default: 2589 changed = true; 2590 break; 2591 } 2592 // TODO(gman): There's a bug here. If the target is invalid the ID will not be 2593 // used. even though it's marked it as used here. 2594 GetIdHandler(id_namespaces::kTextures)->MarkAsUsedForBind(texture); 2595 return changed; 2596 } 2597 2598 bool GLES2Implementation::BindVertexArrayOESHelper(GLuint array) { 2599 // TODO(gman): See note #1 above. 2600 bool changed = false; 2601 if (!vertex_array_object_manager_->BindVertexArray(array, &changed)) { 2602 SetGLError( 2603 GL_INVALID_OPERATION, "glBindVertexArrayOES", 2604 "id was not generated with glGenVertexArrayOES"); 2605 } 2606 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind 2607 // because unlike other resources VertexArrayObject ids must 2608 // be generated by GenVertexArrays. A random id to Bind will not 2609 // generate a new object. 2610 return changed; 2611 } 2612 2613 bool GLES2Implementation::UseProgramHelper(GLuint program) { 2614 bool changed = false; 2615 if (current_program_ != program) { 2616 current_program_ = program; 2617 changed = true; 2618 } 2619 return changed; 2620 } 2621 2622 bool GLES2Implementation::IsBufferReservedId(GLuint id) { 2623 return vertex_array_object_manager_->IsReservedId(id); 2624 } 2625 2626 void GLES2Implementation::DeleteBuffersHelper( 2627 GLsizei n, const GLuint* buffers) { 2628 if (!GetIdHandler(id_namespaces::kBuffers)->FreeIds( 2629 this, n, buffers, &GLES2Implementation::DeleteBuffersStub)) { 2630 SetGLError( 2631 GL_INVALID_VALUE, 2632 "glDeleteBuffers", "id not created by this context."); 2633 return; 2634 } 2635 for (GLsizei ii = 0; ii < n; ++ii) { 2636 if (buffers[ii] == bound_array_buffer_id_) { 2637 bound_array_buffer_id_ = 0; 2638 } 2639 vertex_array_object_manager_->UnbindBuffer(buffers[ii]); 2640 2641 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]); 2642 if (buffer) 2643 RemoveTransferBuffer(buffer); 2644 2645 if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { 2646 bound_pixel_unpack_transfer_buffer_id_ = 0; 2647 } 2648 } 2649 } 2650 2651 void GLES2Implementation::DeleteBuffersStub( 2652 GLsizei n, const GLuint* buffers) { 2653 helper_->DeleteBuffersImmediate(n, buffers); 2654 } 2655 2656 2657 void GLES2Implementation::DeleteFramebuffersHelper( 2658 GLsizei n, const GLuint* framebuffers) { 2659 if (!GetIdHandler(id_namespaces::kFramebuffers)->FreeIds( 2660 this, n, framebuffers, &GLES2Implementation::DeleteFramebuffersStub)) { 2661 SetGLError( 2662 GL_INVALID_VALUE, 2663 "glDeleteFramebuffers", "id not created by this context."); 2664 return; 2665 } 2666 for (GLsizei ii = 0; ii < n; ++ii) { 2667 if (framebuffers[ii] == bound_framebuffer_) { 2668 bound_framebuffer_ = 0; 2669 } 2670 if (framebuffers[ii] == bound_read_framebuffer_) { 2671 bound_read_framebuffer_ = 0; 2672 } 2673 } 2674 } 2675 2676 void GLES2Implementation::DeleteFramebuffersStub( 2677 GLsizei n, const GLuint* framebuffers) { 2678 helper_->DeleteFramebuffersImmediate(n, framebuffers); 2679 } 2680 2681 void GLES2Implementation::DeleteRenderbuffersHelper( 2682 GLsizei n, const GLuint* renderbuffers) { 2683 if (!GetIdHandler(id_namespaces::kRenderbuffers)->FreeIds( 2684 this, n, renderbuffers, &GLES2Implementation::DeleteRenderbuffersStub)) { 2685 SetGLError( 2686 GL_INVALID_VALUE, 2687 "glDeleteRenderbuffers", "id not created by this context."); 2688 return; 2689 } 2690 for (GLsizei ii = 0; ii < n; ++ii) { 2691 if (renderbuffers[ii] == bound_renderbuffer_) { 2692 bound_renderbuffer_ = 0; 2693 } 2694 } 2695 } 2696 2697 void GLES2Implementation::DeleteRenderbuffersStub( 2698 GLsizei n, const GLuint* renderbuffers) { 2699 helper_->DeleteRenderbuffersImmediate(n, renderbuffers); 2700 } 2701 2702 void GLES2Implementation::DeleteTexturesHelper( 2703 GLsizei n, const GLuint* textures) { 2704 if (!GetIdHandler(id_namespaces::kTextures)->FreeIds( 2705 this, n, textures, &GLES2Implementation::DeleteTexturesStub)) { 2706 SetGLError( 2707 GL_INVALID_VALUE, 2708 "glDeleteTextures", "id not created by this context."); 2709 return; 2710 } 2711 for (GLsizei ii = 0; ii < n; ++ii) { 2712 for (GLint tt = 0; 2713 tt < static_state_.int_state.max_combined_texture_image_units; 2714 ++tt) { 2715 TextureUnit& unit = texture_units_[tt]; 2716 if (textures[ii] == unit.bound_texture_2d) { 2717 unit.bound_texture_2d = 0; 2718 } 2719 if (textures[ii] == unit.bound_texture_cube_map) { 2720 unit.bound_texture_cube_map = 0; 2721 } 2722 if (textures[ii] == unit.bound_texture_external_oes) { 2723 unit.bound_texture_external_oes = 0; 2724 } 2725 } 2726 } 2727 } 2728 2729 void GLES2Implementation::DeleteVertexArraysOESHelper( 2730 GLsizei n, const GLuint* arrays) { 2731 vertex_array_object_manager_->DeleteVertexArrays(n, arrays); 2732 if (!GetIdHandler(id_namespaces::kVertexArrays)->FreeIds( 2733 this, n, arrays, &GLES2Implementation::DeleteVertexArraysOESStub)) { 2734 SetGLError( 2735 GL_INVALID_VALUE, 2736 "glDeleteVertexArraysOES", "id not created by this context."); 2737 return; 2738 } 2739 } 2740 2741 void GLES2Implementation::DeleteVertexArraysOESStub( 2742 GLsizei n, const GLuint* arrays) { 2743 helper_->DeleteVertexArraysOESImmediate(n, arrays); 2744 } 2745 2746 void GLES2Implementation::DeleteTexturesStub( 2747 GLsizei n, const GLuint* textures) { 2748 helper_->DeleteTexturesImmediate(n, textures); 2749 } 2750 2751 void GLES2Implementation::DisableVertexAttribArray(GLuint index) { 2752 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2753 GPU_CLIENT_LOG( 2754 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index << ")"); 2755 vertex_array_object_manager_->SetAttribEnable(index, false); 2756 helper_->DisableVertexAttribArray(index); 2757 CheckGLError(); 2758 } 2759 2760 void GLES2Implementation::EnableVertexAttribArray(GLuint index) { 2761 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2762 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray(" 2763 << index << ")"); 2764 vertex_array_object_manager_->SetAttribEnable(index, true); 2765 helper_->EnableVertexAttribArray(index); 2766 CheckGLError(); 2767 } 2768 2769 void GLES2Implementation::DrawArrays(GLenum mode, GLint first, GLsizei count) { 2770 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2771 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays(" 2772 << GLES2Util::GetStringDrawMode(mode) << ", " 2773 << first << ", " << count << ")"); 2774 if (count < 0) { 2775 SetGLError(GL_INVALID_VALUE, "glDrawArrays", "count < 0"); 2776 return; 2777 } 2778 bool simulated = false; 2779 if (!vertex_array_object_manager_->SetupSimulatedClientSideBuffers( 2780 "glDrawArrays", this, helper_, first + count, 0, &simulated)) { 2781 return; 2782 } 2783 helper_->DrawArrays(mode, first, count); 2784 RestoreArrayBuffer(simulated); 2785 CheckGLError(); 2786 } 2787 2788 void GLES2Implementation::GetVertexAttribfv( 2789 GLuint index, GLenum pname, GLfloat* params) { 2790 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2791 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv(" 2792 << index << ", " 2793 << GLES2Util::GetStringVertexAttribute(pname) << ", " 2794 << static_cast<const void*>(params) << ")"); 2795 uint32 value = 0; 2796 if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) { 2797 *params = static_cast<float>(value); 2798 return; 2799 } 2800 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv"); 2801 typedef cmds::GetVertexAttribfv::Result Result; 2802 Result* result = GetResultAs<Result*>(); 2803 if (!result) { 2804 return; 2805 } 2806 result->SetNumResults(0); 2807 helper_->GetVertexAttribfv( 2808 index, pname, GetResultShmId(), GetResultShmOffset()); 2809 WaitForCmd(); 2810 result->CopyResult(params); 2811 GPU_CLIENT_LOG_CODE_BLOCK({ 2812 for (int32 i = 0; i < result->GetNumResults(); ++i) { 2813 GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); 2814 } 2815 }); 2816 CheckGLError(); 2817 } 2818 2819 void GLES2Implementation::GetVertexAttribiv( 2820 GLuint index, GLenum pname, GLint* params) { 2821 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2822 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv(" 2823 << index << ", " 2824 << GLES2Util::GetStringVertexAttribute(pname) << ", " 2825 << static_cast<const void*>(params) << ")"); 2826 uint32 value = 0; 2827 if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) { 2828 *params = value; 2829 return; 2830 } 2831 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv"); 2832 typedef cmds::GetVertexAttribiv::Result Result; 2833 Result* result = GetResultAs<Result*>(); 2834 if (!result) { 2835 return; 2836 } 2837 result->SetNumResults(0); 2838 helper_->GetVertexAttribiv( 2839 index, pname, GetResultShmId(), GetResultShmOffset()); 2840 WaitForCmd(); 2841 result->CopyResult(params); 2842 GPU_CLIENT_LOG_CODE_BLOCK({ 2843 for (int32 i = 0; i < result->GetNumResults(); ++i) { 2844 GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); 2845 } 2846 }); 2847 CheckGLError(); 2848 } 2849 2850 void GLES2Implementation::Swap() { 2851 SwapBuffers(); 2852 gpu_control_->Echo( 2853 base::Bind(&GLES2Implementation::OnSwapBuffersComplete, 2854 weak_ptr_factory_.GetWeakPtr())); 2855 } 2856 2857 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect& sub_buffer) { 2858 PostSubBufferCHROMIUM(sub_buffer.x(), 2859 sub_buffer.y(), 2860 sub_buffer.width(), 2861 sub_buffer.height()); 2862 gpu_control_->Echo(base::Bind(&GLES2Implementation::OnSwapBuffersComplete, 2863 weak_ptr_factory_.GetWeakPtr())); 2864 } 2865 2866 void GLES2Implementation::SetSwapBuffersCompleteCallback( 2867 const base::Closure& swap_buffers_complete_callback) { 2868 swap_buffers_complete_callback_ = swap_buffers_complete_callback; 2869 } 2870 2871 static GLenum GetGLESOverlayTransform(gfx::OverlayTransform plane_transform) { 2872 switch (plane_transform) { 2873 case gfx::OVERLAY_TRANSFORM_INVALID: 2874 break; 2875 case gfx::OVERLAY_TRANSFORM_NONE: 2876 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM; 2877 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL: 2878 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM; 2879 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL: 2880 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM; 2881 case gfx::OVERLAY_TRANSFORM_ROTATE_90: 2882 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM; 2883 case gfx::OVERLAY_TRANSFORM_ROTATE_180: 2884 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM; 2885 case gfx::OVERLAY_TRANSFORM_ROTATE_270: 2886 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM; 2887 } 2888 NOTREACHED(); 2889 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM; 2890 } 2891 2892 void GLES2Implementation::ScheduleOverlayPlane( 2893 int plane_z_order, 2894 gfx::OverlayTransform plane_transform, 2895 unsigned overlay_texture_id, 2896 const gfx::Rect& display_bounds, 2897 const gfx::RectF& uv_rect) { 2898 ScheduleOverlayPlaneCHROMIUM(plane_z_order, 2899 GetGLESOverlayTransform(plane_transform), 2900 overlay_texture_id, 2901 display_bounds.x(), 2902 display_bounds.y(), 2903 display_bounds.width(), 2904 display_bounds.height(), 2905 uv_rect.x(), 2906 uv_rect.y(), 2907 uv_rect.width(), 2908 uv_rect.height()); 2909 } 2910 2911 void GLES2Implementation::OnSwapBuffersComplete() { 2912 if (!swap_buffers_complete_callback_.is_null()) 2913 swap_buffers_complete_callback_.Run(); 2914 } 2915 2916 GLboolean GLES2Implementation::EnableFeatureCHROMIUM( 2917 const char* feature) { 2918 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2919 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM(" 2920 << feature << ")"); 2921 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM"); 2922 typedef cmds::EnableFeatureCHROMIUM::Result Result; 2923 Result* result = GetResultAs<Result*>(); 2924 if (!result) { 2925 return false; 2926 } 2927 *result = 0; 2928 SetBucketAsCString(kResultBucketId, feature); 2929 helper_->EnableFeatureCHROMIUM( 2930 kResultBucketId, GetResultShmId(), GetResultShmOffset()); 2931 WaitForCmd(); 2932 helper_->SetBucketSize(kResultBucketId, 0); 2933 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result)); 2934 return *result; 2935 } 2936 2937 void* GLES2Implementation::MapBufferSubDataCHROMIUM( 2938 GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) { 2939 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2940 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM(" 2941 << target << ", " << offset << ", " << size << ", " 2942 << GLES2Util::GetStringEnum(access) << ")"); 2943 // NOTE: target is NOT checked because the service will check it 2944 // and we don't know what targets are valid. 2945 if (access != GL_WRITE_ONLY) { 2946 SetGLErrorInvalidEnum( 2947 "glMapBufferSubDataCHROMIUM", access, "access"); 2948 return NULL; 2949 } 2950 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size) || 2951 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset)) { 2952 return NULL; 2953 } 2954 2955 int32 shm_id; 2956 unsigned int shm_offset; 2957 void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset); 2958 if (!mem) { 2959 SetGLError(GL_OUT_OF_MEMORY, "glMapBufferSubDataCHROMIUM", "out of memory"); 2960 return NULL; 2961 } 2962 2963 std::pair<MappedBufferMap::iterator, bool> result = 2964 mapped_buffers_.insert(std::make_pair( 2965 mem, 2966 MappedBuffer( 2967 access, shm_id, mem, shm_offset, target, offset, size))); 2968 DCHECK(result.second); 2969 GPU_CLIENT_LOG(" returned " << mem); 2970 return mem; 2971 } 2972 2973 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem) { 2974 GPU_CLIENT_SINGLE_THREAD_CHECK(); 2975 GPU_CLIENT_LOG( 2976 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem << ")"); 2977 MappedBufferMap::iterator it = mapped_buffers_.find(mem); 2978 if (it == mapped_buffers_.end()) { 2979 SetGLError( 2980 GL_INVALID_VALUE, "UnmapBufferSubDataCHROMIUM", "buffer not mapped"); 2981 return; 2982 } 2983 const MappedBuffer& mb = it->second; 2984 helper_->BufferSubData( 2985 mb.target, mb.offset, mb.size, mb.shm_id, mb.shm_offset); 2986 mapped_memory_->FreePendingToken(mb.shm_memory, helper_->InsertToken()); 2987 mapped_buffers_.erase(it); 2988 CheckGLError(); 2989 } 2990 2991 void* GLES2Implementation::MapTexSubImage2DCHROMIUM( 2992 GLenum target, 2993 GLint level, 2994 GLint xoffset, 2995 GLint yoffset, 2996 GLsizei width, 2997 GLsizei height, 2998 GLenum format, 2999 GLenum type, 3000 GLenum access) { 3001 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3002 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM(" 3003 << target << ", " << level << ", " 3004 << xoffset << ", " << yoffset << ", " 3005 << width << ", " << height << ", " 3006 << GLES2Util::GetStringTextureFormat(format) << ", " 3007 << GLES2Util::GetStringPixelType(type) << ", " 3008 << GLES2Util::GetStringEnum(access) << ")"); 3009 if (access != GL_WRITE_ONLY) { 3010 SetGLErrorInvalidEnum( 3011 "glMapTexSubImage2DCHROMIUM", access, "access"); 3012 return NULL; 3013 } 3014 // NOTE: target is NOT checked because the service will check it 3015 // and we don't know what targets are valid. 3016 if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) { 3017 SetGLError( 3018 GL_INVALID_VALUE, "glMapTexSubImage2DCHROMIUM", "bad dimensions"); 3019 return NULL; 3020 } 3021 uint32 size; 3022 if (!GLES2Util::ComputeImageDataSizes( 3023 width, height, format, type, unpack_alignment_, &size, NULL, NULL)) { 3024 SetGLError( 3025 GL_INVALID_VALUE, "glMapTexSubImage2DCHROMIUM", "image size too large"); 3026 return NULL; 3027 } 3028 int32 shm_id; 3029 unsigned int shm_offset; 3030 void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset); 3031 if (!mem) { 3032 SetGLError(GL_OUT_OF_MEMORY, "glMapTexSubImage2DCHROMIUM", "out of memory"); 3033 return NULL; 3034 } 3035 3036 std::pair<MappedTextureMap::iterator, bool> result = 3037 mapped_textures_.insert(std::make_pair( 3038 mem, 3039 MappedTexture( 3040 access, shm_id, mem, shm_offset, 3041 target, level, xoffset, yoffset, width, height, format, type))); 3042 DCHECK(result.second); 3043 GPU_CLIENT_LOG(" returned " << mem); 3044 return mem; 3045 } 3046 3047 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem) { 3048 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3049 GPU_CLIENT_LOG( 3050 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem << ")"); 3051 MappedTextureMap::iterator it = mapped_textures_.find(mem); 3052 if (it == mapped_textures_.end()) { 3053 SetGLError( 3054 GL_INVALID_VALUE, "UnmapTexSubImage2DCHROMIUM", "texture not mapped"); 3055 return; 3056 } 3057 const MappedTexture& mt = it->second; 3058 helper_->TexSubImage2D( 3059 mt.target, mt.level, mt.xoffset, mt.yoffset, mt.width, mt.height, 3060 mt.format, mt.type, mt.shm_id, mt.shm_offset, GL_FALSE); 3061 mapped_memory_->FreePendingToken(mt.shm_memory, helper_->InsertToken()); 3062 mapped_textures_.erase(it); 3063 CheckGLError(); 3064 } 3065 3066 void GLES2Implementation::ResizeCHROMIUM(GLuint width, GLuint height, 3067 float scale_factor) { 3068 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3069 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM(" 3070 << width << ", " << height << ", " << scale_factor << ")"); 3071 helper_->ResizeCHROMIUM(width, height, scale_factor); 3072 CheckGLError(); 3073 } 3074 3075 const GLchar* GLES2Implementation::GetRequestableExtensionsCHROMIUM() { 3076 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3077 GPU_CLIENT_LOG("[" << GetLogPrefix() 3078 << "] glGetRequestableExtensionsCHROMIUM()"); 3079 TRACE_EVENT0("gpu", 3080 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()"); 3081 const char* result = NULL; 3082 // Clear the bucket so if the command fails nothing will be in it. 3083 helper_->SetBucketSize(kResultBucketId, 0); 3084 helper_->GetRequestableExtensionsCHROMIUM(kResultBucketId); 3085 std::string str; 3086 if (GetBucketAsString(kResultBucketId, &str)) { 3087 // The set of requestable extensions shrinks as we enable 3088 // them. Because we don't know when the client will stop referring 3089 // to a previous one it queries (see GetString) we need to cache 3090 // the unique results. 3091 std::set<std::string>::const_iterator sit = 3092 requestable_extensions_set_.find(str); 3093 if (sit != requestable_extensions_set_.end()) { 3094 result = sit->c_str(); 3095 } else { 3096 std::pair<std::set<std::string>::const_iterator, bool> insert_result = 3097 requestable_extensions_set_.insert(str); 3098 DCHECK(insert_result.second); 3099 result = insert_result.first->c_str(); 3100 } 3101 } 3102 GPU_CLIENT_LOG(" returned " << result); 3103 return reinterpret_cast<const GLchar*>(result); 3104 } 3105 3106 // TODO(gman): Remove this command. It's here for WebGL but is incompatible 3107 // with VirtualGL contexts. 3108 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension) { 3109 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3110 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM(" 3111 << extension << ")"); 3112 SetBucketAsCString(kResultBucketId, extension); 3113 helper_->RequestExtensionCHROMIUM(kResultBucketId); 3114 helper_->SetBucketSize(kResultBucketId, 0); 3115 3116 struct ExtensionCheck { 3117 const char* extension; 3118 ExtensionStatus* status; 3119 }; 3120 const ExtensionCheck checks[] = { 3121 { 3122 "GL_ANGLE_pack_reverse_row_order", 3123 &angle_pack_reverse_row_order_status_, 3124 }, 3125 { 3126 "GL_CHROMIUM_framebuffer_multisample", 3127 &chromium_framebuffer_multisample_, 3128 }, 3129 }; 3130 const size_t kNumChecks = sizeof(checks)/sizeof(checks[0]); 3131 for (size_t ii = 0; ii < kNumChecks; ++ii) { 3132 const ExtensionCheck& check = checks[ii]; 3133 if (*check.status == kUnavailableExtensionStatus && 3134 !strcmp(extension, check.extension)) { 3135 *check.status = kUnknownExtensionStatus; 3136 } 3137 } 3138 } 3139 3140 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() { 3141 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3142 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()"); 3143 // Wait if this would add too many rate limit tokens. 3144 if (rate_limit_tokens_.size() == kMaxSwapBuffers) { 3145 helper_->WaitForToken(rate_limit_tokens_.front()); 3146 rate_limit_tokens_.pop(); 3147 } 3148 rate_limit_tokens_.push(helper_->InsertToken()); 3149 } 3150 3151 void GLES2Implementation::GetMultipleIntegervCHROMIUM( 3152 const GLenum* pnames, GLuint count, GLint* results, GLsizeiptr size) { 3153 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3154 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMultipleIntegervCHROMIUM(" 3155 << static_cast<const void*>(pnames) << ", " 3156 << count << ", " << results << ", " 3157 << size << ")"); 3158 GPU_CLIENT_LOG_CODE_BLOCK({ 3159 for (GLuint i = 0; i < count; ++i) { 3160 GPU_CLIENT_LOG( 3161 " " << i << ": " << GLES2Util::GetStringGLState(pnames[i])); 3162 } 3163 }); 3164 DCHECK(size >= 0 && FitInt32NonNegative<GLsizeiptr>(size)); 3165 3166 GetMultipleIntegervState state(pnames, count, results, size); 3167 if (!GetMultipleIntegervSetup(&state)) { 3168 return; 3169 } 3170 state.buffer = transfer_buffer_->Alloc(state.transfer_buffer_size_needed); 3171 if (!state.buffer) { 3172 SetGLError(GL_OUT_OF_MEMORY, "glGetMultipleIntegervCHROMIUM", 3173 "Transfer buffer allocation failed."); 3174 return; 3175 } 3176 GetMultipleIntegervRequest(&state); 3177 WaitForCmd(); 3178 GetMultipleIntegervOnCompleted(&state); 3179 3180 GPU_CLIENT_LOG(" returned"); 3181 GPU_CLIENT_LOG_CODE_BLOCK({ 3182 for (int i = 0; i < state.num_results; ++i) { 3183 GPU_CLIENT_LOG(" " << i << ": " << (results[i])); 3184 } 3185 }); 3186 3187 // TODO(gman): We should be able to free without a token. 3188 transfer_buffer_->FreePendingToken(state.buffer, helper_->InsertToken()); 3189 CheckGLError(); 3190 } 3191 3192 bool GLES2Implementation::GetMultipleIntegervSetup( 3193 GetMultipleIntegervState* state) { 3194 state->num_results = 0; 3195 for (GLuint ii = 0; ii < state->pnames_count; ++ii) { 3196 int num = util_.GLGetNumValuesReturned(state->pnames[ii]); 3197 if (!num) { 3198 SetGLErrorInvalidEnum( 3199 "glGetMultipleIntegervCHROMIUM", state->pnames[ii], "pname"); 3200 return false; 3201 } 3202 state->num_results += num; 3203 } 3204 if (static_cast<size_t>(state->results_size) != 3205 state->num_results * sizeof(GLint)) { 3206 SetGLError(GL_INVALID_VALUE, "glGetMultipleIntegervCHROMIUM", "bad size"); 3207 return false; 3208 } 3209 for (int ii = 0; ii < state->num_results; ++ii) { 3210 if (state->results[ii] != 0) { 3211 SetGLError(GL_INVALID_VALUE, 3212 "glGetMultipleIntegervCHROMIUM", "results not set to zero."); 3213 return false; 3214 } 3215 } 3216 state->transfer_buffer_size_needed = 3217 state->pnames_count * sizeof(state->pnames[0]) + 3218 state->num_results * sizeof(state->results[0]); 3219 return true; 3220 } 3221 3222 void GLES2Implementation::GetMultipleIntegervRequest( 3223 GetMultipleIntegervState* state) { 3224 GLenum* pnames_buffer = static_cast<GLenum*>(state->buffer); 3225 state->results_buffer = pnames_buffer + state->pnames_count; 3226 memcpy(pnames_buffer, state->pnames, state->pnames_count * sizeof(GLenum)); 3227 memset(state->results_buffer, 0, state->num_results * sizeof(GLint)); 3228 helper_->GetMultipleIntegervCHROMIUM( 3229 transfer_buffer_->GetShmId(), 3230 transfer_buffer_->GetOffset(pnames_buffer), 3231 state->pnames_count, 3232 transfer_buffer_->GetShmId(), 3233 transfer_buffer_->GetOffset(state->results_buffer), 3234 state->results_size); 3235 } 3236 3237 void GLES2Implementation::GetMultipleIntegervOnCompleted( 3238 GetMultipleIntegervState* state) { 3239 memcpy(state->results, state->results_buffer, state->results_size);; 3240 } 3241 3242 void GLES2Implementation::GetAllShaderPrecisionFormatsSetup( 3243 GetAllShaderPrecisionFormatsState* state) { 3244 state->transfer_buffer_size_needed = 3245 state->precision_params_count * 3246 sizeof(cmds::GetShaderPrecisionFormat::Result); 3247 } 3248 3249 void GLES2Implementation::GetAllShaderPrecisionFormatsRequest( 3250 GetAllShaderPrecisionFormatsState* state) { 3251 typedef cmds::GetShaderPrecisionFormat::Result Result; 3252 Result* result = static_cast<Result*>(state->results_buffer); 3253 3254 for (int i = 0; i < state->precision_params_count; i++) { 3255 result->success = false; 3256 helper_->GetShaderPrecisionFormat(state->precision_params[i][0], 3257 state->precision_params[i][1], 3258 transfer_buffer_->GetShmId(), 3259 transfer_buffer_->GetOffset(result)); 3260 result++; 3261 } 3262 } 3263 3264 void GLES2Implementation::GetAllShaderPrecisionFormatsOnCompleted( 3265 GetAllShaderPrecisionFormatsState* state) { 3266 typedef cmds::GetShaderPrecisionFormat::Result Result; 3267 Result* result = static_cast<Result*>(state->results_buffer); 3268 3269 for (int i = 0; i < state->precision_params_count; i++) { 3270 if (result->success) { 3271 const GLStaticState::ShaderPrecisionKey key( 3272 state->precision_params[i][0], state->precision_params[i][1]); 3273 static_state_.shader_precisions[key] = *result; 3274 } 3275 result++; 3276 } 3277 } 3278 3279 void GLES2Implementation::GetProgramInfoCHROMIUMHelper( 3280 GLuint program, std::vector<int8>* result) { 3281 DCHECK(result); 3282 // Clear the bucket so if the command fails nothing will be in it. 3283 helper_->SetBucketSize(kResultBucketId, 0); 3284 helper_->GetProgramInfoCHROMIUM(program, kResultBucketId); 3285 GetBucketContents(kResultBucketId, result); 3286 } 3287 3288 void GLES2Implementation::GetProgramInfoCHROMIUM( 3289 GLuint program, GLsizei bufsize, GLsizei* size, void* info) { 3290 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3291 if (bufsize < 0) { 3292 SetGLError( 3293 GL_INVALID_VALUE, "glProgramInfoCHROMIUM", "bufsize less than 0."); 3294 return; 3295 } 3296 if (size == NULL) { 3297 SetGLError(GL_INVALID_VALUE, "glProgramInfoCHROMIUM", "size is null."); 3298 return; 3299 } 3300 // Make sure they've set size to 0 else the value will be undefined on 3301 // lost context. 3302 DCHECK_EQ(0, *size); 3303 std::vector<int8> result; 3304 GetProgramInfoCHROMIUMHelper(program, &result); 3305 if (result.empty()) { 3306 return; 3307 } 3308 *size = result.size(); 3309 if (!info) { 3310 return; 3311 } 3312 if (static_cast<size_t>(bufsize) < result.size()) { 3313 SetGLError(GL_INVALID_OPERATION, 3314 "glProgramInfoCHROMIUM", "bufsize is too small for result."); 3315 return; 3316 } 3317 memcpy(info, &result[0], result.size()); 3318 } 3319 3320 GLuint GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture) { 3321 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3322 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM(" 3323 << texture << ")"); 3324 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM"); 3325 helper_->CommandBufferHelper::Flush(); 3326 return gpu_control_->CreateStreamTexture(texture); 3327 } 3328 3329 void GLES2Implementation::PostSubBufferCHROMIUM( 3330 GLint x, GLint y, GLint width, GLint height) { 3331 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3332 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM(" 3333 << x << ", " << y << ", " << width << ", " << height << ")"); 3334 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM", 3335 "width", width, "height", height); 3336 3337 // Same flow control as GLES2Implementation::SwapBuffers (see comments there). 3338 swap_buffers_tokens_.push(helper_->InsertToken()); 3339 helper_->PostSubBufferCHROMIUM(x, y, width, height); 3340 helper_->CommandBufferHelper::Flush(); 3341 if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) { 3342 helper_->WaitForToken(swap_buffers_tokens_.front()); 3343 swap_buffers_tokens_.pop(); 3344 } 3345 } 3346 3347 void GLES2Implementation::DeleteQueriesEXTHelper( 3348 GLsizei n, const GLuint* queries) { 3349 for (GLsizei ii = 0; ii < n; ++ii) { 3350 query_tracker_->RemoveQuery(queries[ii]); 3351 query_id_allocator_->FreeID(queries[ii]); 3352 } 3353 3354 helper_->DeleteQueriesEXTImmediate(n, queries); 3355 } 3356 3357 GLboolean GLES2Implementation::IsQueryEXT(GLuint id) { 3358 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3359 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id << ")"); 3360 3361 // TODO(gman): To be spec compliant IDs from other contexts sharing 3362 // resources need to return true here even though you can't share 3363 // queries across contexts? 3364 return query_tracker_->GetQuery(id) != NULL; 3365 } 3366 3367 void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) { 3368 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3369 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT(" 3370 << GLES2Util::GetStringQueryTarget(target) 3371 << ", " << id << ")"); 3372 3373 // if any outstanding queries INV_OP 3374 QueryMap::iterator it = current_queries_.find(target); 3375 if (it != current_queries_.end()) { 3376 SetGLError( 3377 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress"); 3378 return; 3379 } 3380 3381 // id = 0 INV_OP 3382 if (id == 0) { 3383 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0"); 3384 return; 3385 } 3386 3387 // if not GENned INV_OPERATION 3388 if (!query_id_allocator_->InUse(id)) { 3389 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "invalid id"); 3390 return; 3391 } 3392 3393 // if id does not have an object 3394 QueryTracker::Query* query = query_tracker_->GetQuery(id); 3395 if (!query) { 3396 query = query_tracker_->CreateQuery(id, target); 3397 if (!query) { 3398 SetGLError(GL_OUT_OF_MEMORY, 3399 "glBeginQueryEXT", 3400 "transfer buffer allocation failed"); 3401 return; 3402 } 3403 } else if (query->target() != target) { 3404 SetGLError( 3405 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match"); 3406 return; 3407 } 3408 3409 current_queries_[target] = query; 3410 3411 query->Begin(this); 3412 CheckGLError(); 3413 } 3414 3415 void GLES2Implementation::EndQueryEXT(GLenum target) { 3416 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3417 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT(" 3418 << GLES2Util::GetStringQueryTarget(target) << ")"); 3419 // Don't do anything if the context is lost. 3420 if (helper_->IsContextLost()) { 3421 return; 3422 } 3423 3424 QueryMap::iterator it = current_queries_.find(target); 3425 if (it == current_queries_.end()) { 3426 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT", "no active query"); 3427 return; 3428 } 3429 3430 QueryTracker::Query* query = it->second; 3431 query->End(this); 3432 current_queries_.erase(it); 3433 CheckGLError(); 3434 } 3435 3436 void GLES2Implementation::GetQueryivEXT( 3437 GLenum target, GLenum pname, GLint* params) { 3438 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3439 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" 3440 << GLES2Util::GetStringQueryTarget(target) << ", " 3441 << GLES2Util::GetStringQueryParameter(pname) << ", " 3442 << static_cast<const void*>(params) << ")"); 3443 3444 if (pname != GL_CURRENT_QUERY_EXT) { 3445 SetGLErrorInvalidEnum("glGetQueryivEXT", pname, "pname"); 3446 return; 3447 } 3448 QueryMap::iterator it = current_queries_.find(target); 3449 if (it != current_queries_.end()) { 3450 QueryTracker::Query* query = it->second; 3451 *params = query->id(); 3452 } else { 3453 *params = 0; 3454 } 3455 GPU_CLIENT_LOG(" " << *params); 3456 CheckGLError(); 3457 } 3458 3459 void GLES2Implementation::GetQueryObjectuivEXT( 3460 GLuint id, GLenum pname, GLuint* params) { 3461 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3462 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id << ", " 3463 << GLES2Util::GetStringQueryObjectParameter(pname) << ", " 3464 << static_cast<const void*>(params) << ")"); 3465 3466 QueryTracker::Query* query = query_tracker_->GetQuery(id); 3467 if (!query) { 3468 SetGLError(GL_INVALID_OPERATION, "glQueryObjectuivEXT", "unknown query id"); 3469 return; 3470 } 3471 3472 QueryMap::iterator it = current_queries_.find(query->target()); 3473 if (it != current_queries_.end()) { 3474 SetGLError( 3475 GL_INVALID_OPERATION, 3476 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?"); 3477 return; 3478 } 3479 3480 if (query->NeverUsed()) { 3481 SetGLError( 3482 GL_INVALID_OPERATION, 3483 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?"); 3484 return; 3485 } 3486 3487 switch (pname) { 3488 case GL_QUERY_RESULT_EXT: 3489 if (!query->CheckResultsAvailable(helper_)) { 3490 helper_->WaitForToken(query->token()); 3491 if (!query->CheckResultsAvailable(helper_)) { 3492 FinishHelper(); 3493 CHECK(query->CheckResultsAvailable(helper_)); 3494 } 3495 } 3496 *params = query->GetResult(); 3497 break; 3498 case GL_QUERY_RESULT_AVAILABLE_EXT: 3499 *params = query->CheckResultsAvailable(helper_); 3500 break; 3501 default: 3502 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname, "pname"); 3503 break; 3504 } 3505 GPU_CLIENT_LOG(" " << *params); 3506 CheckGLError(); 3507 } 3508 3509 void GLES2Implementation::DrawArraysInstancedANGLE( 3510 GLenum mode, GLint first, GLsizei count, GLsizei primcount) { 3511 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3512 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE(" 3513 << GLES2Util::GetStringDrawMode(mode) << ", " 3514 << first << ", " << count << ", " << primcount << ")"); 3515 if (count < 0) { 3516 SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedANGLE", "count < 0"); 3517 return; 3518 } 3519 if (primcount < 0) { 3520 SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedANGLE", "primcount < 0"); 3521 return; 3522 } 3523 if (primcount == 0) { 3524 return; 3525 } 3526 bool simulated = false; 3527 if (!vertex_array_object_manager_->SetupSimulatedClientSideBuffers( 3528 "glDrawArraysInstancedANGLE", this, helper_, first + count, primcount, 3529 &simulated)) { 3530 return; 3531 } 3532 helper_->DrawArraysInstancedANGLE(mode, first, count, primcount); 3533 RestoreArrayBuffer(simulated); 3534 CheckGLError(); 3535 } 3536 3537 void GLES2Implementation::DrawElementsInstancedANGLE( 3538 GLenum mode, GLsizei count, GLenum type, const void* indices, 3539 GLsizei primcount) { 3540 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3541 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE(" 3542 << GLES2Util::GetStringDrawMode(mode) << ", " 3543 << count << ", " 3544 << GLES2Util::GetStringIndexType(type) << ", " 3545 << static_cast<const void*>(indices) << ", " 3546 << primcount << ")"); 3547 if (count < 0) { 3548 SetGLError(GL_INVALID_VALUE, 3549 "glDrawElementsInstancedANGLE", "count less than 0."); 3550 return; 3551 } 3552 if (count == 0) { 3553 return; 3554 } 3555 if (primcount < 0) { 3556 SetGLError(GL_INVALID_VALUE, 3557 "glDrawElementsInstancedANGLE", "primcount < 0"); 3558 return; 3559 } 3560 if (primcount == 0) { 3561 return; 3562 } 3563 if (vertex_array_object_manager_->bound_element_array_buffer() != 0 && 3564 !ValidateOffset("glDrawElementsInstancedANGLE", 3565 reinterpret_cast<GLintptr>(indices))) { 3566 return; 3567 } 3568 GLuint offset = 0; 3569 bool simulated = false; 3570 if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers( 3571 "glDrawElementsInstancedANGLE", this, helper_, count, type, primcount, 3572 indices, &offset, &simulated)) { 3573 return; 3574 } 3575 helper_->DrawElementsInstancedANGLE(mode, count, type, offset, primcount); 3576 RestoreElementAndArrayBuffers(simulated); 3577 CheckGLError(); 3578 } 3579 3580 void GLES2Implementation::GenMailboxCHROMIUM( 3581 GLbyte* mailbox) { 3582 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3583 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM(" 3584 << static_cast<const void*>(mailbox) << ")"); 3585 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM"); 3586 3587 gpu::Mailbox result = gpu::Mailbox::Generate(); 3588 memcpy(mailbox, result.name, sizeof(result.name)); 3589 } 3590 3591 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target, 3592 const GLbyte* data) { 3593 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3594 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM(" 3595 << static_cast<const void*>(data) << ")"); 3596 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data); 3597 DCHECK(mailbox.Verify()) << "ProduceTextureCHROMIUM was passed a " 3598 "mailbox that was not generated by " 3599 "GenMailboxCHROMIUM."; 3600 helper_->ProduceTextureCHROMIUMImmediate(target, data); 3601 CheckGLError(); 3602 } 3603 3604 void GLES2Implementation::ProduceTextureDirectCHROMIUM( 3605 GLuint texture, GLenum target, const GLbyte* data) { 3606 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3607 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM(" 3608 << static_cast<const void*>(data) << ")"); 3609 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data); 3610 DCHECK(mailbox.Verify()) << "ProduceTextureDirectCHROMIUM was passed a " 3611 "mailbox that was not generated by " 3612 "GenMailboxCHROMIUM."; 3613 helper_->ProduceTextureDirectCHROMIUMImmediate(texture, target, data); 3614 CheckGLError(); 3615 } 3616 3617 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target, 3618 const GLbyte* data) { 3619 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3620 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM(" 3621 << static_cast<const void*>(data) << ")"); 3622 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data); 3623 DCHECK(mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a " 3624 "mailbox that was not generated by " 3625 "GenMailboxCHROMIUM."; 3626 helper_->ConsumeTextureCHROMIUMImmediate(target, data); 3627 CheckGLError(); 3628 } 3629 3630 GLuint GLES2Implementation::CreateAndConsumeTextureCHROMIUM( 3631 GLenum target, const GLbyte* data) { 3632 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3633 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM(" 3634 << static_cast<const void*>(data) << ")"); 3635 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data); 3636 DCHECK(mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a " 3637 "mailbox that was not generated by " 3638 "GenMailboxCHROMIUM."; 3639 GLuint client_id; 3640 GetIdHandler(id_namespaces::kTextures)->MakeIds(this, 0, 1, &client_id); 3641 helper_->CreateAndConsumeTextureCHROMIUMImmediate(target, 3642 client_id, data); 3643 if (share_group_->bind_generates_resource()) 3644 helper_->CommandBufferHelper::Flush(); 3645 CheckGLError(); 3646 return client_id; 3647 } 3648 3649 void GLES2Implementation::PushGroupMarkerEXT( 3650 GLsizei length, const GLchar* marker) { 3651 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3652 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT(" 3653 << length << ", " << marker << ")"); 3654 if (!marker) { 3655 marker = ""; 3656 } 3657 SetBucketAsString( 3658 kResultBucketId, 3659 (length ? std::string(marker, length) : std::string(marker))); 3660 helper_->PushGroupMarkerEXT(kResultBucketId); 3661 helper_->SetBucketSize(kResultBucketId, 0); 3662 debug_marker_manager_.PushGroup( 3663 length ? std::string(marker, length) : std::string(marker)); 3664 } 3665 3666 void GLES2Implementation::InsertEventMarkerEXT( 3667 GLsizei length, const GLchar* marker) { 3668 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3669 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT(" 3670 << length << ", " << marker << ")"); 3671 if (!marker) { 3672 marker = ""; 3673 } 3674 SetBucketAsString( 3675 kResultBucketId, 3676 (length ? std::string(marker, length) : std::string(marker))); 3677 helper_->InsertEventMarkerEXT(kResultBucketId); 3678 helper_->SetBucketSize(kResultBucketId, 0); 3679 debug_marker_manager_.SetMarker( 3680 length ? std::string(marker, length) : std::string(marker)); 3681 } 3682 3683 void GLES2Implementation::PopGroupMarkerEXT() { 3684 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3685 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()"); 3686 helper_->PopGroupMarkerEXT(); 3687 debug_marker_manager_.PopGroup(); 3688 } 3689 3690 void GLES2Implementation::TraceBeginCHROMIUM(const char* name) { 3691 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3692 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM(" 3693 << name << ")"); 3694 if (current_trace_name_.get()) { 3695 SetGLError(GL_INVALID_OPERATION, "glTraceBeginCHROMIUM", 3696 "trace already running"); 3697 return; 3698 } 3699 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", name, this); 3700 SetBucketAsCString(kResultBucketId, name); 3701 helper_->TraceBeginCHROMIUM(kResultBucketId); 3702 helper_->SetBucketSize(kResultBucketId, 0); 3703 current_trace_name_.reset(new std::string(name)); 3704 } 3705 3706 void GLES2Implementation::TraceEndCHROMIUM() { 3707 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3708 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")"); 3709 if (!current_trace_name_.get()) { 3710 SetGLError(GL_INVALID_OPERATION, "glTraceEndCHROMIUM", 3711 "missing begin trace"); 3712 return; 3713 } 3714 helper_->TraceEndCHROMIUM(); 3715 TRACE_EVENT_COPY_ASYNC_END0("gpu", current_trace_name_->c_str(), this); 3716 current_trace_name_.reset(); 3717 } 3718 3719 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) { 3720 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3721 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM(" 3722 << target << ", " << GLES2Util::GetStringEnum(access) << ")"); 3723 switch (target) { 3724 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: 3725 if (access != GL_READ_ONLY) { 3726 SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode"); 3727 return NULL; 3728 } 3729 break; 3730 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: 3731 if (access != GL_WRITE_ONLY) { 3732 SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode"); 3733 return NULL; 3734 } 3735 break; 3736 default: 3737 SetGLError( 3738 GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target"); 3739 return NULL; 3740 } 3741 GLuint buffer_id; 3742 GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id); 3743 if (!buffer_id) { 3744 return NULL; 3745 } 3746 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); 3747 if (!buffer) { 3748 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer"); 3749 return NULL; 3750 } 3751 if (buffer->mapped()) { 3752 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped"); 3753 return NULL; 3754 } 3755 // Here we wait for previous transfer operations to be finished. 3756 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work 3757 // with this method of synchronization. Until this is fixed, 3758 // MapBufferCHROMIUM will not block even if the transfer is not ready 3759 // for these calls. 3760 if (buffer->last_usage_token()) { 3761 helper_->WaitForToken(buffer->last_usage_token()); 3762 buffer->set_last_usage_token(0); 3763 } 3764 buffer->set_mapped(true); 3765 3766 GPU_CLIENT_LOG(" returned " << buffer->address()); 3767 CheckGLError(); 3768 return buffer->address(); 3769 } 3770 3771 GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) { 3772 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3773 GPU_CLIENT_LOG( 3774 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target << ")"); 3775 GLuint buffer_id; 3776 if (!GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id)) { 3777 SetGLError(GL_INVALID_ENUM, "glUnmapBufferCHROMIUM", "invalid target"); 3778 } 3779 if (!buffer_id) { 3780 return false; 3781 } 3782 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); 3783 if (!buffer) { 3784 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "invalid buffer"); 3785 return false; 3786 } 3787 if (!buffer->mapped()) { 3788 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped"); 3789 return false; 3790 } 3791 buffer->set_mapped(false); 3792 CheckGLError(); 3793 return true; 3794 } 3795 3796 bool GLES2Implementation::EnsureAsyncUploadSync() { 3797 if (async_upload_sync_) 3798 return true; 3799 3800 int32 shm_id; 3801 unsigned int shm_offset; 3802 void* mem = mapped_memory_->Alloc(sizeof(AsyncUploadSync), 3803 &shm_id, 3804 &shm_offset); 3805 if (!mem) 3806 return false; 3807 3808 async_upload_sync_shm_id_ = shm_id; 3809 async_upload_sync_shm_offset_ = shm_offset; 3810 async_upload_sync_ = static_cast<AsyncUploadSync*>(mem); 3811 async_upload_sync_->Reset(); 3812 3813 return true; 3814 } 3815 3816 uint32 GLES2Implementation::NextAsyncUploadToken() { 3817 async_upload_token_++; 3818 if (async_upload_token_ == 0) 3819 async_upload_token_++; 3820 return async_upload_token_; 3821 } 3822 3823 void GLES2Implementation::PollAsyncUploads() { 3824 if (!async_upload_sync_) 3825 return; 3826 3827 if (helper_->IsContextLost()) { 3828 DetachedAsyncUploadMemoryList::iterator it = 3829 detached_async_upload_memory_.begin(); 3830 while (it != detached_async_upload_memory_.end()) { 3831 mapped_memory_->Free(it->first); 3832 it = detached_async_upload_memory_.erase(it); 3833 } 3834 return; 3835 } 3836 3837 DetachedAsyncUploadMemoryList::iterator it = 3838 detached_async_upload_memory_.begin(); 3839 while (it != detached_async_upload_memory_.end()) { 3840 if (HasAsyncUploadTokenPassed(it->second)) { 3841 mapped_memory_->Free(it->first); 3842 it = detached_async_upload_memory_.erase(it); 3843 } else { 3844 break; 3845 } 3846 } 3847 } 3848 3849 void GLES2Implementation::FreeAllAsyncUploadBuffers() { 3850 // Free all completed unmanaged async uploads buffers. 3851 PollAsyncUploads(); 3852 3853 // Synchronously free rest of the unmanaged async upload buffers. 3854 if (!detached_async_upload_memory_.empty()) { 3855 WaitAllAsyncTexImage2DCHROMIUM(); 3856 WaitForCmd(); 3857 PollAsyncUploads(); 3858 } 3859 } 3860 3861 void GLES2Implementation::AsyncTexImage2DCHROMIUM( 3862 GLenum target, GLint level, GLenum internalformat, GLsizei width, 3863 GLsizei height, GLint border, GLenum format, GLenum type, 3864 const void* pixels) { 3865 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3866 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D(" 3867 << GLES2Util::GetStringTextureTarget(target) << ", " 3868 << level << ", " 3869 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " 3870 << width << ", " << height << ", " << border << ", " 3871 << GLES2Util::GetStringTextureFormat(format) << ", " 3872 << GLES2Util::GetStringPixelType(type) << ", " 3873 << static_cast<const void*>(pixels) << ")"); 3874 if (level < 0 || height < 0 || width < 0) { 3875 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "dimension < 0"); 3876 return; 3877 } 3878 if (border != 0) { 3879 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "border != 0"); 3880 return; 3881 } 3882 uint32 size; 3883 uint32 unpadded_row_size; 3884 uint32 padded_row_size; 3885 if (!GLES2Util::ComputeImageDataSizes( 3886 width, height, format, type, unpack_alignment_, &size, 3887 &unpadded_row_size, &padded_row_size)) { 3888 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large"); 3889 return; 3890 } 3891 3892 // If there's no data/buffer just issue the AsyncTexImage2D 3893 if (!pixels && !bound_pixel_unpack_transfer_buffer_id_) { 3894 helper_->AsyncTexImage2DCHROMIUM( 3895 target, level, internalformat, width, height, format, type, 3896 0, 0, 0, 0, 0); 3897 return; 3898 } 3899 3900 if (!EnsureAsyncUploadSync()) { 3901 SetGLError(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory"); 3902 return; 3903 } 3904 3905 // Otherwise, async uploads require a transfer buffer to be bound. 3906 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use 3907 // the buffer before the transfer is finished. (Currently such 3908 // synchronization has to be handled manually.) 3909 GLuint offset = ToGLuint(pixels); 3910 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 3911 bound_pixel_unpack_transfer_buffer_id_, 3912 "glAsyncTexImage2DCHROMIUM", offset, size); 3913 if (buffer && buffer->shm_id() != -1) { 3914 uint32 async_token = NextAsyncUploadToken(); 3915 buffer->set_last_async_upload_token(async_token); 3916 helper_->AsyncTexImage2DCHROMIUM( 3917 target, level, internalformat, width, height, format, type, 3918 buffer->shm_id(), buffer->shm_offset() + offset, 3919 async_token, 3920 async_upload_sync_shm_id_, async_upload_sync_shm_offset_); 3921 } 3922 } 3923 3924 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( 3925 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, 3926 GLsizei height, GLenum format, GLenum type, const void* pixels) { 3927 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3928 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM(" 3929 << GLES2Util::GetStringTextureTarget(target) << ", " 3930 << level << ", " 3931 << xoffset << ", " << yoffset << ", " 3932 << width << ", " << height << ", " 3933 << GLES2Util::GetStringTextureFormat(format) << ", " 3934 << GLES2Util::GetStringPixelType(type) << ", " 3935 << static_cast<const void*>(pixels) << ")"); 3936 if (level < 0 || height < 0 || width < 0) { 3937 SetGLError( 3938 GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0"); 3939 return; 3940 } 3941 3942 uint32 size; 3943 uint32 unpadded_row_size; 3944 uint32 padded_row_size; 3945 if (!GLES2Util::ComputeImageDataSizes( 3946 width, height, format, type, unpack_alignment_, &size, 3947 &unpadded_row_size, &padded_row_size)) { 3948 SetGLError( 3949 GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "size to large"); 3950 return; 3951 } 3952 3953 if (!EnsureAsyncUploadSync()) { 3954 SetGLError(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory"); 3955 return; 3956 } 3957 3958 // Async uploads require a transfer buffer to be bound. 3959 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use 3960 // the buffer before the transfer is finished. (Currently such 3961 // synchronization has to be handled manually.) 3962 GLuint offset = ToGLuint(pixels); 3963 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 3964 bound_pixel_unpack_transfer_buffer_id_, 3965 "glAsyncTexSubImage2DCHROMIUM", offset, size); 3966 if (buffer && buffer->shm_id() != -1) { 3967 uint32 async_token = NextAsyncUploadToken(); 3968 buffer->set_last_async_upload_token(async_token); 3969 helper_->AsyncTexSubImage2DCHROMIUM( 3970 target, level, xoffset, yoffset, width, height, format, type, 3971 buffer->shm_id(), buffer->shm_offset() + offset, 3972 async_token, 3973 async_upload_sync_shm_id_, async_upload_sync_shm_offset_); 3974 } 3975 } 3976 3977 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) { 3978 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3979 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM(" 3980 << GLES2Util::GetStringTextureTarget(target) << ")"); 3981 helper_->WaitAsyncTexImage2DCHROMIUM(target); 3982 CheckGLError(); 3983 } 3984 3985 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() { 3986 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3987 GPU_CLIENT_LOG("[" << GetLogPrefix() 3988 << "] glWaitAllAsyncTexImage2DCHROMIUM()"); 3989 helper_->WaitAllAsyncTexImage2DCHROMIUM(); 3990 CheckGLError(); 3991 } 3992 3993 GLuint GLES2Implementation::InsertSyncPointCHROMIUM() { 3994 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3995 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM"); 3996 helper_->CommandBufferHelper::Flush(); 3997 return gpu_control_->InsertSyncPoint(); 3998 } 3999 4000 GLuint GLES2Implementation::InsertFutureSyncPointCHROMIUM() { 4001 GPU_CLIENT_SINGLE_THREAD_CHECK(); 4002 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM"); 4003 DCHECK(capabilities_.future_sync_points); 4004 helper_->CommandBufferHelper::Flush(); 4005 return gpu_control_->InsertFutureSyncPoint(); 4006 } 4007 4008 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point) { 4009 GPU_CLIENT_SINGLE_THREAD_CHECK(); 4010 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM(" 4011 << sync_point << ")"); 4012 DCHECK(capabilities_.future_sync_points); 4013 helper_->CommandBufferHelper::Flush(); 4014 gpu_control_->RetireSyncPoint(sync_point); 4015 } 4016 4017 GLuint GLES2Implementation::CreateImageCHROMIUMHelper(GLsizei width, 4018 GLsizei height, 4019 GLenum internalformat, 4020 GLenum usage) { 4021 if (width <= 0) { 4022 SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "width <= 0"); 4023 return 0; 4024 } 4025 4026 if (height <= 0) { 4027 SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "height <= 0"); 4028 return 0; 4029 } 4030 // Flush the command stream to ensure ordering in case the newly 4031 // returned image_id has recently been in use with a different buffer. 4032 helper_->CommandBufferHelper::Flush(); 4033 4034 // Create new buffer. 4035 GLuint buffer_id = gpu_memory_buffer_tracker_->CreateBuffer( 4036 width, height, internalformat, usage); 4037 if (buffer_id == 0) { 4038 SetGLError(GL_OUT_OF_MEMORY, "glCreateImageCHROMIUM", "out of GPU memory."); 4039 return 0; 4040 } 4041 return buffer_id; 4042 } 4043 4044 GLuint GLES2Implementation::CreateImageCHROMIUM(GLsizei width, 4045 GLsizei height, 4046 GLenum internalformat, 4047 GLenum usage) { 4048 GPU_CLIENT_SINGLE_THREAD_CHECK(); 4049 GPU_CLIENT_LOG( 4050 "[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width << ", " 4051 << height << ", " 4052 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " 4053 << GLES2Util::GetStringTextureInternalFormat(usage) << ")"); 4054 GLuint image_id = 4055 CreateImageCHROMIUMHelper(width, height, internalformat, usage); 4056 CheckGLError(); 4057 return image_id; 4058 } 4059 4060 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id) { 4061 gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer( 4062 image_id); 4063 if (!gpu_buffer) { 4064 SetGLError(GL_INVALID_OPERATION, "glDestroyImageCHROMIUM", "invalid image"); 4065 return; 4066 } 4067 4068 // Flush the command stream to make sure all pending commands 4069 // that may refer to the image_id are executed on the service side. 4070 helper_->CommandBufferHelper::Flush(); 4071 gpu_memory_buffer_tracker_->RemoveBuffer(image_id); 4072 } 4073 4074 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id) { 4075 GPU_CLIENT_SINGLE_THREAD_CHECK(); 4076 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM(" 4077 << image_id << ")"); 4078 DestroyImageCHROMIUMHelper(image_id); 4079 CheckGLError(); 4080 } 4081 4082 void GLES2Implementation::UnmapImageCHROMIUMHelper(GLuint image_id) { 4083 gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer( 4084 image_id); 4085 if (!gpu_buffer) { 4086 SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "invalid image"); 4087 return; 4088 } 4089 4090 if (!gpu_buffer->IsMapped()) { 4091 SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "not mapped"); 4092 return; 4093 } 4094 gpu_buffer->Unmap(); 4095 } 4096 4097 void GLES2Implementation::UnmapImageCHROMIUM(GLuint image_id) { 4098 GPU_CLIENT_SINGLE_THREAD_CHECK(); 4099 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapImageCHROMIUM(" 4100 << image_id << ")"); 4101 4102 UnmapImageCHROMIUMHelper(image_id); 4103 CheckGLError(); 4104 } 4105 4106 void* GLES2Implementation::MapImageCHROMIUMHelper(GLuint image_id) { 4107 gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer( 4108 image_id); 4109 if (!gpu_buffer) { 4110 SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "invalid image"); 4111 return NULL; 4112 } 4113 4114 if (gpu_buffer->IsMapped()) { 4115 SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "already mapped"); 4116 return NULL; 4117 } 4118 4119 return gpu_buffer->Map(); 4120 } 4121 4122 void* GLES2Implementation::MapImageCHROMIUM(GLuint image_id) { 4123 GPU_CLIENT_SINGLE_THREAD_CHECK(); 4124 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM(" << image_id 4125 << ")"); 4126 4127 void* mapped = MapImageCHROMIUMHelper(image_id); 4128 CheckGLError(); 4129 return mapped; 4130 } 4131 4132 void GLES2Implementation::GetImageParameterivCHROMIUMHelper( 4133 GLuint image_id, GLenum pname, GLint* params) { 4134 if (pname != GL_IMAGE_ROWBYTES_CHROMIUM) { 4135 SetGLError(GL_INVALID_ENUM, "glGetImageParameterivCHROMIUM", 4136 "invalid parameter"); 4137 return; 4138 } 4139 4140 gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer( 4141 image_id); 4142 if (!gpu_buffer) { 4143 SetGLError(GL_INVALID_OPERATION, "glGetImageParameterivCHROMIUM", 4144 "invalid image"); 4145 return; 4146 } 4147 4148 if (!gpu_buffer->IsMapped()) { 4149 SetGLError( 4150 GL_INVALID_OPERATION, "glGetImageParameterivCHROMIUM", "not mapped"); 4151 return; 4152 } 4153 4154 *params = gpu_buffer->GetStride(); 4155 } 4156 4157 void GLES2Implementation::GetImageParameterivCHROMIUM( 4158 GLuint image_id, GLenum pname, GLint* params) { 4159 GPU_CLIENT_SINGLE_THREAD_CHECK(); 4160 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params); 4161 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glImageParameterivCHROMIUM(" 4162 << image_id << ", " 4163 << GLES2Util::GetStringBufferParameter(pname) << ", " 4164 << static_cast<const void*>(params) << ")"); 4165 GetImageParameterivCHROMIUMHelper(image_id, pname, params); 4166 CheckGLError(); 4167 } 4168 4169 bool GLES2Implementation::ValidateSize(const char* func, GLsizeiptr size) { 4170 if (size < 0) { 4171 SetGLError(GL_INVALID_VALUE, func, "size < 0"); 4172 return false; 4173 } 4174 if (!FitInt32NonNegative<GLsizeiptr>(size)) { 4175 SetGLError(GL_INVALID_OPERATION, func, "size more than 32-bit"); 4176 return false; 4177 } 4178 return true; 4179 } 4180 4181 bool GLES2Implementation::ValidateOffset(const char* func, GLintptr offset) { 4182 if (offset < 0) { 4183 SetGLError(GL_INVALID_VALUE, func, "offset < 0"); 4184 return false; 4185 } 4186 if (!FitInt32NonNegative<GLintptr>(offset)) { 4187 SetGLError(GL_INVALID_OPERATION, func, "offset more than 32-bit"); 4188 return false; 4189 } 4190 return true; 4191 } 4192 4193 // Include the auto-generated part of this file. We split this because it means 4194 // we can easily edit the non-auto generated parts right here in this file 4195 // instead of having to edit some template or the code generator. 4196 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" 4197 4198 } // namespace gles2 4199 } // namespace gpu 4200