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