diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/gpu/command_buffer/service | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/gpu/command_buffer/service')
134 files changed, 19418 insertions, 15578 deletions
diff --git a/chromium/gpu/command_buffer/service/BUILD.gn b/chromium/gpu/command_buffer/service/BUILD.gn new file mode 100644 index 00000000000..c9f8f57e9dc --- /dev/null +++ b/chromium/gpu/command_buffer/service/BUILD.gn @@ -0,0 +1,155 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ui.gni") +import("//third_party/protobuf/proto_library.gni") + +source_set("service") { + sources = [ + "async_pixel_transfer_delegate.cc", + "async_pixel_transfer_delegate.h", + "async_pixel_transfer_manager_android.cc", + "async_pixel_transfer_manager_idle.cc", + "async_pixel_transfer_manager_idle.h", + "async_pixel_transfer_manager_linux.cc", + "async_pixel_transfer_manager_mac.cc", + "async_pixel_transfer_manager_share_group.cc", + "async_pixel_transfer_manager_share_group.h", + "async_pixel_transfer_manager_stub.cc", + "async_pixel_transfer_manager_stub.h", + "async_pixel_transfer_manager_sync.cc", + "async_pixel_transfer_manager_sync.h", + "async_pixel_transfer_manager_win.cc", + "async_pixel_transfer_manager.cc", + "async_pixel_transfer_manager.h", + "buffer_manager.h", + "buffer_manager.cc", + "cmd_buffer_engine.h", + "cmd_parser.cc", + "cmd_parser.h", + "command_buffer_service.cc", + "command_buffer_service.h", + "common_decoder.cc", + "common_decoder.h", + "context_group.h", + "context_group.cc", + "context_state.h", + "context_state_autogen.h", + "context_state_impl_autogen.h", + "context_state.cc", + "error_state.cc", + "error_state.h", + "feature_info.h", + "feature_info.cc", + "framebuffer_manager.h", + "framebuffer_manager.cc", + "gles2_cmd_copy_texture_chromium.cc", + "gles2_cmd_copy_texture_chromium.h", + "gles2_cmd_decoder.h", + "gles2_cmd_decoder_autogen.h", + "gles2_cmd_decoder.cc", + "gles2_cmd_validation.h", + "gles2_cmd_validation.cc", + "gles2_cmd_validation_autogen.h", + "gles2_cmd_validation_implementation_autogen.h", + "gl_context_virtual.cc", + "gl_context_virtual.h", + "gl_state_restorer_impl.cc", + "gl_state_restorer_impl.h", + "gl_utils.h", + "gpu_control_service.cc", + "gpu_control_service.h", + "gpu_memory_buffer_manager.h", + "gpu_scheduler.cc", + "gpu_scheduler.h", + "gpu_scheduler_mock.h", + "gpu_state_tracer.cc", + "gpu_state_tracer.h", + "gpu_switches.cc", + "gpu_switches.h", + "gpu_tracer.cc", + "gpu_tracer.h", + "id_manager.h", + "id_manager.cc", + "image_manager.cc", + "image_manager.h", + "in_process_command_buffer.cc", + "in_process_command_buffer.h", + "logger.cc", + "logger.h", + "mailbox_manager.cc", + "mailbox_manager.h", + "mailbox_synchronizer.cc", + "mailbox_synchronizer.h", + "memory_program_cache.h", + "memory_program_cache.cc", + "mocks.h", + "program_manager.h", + "program_manager.cc", + "query_manager.h", + "query_manager.cc", + "renderbuffer_manager.h", + "renderbuffer_manager.cc", + "program_cache.h", + "program_cache.cc", + "shader_manager.h", + "shader_manager.cc", + "shader_translator.h", + "shader_translator.cc", + "shader_translator_cache.h", + "shader_translator_cache.cc", + "stream_texture_manager_in_process_android.h", + "stream_texture_manager_in_process_android.cc", + "texture_definition.h", + "texture_definition.cc", + "texture_manager.h", + "texture_manager.cc", + "transfer_buffer_manager.cc", + "transfer_buffer_manager.h", + "vertex_array_manager.h", + "vertex_array_manager.cc", + "vertex_attrib_manager.h", + "vertex_attrib_manager.cc", + ] + + configs += [ + "//third_party/khronos:khronos_headers", + ] + + deps = [ + ":disk_cache_proto", + "//base", + "//base/third_party/dynamic_annotations", + "//crypto", + "//gpu/command_buffer/common", + "//third_party/angle:translator", + "//third_party/protobuf:protobuf_lite", + "//third_party/re2", + "//third_party/smhasher:cityhash", + "//ui/gfx", + "//ui/gfx/geometry", + "//ui/gl", + ] + + if (ui_compositor_image_transport) { + include_dirs = [ "//third_party/khronos" ] + } + + if (is_win || is_android || (is_linux && use_x11)) { + sources += [ + "async_pixel_transfer_manager_egl.cc", + "async_pixel_transfer_manager_egl.h", + ] + } + + if (is_android && !is_debug) { + # On Android optimize more since this component can be a bottleneck. + configs -= [ "//build/config/compiler:optimize" ] + configs += [ "//build/config/compiler:optimize_max" ] + } +} + +proto_library("disk_cache_proto") { + sources = [ "disk_cache_proto.proto" ] +} diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.cc index 074f6752dd8..6b1dbc6eb3b 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.cc @@ -4,26 +4,18 @@ #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" -#include "base/memory/shared_memory.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" - namespace gpu { -namespace { - -void* GetAddressImpl(base::SharedMemory* shared_memory, - uint32 shm_size, - uint32 shm_data_offset, - uint32 shm_data_size) { - // Memory bounds have already been validated, so there - // are just DCHECKS here. - DCHECK(shared_memory); - DCHECK(shared_memory->memory()); - DCHECK_LE(shm_data_offset + shm_data_size, shm_size); - return static_cast<int8*>(shared_memory->memory()) + shm_data_offset; +AsyncMemoryParams::AsyncMemoryParams(scoped_refptr<Buffer> buffer, + uint32 data_offset, + uint32 data_size) + : buffer_(buffer), data_offset_(data_offset), data_size_(data_size) { + DCHECK(buffer_); + DCHECK(buffer_->memory()); } -} // namespace +AsyncMemoryParams::~AsyncMemoryParams() { +} AsyncPixelTransferUploadStats::AsyncPixelTransferUploadStats() : texture_upload_count_(0) {} @@ -44,27 +36,8 @@ int AsyncPixelTransferUploadStats::GetStats( return texture_upload_count_; } -AsyncPixelTransferDelegate::AsyncPixelTransferDelegate(){} - -AsyncPixelTransferDelegate::~AsyncPixelTransferDelegate(){} +AsyncPixelTransferDelegate::AsyncPixelTransferDelegate() {} -// static -void* AsyncPixelTransferDelegate::GetAddress( - const AsyncMemoryParams& mem_params) { - return GetAddressImpl(mem_params.shared_memory, - mem_params.shm_size, - mem_params.shm_data_offset, - mem_params.shm_data_size); -} - -// static -void* AsyncPixelTransferDelegate::GetAddress( - ScopedSafeSharedMemory* safe_shared_memory, - const AsyncMemoryParams& mem_params) { - return GetAddressImpl(safe_shared_memory->shared_memory(), - mem_params.shm_size, - mem_params.shm_data_offset, - mem_params.shm_data_size); -} +AsyncPixelTransferDelegate::~AsyncPixelTransferDelegate() {} } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.h index dc0f2d7b62f..b41bcd52444 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_delegate.h @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/time/time.h" +#include "gpu/command_buffer/common/buffer.h" #include "gpu/gpu_export.h" #include "ui/gl/gl_bindings.h" @@ -20,8 +21,6 @@ class SharedMemory; namespace gpu { -class ScopedSafeSharedMemory; - struct AsyncTexImage2DParams { GLenum target; GLint level; @@ -44,11 +43,24 @@ struct AsyncTexSubImage2DParams { GLenum type; }; -struct AsyncMemoryParams { - base::SharedMemory* shared_memory; - uint32 shm_size; - uint32 shm_data_offset; - uint32 shm_data_size; +class AsyncMemoryParams { + public: + AsyncMemoryParams(scoped_refptr<Buffer> buffer, + uint32 data_offset, + uint32 data_size); + ~AsyncMemoryParams(); + + scoped_refptr<Buffer> buffer() const { return buffer_; } + uint32 data_size() const { return data_size_; } + uint32 data_offset() const { return data_offset_; } + void* GetDataAddress() const { + return buffer_->GetDataAddress(data_offset_, data_size_); + } + + private: + scoped_refptr<Buffer> buffer_; + uint32 data_offset_; + uint32 data_size_; }; class AsyncPixelTransferUploadStats @@ -92,13 +104,6 @@ class GPU_EXPORT AsyncPixelTransferDelegate { // Block until the specified transfer completes. virtual void WaitForTransferCompletion() = 0; - // Gets the address of the data from shared memory. - static void* GetAddress(const AsyncMemoryParams& mem_params); - - // Sometimes the |safe_shared_memory| is duplicate to prevent use after free. - static void* GetAddress(ScopedSafeSharedMemory* safe_shared_memory, - const AsyncMemoryParams& mem_params); - protected: AsyncPixelTransferDelegate(); diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.cc index 3084dd61964..efc893a40ca 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.cc @@ -17,6 +17,12 @@ AsyncPixelTransferManager::AsyncPixelTransferManager() {} AsyncPixelTransferManager::~AsyncPixelTransferManager() { if (manager_) manager_->RemoveObserver(this); + + for (TextureToDelegateMap::iterator ref = delegate_map_.begin(); + ref != delegate_map_.end(); + ref++) { + ref->first->RemoveObserver(); + } } void AsyncPixelTransferManager::Initialize(gles2::TextureManager* manager) { @@ -32,6 +38,7 @@ AsyncPixelTransferManager::CreatePixelTransferDelegate( AsyncPixelTransferDelegate* delegate = CreatePixelTransferDelegateImpl(ref, define_params); delegate_map_[ref] = make_linked_ptr(delegate); + ref->AddObserver(); return delegate; } @@ -49,8 +56,10 @@ AsyncPixelTransferManager::GetPixelTransferDelegate( void AsyncPixelTransferManager::ClearPixelTransferDelegateForTest( gles2::TextureRef* ref) { TextureToDelegateMap::iterator it = delegate_map_.find(ref); - if (it != delegate_map_.end()) + if (it != delegate_map_.end()) { delegate_map_.erase(it); + ref->RemoveObserver(); + } } bool AsyncPixelTransferManager::AsyncTransferIsInProgress( @@ -69,8 +78,10 @@ void AsyncPixelTransferManager::OnTextureManagerDestroying( void AsyncPixelTransferManager::OnTextureRefDestroying( gles2::TextureRef* texture) { TextureToDelegateMap::iterator it = delegate_map_.find(texture); - if (it != delegate_map_.end()) + if (it != delegate_map_.end()) { delegate_map_.erase(it); + texture->RemoveObserver(); + } } } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.h index d0ea5da153c..1a818f3c1ad 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager.h @@ -32,7 +32,7 @@ class GLContext; namespace gpu { class AsyncPixelTransferDelegate; -struct AsyncMemoryParams; +class AsyncMemoryParams; struct AsyncTexImage2DParams; class AsyncPixelTransferCompletionObserver @@ -78,6 +78,9 @@ class GPU_EXPORT AsyncPixelTransferManager virtual void ProcessMorePendingTransfers() = 0; virtual bool NeedsProcessMorePendingTransfers() = 0; + // Wait for all AsyncTex(Sub)Image2D uploads to finish before returning. + virtual void WaitAllAsyncTexImage2D() = 0; + AsyncPixelTransferDelegate* CreatePixelTransferDelegate( gles2::TextureRef* ref, const AsyncTexImage2DParams& define_params); diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc index 5aaabf4ea8a..a2b22552a46 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc @@ -30,6 +30,14 @@ bool IsImagination() { return false; } +bool IsNvidia31() { + const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); + const char* version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); + return vendor && version && + std::string(vendor).find("NVIDIA") != std::string::npos && + std::string(version).find("OpenGL ES 3.1") != std::string::npos; +} + } // We only used threaded uploads when we can: @@ -54,10 +62,12 @@ AsyncPixelTransferManager* AsyncPixelTransferManager::Create( context->HasExtension("GL_OES_EGL_image") && !IsBroadcom() && !IsImagination() && + !IsNvidia31() && !base::android::SysUtils::IsLowEndDevice()) { return new AsyncPixelTransferManagerEGL; } - LOG(INFO) << "Async pixel transfers not supported"; + return new AsyncPixelTransferManagerIdle; + case gfx::kGLImplementationOSMesaGL: return new AsyncPixelTransferManagerIdle; case gfx::kGLImplementationMockGL: return new AsyncPixelTransferManagerStub; diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc index 7e0d515e49c..2bbe76b3371 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc @@ -9,13 +9,13 @@ #include "base/bind.h" #include "base/debug/trace_event.h" +#include "base/debug/trace_event_synthetic_delay.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_surface_egl.h" #include "ui/gl/scoped_binders.h" @@ -80,12 +80,9 @@ void SetGlParametersForEglImageTexture() { void PerformNotifyCompletion( AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { TRACE_EVENT0("gpu", "PerformNotifyCompletion"); - AsyncMemoryParams safe_mem_params = mem_params; - safe_mem_params.shared_memory = safe_shared_memory->shared_memory(); - observer->DidComplete(safe_mem_params); + observer->DidComplete(mem_params); } class TransferThread : public base::Thread { @@ -116,16 +113,10 @@ class TransferThread : public base::Thread { context_ = NULL; } - SafeSharedMemoryPool* safe_shared_memory_pool() { - return &safe_shared_memory_pool_; - } - private: scoped_refptr<gfx::GLContext> context_; scoped_refptr<gfx::GLSurface> surface_; - SafeSharedMemoryPool safe_shared_memory_pool_; - DISALLOW_COPY_AND_ASSIGN(TransferThread); }; @@ -136,10 +127,6 @@ base::MessageLoopProxy* transfer_message_loop_proxy() { return g_transfer_thread.Pointer()->message_loop_proxy().get(); } -SafeSharedMemoryPool* safe_shared_memory_pool() { - return g_transfer_thread.Pointer()->safe_shared_memory_pool(); -} - // Class which holds async pixel transfers state (EGLImage). // The EGLImage is accessed by either thread, but everything // else accessed only on the main thread. @@ -234,10 +221,12 @@ class TransferStateInternal } void MarkAsTransferIsInProgress() { + TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); transfer_completion_.Reset(); } void MarkAsCompleted() { + TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); transfer_completion_.Signal(); } @@ -251,7 +240,6 @@ class TransferStateInternal void PerformAsyncTexImage2D( AsyncTexImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexImage", @@ -266,8 +254,7 @@ class TransferStateInternal return; } - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time; if (texture_upload_stats.get()) @@ -314,7 +301,6 @@ class TransferStateInternal void PerformAsyncTexSubImage2D( AsyncTexSubImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", @@ -326,8 +312,7 @@ class TransferStateInternal DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); DCHECK_EQ(0, tex_params.level); - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time; if (texture_upload_stats.get()) @@ -506,9 +491,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexImage2D( if (WorkAroundAsyncTexImage2D(tex_params, mem_params, bind_callback)) return; - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK(!state_->TransferIsInProgress()); DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); @@ -530,9 +512,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexImage2D( state_, tex_params, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), shared_state_->texture_upload_stats)); DCHECK(CHECK_GL()); @@ -547,9 +526,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params)) return; DCHECK(!state_->TransferIsInProgress()); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); DCHECK_EQ(tex_params.level, 0); @@ -568,9 +544,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( state_, tex_params, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), shared_state_->texture_upload_stats)); DCHECK(CHECK_GL()); @@ -618,7 +591,7 @@ bool AsyncPixelTransferDelegateEGL::WorkAroundAsyncTexImage2D( // On imagination we allocate synchronously all the time, even // if the dimensions support fast uploads. This is for part a.) // above, so allocations occur on a different thread/context as uploads. - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); SetGlParametersForEglImageTexture(); { @@ -669,7 +642,7 @@ bool AsyncPixelTransferDelegateEGL::WorkAroundAsyncTexSubImage2D( DCHECK_EQ(state_->define_params_.format, tex_params.format); DCHECK_EQ(state_->define_params_.type, tex_params.type); - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time; if (shared_state_->texture_upload_stats.get()) begin_time = base::TimeTicks::HighResNow(); @@ -730,19 +703,12 @@ void AsyncPixelTransferManagerEGL::BindCompletedAsyncTransfers() { void AsyncPixelTransferManagerEGL::AsyncNotifyCompletion( const AsyncMemoryParams& mem_params, AsyncPixelTransferCompletionObserver* observer) { - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); // Post a PerformNotifyCompletion task to the upload thread. This task // will run after all async transfers are complete. transfer_message_loop_proxy()->PostTask( FROM_HERE, base::Bind(&PerformNotifyCompletion, mem_params, - base::Owned( - new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), make_scoped_refptr(observer))); } @@ -763,6 +729,16 @@ bool AsyncPixelTransferManagerEGL::NeedsProcessMorePendingTransfers() { return false; } +void AsyncPixelTransferManagerEGL::WaitAllAsyncTexImage2D() { + if (shared_state_.pending_allocations.empty()) + return; + + AsyncPixelTransferDelegateEGL* delegate = + shared_state_.pending_allocations.back().get(); + if (delegate) + delegate->WaitForTransferCompletion(); +} + AsyncPixelTransferDelegate* AsyncPixelTransferManagerEGL::CreatePixelTransferDelegateImpl( gles2::TextureRef* ref, diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.h index 4c273fe7f52..8f0c4b3d7ec 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.h @@ -27,6 +27,7 @@ class AsyncPixelTransferManagerEGL : public AsyncPixelTransferManager { virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; virtual void ProcessMorePendingTransfers() OVERRIDE; virtual bool NeedsProcessMorePendingTransfers() OVERRIDE; + virtual void WaitAllAsyncTexImage2D() OVERRIDE; // State shared between Managers and Delegates. struct SharedState { diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc index 88aff575b08..40ec87f6896 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc @@ -6,32 +6,22 @@ #include "base/bind.h" #include "base/debug/trace_event.h" +#include "base/debug/trace_event_synthetic_delay.h" #include "base/lazy_instance.h" #include "base/memory/weak_ptr.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" #include "ui/gl/scoped_binders.h" namespace gpu { namespace { -base::LazyInstance<SafeSharedMemoryPool> g_safe_shared_memory_pool = - LAZY_INSTANCE_INITIALIZER; - -SafeSharedMemoryPool* safe_shared_memory_pool() { - return g_safe_shared_memory_pool.Pointer(); -} - static uint64 g_next_pixel_transfer_state_id = 1; void PerformNotifyCompletion( AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { TRACE_EVENT0("gpu", "PerformNotifyCompletion"); - AsyncMemoryParams safe_mem_params = mem_params; - safe_mem_params.shared_memory = safe_shared_memory->shared_memory(); - observer->DidComplete(safe_mem_params); + observer->DidComplete(mem_params); } } // namespace @@ -60,15 +50,11 @@ class AsyncPixelTransferDelegateIdle virtual void WaitForTransferCompletion() OVERRIDE; private: - void PerformAsyncTexImage2D( - AsyncTexImage2DParams tex_params, - AsyncMemoryParams mem_params, - const base::Closure& bind_callback, - ScopedSafeSharedMemory* safe_shared_memory); - void PerformAsyncTexSubImage2D( - AsyncTexSubImage2DParams tex_params, - AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory); + void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params, + AsyncMemoryParams mem_params, + const base::Closure& bind_callback); + void PerformAsyncTexSubImage2D(AsyncTexSubImage2DParams tex_params, + AsyncMemoryParams mem_params); uint64 id_; GLuint texture_id_; @@ -98,22 +84,17 @@ void AsyncPixelTransferDelegateIdle::AsyncTexImage2D( const AsyncTexImage2DParams& tex_params, const AsyncMemoryParams& mem_params, const base::Closure& bind_callback) { + TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task( id_, - base::Bind( - &AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D, - AsWeakPtr(), - tex_params, - mem_params, - bind_callback, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size))))); + this, + base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D, + AsWeakPtr(), + tex_params, + mem_params, + bind_callback))); transfer_in_progress_ = true; } @@ -121,21 +102,16 @@ void AsyncPixelTransferDelegateIdle::AsyncTexImage2D( void AsyncPixelTransferDelegateIdle::AsyncTexSubImage2D( const AsyncTexSubImage2DParams& tex_params, const AsyncMemoryParams& mem_params) { + TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task( id_, - base::Bind( - &AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D, - AsWeakPtr(), - tex_params, - mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size))))); + this, + base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D, + AsWeakPtr(), + tex_params, + mem_params))); transfer_in_progress_ = true; } @@ -163,13 +139,12 @@ void AsyncPixelTransferDelegateIdle::WaitForTransferCompletion() { void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D( AsyncTexImage2DParams tex_params, AsyncMemoryParams mem_params, - const base::Closure& bind_callback, - ScopedSafeSharedMemory* safe_shared_memory) { + const base::Closure& bind_callback) { TRACE_EVENT2("gpu", "PerformAsyncTexImage2D", "width", tex_params.width, "height", tex_params.height); - void* data = GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); @@ -188,6 +163,7 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D( data); } + TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); transfer_in_progress_ = false; shared_state_->texture_upload_count++; shared_state_->total_texture_upload_time += @@ -199,13 +175,12 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D( void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D( AsyncTexSubImage2DParams tex_params, - AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory) { + AsyncMemoryParams mem_params) { TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", "width", tex_params.width, "height", tex_params.height); - void* data = GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); @@ -243,6 +218,7 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D( data); } + TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); transfer_in_progress_ = false; shared_state_->texture_upload_count++; shared_state_->total_texture_upload_time += @@ -250,8 +226,11 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D( } AsyncPixelTransferManagerIdle::Task::Task( - uint64 transfer_id, const base::Closure& task) + uint64 transfer_id, + AsyncPixelTransferDelegate* delegate, + const base::Closure& task) : transfer_id(transfer_id), + delegate(delegate), task(task) { } @@ -293,12 +272,10 @@ void AsyncPixelTransferManagerIdle::AsyncNotifyCompletion( shared_state_.tasks.push_back( Task(0, // 0 transfer_id for notification tasks. + NULL, base::Bind( &PerformNotifyCompletion, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), make_scoped_refptr(observer)))); } @@ -326,6 +303,15 @@ bool AsyncPixelTransferManagerIdle::NeedsProcessMorePendingTransfers() { return !shared_state_.tasks.empty(); } +void AsyncPixelTransferManagerIdle::WaitAllAsyncTexImage2D() { + if (shared_state_.tasks.empty()) + return; + + const Task& task = shared_state_.tasks.back(); + if (task.delegate) + task.delegate->WaitForTransferCompletion(); +} + AsyncPixelTransferDelegate* AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl( gles2::TextureRef* ref, diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h index e7f990e317a..af3262f2889 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h @@ -25,14 +25,19 @@ class AsyncPixelTransferManagerIdle : public AsyncPixelTransferManager { virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; virtual void ProcessMorePendingTransfers() OVERRIDE; virtual bool NeedsProcessMorePendingTransfers() OVERRIDE; + virtual void WaitAllAsyncTexImage2D() OVERRIDE; struct Task { - Task(uint64 transfer_id, const base::Closure& task); + Task(uint64 transfer_id, + AsyncPixelTransferDelegate* delegate, + const base::Closure& task); ~Task(); // This is non-zero if pixel transfer task. uint64 transfer_id; + AsyncPixelTransferDelegate* delegate; + base::Closure task; }; diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_mock.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_mock.h index adc2a6f939e..3bc8b6bd036 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_mock.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_mock.h @@ -24,6 +24,7 @@ class MockAsyncPixelTransferManager : public AsyncPixelTransferManager { MOCK_METHOD0(GetTotalTextureUploadTime, base::TimeDelta()); MOCK_METHOD0(ProcessMorePendingTransfers, void()); MOCK_METHOD0(NeedsProcessMorePendingTransfers, bool()); + MOCK_METHOD0(WaitAllAsyncTexImage2D, void()); MOCK_METHOD2( CreatePixelTransferDelegateImpl, AsyncPixelTransferDelegate*(gles2::TextureRef* ref, diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc index f71e07e76ee..99103b81c65 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/debug/trace_event.h" +#include "base/debug/trace_event_synthetic_delay.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/ref_counted.h" @@ -18,7 +19,6 @@ #include "base/threading/thread.h" #include "base/threading/thread_checker.h" #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_surface.h" @@ -33,12 +33,9 @@ const char kAsyncTransferThreadName[] = "AsyncTransferThread"; void PerformNotifyCompletion( AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { TRACE_EVENT0("gpu", "PerformNotifyCompletion"); - AsyncMemoryParams safe_mem_params = mem_params; - safe_mem_params.shared_memory = safe_shared_memory->shared_memory(); - observer->DidComplete(safe_mem_params); + observer->DidComplete(mem_params); } // TODO(backer): Factor out common thread scheduling logic from the EGL and @@ -79,16 +76,11 @@ class TransferThread : public base::Thread { context_ = NULL; } - SafeSharedMemoryPool* safe_shared_memory_pool() { - return &safe_shared_memory_pool_; - } - private: bool initialized_; scoped_refptr<gfx::GLSurface> surface_; scoped_refptr<gfx::GLContext> context_; - SafeSharedMemoryPool safe_shared_memory_pool_; void InitializeOnTransferThread(gfx::GLContext* parent_context, base::WaitableEvent* caller_wait) { @@ -135,10 +127,6 @@ base::MessageLoopProxy* transfer_message_loop_proxy() { return g_transfer_thread.Pointer()->message_loop_proxy().get(); } -SafeSharedMemoryPool* safe_shared_memory_pool() { - return g_transfer_thread.Pointer()->safe_shared_memory_pool(); -} - class PendingTask : public base::RefCountedThreadSafe<PendingTask> { public: explicit PendingTask(const base::Closure& task) @@ -251,16 +239,12 @@ class TransferStateInternal const AsyncMemoryParams mem_params, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats, const base::Closure& bind_callback) { + TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); pending_upload_task_ = new PendingTask(base::Bind( &TransferStateInternal::PerformAsyncTexImage2D, this, tex_params, mem_params, - // Duplicate the shared memory so there is no way we can get - // a use-after-free of the raw pixels. - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), texture_upload_stats)); transfer_message_loop_proxy()->PostTask( FROM_HERE, @@ -276,14 +260,12 @@ class TransferStateInternal AsyncTexSubImage2DParams tex_params, AsyncMemoryParams mem_params, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { + TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); pending_upload_task_ = new PendingTask(base::Bind( &TransferStateInternal::PerformAsyncTexSubImage2D, this, tex_params, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), texture_upload_stats)); transfer_message_loop_proxy()->PostTask( FROM_HERE, @@ -300,7 +282,6 @@ class TransferStateInternal void PerformAsyncTexImage2D( AsyncTexImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexImage", @@ -314,8 +295,7 @@ class TransferStateInternal if (texture_upload_stats.get()) begin_time = base::TimeTicks::HighResNow(); - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); { TRACE_EVENT0("gpu", "glTexImage2D"); @@ -328,6 +308,7 @@ class TransferStateInternal tex_params.format, tex_params.type, data); + TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); } if (texture_upload_stats.get()) { @@ -339,7 +320,6 @@ class TransferStateInternal void PerformAsyncTexSubImage2D( AsyncTexSubImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", @@ -353,9 +333,7 @@ class TransferStateInternal if (texture_upload_stats.get()) begin_time = base::TimeTicks::HighResNow(); - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); - + void* data = mem_params.GetDataAddress(); { TRACE_EVENT0("gpu", "glTexSubImage2D"); glTexSubImage2D(GL_TEXTURE_2D, @@ -367,6 +345,7 @@ class TransferStateInternal tex_params.format, tex_params.type, data); + TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); } if (texture_upload_stats.get()) { @@ -462,9 +441,6 @@ void AsyncPixelTransferDelegateShareGroup::AsyncTexImage2D( const AsyncTexImage2DParams& tex_params, const AsyncMemoryParams& mem_params, const base::Closure& bind_callback) { - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK(!state_->TransferIsInProgress()); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); DCHECK_EQ(tex_params.level, 0); @@ -483,9 +459,6 @@ void AsyncPixelTransferDelegateShareGroup::AsyncTexSubImage2D( "width", tex_params.width, "height", tex_params.height); DCHECK(!state_->TransferIsInProgress()); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); DCHECK_EQ(tex_params.level, 0); @@ -534,19 +507,12 @@ void AsyncPixelTransferManagerShareGroup::BindCompletedAsyncTransfers() { void AsyncPixelTransferManagerShareGroup::AsyncNotifyCompletion( const AsyncMemoryParams& mem_params, AsyncPixelTransferCompletionObserver* observer) { - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); // Post a PerformNotifyCompletion task to the upload thread. This task // will run after all async transfers are complete. transfer_message_loop_proxy()->PostTask( FROM_HERE, base::Bind(&PerformNotifyCompletion, mem_params, - base::Owned( - new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), make_scoped_refptr(observer))); } @@ -568,6 +534,16 @@ bool AsyncPixelTransferManagerShareGroup::NeedsProcessMorePendingTransfers() { return false; } +void AsyncPixelTransferManagerShareGroup::WaitAllAsyncTexImage2D() { + if (shared_state_.pending_allocations.empty()) + return; + + AsyncPixelTransferDelegateShareGroup* delegate = + shared_state_.pending_allocations.back().get(); + if (delegate) + delegate->WaitForTransferCompletion(); +} + AsyncPixelTransferDelegate* AsyncPixelTransferManagerShareGroup::CreatePixelTransferDelegateImpl( gles2::TextureRef* ref, diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h index 173b5322faf..64daffe60f7 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h @@ -31,6 +31,7 @@ class AsyncPixelTransferManagerShareGroup : public AsyncPixelTransferManager { virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; virtual void ProcessMorePendingTransfers() OVERRIDE; virtual bool NeedsProcessMorePendingTransfers() OVERRIDE; + virtual void WaitAllAsyncTexImage2D() OVERRIDE; // State shared between Managers and Delegates. struct SharedState { diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.cc index ccd5d3d3e60..d5f96b03b73 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.cc @@ -78,6 +78,9 @@ bool AsyncPixelTransferManagerStub::NeedsProcessMorePendingTransfers() { return false; } +void AsyncPixelTransferManagerStub::WaitAllAsyncTexImage2D() { +} + AsyncPixelTransferDelegate* AsyncPixelTransferManagerStub::CreatePixelTransferDelegateImpl( gles2::TextureRef* ref, diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.h index 0f4e4ba95cd..a93ce9499e5 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_stub.h @@ -23,6 +23,7 @@ class AsyncPixelTransferManagerStub : public AsyncPixelTransferManager { virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; virtual void ProcessMorePendingTransfers() OVERRIDE; virtual bool NeedsProcessMorePendingTransfers() OVERRIDE; + virtual void WaitAllAsyncTexImage2D() OVERRIDE; private: // AsyncPixelTransferManager implementation: diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc index ffe55849358..cd7d087730f 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc @@ -46,7 +46,7 @@ void AsyncPixelTransferDelegateSync::AsyncTexImage2D( const base::Closure& bind_callback) { // Save the define params to return later during deferred // binding of the transfer texture. - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); glTexImage2D( tex_params.target, @@ -68,7 +68,7 @@ void AsyncPixelTransferDelegateSync::AsyncTexImage2D( void AsyncPixelTransferDelegateSync::AsyncTexSubImage2D( const AsyncTexSubImage2DParams& tex_params, const AsyncMemoryParams& mem_params) { - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); glTexSubImage2D( tex_params.target, @@ -128,6 +128,9 @@ bool AsyncPixelTransferManagerSync::NeedsProcessMorePendingTransfers() { return false; } +void AsyncPixelTransferManagerSync::WaitAllAsyncTexImage2D() { +} + AsyncPixelTransferDelegate* AsyncPixelTransferManagerSync::CreatePixelTransferDelegateImpl( gles2::TextureRef* ref, diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.h b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.h index cb62062a860..7d0b8b6636b 100644 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.h +++ b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_sync.h @@ -23,6 +23,7 @@ class AsyncPixelTransferManagerSync : public AsyncPixelTransferManager { virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; virtual void ProcessMorePendingTransfers() OVERRIDE; virtual bool NeedsProcessMorePendingTransfers() OVERRIDE; + virtual void WaitAllAsyncTexImage2D() OVERRIDE; // State shared between Managers and Delegates. struct SharedState { diff --git a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc index 444c3935bf5..77f32dcc416 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc @@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mocks.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,14 +18,13 @@ using ::testing::StrictMock; namespace gpu { namespace gles2 { -class BufferManagerTestBase : public testing::Test { +class BufferManagerTestBase : public GpuServiceTest { protected: void SetUpBase( MemoryTracker* memory_tracker, FeatureInfo* feature_info, const char* extensions) { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); if (feature_info) { TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions); feature_info->Initialize(); @@ -36,9 +36,8 @@ class BufferManagerTestBase : public testing::Test { virtual void TearDown() { manager_->Destroy(false); manager_.reset(); - ::gfx::GLInterface::SetGLInterface(NULL); error_state_.reset(); - gl_.reset(); + GpuServiceTest::TearDown(); } GLenum GetTarget(const Buffer* buffer) const { @@ -73,8 +72,6 @@ class BufferManagerTestBase : public testing::Test { return success; } - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_ptr<BufferManager> manager_; scoped_ptr<MockErrorState> error_state_; }; diff --git a/chromium/gpu/command_buffer/service/cmd_buffer_engine.h b/chromium/gpu/command_buffer/service/cmd_buffer_engine.h index 6aefe82e35e..75e60691f51 100644 --- a/chromium/gpu/command_buffer/service/cmd_buffer_engine.h +++ b/chromium/gpu/command_buffer/service/cmd_buffer_engine.h @@ -24,7 +24,7 @@ class CommandBufferEngine { // Gets the base address and size of a registered shared memory buffer. // Parameters: // shm_id: the identifier for the shared memory buffer. - virtual Buffer GetSharedMemoryBuffer(int32 shm_id) = 0; + virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id) = 0; // Sets the token value. virtual void set_token(int32 token) = 0; diff --git a/chromium/gpu/command_buffer/service/command_buffer_service.cc b/chromium/gpu/command_buffer/service/command_buffer_service.cc index bae2d801dd5..c9c07822e81 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service.cc +++ b/chromium/gpu/command_buffer/service/command_buffer_service.cc @@ -37,7 +37,7 @@ bool CommandBufferService::Initialize() { return true; } -CommandBufferService::State CommandBufferService::GetState() { +CommandBufferService::State CommandBufferService::GetLastState() { State state; state.num_entries = num_entries_; state.get_offset = get_offset_; @@ -50,34 +50,23 @@ CommandBufferService::State CommandBufferService::GetState() { return state; } -CommandBufferService::State CommandBufferService::GetLastState() { - return GetState(); -} - int32 CommandBufferService::GetLastToken() { - return GetState().token; + return GetLastState().token; } void CommandBufferService::UpdateState() { if (shared_state_) { - CommandBufferService::State state = GetState(); + CommandBufferService::State state = GetLastState(); shared_state_->Write(state); } } -CommandBufferService::State CommandBufferService::FlushSync( - int32 put_offset, int32 last_known_get) { - if (put_offset < 0 || put_offset > num_entries_) { - error_ = gpu::error::kOutOfBounds; - return GetState(); - } - - put_offset_ = put_offset; - - if (!put_offset_change_callback_.is_null()) - put_offset_change_callback_.Run(); +void CommandBufferService::WaitForTokenInRange(int32 start, int32 end) { + DCHECK(error_ != error::kNoError || InRange(start, end, token_)); +} - return GetState(); +void CommandBufferService::WaitForGetOffsetInRange(int32 start, int32 end) { + DCHECK(error_ != error::kNoError || InRange(start, end, get_offset_)); } void CommandBufferService::Flush(int32 put_offset) { @@ -95,10 +84,12 @@ void CommandBufferService::Flush(int32 put_offset) { void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) { DCHECK_EQ(-1, ring_buffer_id_); DCHECK_EQ(put_offset_, get_offset_); // Only if it's empty. + // If the buffer is invalid we handle it gracefully. + // This means ring_buffer_ can be NULL. ring_buffer_ = GetTransferBuffer(transfer_buffer_id); - DCHECK(ring_buffer_.ptr); ring_buffer_id_ = transfer_buffer_id; - num_entries_ = ring_buffer_.size / sizeof(CommandBufferEntry); + int32 size = ring_buffer_ ? ring_buffer_->size() : 0; + num_entries_ = size / sizeof(CommandBufferEntry); put_offset_ = 0; SetGetOffset(0); if (!get_buffer_change_callback_.is_null()) { @@ -108,17 +99,15 @@ void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) { UpdateState(); } -bool CommandBufferService::SetSharedStateBuffer( - scoped_ptr<base::SharedMemory> shared_state_shm) { - shared_state_shm_.reset(shared_state_shm.release()); - if (!shared_state_shm_->Map(sizeof(*shared_state_))) - return false; +void CommandBufferService::SetSharedStateBuffer( + scoped_ptr<BufferBacking> shared_state_buffer) { + shared_state_buffer_ = shared_state_buffer.Pass(); + DCHECK(shared_state_buffer_->GetSize() >= sizeof(*shared_state_)); shared_state_ = - static_cast<CommandBufferSharedState*>(shared_state_shm_->memory()); + static_cast<CommandBufferSharedState*>(shared_state_buffer_->GetMemory()); UpdateState(); - return true; } void CommandBufferService::SetGetOffset(int32 get_offset) { @@ -126,20 +115,21 @@ void CommandBufferService::SetGetOffset(int32 get_offset) { get_offset_ = get_offset; } -Buffer CommandBufferService::CreateTransferBuffer(size_t size, - int32* id) { +scoped_refptr<Buffer> CommandBufferService::CreateTransferBuffer(size_t size, + int32* id) { *id = -1; - SharedMemory buffer; - if (!buffer.CreateAnonymous(size)) - return Buffer(); + scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); + if (!shared_memory->CreateAndMapAnonymous(size)) + return NULL; static int32 next_id = 1; *id = next_id++; - if (!RegisterTransferBuffer(*id, &buffer, size)) { + if (!RegisterTransferBuffer( + *id, MakeBackingFromSharedMemory(shared_memory.Pass(), size))) { *id = -1; - return Buffer(); + return NULL; } return GetTransferBuffer(*id); @@ -149,24 +139,21 @@ void CommandBufferService::DestroyTransferBuffer(int32 id) { transfer_buffer_manager_->DestroyTransferBuffer(id); if (id == ring_buffer_id_) { ring_buffer_id_ = -1; - ring_buffer_ = Buffer(); + ring_buffer_ = NULL; num_entries_ = 0; get_offset_ = 0; put_offset_ = 0; } } -Buffer CommandBufferService::GetTransferBuffer(int32 id) { +scoped_refptr<Buffer> CommandBufferService::GetTransferBuffer(int32 id) { return transfer_buffer_manager_->GetTransferBuffer(id); } bool CommandBufferService::RegisterTransferBuffer( int32 id, - base::SharedMemory* shared_memory, - size_t size) { - return transfer_buffer_manager_->RegisterTransferBuffer(id, - shared_memory, - size); + scoped_ptr<BufferBacking> buffer) { + return transfer_buffer_manager_->RegisterTransferBuffer(id, buffer.Pass()); } void CommandBufferService::SetToken(int32 token) { diff --git a/chromium/gpu/command_buffer/service/command_buffer_service.h b/chromium/gpu/command_buffer/service/command_buffer_service.h index b1f8fa15fea..ac2330100b8 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service.h +++ b/chromium/gpu/command_buffer/service/command_buffer_service.h @@ -14,9 +14,30 @@ namespace gpu { class TransferBufferManagerInterface; +class GPU_EXPORT CommandBufferServiceBase : public CommandBuffer { + public: + // Sets the current get offset. This can be called from any thread. + virtual void SetGetOffset(int32 get_offset) = 0; + + // Get the transfer buffer associated with an ID. Returns a null buffer for + // ID 0. + virtual scoped_refptr<gpu::Buffer> GetTransferBuffer(int32 id) = 0; + + // Allows the reader to update the current token value. + virtual void SetToken(int32 token) = 0; + + // Allows the reader to set the current parse error. + virtual void SetParseError(error::Error) = 0; + + // Allows the reader to set the current context lost reason. + // NOTE: if calling this in conjunction with SetParseError, + // call this first. + virtual void SetContextLostReason(error::ContextLostReason) = 0; +}; + // An object that implements a shared memory command buffer and a synchronous // API to manage the put and get pointers. -class GPU_EXPORT CommandBufferService : public CommandBuffer { +class GPU_EXPORT CommandBufferService : public CommandBufferServiceBase { public: typedef base::Callback<bool(int32)> GetBufferChangedCallback; explicit CommandBufferService( @@ -25,16 +46,19 @@ class GPU_EXPORT CommandBufferService : public CommandBuffer { // CommandBuffer implementation: virtual bool Initialize() OVERRIDE; - virtual State GetState() OVERRIDE; virtual State GetLastState() OVERRIDE; virtual int32 GetLastToken() OVERRIDE; virtual void Flush(int32 put_offset) OVERRIDE; - virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE; + virtual void WaitForTokenInRange(int32 start, int32 end) OVERRIDE; + virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE; virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE; - virtual void SetGetOffset(int32 get_offset) OVERRIDE; - virtual Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE; + virtual scoped_refptr<Buffer> CreateTransferBuffer(size_t size, + int32* id) OVERRIDE; virtual void DestroyTransferBuffer(int32 id) OVERRIDE; - virtual Buffer GetTransferBuffer(int32 id) OVERRIDE; + + // CommandBufferServiceBase implementation: + virtual void SetGetOffset(int32 get_offset) OVERRIDE; + virtual scoped_refptr<Buffer> GetTransferBuffer(int32 id) OVERRIDE; virtual void SetToken(int32 token) OVERRIDE; virtual void SetParseError(error::Error error) OVERRIDE; virtual void SetContextLostReason(error::ContextLostReason) OVERRIDE; @@ -54,22 +78,19 @@ class GPU_EXPORT CommandBufferService : public CommandBuffer { virtual void SetParseErrorCallback(const base::Closure& callback); // Setup the shared memory that shared state should be copied into. - bool SetSharedStateBuffer(scoped_ptr<base::SharedMemory> shared_state_shm); + void SetSharedStateBuffer(scoped_ptr<BufferBacking> shared_state_buffer); // Copy the current state into the shared state transfer buffer. void UpdateState(); - // Register an existing shared memory object and get an ID that can be used - // to identify it in the command buffer. Callee dups the handle until - // DestroyTransferBuffer is called. - bool RegisterTransferBuffer(int32 id, - base::SharedMemory* shared_memory, - size_t size); + // Registers an existing shared memory object and get an ID that can be used + // to identify it in the command buffer. + bool RegisterTransferBuffer(int32 id, scoped_ptr<BufferBacking> buffer); private: int32 ring_buffer_id_; - Buffer ring_buffer_; - scoped_ptr<base::SharedMemory> shared_state_shm_; + scoped_refptr<Buffer> ring_buffer_; + scoped_ptr<BufferBacking> shared_state_buffer_; CommandBufferSharedState* shared_state_; int32 num_entries_; int32 get_offset_; diff --git a/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc b/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc index bf4d619f819..229aafaf1d0 100644 --- a/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc +++ b/chromium/gpu/command_buffer/service/command_buffer_service_unittest.cc @@ -34,19 +34,19 @@ class CommandBufferServiceTest : public testing::Test { } int32 GetGetOffset() { - return command_buffer_->GetState().get_offset; + return command_buffer_->GetLastState().get_offset; } int32 GetPutOffset() { - return command_buffer_->GetState().put_offset; + return command_buffer_->GetLastState().put_offset; } int32 GetToken() { - return command_buffer_->GetState().token; + return command_buffer_->GetLastState().token; } int32 GetError() { - return command_buffer_->GetState().error; + return command_buffer_->GetLastState().error; } bool Initialize(size_t size) { @@ -63,7 +63,7 @@ class CommandBufferServiceTest : public testing::Test { TEST_F(CommandBufferServiceTest, InitializesCommandBuffer) { EXPECT_TRUE(Initialize(1024)); - CommandBuffer::State state = command_buffer_->GetState(); + CommandBuffer::State state = command_buffer_->GetLastState(); EXPECT_EQ(0, state.get_offset); EXPECT_EQ(0, state.put_offset); EXPECT_EQ(0, state.token); diff --git a/chromium/gpu/command_buffer/service/common_decoder.cc b/chromium/gpu/command_buffer/service/common_decoder.cc index 72f30a30bfc..06cf3a4bb37 100644 --- a/chromium/gpu/command_buffer/service/common_decoder.cc +++ b/chromium/gpu/command_buffer/service/common_decoder.cc @@ -61,20 +61,17 @@ CommonDecoder::CommonDecoder() : engine_(NULL) {} CommonDecoder::~CommonDecoder() {} void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, - unsigned int offset, - unsigned int size) { + unsigned int data_offset, + unsigned int data_size) { CHECK(engine_); - Buffer buffer = engine_->GetSharedMemoryBuffer(shm_id); - if (!buffer.ptr) + scoped_refptr<gpu::Buffer> buffer = engine_->GetSharedMemoryBuffer(shm_id); + if (!buffer) return NULL; - unsigned int end = offset + size; - if (end > buffer.size || end < offset) { - return NULL; - } - return static_cast<int8*>(buffer.ptr) + offset; + return buffer->GetDataAddress(data_offset, data_size); } -Buffer CommonDecoder::GetSharedMemoryBuffer(unsigned int shm_id) { +scoped_refptr<gpu::Buffer> CommonDecoder::GetSharedMemoryBuffer( + unsigned int shm_id) { return engine_->GetSharedMemoryBuffer(shm_id); } @@ -111,17 +108,23 @@ RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) { return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))); } +// TODO(vmiura): Looks like this g_command_info is duplicated in +// common_decoder.cc +// and gles2_cmd_decoder.cc. Fix it! + // A struct to hold info about each command. struct CommandInfo { - int arg_flags; // How to handle the arguments for this command - int arg_count; // How many arguments are expected for this command. + uint8 arg_flags; // How to handle the arguments for this command + uint8 cmd_flags; // How to handle this command + uint16 arg_count; // How many arguments are expected for this command. }; // A table of CommandInfo for all the commands. const CommandInfo g_command_info[] = { #define COMMON_COMMAND_BUFFER_CMD_OP(name) { \ cmd::name::kArgFlags, \ - sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \ + cmd::name::cmd_flags, \ + sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) diff --git a/chromium/gpu/command_buffer/service/common_decoder.h b/chromium/gpu/command_buffer/service/common_decoder.h index 03002c8b06f..2132afbf4fb 100644 --- a/chromium/gpu/command_buffer/service/common_decoder.h +++ b/chromium/gpu/command_buffer/service/common_decoder.h @@ -132,7 +132,7 @@ class GPU_EXPORT CommonDecoder : NON_EXPORTED_BASE(public AsyncAPIInterface) { } // Get the actual shared memory buffer. - Buffer GetSharedMemoryBuffer(unsigned int shm_id); + scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(unsigned int shm_id); protected: // Executes a common command. diff --git a/chromium/gpu/command_buffer/service/common_decoder_unittest.cc b/chromium/gpu/command_buffer/service/common_decoder_unittest.cc index d90e34bf93b..11274e05f07 100644 --- a/chromium/gpu/command_buffer/service/common_decoder_unittest.cc +++ b/chromium/gpu/command_buffer/service/common_decoder_unittest.cc @@ -81,26 +81,29 @@ class MockCommandBufferEngine : public CommandBufferEngine { : CommandBufferEngine(), token_(), get_offset_(0) { + scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + shared_memory->CreateAndMapAnonymous(kBufferSize); + buffer_ = MakeBufferFromSharedMemory(shared_memory.Pass(), kBufferSize); } // Overridden from CommandBufferEngine. - virtual Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE { - Buffer buffer; - if (IsValidSharedMemoryId(shm_id)) { - buffer.ptr = buffer_; - buffer.size = kBufferSize; - } - return buffer; + virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id) + OVERRIDE { + if (IsValidSharedMemoryId(shm_id)) + return buffer_; + return NULL; } template <typename T> T GetSharedMemoryAs(uint32 offset) { DCHECK_LT(offset, kBufferSize); - return reinterpret_cast<T>(&buffer_[offset]); + int8* buffer_memory = static_cast<int8*>(buffer_->memory()); + return reinterpret_cast<T>(&buffer_memory[offset]); } int32 GetSharedMemoryOffset(const void* memory) { - ptrdiff_t offset = reinterpret_cast<const int8*>(memory) - &buffer_[0]; + int8* buffer_memory = static_cast<int8*>(buffer_->memory()); + ptrdiff_t offset = static_cast<const int8*>(memory) - &buffer_memory[0]; DCHECK_GE(offset, 0); DCHECK_LT(static_cast<size_t>(offset), kBufferSize); return static_cast<int32>(offset); @@ -140,7 +143,7 @@ class MockCommandBufferEngine : public CommandBufferEngine { return shm_id == kValidShmId || shm_id == kStartValidShmId; } - int8 buffer_[kBufferSize]; + scoped_refptr<gpu::Buffer> buffer_; int32 token_; int32 get_offset_; }; diff --git a/chromium/gpu/command_buffer/service/context_group.cc b/chromium/gpu/command_buffer/service/context_group.cc index 27af0abafad..ba0437bfd4e 100644 --- a/chromium/gpu/command_buffer/service/context_group.cc +++ b/chromium/gpu/command_buffer/service/context_group.cc @@ -32,13 +32,13 @@ ContextGroup::ContextGroup( MailboxManager* mailbox_manager, ImageManager* image_manager, MemoryTracker* memory_tracker, - StreamTextureManager* stream_texture_manager, + ShaderTranslatorCache* shader_translator_cache, FeatureInfo* feature_info, bool bind_generates_resource) : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager), image_manager_(image_manager ? image_manager : new ImageManager), memory_tracker_(memory_tracker), - stream_texture_manager_(stream_texture_manager), + shader_translator_cache_(shader_translator_cache), enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnforceGLMinimums)), bind_generates_resource_(bind_generates_resource), @@ -178,9 +178,9 @@ bool ContextGroup::Initialize( texture_manager_.reset(new TextureManager(memory_tracker_.get(), feature_info_.get(), max_texture_size, - max_cube_map_texture_size)); + max_cube_map_texture_size, + bind_generates_resource_)); texture_manager_->set_framebuffer_manager(framebuffer_manager_.get()); - texture_manager_->set_stream_texture_manager(stream_texture_manager_); const GLint kMinTextureImageUnits = 8; const GLint kMinVertexTextureImageUnits = 0; @@ -223,18 +223,24 @@ bool ContextGroup::Initialize( return false; } - // TODO(gman): Use workarounds similar to max_texture_size above to implement. - if (gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) { - // Some shaders in Skia needed more than the min. - max_fragment_uniform_vectors_ = - std::min(static_cast<uint32>(kMinFragmentUniformVectors * 2), - max_fragment_uniform_vectors_); - max_varying_vectors_ = - std::min(static_cast<uint32>(kMinVaryingVectors * 2), - max_varying_vectors_); + // Some shaders in Skia need more than the min available vertex and + // fragment shader uniform vectors in case of OSMesa GL Implementation + if (feature_info_->workarounds().max_fragment_uniform_vectors) { + max_fragment_uniform_vectors_ = std::min( + max_fragment_uniform_vectors_, + static_cast<uint32>( + feature_info_->workarounds().max_fragment_uniform_vectors)); + } + if (feature_info_->workarounds().max_varying_vectors) { + max_varying_vectors_ = std::min( + max_varying_vectors_, + static_cast<uint32>(feature_info_->workarounds().max_varying_vectors)); + } + if (feature_info_->workarounds().max_vertex_uniform_vectors) { max_vertex_uniform_vectors_ = - std::min(static_cast<uint32>(kMinVertexUniformVectors * 2), - max_vertex_uniform_vectors_); + std::min(max_vertex_uniform_vectors_, + static_cast<uint32>( + feature_info_->workarounds().max_vertex_uniform_vectors)); } program_manager_.reset(new ProgramManager( @@ -319,7 +325,6 @@ void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) { } memory_tracker_ = NULL; - stream_texture_manager_ = NULL; } IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) { diff --git a/chromium/gpu/command_buffer/service/context_group.h b/chromium/gpu/command_buffer/service/context_group.h index 391db1a4ace..924527f87de 100644 --- a/chromium/gpu/command_buffer/service/context_group.h +++ b/chromium/gpu/command_buffer/service/context_group.h @@ -16,12 +16,12 @@ #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" +#include "gpu/command_buffer/service/shader_translator_cache.h" #include "gpu/gpu_export.h" namespace gpu { class IdAllocatorInterface; -class StreamTextureManager; class TransferBufferManagerInterface; namespace gles2 { @@ -47,7 +47,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { MailboxManager* mailbox_manager, ImageManager* image_manager, MemoryTracker* memory_tracker, - StreamTextureManager* stream_texture_manager, + ShaderTranslatorCache* shader_translator_cache, FeatureInfo* feature_info, bool bind_generates_resource); @@ -73,8 +73,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { return memory_tracker_.get(); } - StreamTextureManager* stream_texture_manager() const { - return stream_texture_manager_; + ShaderTranslatorCache* shader_translator_cache() const { + return shader_translator_cache_.get(); } bool bind_generates_resource() { @@ -185,7 +185,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { scoped_refptr<MailboxManager> mailbox_manager_; scoped_refptr<ImageManager> image_manager_; scoped_refptr<MemoryTracker> memory_tracker_; - StreamTextureManager* stream_texture_manager_; + scoped_refptr<ShaderTranslatorCache> shader_translator_cache_; scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; bool enforce_gl_minimums_; diff --git a/chromium/gpu/command_buffer/service/context_group_unittest.cc b/chromium/gpu/command_buffer/service/context_group_unittest.cc index 0c710362d69..608109dffd0 100644 --- a/chromium/gpu/command_buffer/service/context_group_unittest.cc +++ b/chromium/gpu/command_buffer/service/context_group_unittest.cc @@ -6,12 +6,12 @@ #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" -using ::gfx::MockGLInterface; using ::testing::_; using ::testing::DoAll; using ::testing::HasSubstr; @@ -23,31 +23,24 @@ using ::testing::Return; using ::testing::SetArrayArgument; using ::testing::SetArgumentPointee; using ::testing::StrEq; -using ::testing::StrictMock; namespace gpu { namespace gles2 { -class ContextGroupTest : public testing::Test { +class ContextGroupTest : public GpuServiceTest { public: - ContextGroupTest() { - } + static const bool kBindGeneratesResource = false; + + ContextGroupTest() {} protected: virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); decoder_.reset(new MockGLES2Decoder()); group_ = scoped_refptr<ContextGroup>( - new ContextGroup(NULL, NULL, NULL, NULL, NULL, true)); - } - - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + new ContextGroup(NULL, NULL, NULL, NULL, NULL, kBindGeneratesResource)); } - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_ptr<MockGLES2Decoder> decoder_; scoped_refptr<ContextGroup> group_; }; @@ -70,8 +63,8 @@ TEST_F(ContextGroupTest, Basic) { } TEST_F(ContextGroupTest, InitializeNoExtensions) { - TestHelper::SetupContextGroupInitExpectations(gl_.get(), - DisallowedFeatures(), ""); + TestHelper::SetupContextGroupInitExpectations( + gl_.get(), DisallowedFeatures(), "", "", kBindGeneratesResource); group_->Initialize(decoder_.get(), DisallowedFeatures()); EXPECT_EQ(static_cast<uint32>(TestHelper::kNumVertexAttribs), group_->max_vertex_attribs()); @@ -105,8 +98,8 @@ TEST_F(ContextGroupTest, InitializeNoExtensions) { TEST_F(ContextGroupTest, MultipleContexts) { scoped_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder()); - TestHelper::SetupContextGroupInitExpectations(gl_.get(), - DisallowedFeatures(), ""); + TestHelper::SetupContextGroupInitExpectations( + gl_.get(), DisallowedFeatures(), "", "", kBindGeneratesResource); group_->Initialize(decoder_.get(), DisallowedFeatures()); group_->Initialize(decoder2_.get(), DisallowedFeatures()); diff --git a/chromium/gpu/command_buffer/service/context_state.cc b/chromium/gpu/command_buffer/service/context_state.cc index e8912cfe162..77d1f9286d1 100644 --- a/chromium/gpu/command_buffer/service/context_state.cc +++ b/chromium/gpu/command_buffer/service/context_state.cc @@ -18,7 +18,7 @@ namespace gles2 { namespace { -void EnableDisable(GLenum pname, bool enable) { +static void EnableDisable(GLenum pname, bool enable) { if (enable) { glEnable(pname); } else { @@ -26,6 +26,58 @@ void EnableDisable(GLenum pname, bool enable) { } } +GLuint Get2dServiceId(const TextureUnit& unit) { + return unit.bound_texture_2d.get() + ? unit.bound_texture_2d->service_id() : 0; +} + +GLuint GetCubeServiceId(const TextureUnit& unit) { + return unit.bound_texture_cube_map.get() + ? unit.bound_texture_cube_map->service_id() : 0; +} + +GLuint GetOesServiceId(const TextureUnit& unit) { + return unit.bound_texture_external_oes.get() + ? unit.bound_texture_external_oes->service_id() : 0; +} + +GLuint GetArbServiceId(const TextureUnit& unit) { + return unit.bound_texture_rectangle_arb.get() + ? unit.bound_texture_rectangle_arb->service_id() : 0; +} + +GLuint GetServiceId(const TextureUnit& unit, GLuint target) { + switch (target) { + case GL_TEXTURE_2D: + return Get2dServiceId(unit); + case GL_TEXTURE_CUBE_MAP: + return GetCubeServiceId(unit); + case GL_TEXTURE_RECTANGLE_ARB: + return GetArbServiceId(unit); + case GL_TEXTURE_EXTERNAL_OES: + return GetOesServiceId(unit); + default: + NOTREACHED(); + return 0; + } +} + +bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) { + switch (target) { + case GL_TEXTURE_2D: + return true; + case GL_TEXTURE_CUBE_MAP: + return true; + case GL_TEXTURE_RECTANGLE_ARB: + return feature_info->feature_flags().arb_texture_rectangle; + case GL_TEXTURE_EXTERNAL_OES: + return feature_info->feature_flags().oes_egl_image_external; + default: + NOTREACHED(); + return false; + } +} + } // anonymous namespace. TextureUnit::TextureUnit() @@ -35,43 +87,63 @@ TextureUnit::TextureUnit() TextureUnit::~TextureUnit() { } -ContextState::ContextState(FeatureInfo* feature_info, Logger* logger) +ContextState::ContextState(FeatureInfo* feature_info, + ErrorStateClient* error_state_client, + Logger* logger) : active_texture_unit(0), pack_reverse_row_order(false), + ignore_cached_state(false), fbo_binding_for_scissor_workaround_dirty_(false), feature_info_(feature_info), - error_state_(ErrorState::Create(logger)) { + error_state_(ErrorState::Create(error_state_client, logger)) { Initialize(); } ContextState::~ContextState() { } -void ContextState::RestoreTextureUnitBindings(GLuint unit) const { +void ContextState::RestoreTextureUnitBindings( + GLuint unit, const ContextState* prev_state) const { DCHECK_LT(unit, texture_units.size()); const TextureUnit& texture_unit = texture_units[unit]; - glActiveTexture(GL_TEXTURE0 + unit); - GLuint service_id = texture_unit.bound_texture_2d.get() - ? texture_unit.bound_texture_2d->service_id() - : 0; - glBindTexture(GL_TEXTURE_2D, service_id); - service_id = texture_unit.bound_texture_cube_map.get() - ? texture_unit.bound_texture_cube_map->service_id() - : 0; - glBindTexture(GL_TEXTURE_CUBE_MAP, service_id); - - if (feature_info_->feature_flags().oes_egl_image_external) { - service_id = texture_unit.bound_texture_external_oes.get() - ? texture_unit.bound_texture_external_oes->service_id() - : 0; - glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id); + GLuint service_id_2d = Get2dServiceId(texture_unit); + GLuint service_id_cube = GetCubeServiceId(texture_unit); + GLuint service_id_oes = GetOesServiceId(texture_unit); + GLuint service_id_arb = GetArbServiceId(texture_unit); + + bool bind_texture_2d = true; + bool bind_texture_cube = true; + bool bind_texture_oes = feature_info_->feature_flags().oes_egl_image_external; + bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle; + + if (prev_state) { + const TextureUnit& prev_unit = prev_state->texture_units[unit]; + bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit); + bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit); + bind_texture_oes = + bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit); + bind_texture_arb = + bind_texture_arb && service_id_arb != GetArbServiceId(prev_unit); + } + + // Early-out if nothing has changed from the previous state. + if (!bind_texture_2d && !bind_texture_cube + && !bind_texture_oes && !bind_texture_arb) { + return; } - if (feature_info_->feature_flags().arb_texture_rectangle) { - service_id = texture_unit.bound_texture_rectangle_arb.get() - ? texture_unit.bound_texture_rectangle_arb->service_id() - : 0; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, service_id); + glActiveTexture(GL_TEXTURE0 + unit); + if (bind_texture_2d) { + glBindTexture(GL_TEXTURE_2D, service_id_2d); + } + if (bind_texture_cube) { + glBindTexture(GL_TEXTURE_CUBE_MAP, service_id_cube); + } + if (bind_texture_oes) { + glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id_oes); + } + if (bind_texture_arb) { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, service_id_arb); } } @@ -101,62 +173,117 @@ void ContextState::RestoreActiveTexture() const { glActiveTexture(GL_TEXTURE0 + active_texture_unit); } -void ContextState::RestoreAllTextureUnitBindings() const { +void ContextState::RestoreAllTextureUnitBindings( + const ContextState* prev_state) const { // Restore Texture state. for (size_t ii = 0; ii < texture_units.size(); ++ii) { - RestoreTextureUnitBindings(ii); + RestoreTextureUnitBindings(ii, prev_state); } RestoreActiveTexture(); } -void ContextState::RestoreAttribute(GLuint attrib_index) const { - const VertexAttrib* attrib = - vertex_attrib_manager->GetVertexAttrib(attrib_index); - const void* ptr = reinterpret_cast<const void*>(attrib->offset()); - Buffer* buffer = attrib->buffer(); - glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0); - glVertexAttribPointer( - attrib_index, attrib->size(), attrib->type(), attrib->normalized(), - attrib->gl_stride(), ptr); - if (attrib->divisor()) - glVertexAttribDivisorANGLE(attrib_index, attrib->divisor()); - // Never touch vertex attribute 0's state (in particular, never - // disable it) when running on desktop GL because it will never be - // re-enabled. - if (attrib_index != 0 || - gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { - if (attrib->enabled()) { - glEnableVertexAttribArray(attrib_index); - } else { - glDisableVertexAttribArray(attrib_index); - } - } - glVertexAttrib4fv(attrib_index, attrib_values[attrib_index].v); +void ContextState::RestoreActiveTextureUnitBinding(unsigned int target) const { + DCHECK_LT(active_texture_unit, texture_units.size()); + const TextureUnit& texture_unit = texture_units[active_texture_unit]; + if (TargetIsSupported(feature_info_, target)) + glBindTexture(target, GetServiceId(texture_unit, target)); } -void ContextState::RestoreGlobalState() const { - InitCapabilities(); - InitState(); +void ContextState::RestoreVertexAttribValues() const { + for (size_t attrib = 0; attrib < vertex_attrib_manager->num_attribs(); + ++attrib) { + glVertexAttrib4fv(attrib, attrib_values[attrib].v); + } } -void ContextState::RestoreState() const { - RestoreAllTextureUnitBindings(); +void ContextState::RestoreVertexAttribArrays( + const scoped_refptr<VertexAttribManager> attrib_manager) const { + // This is expected to be called only for VAO with service_id 0, + // either to restore the default VAO or a virtual VAO with service_id 0. + GLuint vao_service_id = attrib_manager->service_id(); + DCHECK(vao_service_id == 0); + + // Bind VAO if supported. + if (feature_info_->feature_flags().native_vertex_array_object) + glBindVertexArrayOES(vao_service_id); + + // Restore vertex attrib arrays. + for (size_t attrib_index = 0; attrib_index < attrib_manager->num_attribs(); + ++attrib_index) { + const VertexAttrib* attrib = attrib_manager->GetVertexAttrib(attrib_index); + + // Restore vertex array. + Buffer* buffer = attrib->buffer(); + GLuint buffer_service_id = buffer ? buffer->service_id() : 0; + glBindBuffer(GL_ARRAY_BUFFER, buffer_service_id); + const void* ptr = reinterpret_cast<const void*>(attrib->offset()); + glVertexAttribPointer(attrib_index, + attrib->size(), + attrib->type(), + attrib->normalized(), + attrib->gl_stride(), + ptr); + + // Restore attrib divisor if supported. + if (feature_info_->feature_flags().angle_instanced_arrays) + glVertexAttribDivisorANGLE(attrib_index, attrib->divisor()); - // Restore Attrib State + // Never touch vertex attribute 0's state (in particular, never + // disable it) when running on desktop GL because it will never be + // re-enabled. + if (attrib_index != 0 || + gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { + if (attrib->enabled()) { + glEnableVertexAttribArray(attrib_index); + } else { + glDisableVertexAttribArray(attrib_index); + } + } + } +} + +void ContextState::RestoreVertexAttribs() const { + // Restore Vertex Attrib Arrays // TODO: This if should not be needed. RestoreState is getting called // before GLES2Decoder::Initialize which is a bug. if (vertex_attrib_manager.get()) { - // TODO(gman): Move this restoration to VertexAttribManager. - for (size_t attrib = 0; attrib < vertex_attrib_manager->num_attribs(); - ++attrib) { - RestoreAttribute(attrib); + // Restore VAOs. + if (feature_info_->feature_flags().native_vertex_array_object) { + // If default VAO is still using shared id 0 instead of unique ids + // per-context, default VAO state must be restored. + GLuint default_vao_service_id = + default_vertex_attrib_manager->service_id(); + if (default_vao_service_id == 0) + RestoreVertexAttribArrays(default_vertex_attrib_manager); + + // Restore the current VAO binding, unless it's the same as the + // default above. + GLuint curr_vao_service_id = vertex_attrib_manager->service_id(); + if (curr_vao_service_id != 0) + glBindVertexArrayOES(curr_vao_service_id); + } else { + // If native VAO isn't supported, emulated VAOs are used. + // Restore to the currently bound VAO. + RestoreVertexAttribArrays(vertex_attrib_manager); } } + // glVertexAttrib4fv aren't part of VAO state and must be restored. + RestoreVertexAttribValues(); +} + +void ContextState::RestoreGlobalState(const ContextState* prev_state) const { + InitCapabilities(prev_state); + InitState(prev_state); +} + +void ContextState::RestoreState(const ContextState* prev_state) const { + RestoreAllTextureUnitBindings(prev_state); + RestoreVertexAttribs(); RestoreBufferBindings(); RestoreRenderbufferBindings(); RestoreProgramBindings(); - RestoreGlobalState(); + RestoreGlobalState(prev_state); } ErrorState* ContextState::GetErrorState() { diff --git a/chromium/gpu/command_buffer/service/context_state.h b/chromium/gpu/command_buffer/service/context_state.h index 8d5edcaea61..e436e74e280 100644 --- a/chromium/gpu/command_buffer/service/context_state.h +++ b/chromium/gpu/command_buffer/service/context_state.h @@ -22,6 +22,7 @@ namespace gles2 { class Buffer; class ErrorState; +class ErrorStateClient; class FeatureInfo; class Framebuffer; class Program; @@ -93,23 +94,34 @@ struct Vec4 { }; struct GPU_EXPORT ContextState { - ContextState(FeatureInfo* feature_info, Logger* logger); + ContextState(FeatureInfo* feature_info, + ErrorStateClient* error_state_client, + Logger* logger); ~ContextState(); void Initialize(); - void RestoreState() const; - void InitCapabilities() const; - void InitState() const; + void SetIgnoreCachedStateForTest(bool ignore) { + ignore_cached_state = ignore; + } + + void RestoreState(const ContextState* prev_state) const; + void InitCapabilities(const ContextState* prev_state) const; + void InitState(const ContextState* prev_state) const; void RestoreActiveTexture() const; - void RestoreAllTextureUnitBindings() const; - void RestoreAttribute(GLuint index) const; + void RestoreAllTextureUnitBindings(const ContextState* prev_state) const; + void RestoreActiveTextureUnitBinding(unsigned int target) const; + void RestoreVertexAttribValues() const; + void RestoreVertexAttribArrays( + const scoped_refptr<VertexAttribManager> attrib_manager) const; + void RestoreVertexAttribs() const; void RestoreBufferBindings() const; - void RestoreGlobalState() const; + void RestoreGlobalState(const ContextState* prev_state) const; void RestoreProgramBindings() const; void RestoreRenderbufferBindings() const; - void RestoreTextureUnitBindings(GLuint unit) const; + void RestoreTextureUnitBindings( + GLuint unit, const ContextState* prev_state) const; // Helper for getting cached state. bool GetStateAsGLint( @@ -118,6 +130,44 @@ struct GPU_EXPORT ContextState { GLenum pname, GLfloat* params, GLsizei* num_written) const; bool GetEnabled(GLenum cap) const; + inline void SetDeviceColorMask(GLboolean red, + GLboolean green, + GLboolean blue, + GLboolean alpha) { + if (cached_color_mask_red == red && cached_color_mask_green == green && + cached_color_mask_blue == blue && cached_color_mask_alpha == alpha && + !ignore_cached_state) + return; + cached_color_mask_red = red; + cached_color_mask_green = green; + cached_color_mask_blue = blue; + cached_color_mask_alpha = alpha; + glColorMask(red, green, blue, alpha); + } + + inline void SetDeviceDepthMask(GLboolean mask) { + if (cached_depth_mask == mask && !ignore_cached_state) + return; + cached_depth_mask = mask; + glDepthMask(mask); + } + + inline void SetDeviceStencilMaskSeparate(GLenum op, GLuint mask) { + if (op == GL_FRONT) { + if (cached_stencil_front_writemask == mask && !ignore_cached_state) + return; + cached_stencil_front_writemask = mask; + } else if (op == GL_BACK) { + if (cached_stencil_back_writemask == mask && !ignore_cached_state) + return; + cached_stencil_back_writemask = mask; + } else { + NOTREACHED(); + return; + } + glStencilMaskSeparate(op, mask); + } + ErrorState* GetErrorState(); #include "gpu/command_buffer/service/context_state_autogen.h" @@ -141,6 +191,7 @@ struct GPU_EXPORT ContextState { // Class that manages vertex attribs. scoped_refptr<VertexAttribManager> vertex_attrib_manager; + scoped_refptr<VertexAttribManager> default_vertex_attrib_manager; // The program in use by glUseProgram scoped_refptr<Program> current_program; @@ -148,9 +199,12 @@ struct GPU_EXPORT ContextState { // The currently bound renderbuffer scoped_refptr<Renderbuffer> bound_renderbuffer; - scoped_refptr<QueryManager::Query> current_query; + // A map of of target -> Query for current queries + typedef std::map<GLuint, scoped_refptr<QueryManager::Query> > QueryMap; + QueryMap current_queries; bool pack_reverse_row_order; + bool ignore_cached_state; mutable bool fbo_binding_for_scissor_workaround_dirty_; FeatureInfo* feature_info_; diff --git a/chromium/gpu/command_buffer/service/context_state_autogen.h b/chromium/gpu/command_buffer/service/context_state_autogen.h index a76aabccac7..309301f1b28 100644 --- a/chromium/gpu/command_buffer/service/context_state_autogen.h +++ b/chromium/gpu/command_buffer/service/context_state_autogen.h @@ -1,9 +1,11 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! // It is included by context_state.h @@ -13,14 +15,23 @@ struct EnableFlags { EnableFlags(); bool blend; + bool cached_blend; bool cull_face; + bool cached_cull_face; bool depth_test; + bool cached_depth_test; bool dither; + bool cached_dither; bool polygon_offset_fill; + bool cached_polygon_offset_fill; bool sample_alpha_to_coverage; + bool cached_sample_alpha_to_coverage; bool sample_coverage; + bool cached_sample_coverage; bool scissor_test; + bool cached_scissor_test; bool stencil_test; + bool cached_stencil_test; }; GLfloat blend_color_red; @@ -40,12 +51,17 @@ GLfloat color_clear_alpha; GLclampf depth_clear; GLint stencil_clear; GLboolean color_mask_red; +GLboolean cached_color_mask_red; GLboolean color_mask_green; +GLboolean cached_color_mask_green; GLboolean color_mask_blue; +GLboolean cached_color_mask_blue; GLboolean color_mask_alpha; +GLboolean cached_color_mask_alpha; GLenum cull_mode; GLenum depth_func; GLboolean depth_mask; +GLboolean cached_depth_mask; GLclampf z_near; GLclampf z_far; GLenum front_face; @@ -69,7 +85,9 @@ GLenum stencil_back_func; GLint stencil_back_ref; GLuint stencil_back_mask; GLuint stencil_front_writemask; +GLuint cached_stencil_front_writemask; GLuint stencil_back_writemask; +GLuint cached_stencil_back_writemask; GLenum stencil_front_fail_op; GLenum stencil_front_z_fail_op; GLenum stencil_front_z_pass_op; @@ -81,5 +99,62 @@ GLint viewport_y; GLsizei viewport_width; GLsizei viewport_height; +inline void SetDeviceCapabilityState(GLenum cap, bool enable) { + switch (cap) { + case GL_BLEND: + if (enable_flags.cached_blend == enable && !ignore_cached_state) + return; + enable_flags.cached_blend = enable; + break; + case GL_CULL_FACE: + if (enable_flags.cached_cull_face == enable && !ignore_cached_state) + return; + enable_flags.cached_cull_face = enable; + break; + case GL_DEPTH_TEST: + if (enable_flags.cached_depth_test == enable && !ignore_cached_state) + return; + enable_flags.cached_depth_test = enable; + break; + case GL_DITHER: + if (enable_flags.cached_dither == enable && !ignore_cached_state) + return; + enable_flags.cached_dither = enable; + break; + case GL_POLYGON_OFFSET_FILL: + if (enable_flags.cached_polygon_offset_fill == enable && + !ignore_cached_state) + return; + enable_flags.cached_polygon_offset_fill = enable; + break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: + if (enable_flags.cached_sample_alpha_to_coverage == enable && + !ignore_cached_state) + return; + enable_flags.cached_sample_alpha_to_coverage = enable; + break; + case GL_SAMPLE_COVERAGE: + if (enable_flags.cached_sample_coverage == enable && !ignore_cached_state) + return; + enable_flags.cached_sample_coverage = enable; + break; + case GL_SCISSOR_TEST: + if (enable_flags.cached_scissor_test == enable && !ignore_cached_state) + return; + enable_flags.cached_scissor_test = enable; + break; + case GL_STENCIL_TEST: + if (enable_flags.cached_stencil_test == enable && !ignore_cached_state) + return; + enable_flags.cached_stencil_test = enable; + break; + default: + NOTREACHED(); + return; + } + if (enable) + glEnable(cap); + else + glDisable(cap); +} #endif // GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_AUTOGEN_H_ - diff --git a/chromium/gpu/command_buffer/service/context_state_impl_autogen.h b/chromium/gpu/command_buffer/service/context_state_impl_autogen.h index 100199c6b49..056a382d24d 100644 --- a/chromium/gpu/command_buffer/service/context_state_impl_autogen.h +++ b/chromium/gpu/command_buffer/service/context_state_impl_autogen.h @@ -1,9 +1,11 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! // It is included by context_state.cc @@ -12,14 +14,23 @@ ContextState::EnableFlags::EnableFlags() : blend(false), + cached_blend(false), cull_face(false), + cached_cull_face(false), depth_test(false), + cached_depth_test(false), dither(true), + cached_dither(true), polygon_offset_fill(false), + cached_polygon_offset_fill(false), sample_alpha_to_coverage(false), + cached_sample_alpha_to_coverage(false), sample_coverage(false), + cached_sample_coverage(false), scissor_test(false), - stencil_test(false) { + cached_scissor_test(false), + stencil_test(false), + cached_stencil_test(false) { } void ContextState::Initialize() { @@ -40,12 +51,17 @@ void ContextState::Initialize() { depth_clear = 1.0f; stencil_clear = 0; color_mask_red = true; + cached_color_mask_red = true; color_mask_green = true; + cached_color_mask_green = true; color_mask_blue = true; + cached_color_mask_blue = true; color_mask_alpha = true; + cached_color_mask_alpha = true; cull_mode = GL_BACK; depth_func = GL_LESS; depth_mask = true; + cached_depth_mask = true; z_near = 0.0f; z_far = 1.0f; front_face = GL_CCW; @@ -69,7 +85,9 @@ void ContextState::Initialize() { stencil_back_ref = 0; stencil_back_mask = 0xFFFFFFFFU; stencil_front_writemask = 0xFFFFFFFFU; + cached_stencil_front_writemask = 0xFFFFFFFFU; stencil_back_writemask = 0xFFFFFFFFU; + cached_stencil_back_writemask = 0xFFFFFFFFU; stencil_front_fail_op = GL_KEEP; stencil_front_z_fail_op = GL_KEEP; stencil_front_z_pass_op = GL_KEEP; @@ -82,59 +100,209 @@ void ContextState::Initialize() { viewport_height = 1; } -void ContextState::InitCapabilities() const { - EnableDisable(GL_BLEND, enable_flags.blend); - EnableDisable(GL_CULL_FACE, enable_flags.cull_face); - EnableDisable(GL_DEPTH_TEST, enable_flags.depth_test); - EnableDisable(GL_DITHER, enable_flags.dither); - EnableDisable(GL_POLYGON_OFFSET_FILL, enable_flags.polygon_offset_fill); - EnableDisable( - GL_SAMPLE_ALPHA_TO_COVERAGE, enable_flags.sample_alpha_to_coverage); - EnableDisable(GL_SAMPLE_COVERAGE, enable_flags.sample_coverage); - EnableDisable(GL_SCISSOR_TEST, enable_flags.scissor_test); - EnableDisable(GL_STENCIL_TEST, enable_flags.stencil_test); +void ContextState::InitCapabilities(const ContextState* prev_state) const { + if (prev_state) { + if (prev_state->enable_flags.cached_blend != enable_flags.cached_blend) + EnableDisable(GL_BLEND, enable_flags.cached_blend); + if (prev_state->enable_flags.cached_cull_face != + enable_flags.cached_cull_face) + EnableDisable(GL_CULL_FACE, enable_flags.cached_cull_face); + if (prev_state->enable_flags.cached_depth_test != + enable_flags.cached_depth_test) + EnableDisable(GL_DEPTH_TEST, enable_flags.cached_depth_test); + if (prev_state->enable_flags.cached_dither != enable_flags.cached_dither) + EnableDisable(GL_DITHER, enable_flags.cached_dither); + if (prev_state->enable_flags.cached_polygon_offset_fill != + enable_flags.cached_polygon_offset_fill) + EnableDisable(GL_POLYGON_OFFSET_FILL, + enable_flags.cached_polygon_offset_fill); + if (prev_state->enable_flags.cached_sample_alpha_to_coverage != + enable_flags.cached_sample_alpha_to_coverage) + EnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE, + enable_flags.cached_sample_alpha_to_coverage); + if (prev_state->enable_flags.cached_sample_coverage != + enable_flags.cached_sample_coverage) + EnableDisable(GL_SAMPLE_COVERAGE, enable_flags.cached_sample_coverage); + if (prev_state->enable_flags.cached_scissor_test != + enable_flags.cached_scissor_test) + EnableDisable(GL_SCISSOR_TEST, enable_flags.cached_scissor_test); + if (prev_state->enable_flags.cached_stencil_test != + enable_flags.cached_stencil_test) + EnableDisable(GL_STENCIL_TEST, enable_flags.cached_stencil_test); + } else { + EnableDisable(GL_BLEND, enable_flags.cached_blend); + EnableDisable(GL_CULL_FACE, enable_flags.cached_cull_face); + EnableDisable(GL_DEPTH_TEST, enable_flags.cached_depth_test); + EnableDisable(GL_DITHER, enable_flags.cached_dither); + EnableDisable(GL_POLYGON_OFFSET_FILL, + enable_flags.cached_polygon_offset_fill); + EnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE, + enable_flags.cached_sample_alpha_to_coverage); + EnableDisable(GL_SAMPLE_COVERAGE, enable_flags.cached_sample_coverage); + EnableDisable(GL_SCISSOR_TEST, enable_flags.cached_scissor_test); + EnableDisable(GL_STENCIL_TEST, enable_flags.cached_stencil_test); + } } -void ContextState::InitState() const { - glBlendColor( - blend_color_red, blend_color_green, blend_color_blue, blend_color_alpha); - glBlendEquationSeparate(blend_equation_rgb, blend_equation_alpha); - glBlendFuncSeparate( - blend_source_rgb, blend_dest_rgb, blend_source_alpha, blend_dest_alpha); - glClearColor( - color_clear_red, color_clear_green, color_clear_blue, color_clear_alpha); - glClearDepth(depth_clear); - glClearStencil(stencil_clear); - glColorMask( - color_mask_red, color_mask_green, color_mask_blue, color_mask_alpha); - glCullFace(cull_mode); - glDepthFunc(depth_func); - glDepthMask(depth_mask); - glDepthRange(z_near, z_far); - glFrontFace(front_face); - glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap); - if (feature_info_->feature_flags().oes_standard_derivatives) - glHint( - GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, hint_fragment_shader_derivative); - glLineWidth(line_width); - glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); - glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); - glPolygonOffset(polygon_offset_factor, polygon_offset_units); - glSampleCoverage(sample_coverage_value, sample_coverage_invert); - glScissor(scissor_x, scissor_y, scissor_width, scissor_height); - glStencilFuncSeparate( - GL_FRONT, stencil_front_func, stencil_front_ref, stencil_front_mask); - glStencilFuncSeparate( - GL_BACK, stencil_back_func, stencil_back_ref, stencil_back_mask); - glStencilMaskSeparate(GL_FRONT, stencil_front_writemask); - glStencilMaskSeparate(GL_BACK, stencil_back_writemask); - glStencilOpSeparate( - GL_FRONT, stencil_front_fail_op, stencil_front_z_fail_op, - stencil_front_z_pass_op); - glStencilOpSeparate( - GL_BACK, stencil_back_fail_op, stencil_back_z_fail_op, - stencil_back_z_pass_op); - glViewport(viewport_x, viewport_y, viewport_width, viewport_height); +void ContextState::InitState(const ContextState* prev_state) const { + if (prev_state) { + if ((blend_color_red != prev_state->blend_color_red) || + (blend_color_green != prev_state->blend_color_green) || + (blend_color_blue != prev_state->blend_color_blue) || + (blend_color_alpha != prev_state->blend_color_alpha)) + glBlendColor(blend_color_red, + blend_color_green, + blend_color_blue, + blend_color_alpha); + if ((blend_equation_rgb != prev_state->blend_equation_rgb) || + (blend_equation_alpha != prev_state->blend_equation_alpha)) + glBlendEquationSeparate(blend_equation_rgb, blend_equation_alpha); + if ((blend_source_rgb != prev_state->blend_source_rgb) || + (blend_dest_rgb != prev_state->blend_dest_rgb) || + (blend_source_alpha != prev_state->blend_source_alpha) || + (blend_dest_alpha != prev_state->blend_dest_alpha)) + glBlendFuncSeparate(blend_source_rgb, + blend_dest_rgb, + blend_source_alpha, + blend_dest_alpha); + if ((color_clear_red != prev_state->color_clear_red) || + (color_clear_green != prev_state->color_clear_green) || + (color_clear_blue != prev_state->color_clear_blue) || + (color_clear_alpha != prev_state->color_clear_alpha)) + glClearColor(color_clear_red, + color_clear_green, + color_clear_blue, + color_clear_alpha); + if ((depth_clear != prev_state->depth_clear)) + glClearDepth(depth_clear); + if ((stencil_clear != prev_state->stencil_clear)) + glClearStencil(stencil_clear); + if ((cached_color_mask_red != prev_state->cached_color_mask_red) || + (cached_color_mask_green != prev_state->cached_color_mask_green) || + (cached_color_mask_blue != prev_state->cached_color_mask_blue) || + (cached_color_mask_alpha != prev_state->cached_color_mask_alpha)) + glColorMask(cached_color_mask_red, + cached_color_mask_green, + cached_color_mask_blue, + cached_color_mask_alpha); + if ((cull_mode != prev_state->cull_mode)) + glCullFace(cull_mode); + if ((depth_func != prev_state->depth_func)) + glDepthFunc(depth_func); + if ((cached_depth_mask != prev_state->cached_depth_mask)) + glDepthMask(cached_depth_mask); + if ((z_near != prev_state->z_near) || (z_far != prev_state->z_far)) + glDepthRange(z_near, z_far); + if ((front_face != prev_state->front_face)) + glFrontFace(front_face); + if (prev_state->hint_generate_mipmap != hint_generate_mipmap) + glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap); + if (feature_info_->feature_flags().oes_standard_derivatives) + if (prev_state->hint_fragment_shader_derivative != + hint_fragment_shader_derivative) + glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, + hint_fragment_shader_derivative); + if ((line_width != prev_state->line_width)) + glLineWidth(line_width); + if (prev_state->pack_alignment != pack_alignment) + glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); + if (prev_state->unpack_alignment != unpack_alignment) + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); + if ((polygon_offset_factor != prev_state->polygon_offset_factor) || + (polygon_offset_units != prev_state->polygon_offset_units)) + glPolygonOffset(polygon_offset_factor, polygon_offset_units); + if ((sample_coverage_value != prev_state->sample_coverage_value) || + (sample_coverage_invert != prev_state->sample_coverage_invert)) + glSampleCoverage(sample_coverage_value, sample_coverage_invert); + if ((scissor_x != prev_state->scissor_x) || + (scissor_y != prev_state->scissor_y) || + (scissor_width != prev_state->scissor_width) || + (scissor_height != prev_state->scissor_height)) + glScissor(scissor_x, scissor_y, scissor_width, scissor_height); + if ((stencil_front_func != prev_state->stencil_front_func) || + (stencil_front_ref != prev_state->stencil_front_ref) || + (stencil_front_mask != prev_state->stencil_front_mask)) + glStencilFuncSeparate( + GL_FRONT, stencil_front_func, stencil_front_ref, stencil_front_mask); + if ((stencil_back_func != prev_state->stencil_back_func) || + (stencil_back_ref != prev_state->stencil_back_ref) || + (stencil_back_mask != prev_state->stencil_back_mask)) + glStencilFuncSeparate( + GL_BACK, stencil_back_func, stencil_back_ref, stencil_back_mask); + if ((cached_stencil_front_writemask != + prev_state->cached_stencil_front_writemask)) + glStencilMaskSeparate(GL_FRONT, cached_stencil_front_writemask); + if ((cached_stencil_back_writemask != + prev_state->cached_stencil_back_writemask)) + glStencilMaskSeparate(GL_BACK, cached_stencil_back_writemask); + if ((stencil_front_fail_op != prev_state->stencil_front_fail_op) || + (stencil_front_z_fail_op != prev_state->stencil_front_z_fail_op) || + (stencil_front_z_pass_op != prev_state->stencil_front_z_pass_op)) + glStencilOpSeparate(GL_FRONT, + stencil_front_fail_op, + stencil_front_z_fail_op, + stencil_front_z_pass_op); + if ((stencil_back_fail_op != prev_state->stencil_back_fail_op) || + (stencil_back_z_fail_op != prev_state->stencil_back_z_fail_op) || + (stencil_back_z_pass_op != prev_state->stencil_back_z_pass_op)) + glStencilOpSeparate(GL_BACK, + stencil_back_fail_op, + stencil_back_z_fail_op, + stencil_back_z_pass_op); + if ((viewport_x != prev_state->viewport_x) || + (viewport_y != prev_state->viewport_y) || + (viewport_width != prev_state->viewport_width) || + (viewport_height != prev_state->viewport_height)) + glViewport(viewport_x, viewport_y, viewport_width, viewport_height); + } else { + glBlendColor(blend_color_red, + blend_color_green, + blend_color_blue, + blend_color_alpha); + glBlendEquationSeparate(blend_equation_rgb, blend_equation_alpha); + glBlendFuncSeparate( + blend_source_rgb, blend_dest_rgb, blend_source_alpha, blend_dest_alpha); + glClearColor(color_clear_red, + color_clear_green, + color_clear_blue, + color_clear_alpha); + glClearDepth(depth_clear); + glClearStencil(stencil_clear); + glColorMask(cached_color_mask_red, + cached_color_mask_green, + cached_color_mask_blue, + cached_color_mask_alpha); + glCullFace(cull_mode); + glDepthFunc(depth_func); + glDepthMask(cached_depth_mask); + glDepthRange(z_near, z_far); + glFrontFace(front_face); + glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap); + if (feature_info_->feature_flags().oes_standard_derivatives) + glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, + hint_fragment_shader_derivative); + glLineWidth(line_width); + glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); + glPolygonOffset(polygon_offset_factor, polygon_offset_units); + glSampleCoverage(sample_coverage_value, sample_coverage_invert); + glScissor(scissor_x, scissor_y, scissor_width, scissor_height); + glStencilFuncSeparate( + GL_FRONT, stencil_front_func, stencil_front_ref, stencil_front_mask); + glStencilFuncSeparate( + GL_BACK, stencil_back_func, stencil_back_ref, stencil_back_mask); + glStencilMaskSeparate(GL_FRONT, cached_stencil_front_writemask); + glStencilMaskSeparate(GL_BACK, cached_stencil_back_writemask); + glStencilOpSeparate(GL_FRONT, + stencil_front_fail_op, + stencil_front_z_fail_op, + stencil_front_z_pass_op); + glStencilOpSeparate(GL_BACK, + stencil_back_fail_op, + stencil_back_z_fail_op, + stencil_back_z_pass_op); + glViewport(viewport_x, viewport_y, viewport_width, viewport_height); + } } bool ContextState::GetEnabled(GLenum cap) const { switch (cap) { @@ -162,8 +330,9 @@ bool ContextState::GetEnabled(GLenum cap) const { } } -bool ContextState::GetStateAsGLint( - GLenum pname, GLint* params, GLsizei* num_written) const { +bool ContextState::GetStateAsGLint(GLenum pname, + GLint* params, + GLsizei* num_written) const { switch (pname) { case GL_BLEND_COLOR: *num_written = 4; @@ -486,8 +655,9 @@ bool ContextState::GetStateAsGLint( } } -bool ContextState::GetStateAsGLfloat( - GLenum pname, GLfloat* params, GLsizei* num_written) const { +bool ContextState::GetStateAsGLfloat(GLenum pname, + GLfloat* params, + GLsizei* num_written) const { switch (pname) { case GL_BLEND_COLOR: *num_written = 4; @@ -784,8 +954,7 @@ bool ContextState::GetStateAsGLfloat( case GL_SAMPLE_ALPHA_TO_COVERAGE: *num_written = 1; if (params) { - params[0] = - static_cast<GLfloat>(enable_flags.sample_alpha_to_coverage); + params[0] = static_cast<GLfloat>(enable_flags.sample_alpha_to_coverage); } return true; case GL_SAMPLE_COVERAGE: @@ -811,4 +980,3 @@ bool ContextState::GetStateAsGLfloat( } } #endif // GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_IMPL_AUTOGEN_H_ - diff --git a/chromium/gpu/command_buffer/service/error_state.cc b/chromium/gpu/command_buffer/service/error_state.cc index 524ea4f79ec..ce65aa194d0 100644 --- a/chromium/gpu/command_buffer/service/error_state.cc +++ b/chromium/gpu/command_buffer/service/error_state.cc @@ -16,7 +16,7 @@ namespace gles2 { class ErrorStateImpl : public ErrorState { public: - explicit ErrorStateImpl(Logger* logger); + explicit ErrorStateImpl(ErrorStateClient* client, Logger* logger); virtual ~ErrorStateImpl(); virtual uint32 GetGLError() OVERRIDE; @@ -33,13 +33,20 @@ class ErrorStateImpl : public ErrorState { const char* function_name, unsigned int value, const char* label) OVERRIDE; - virtual void SetGLErrorInvalidParam( + virtual void SetGLErrorInvalidParami( const char* filename, int line, unsigned int error, const char* function_name, unsigned int pname, int param) OVERRIDE; + virtual void SetGLErrorInvalidParamf( + const char* filename, + int line, + unsigned int error, + const char* function_name, + unsigned int pname, + float param) OVERRIDE; virtual unsigned int PeekGLError( const char* filename, int line, const char* function_name) OVERRIDE; @@ -56,6 +63,7 @@ class ErrorStateImpl : public ErrorState { // Current GL error bits. uint32 error_bits_; + ErrorStateClient* client_; Logger* logger_; DISALLOW_COPY_AND_ASSIGN(ErrorStateImpl); @@ -65,13 +73,12 @@ ErrorState::ErrorState() {} ErrorState::~ErrorState() {} -ErrorState* ErrorState::Create(Logger* logger) { - return new ErrorStateImpl(logger); +ErrorState* ErrorState::Create(ErrorStateClient* client, Logger* logger) { + return new ErrorStateImpl(client, logger); } -ErrorStateImpl::ErrorStateImpl(Logger* logger) - : error_bits_(0), - logger_(logger) {} +ErrorStateImpl::ErrorStateImpl(ErrorStateClient* client, Logger* logger) + : error_bits_(0), client_(client), logger_(logger) {} ErrorStateImpl::~ErrorStateImpl() {} @@ -118,6 +125,8 @@ void ErrorStateImpl::SetGLError( function_name + ": " + msg); } error_bits_ |= GLES2Util::GLErrorToErrorBit(error); + if (error == GL_OUT_OF_MEMORY) + client_->OnOutOfMemoryError(); } void ErrorStateImpl::SetGLErrorInvalidEnum( @@ -131,7 +140,7 @@ void ErrorStateImpl::SetGLErrorInvalidEnum( GLES2Util::GetStringEnum(value)).c_str()); } -void ErrorStateImpl::SetGLErrorInvalidParam( +void ErrorStateImpl::SetGLErrorInvalidParami( const char* filename, int line, unsigned int error, @@ -152,6 +161,19 @@ void ErrorStateImpl::SetGLErrorInvalidParam( } } +void ErrorStateImpl::SetGLErrorInvalidParamf( + const char* filename, + int line, + unsigned int error, + const char* function_name, + unsigned int pname, float param) { + SetGLError( + filename, line, error, function_name, + (std::string("trying to set ") + + GLES2Util::GetStringEnum(pname) + " to " + + base::StringPrintf("%G", param)).c_str()); +} + void ErrorStateImpl::CopyRealGLErrorsToWrapper( const char* filename, int line, const char* function_name) { GLenum error; diff --git a/chromium/gpu/command_buffer/service/error_state.h b/chromium/gpu/command_buffer/service/error_state.h index 507b7383670..95f118c53c9 100644 --- a/chromium/gpu/command_buffer/service/error_state.h +++ b/chromium/gpu/command_buffer/service/error_state.h @@ -7,8 +7,10 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_ERROR_STATE_H_ #define GPU_COMMAND_BUFFER_SERVICE_ERROR_STATE_H_ +#include <stdint.h> + #include "base/compiler_specific.h" -#include "gpu/command_buffer/common/types.h" +#include "base/macros.h" #include "gpu/gpu_export.h" namespace gpu { @@ -31,10 +33,17 @@ class Logger; __FILE__, __LINE__, function_name, value, label) // Use to synthesize a GL error on the error_state for an invalid enum based -// parameter. Will attempt to expand the parameter to a string. -#define ERRORSTATE_SET_GL_ERROR_INVALID_PARAM( \ +// integer parameter. Will attempt to expand the parameter to a string. +#define ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI( \ + error_state, error, function_name, pname, param) \ + error_state->SetGLErrorInvalidParami( \ + __FILE__, __LINE__, error, function_name, pname, param) + +// Use to synthesize a GL error on the error_state for an invalid enum based +// float parameter. Will attempt to expand the parameter to a string. +#define ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF( \ error_state, error, function_name, pname, param) \ - error_state->SetGLErrorInvalidParam( \ + error_state->SetGLErrorInvalidParamf( \ __FILE__, __LINE__, error, function_name, pname, param) // Use to move all pending error to the wrapper so on your next GL call @@ -48,14 +57,19 @@ class Logger; #define ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state, function_name) \ error_state->ClearRealGLErrors(__FILE__, __LINE__, function_name) +class GPU_EXPORT ErrorStateClient { + public: + // GL_OUT_OF_MEMORY can cause side effects such as losing the context. + virtual void OnOutOfMemoryError() = 0; +}; class GPU_EXPORT ErrorState { public: virtual ~ErrorState(); - static ErrorState* Create(Logger* logger); + static ErrorState* Create(ErrorStateClient* client, Logger* logger); - virtual uint32 GetGLError() = 0; + virtual uint32_t GetGLError() = 0; virtual void SetGLError( const char* filename, @@ -69,13 +83,20 @@ class GPU_EXPORT ErrorState { const char* function_name, unsigned int value, const char* label) = 0; - virtual void SetGLErrorInvalidParam( + virtual void SetGLErrorInvalidParami( const char* filename, int line, unsigned int error, const char* function_name, unsigned int pname, int param) = 0; + virtual void SetGLErrorInvalidParamf( + const char* filename, + int line, + unsigned int error, + const char* function_name, + unsigned int pname, + float param) = 0; // Gets the GLError and stores it in our wrapper. Effectively // this lets us peek at the error without losing it. diff --git a/chromium/gpu/command_buffer/service/error_state_mock.h b/chromium/gpu/command_buffer/service/error_state_mock.h index 00bed9a4712..eb056f34f4b 100644 --- a/chromium/gpu/command_buffer/service/error_state_mock.h +++ b/chromium/gpu/command_buffer/service/error_state_mock.h @@ -18,20 +18,27 @@ class MockErrorState : public ErrorState { MockErrorState(); virtual ~MockErrorState(); - MOCK_METHOD0(GetGLError, uint32()); + MOCK_METHOD0(GetGLError, uint32_t()); MOCK_METHOD5(SetGLError, void( const char* filename, int line, unsigned error, const char* function_name, const char* msg)); MOCK_METHOD5(SetGLErrorInvalidEnum, void( const char* filename, int line, const char* function_name, unsigned value, const char* label)); - MOCK_METHOD6(SetGLErrorInvalidParam, void( + MOCK_METHOD6(SetGLErrorInvalidParami, void( const char* filename, int line, unsigned error, const char* function_name, unsigned pname, int param)); + MOCK_METHOD6(SetGLErrorInvalidParamf, void( + const char* filename, + int line, + unsigned error, + const char* function_name, + unsigned pname, + float param)); MOCK_METHOD3(PeekGLError, unsigned( const char* file, int line, const char* filename)); MOCK_METHOD3(CopyRealGLErrorsToWrapper, void( diff --git a/chromium/gpu/command_buffer/service/feature_info.cc b/chromium/gpu/command_buffer/service/feature_info.cc index cbcf968adc2..94eb4cc0a23 100644 --- a/chromium/gpu/command_buffer/service/feature_info.cc +++ b/chromium/gpu/command_buffer/service/feature_info.cc @@ -7,6 +7,8 @@ #include <set> #include "base/command_line.h" +#include "base/macros.h" +#include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -14,10 +16,6 @@ #include "gpu/command_buffer/service/gpu_switches.h" #include "ui/gl/gl_implementation.h" -#if defined(OS_MACOSX) -#include "ui/gl/io_surface_support_mac.h" -#endif - namespace gpu { namespace gles2 { @@ -94,12 +92,22 @@ void StringToWorkarounds( workarounds->max_cube_map_texture_size = 1024; if (workarounds->max_cube_map_texture_size_limit_512) workarounds->max_cube_map_texture_size = 512; + + if (workarounds->max_fragment_uniform_vectors_32) + workarounds->max_fragment_uniform_vectors = 32; + if (workarounds->max_varying_vectors_16) + workarounds->max_varying_vectors = 16; + if (workarounds->max_vertex_uniform_vectors_256) + workarounds->max_vertex_uniform_vectors = 256; } } // anonymous namespace. FeatureInfo::FeatureFlags::FeatureFlags() - : chromium_framebuffer_multisample(false), + : chromium_color_buffer_float_rgba(false), + chromium_color_buffer_float_rgb(false), + chromium_framebuffer_multisample(false), + chromium_sync_query(false), use_core_framebuffer_multisample(false), multisampled_render_to_texture(false), use_img_for_multisampled_render_to_texture(false), @@ -111,7 +119,6 @@ FeatureInfo::FeatureFlags::FeatureFlags() npot_ok(false), enable_texture_float_linear(false), enable_texture_half_float_linear(false), - chromium_stream_texture(false), angle_translated_shader_source(false), angle_pack_reverse_row_order(false), arb_texture_rectangle(false), @@ -125,6 +132,7 @@ FeatureInfo::FeatureFlags::FeatureFlags() enable_samplers(false), ext_draw_buffers(false), ext_frag_depth(false), + ext_shader_texture_lod(false), use_async_readpixels(false), map_buffer_range(false), ext_discard_framebuffer(false), @@ -140,7 +148,10 @@ FeatureInfo::Workarounds::Workarounds() : GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) #undef GPU_OP max_texture_size(0), - max_cube_map_texture_size(0) { + max_cube_map_texture_size(0), + max_fragment_uniform_vectors(0), + max_varying_vectors(0), + max_vertex_uniform_vectors(0) { } FeatureInfo::FeatureInfo() { @@ -244,15 +255,9 @@ void FeatureInfo::InitializeFeatures() { AddExtensionString("GL_CHROMIUM_resize"); AddExtensionString("GL_CHROMIUM_resource_safe"); AddExtensionString("GL_CHROMIUM_strict_attribs"); - AddExtensionString("GL_CHROMIUM_stream_texture"); AddExtensionString("GL_CHROMIUM_texture_mailbox"); AddExtensionString("GL_EXT_debug_marker"); - if (workarounds_.enable_chromium_fast_npot_mo8_textures) - AddExtensionString("GL_CHROMIUM_fast_NPOT_MO8_textures"); - - feature_flags_.chromium_stream_texture = true; - // OES_vertex_array_object is emulated if not present natively, // so the extension string is always exposed. AddExtensionString("GL_OES_vertex_array_object"); @@ -444,26 +449,28 @@ void FeatureInfo::InitializeFeatures() { bool enable_texture_half_float = false; bool enable_texture_half_float_linear = false; - bool have_arb_texture_float = extensions.Contains("GL_ARB_texture_float"); + bool may_enable_chromium_color_buffer_float = false; - if (have_arb_texture_float) { + if (extensions.Contains("GL_ARB_texture_float")) { enable_texture_float = true; enable_texture_float_linear = true; enable_texture_half_float = true; enable_texture_half_float_linear = true; + may_enable_chromium_color_buffer_float = true; } else { - if (extensions.Contains("GL_OES_texture_float") || have_arb_texture_float) { + if (extensions.Contains("GL_OES_texture_float")) { enable_texture_float = true; - if (extensions.Contains("GL_OES_texture_float_linear") || - have_arb_texture_float) { + if (extensions.Contains("GL_OES_texture_float_linear")) { enable_texture_float_linear = true; } + if ((is_es3 && extensions.Contains("GL_EXT_color_buffer_float")) || + feature_flags_.is_angle) { + may_enable_chromium_color_buffer_float = true; + } } - if (extensions.Contains("GL_OES_texture_half_float") || - have_arb_texture_float) { + if (extensions.Contains("GL_OES_texture_half_float")) { enable_texture_half_float = true; - if (extensions.Contains("GL_OES_texture_half_float_linear") || - have_arb_texture_float) { + if (extensions.Contains("GL_OES_texture_half_float_linear")) { enable_texture_half_float_linear = true; } } @@ -497,9 +504,64 @@ void FeatureInfo::InitializeFeatures() { } } + if (may_enable_chromium_color_buffer_float) { + COMPILE_ASSERT(GL_RGBA32F_ARB == GL_RGBA32F && + GL_RGBA32F_EXT == GL_RGBA32F && + GL_RGB32F_ARB == GL_RGB32F && + GL_RGB32F_EXT == GL_RGB32F, + sized_float_internal_format_variations_must_match); + // We don't check extension support beyond ARB_texture_float on desktop GL, + // and format support varies between GL configurations. For example, spec + // prior to OpenGL 3.0 mandates framebuffer support only for one + // implementation-chosen format, and ES3.0 EXT_color_buffer_float does not + // support rendering to RGB32F. Check for framebuffer completeness with + // formats that the extensions expose, and only enable an extension when a + // framebuffer created with its texture format is reported as complete. + GLint fb_binding = 0; + GLint tex_binding = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb_binding); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex_binding); + + GLuint tex_id = 0; + GLuint fb_id = 0; + GLsizei width = 16; + + glGenTextures(1, &tex_id); + glGenFramebuffersEXT(1, &fb_id); + glBindTexture(GL_TEXTURE_2D, tex_id); + // Nearest filter needed for framebuffer completeness on some drivers. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, GL_RGBA, + GL_FLOAT, NULL); + glBindFramebufferEXT(GL_FRAMEBUFFER, fb_id); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, tex_id, 0); + GLenum statusRGBA = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, GL_RGB, + GL_FLOAT, NULL); + GLenum statusRGB = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + glDeleteFramebuffersEXT(1, &fb_id); + glDeleteTextures(1, &tex_id); + + glBindFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLuint>(fb_binding)); + glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(tex_binding)); + + DCHECK(glGetError() == GL_NO_ERROR); + + if (statusRGBA == GL_FRAMEBUFFER_COMPLETE) { + validators_.texture_internal_format.AddValue(GL_RGBA32F); + feature_flags_.chromium_color_buffer_float_rgba = true; + AddExtensionString("GL_CHROMIUM_color_buffer_float_rgba"); + } + if (statusRGB == GL_FRAMEBUFFER_COMPLETE) { + validators_.texture_internal_format.AddValue(GL_RGB32F); + feature_flags_.chromium_color_buffer_float_rgb = true; + AddExtensionString("GL_CHROMIUM_color_buffer_float_rgb"); + } + } + // Check for multisample support - if (!disallowed_features_.multisampling && - !workarounds_.disable_framebuffer_multisample) { + if (!workarounds_.disable_multisampling) { bool ext_has_multisample = extensions.Contains("GL_EXT_framebuffer_multisample") || is_es3; if (feature_flags_.is_angle) { @@ -515,21 +577,20 @@ void FeatureInfo::InitializeFeatures() { validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT); validators_.render_buffer_parameter.AddValue(GL_RENDERBUFFER_SAMPLES_EXT); AddExtensionString("GL_CHROMIUM_framebuffer_multisample"); - } else { - if (extensions.Contains("GL_EXT_multisampled_render_to_texture")) { - feature_flags_.multisampled_render_to_texture = true; - } else if (extensions.Contains("GL_IMG_multisampled_render_to_texture")) { - feature_flags_.multisampled_render_to_texture = true; - feature_flags_.use_img_for_multisampled_render_to_texture = true; - } - if (feature_flags_.multisampled_render_to_texture) { - validators_.render_buffer_parameter.AddValue( - GL_RENDERBUFFER_SAMPLES_EXT); - validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT); - validators_.frame_buffer_parameter.AddValue( - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT); - AddExtensionString("GL_EXT_multisampled_render_to_texture"); - } + } + if (extensions.Contains("GL_EXT_multisampled_render_to_texture")) { + feature_flags_.multisampled_render_to_texture = true; + } else if (extensions.Contains("GL_IMG_multisampled_render_to_texture")) { + feature_flags_.multisampled_render_to_texture = true; + feature_flags_.use_img_for_multisampled_render_to_texture = true; + } + if (feature_flags_.multisampled_render_to_texture) { + validators_.render_buffer_parameter.AddValue( + GL_RENDERBUFFER_SAMPLES_EXT); + validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT); + validators_.frame_buffer_parameter.AddValue( + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT); + AddExtensionString("GL_EXT_multisampled_render_to_texture"); } } @@ -564,6 +625,28 @@ void FeatureInfo::InitializeFeatures() { validators_.compressed_texture_format.AddValue(GL_ETC1_RGB8_OES); } + if (extensions.Contains("GL_AMD_compressed_ATC_texture")) { + AddExtensionString("GL_AMD_compressed_ATC_texture"); + validators_.compressed_texture_format.AddValue( + GL_ATC_RGB_AMD); + validators_.compressed_texture_format.AddValue( + GL_ATC_RGBA_EXPLICIT_ALPHA_AMD); + validators_.compressed_texture_format.AddValue( + GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD); + } + + if (extensions.Contains("GL_IMG_texture_compression_pvrtc")) { + AddExtensionString("GL_IMG_texture_compression_pvrtc"); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); + } + // Ideally we would only expose this extension on Mac OS X, to // support GL_CHROMIUM_iosurface and the compositor. We don't want // applications to start using it; they should use ordinary non- @@ -583,9 +666,7 @@ void FeatureInfo::InitializeFeatures() { } #if defined(OS_MACOSX) - if (IOSurfaceSupport::Initialize()) { - AddExtensionString("GL_CHROMIUM_iosurface"); - } + AddExtensionString("GL_CHROMIUM_iosurface"); #endif // TODO(gman): Add support for these extensions. @@ -658,7 +739,8 @@ void FeatureInfo::InitializeFeatures() { if (!workarounds_.disable_angle_instanced_arrays && (extensions.Contains("GL_ANGLE_instanced_arrays") || (extensions.Contains("GL_ARB_instanced_arrays") && - extensions.Contains("GL_ARB_draw_instanced")))) { + extensions.Contains("GL_ARB_draw_instanced")) || + is_es3)) { AddExtensionString("GL_ANGLE_instanced_arrays"); feature_flags_.angle_instanced_arrays = true; validators_.vertex_attribute.AddValue(GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); @@ -689,14 +771,37 @@ void FeatureInfo::InitializeFeatures() { } } + if (extensions.Contains("GL_EXT_blend_minmax") || + gfx::HasDesktopGLFeatures()) { + AddExtensionString("GL_EXT_blend_minmax"); + validators_.equation.AddValue(GL_MIN_EXT); + validators_.equation.AddValue(GL_MAX_EXT); + } + if (extensions.Contains("GL_EXT_frag_depth") || gfx::HasDesktopGLFeatures()) { AddExtensionString("GL_EXT_frag_depth"); feature_flags_.ext_frag_depth = true; } - bool ui_gl_fence_works = extensions.Contains("GL_NV_fence") || - extensions.Contains("GL_ARB_sync") || - extensions.Contains("EGL_KHR_fence_sync"); + if (extensions.Contains("GL_EXT_shader_texture_lod") || + gfx::HasDesktopGLFeatures()) { + AddExtensionString("GL_EXT_shader_texture_lod"); + feature_flags_.ext_shader_texture_lod = true; + } + + bool egl_khr_fence_sync = false; +#if !defined(OS_MACOSX) + if (workarounds_.disable_egl_khr_fence_sync) { + gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync = false; + } + egl_khr_fence_sync = gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync; +#endif + if (workarounds_.disable_arb_sync) + gfx::g_driver_gl.ext.b_GL_ARB_sync = false; + bool ui_gl_fence_works = is_es3 || extensions.Contains("GL_NV_fence") || + gfx::g_driver_gl.ext.b_GL_ARB_sync || + egl_khr_fence_sync; + UMA_HISTOGRAM_BOOLEAN("GPU.FenceSupport", ui_gl_fence_works); feature_flags_.map_buffer_range = is_es3 || extensions.Contains("GL_ARB_map_buffer_range"); @@ -724,10 +829,22 @@ void FeatureInfo::InitializeFeatures() { AddExtensionString("GL_EXT_discard_framebuffer"); feature_flags_.ext_discard_framebuffer = true; } + + if (ui_gl_fence_works) { + AddExtensionString("GL_CHROMIUM_sync_query"); + feature_flags_.chromium_sync_query = true; + } } void FeatureInfo::AddExtensionString(const std::string& str) { - if (extensions_.find(str) == std::string::npos) { + size_t pos = extensions_.find(str); + while (pos != std::string::npos && + pos + str.length() < extensions_.length() && + extensions_.substr(pos + str.length(), 1) != " ") { + // This extension name is a substring of another. + pos = extensions_.find(str, pos + str.length()); + } + if (pos == std::string::npos) { extensions_ += (extensions_.empty() ? "" : " ") + str; } } diff --git a/chromium/gpu/command_buffer/service/feature_info.h b/chromium/gpu/command_buffer/service/feature_info.h index ca8c03c7328..8e9c07cac32 100644 --- a/chromium/gpu/command_buffer/service/feature_info.h +++ b/chromium/gpu/command_buffer/service/feature_info.h @@ -15,7 +15,9 @@ #include "gpu/config/gpu_driver_bug_workaround_type.h" #include "gpu/gpu_export.h" +namespace base { class CommandLine; +} namespace gpu { namespace gles2 { @@ -26,7 +28,10 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { struct FeatureFlags { FeatureFlags(); + bool chromium_color_buffer_float_rgba; + bool chromium_color_buffer_float_rgb; bool chromium_framebuffer_multisample; + bool chromium_sync_query; // Use glBlitFramebuffer() and glRenderbufferStorageMultisample() with // GL_EXT_framebuffer_multisample-style semantics, since they are exposed // as core GL functions on this implementation. @@ -42,7 +47,6 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool npot_ok; bool enable_texture_float_linear; bool enable_texture_half_float_linear; - bool chromium_stream_texture; bool angle_translated_shader_source; bool angle_pack_reverse_row_order; bool arb_texture_rectangle; @@ -56,6 +60,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool enable_samplers; bool ext_draw_buffers; bool ext_frag_depth; + bool ext_shader_texture_lod; bool use_async_readpixels; bool map_buffer_range; bool ext_discard_framebuffer; @@ -76,13 +81,16 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { // Note: 0 here means use driver limit. GLint max_texture_size; GLint max_cube_map_texture_size; + GLint max_fragment_uniform_vectors; + GLint max_varying_vectors; + GLint max_vertex_uniform_vectors; }; // Constructor with workarounds taken from the current process's CommandLine FeatureInfo(); // Constructor with workarounds taken from |command_line| - FeatureInfo(const CommandLine& command_line); + FeatureInfo(const base::CommandLine& command_line); // Initializes the feature information. Needs a current GL context. bool Initialize(); @@ -111,7 +119,6 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { private: friend class base::RefCounted<FeatureInfo>; friend class BufferManagerClientSideArraysTest; - friend class GLES2DecoderTestBase; typedef base::hash_map<GLenum, ValueValidator<GLenum> > ValidatorMap; ValidatorMap texture_format_validators_; @@ -119,7 +126,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { ~FeatureInfo(); void AddExtensionString(const std::string& str); - void InitializeBasicState(const CommandLine& command_line); + void InitializeBasicState(const base::CommandLine& command_line); void InitializeFeatures(); Validators validators_; diff --git a/chromium/gpu/command_buffer/service/feature_info_unittest.cc b/chromium/gpu/command_buffer/service/feature_info_unittest.cc index 8164b3580ac..be3e38a6715 100644 --- a/chromium/gpu/command_buffer/service/feature_info_unittest.cc +++ b/chromium/gpu/command_buffer/service/feature_info_unittest.cc @@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" @@ -15,7 +16,6 @@ #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_mock.h" -using ::gfx::MockGLInterface; using ::testing::_; using ::testing::DoAll; using ::testing::HasSubstr; @@ -27,7 +27,6 @@ using ::testing::Return; using ::testing::SetArrayArgument; using ::testing::SetArgumentPointee; using ::testing::StrEq; -using ::testing::StrictMock; namespace gpu { namespace gles2 { @@ -36,7 +35,7 @@ namespace { const char kGLRendererStringANGLE[] = "ANGLE (some renderer)"; } // anonymous namespace -class FeatureInfoTest : public testing::Test { +class FeatureInfoTest : public GpuServiceTest { public: FeatureInfoTest() { } @@ -70,18 +69,11 @@ class FeatureInfoTest : public testing::Test { } protected: - virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - } - virtual void TearDown() { info_ = NULL; - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + GpuServiceTest::TearDown(); } - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<FeatureInfo> info_; }; @@ -110,7 +102,6 @@ TEST_F(FeatureInfoTest, Basic) { EXPECT_FALSE(info_->feature_flags().oes_egl_image_external); EXPECT_FALSE(info_->feature_flags().oes_depth24); EXPECT_FALSE(info_->feature_flags().packed_depth24_stencil8); - EXPECT_FALSE(info_->feature_flags().chromium_stream_texture); EXPECT_FALSE(info_->feature_flags().angle_translated_shader_source); EXPECT_FALSE(info_->feature_flags().angle_pack_reverse_row_order); EXPECT_FALSE(info_->feature_flags().arb_texture_rectangle); @@ -247,6 +238,10 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) { Not(HasSubstr("GL_EXT_texture_storage"))); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_OES_compressed_ETC1_RGB8_texture"))); + EXPECT_THAT(info_->extensions(), + Not(HasSubstr("GL_AMD_compressed_ATC_texture"))); + EXPECT_THAT(info_->extensions(), + Not(HasSubstr("GL_IMG_texture_compression_pvrtc"))); EXPECT_FALSE(info_->feature_flags().npot_ok); EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( GL_COMPRESSED_RGB_S3TC_DXT1_EXT)); @@ -258,6 +253,20 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)); EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( GL_ETC1_RGB8_OES)); + EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( + GL_ATC_RGB_AMD)); + EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( + GL_ATC_RGBA_EXPLICIT_ALPHA_AMD)); + EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( + GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD)); + EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG)); + EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG)); + EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG)); + EXPECT_FALSE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)); EXPECT_FALSE(info_->validators()->read_pixel_format.IsValid( GL_BGRA_EXT)); EXPECT_FALSE(info_->validators()->texture_parameter.IsValid( @@ -281,6 +290,10 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) { GL_DEPTH24_STENCIL8)); EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid( GL_DEPTH_STENCIL)); + EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid( + GL_RGBA32F)); + EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid( + GL_RGB32F)); EXPECT_FALSE(info_->validators()->texture_format.IsValid( GL_DEPTH_STENCIL)); EXPECT_FALSE(info_->validators()->pixel_type.IsValid( @@ -295,6 +308,8 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) { GL_DEPTH_COMPONENT32_OES)); EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( GL_DEPTH24_STENCIL8_OES)); + EXPECT_FALSE(info_->validators()->equation.IsValid(GL_MIN_EXT)); + EXPECT_FALSE(info_->validators()->equation.IsValid(GL_MAX_EXT)); } TEST_F(FeatureInfoTest, InitializeWithANGLE) { @@ -408,6 +423,19 @@ TEST_F(FeatureInfoTest, InitializeEXT_read_format_bgra) { GL_BGRA8_EXT)); } +TEST_F(FeatureInfoTest, InitializeARB_texture_float) { + SetupInitExpectations("GL_ARB_texture_float"); + EXPECT_TRUE(info_->feature_flags().chromium_color_buffer_float_rgba); + EXPECT_TRUE(info_->feature_flags().chromium_color_buffer_float_rgb); + std::string extensions = info_->extensions() + " "; + EXPECT_THAT(extensions, HasSubstr("GL_CHROMIUM_color_buffer_float_rgb ")); + EXPECT_THAT(extensions, HasSubstr("GL_CHROMIUM_color_buffer_float_rgba")); + EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( + GL_RGBA32F)); + EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( + GL_RGB32F)); +} + TEST_F(FeatureInfoTest, InitializeOES_texture_floatGLES2) { SetupInitExpectations("GL_OES_texture_float"); EXPECT_FALSE(info_->feature_flags().enable_texture_float_linear); @@ -618,7 +646,7 @@ TEST_F(FeatureInfoTest, InitializeEXT_multisampled_render_to_texture) { TEST_F(FeatureInfoTest, InitializeIMG_multisampled_render_to_texture) { SetupInitExpectations("GL_IMG_multisampled_render_to_texture"); EXPECT_TRUE(info_->feature_flags( - ).use_img_for_multisampled_render_to_texture); + ).multisampled_render_to_texture); EXPECT_TRUE(info_->feature_flags( ).use_img_for_multisampled_render_to_texture); EXPECT_THAT(info_->extensions(), @@ -810,11 +838,30 @@ TEST_F(FeatureInfoTest, InitializeOES_compressed_ETC1_RGB8_texture) { GL_ETC1_RGB8_OES)); } -TEST_F(FeatureInfoTest, InitializeCHROMIUM_stream_texture) { - SetupInitExpectations("GL_CHROMIUM_stream_texture"); +TEST_F(FeatureInfoTest, InitializeAMD_compressed_ATC_texture) { + SetupInitExpectations("GL_AMD_compressed_ATC_texture"); EXPECT_THAT(info_->extensions(), - HasSubstr("GL_CHROMIUM_stream_texture")); - EXPECT_TRUE(info_->feature_flags().chromium_stream_texture); + HasSubstr("GL_AMD_compressed_ATC_texture")); + EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( + GL_ATC_RGB_AMD)); + EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( + GL_ATC_RGBA_EXPLICIT_ALPHA_AMD)); + EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( + GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD)); +} + +TEST_F(FeatureInfoTest, InitializeIMG_texture_compression_pvrtc) { + SetupInitExpectations("GL_IMG_texture_compression_pvrtc"); + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_IMG_texture_compression_pvrtc")); + EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG)); + EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG)); + EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG)); + EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)); } TEST_F(FeatureInfoTest, InitializeEXT_occlusion_query_boolean) { @@ -899,12 +946,25 @@ TEST_F(FeatureInfoTest, InitializeVAOsWithClientSideArrays) { EXPECT_FALSE(info_->feature_flags().native_vertex_array_object); } +TEST_F(FeatureInfoTest, InitializeEXT_blend_minmax) { + SetupInitExpectations("GL_EXT_blend_minmax"); + EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_blend_minmax")); + EXPECT_TRUE(info_->validators()->equation.IsValid(GL_MIN_EXT)); + EXPECT_TRUE(info_->validators()->equation.IsValid(GL_MAX_EXT)); +} + TEST_F(FeatureInfoTest, InitializeEXT_frag_depth) { SetupInitExpectations("GL_EXT_frag_depth"); EXPECT_TRUE(info_->feature_flags().ext_frag_depth); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_frag_depth")); } +TEST_F(FeatureInfoTest, InitializeEXT_shader_texture_lod) { + SetupInitExpectations("GL_EXT_shader_texture_lod"); + EXPECT_TRUE(info_->feature_flags().ext_shader_texture_lod); + EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_shader_texture_lod")); +} + TEST_F(FeatureInfoTest, InitializeEXT_discard_framebuffer) { SetupInitExpectations("GL_EXT_discard_framebuffer"); EXPECT_TRUE(info_->feature_flags().ext_discard_framebuffer); @@ -927,7 +987,7 @@ TEST_F(FeatureInfoTest, InitializeWithES3) { EXPECT_TRUE(info_->feature_flags().use_core_framebuffer_multisample); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_framebuffer_multisample")); - EXPECT_FALSE(info_->feature_flags().use_async_readpixels); + EXPECT_TRUE(info_->feature_flags().use_async_readpixels); EXPECT_TRUE(info_->feature_flags().oes_depth24); EXPECT_THAT(info_->extensions(), HasSubstr("GL_GOOGLE_depth_texture")); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_depth_texture")); diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.cc b/chromium/gpu/command_buffer/service/framebuffer_manager.cc index 48e503cb45b..4022b3defaa 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.cc @@ -119,6 +119,9 @@ class RenderbufferAttachment renderbuffer_->AddToSignature(signature); } + virtual void OnWillRenderTo() const OVERRIDE {} + virtual void OnDidRenderTo() const OVERRIDE {} + protected: virtual ~RenderbufferAttachment() { } @@ -243,6 +246,14 @@ class TextureAttachment texture_ref_.get(), target_, level_, signature); } + virtual void OnWillRenderTo() const OVERRIDE { + texture_ref_->texture()->OnWillModifyPixels(); + } + + virtual void OnDidRenderTo() const OVERRIDE { + texture_ref_->texture()->OnDidModifyPixels(); + } + protected: virtual ~TextureAttachment() {} @@ -349,6 +360,55 @@ bool Framebuffer::HasUnclearedAttachment( return false; } +bool Framebuffer::HasUnclearedColorAttachments() const { + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + if (it->first >= GL_COLOR_ATTACHMENT0 && + it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) { + const Attachment* attachment = it->second.get(); + if (!attachment->cleared()) + return true; + } + } + return false; +} + +void Framebuffer::ChangeDrawBuffersHelper(bool recover) const { + scoped_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]); + for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) + buffers[i] = GL_NONE; + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + if (it->first >= GL_COLOR_ATTACHMENT0 && + it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) { + buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first; + } + } + bool different = false; + for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) { + if (buffers[i] != draw_buffers_[i]) { + different = true; + break; + } + } + if (different) { + if (recover) + glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get()); + else + glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get()); + } +} + +void Framebuffer::PrepareDrawBuffersForClear() const { + bool recover = false; + ChangeDrawBuffersHelper(recover); +} + +void Framebuffer::RestoreDrawBuffersAfterClear() const { + bool recover = true; + ChangeDrawBuffersHelper(recover); +} + void Framebuffer::MarkAttachmentAsCleared( RenderbufferManager* renderbuffer_manager, TextureManager* texture_manager, @@ -505,6 +565,8 @@ void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) { draw_buffers_[i] = bufs[i]; } + + bool Framebuffer::HasAlphaMRT() const { for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) { if (draw_buffers_[i] != GL_NONE) { @@ -615,6 +677,20 @@ void Framebuffer::OnTextureRefDetached(TextureRef* texture) { manager_->OnTextureRefDetached(texture); } +void Framebuffer::OnWillRenderTo() const { + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + it->second->OnWillRenderTo(); + } +} + +void Framebuffer::OnDidRenderTo() const { + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + it->second->OnDidRenderTo(); + } +} + bool FramebufferManager::GetClientId( GLuint service_id, GLuint* client_id) const { // This doesn't need to be fast. It's only used during slow queries. diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.h b/chromium/gpu/command_buffer/service/framebuffer_manager.h index c469bf87435..b68ab7d9f12 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.h +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.h @@ -49,6 +49,8 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { GLenum attachment_type, uint32 max_color_attachments) = 0; virtual void AddToSignature( TextureManager* texture_manager, std::string* signature) const = 0; + virtual void OnWillRenderTo() const = 0; + virtual void OnDidRenderTo() const = 0; protected: friend class base::RefCounted<Attachment>; @@ -62,6 +64,7 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { } bool HasUnclearedAttachment(GLenum attachment) const; + bool HasUnclearedColorAttachments() const; void MarkAttachmentAsCleared( RenderbufferManager* renderbuffer_manager, @@ -127,6 +130,14 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { void SetDrawBuffers(GLsizei n, const GLenum* bufs); + // If a color buffer is attached to GL_COLOR_ATTACHMENTi, enable that + // draw buffer for glClear(). + void PrepareDrawBuffersForClear() const; + + // Restore draw buffers states that have been changed in + // PrepareDrawBuffersForClear(). + void RestoreDrawBuffersAfterClear() const; + // Return true if any draw buffers has an alpha channel. bool HasAlphaMRT() const; @@ -137,6 +148,8 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { } void OnTextureRefDetached(TextureRef* texture); + void OnWillRenderTo() const; + void OnDidRenderTo() const; private: friend class FramebufferManager; @@ -159,6 +172,10 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { return framebuffer_complete_state_count_id_; } + // Helper function for PrepareDrawBuffersForClear() and + // RestoreDrawBuffersAfterClear(). + void ChangeDrawBuffersHelper(bool recover) const; + // The managers that owns this. FramebufferManager* manager_; diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc index 079325807d4..1ded5585e45 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -5,12 +5,14 @@ #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" +using ::testing::_; using ::testing::Return; namespace gpu { @@ -21,20 +23,26 @@ const GLint kMaxTextureSize = 64; const GLint kMaxCubemapSize = 64; const GLint kMaxRenderbufferSize = 64; const GLint kMaxSamples = 4; +const uint32 kMaxDrawBuffers = 16; +const uint32 kMaxColorAttachments = 16; const bool kDepth24Supported = false; +const bool kUseDefaultTextures = false; } // namespace -class FramebufferManagerTest : public testing::Test { +class FramebufferManagerTest : public GpuServiceTest { public: FramebufferManagerTest() : manager_(1, 1), - texture_manager_( - NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize), - renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples, - kDepth24Supported) { - - } + texture_manager_(NULL, + new FeatureInfo(), + kMaxTextureSize, + kMaxCubemapSize, + kUseDefaultTextures), + renderbuffer_manager_(NULL, + kMaxRenderbufferSize, + kMaxSamples, + kDepth24Supported) {} virtual ~FramebufferManagerTest() { manager_.Destroy(false); texture_manager_.Destroy(false); @@ -42,18 +50,7 @@ class FramebufferManagerTest : public testing::Test { } protected: - virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - } - - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); - } - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; FramebufferManager manager_; TextureManager texture_manager_; RenderbufferManager renderbuffer_manager_; @@ -103,44 +100,48 @@ TEST_F(FramebufferManagerTest, Destroy) { ASSERT_TRUE(framebuffer1 == NULL); } -class FramebufferInfoTest : public testing::Test { +class FramebufferInfoTest : public GpuServiceTest { public: static const GLuint kClient1Id = 1; static const GLuint kService1Id = 11; FramebufferInfoTest() - : manager_(1, 1), - texture_manager_( - NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize), + : manager_(kMaxDrawBuffers, kMaxColorAttachments), + feature_info_(new FeatureInfo()), renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples, kDepth24Supported) { + texture_manager_.reset(new TextureManager(NULL, + feature_info_.get(), + kMaxTextureSize, + kMaxCubemapSize, + kUseDefaultTextures)); } virtual ~FramebufferInfoTest() { manager_.Destroy(false); - texture_manager_.Destroy(false); + texture_manager_->Destroy(false); renderbuffer_manager_.Destroy(false); } protected: virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + InitializeContext("", ""); + } + + void InitializeContext(const char* gl_version, const char* extensions) { + GpuServiceTest::SetUp(); + TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(gl_.get(), + extensions, "", gl_version); + feature_info_->Initialize(); manager_.CreateFramebuffer(kClient1Id, kService1Id); error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>()); framebuffer_ = manager_.GetFramebuffer(kClient1Id); ASSERT_TRUE(framebuffer_ != NULL); } - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); - } - - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; FramebufferManager manager_; Framebuffer* framebuffer_; - TextureManager texture_manager_; + scoped_refptr<FeatureInfo> feature_info_; + scoped_ptr<TextureManager> texture_manager_; RenderbufferManager renderbuffer_manager_; scoped_ptr<MockErrorState> error_state_; }; @@ -268,7 +269,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { // check marking them as cleared. manager_.MarkAttachmentsAsCleared( - framebuffer_, &renderbuffer_manager_, &texture_manager_); + framebuffer_, &renderbuffer_manager_, texture_manager_.get()); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT)); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), @@ -319,7 +320,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { // Clear it. manager_.MarkAttachmentsAsCleared( - framebuffer_, &renderbuffer_manager_, &texture_manager_); + framebuffer_, &renderbuffer_manager_, texture_manager_.get()); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_TRUE(framebuffer_->IsCleared()); @@ -419,9 +420,9 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT), framebuffer_->IsPossiblyComplete()); - texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id); + texture_manager_->CreateTexture(kTextureClient1Id, kTextureService1Id); scoped_refptr<TextureRef> texture1( - texture_manager_.GetTexture(kTextureClient1Id)); + texture_manager_->GetTexture(kTextureClient1Id)); ASSERT_TRUE(texture1.get() != NULL); // check adding one attachment @@ -434,8 +435,8 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat()); // Try format that doesn't work with COLOR_ATTACHMENT0 - texture_manager_.SetTarget(texture1.get(), GL_TEXTURE_2D); - texture_manager_.SetLevelInfo(texture1.get(), + texture_manager_->SetTarget(texture1.get(), GL_TEXTURE_2D); + texture_manager_->SetLevelInfo(texture1.get(), GL_TEXTURE_2D, kLevel1, kBadFormat1, @@ -450,7 +451,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { framebuffer_->IsPossiblyComplete()); // Try a good format. - texture_manager_.SetLevelInfo(texture1.get(), + texture_manager_->SetLevelInfo(texture1.get(), GL_TEXTURE_2D, kLevel1, kFormat1, @@ -464,7 +465,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), framebuffer_->IsPossiblyComplete()); EXPECT_FALSE(framebuffer_->IsCleared()); - texture_manager_.SetLevelInfo(texture1.get(), + texture_manager_->SetLevelInfo(texture1.get(), GL_TEXTURE_2D, kLevel1, kFormat1, @@ -491,12 +492,12 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_TRUE(attachment->cleared()); // Check replacing an attachment - texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id); + texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id); scoped_refptr<TextureRef> texture2( - texture_manager_.GetTexture(kTextureClient2Id)); + texture_manager_->GetTexture(kTextureClient2Id)); ASSERT_TRUE(texture2.get() != NULL); - texture_manager_.SetTarget(texture2.get(), GL_TEXTURE_2D); - texture_manager_.SetLevelInfo(texture2.get(), + texture_manager_->SetTarget(texture2.get(), GL_TEXTURE_2D); + texture_manager_->SetLevelInfo(texture2.get(), GL_TEXTURE_2D, kLevel2, kFormat2, @@ -525,7 +526,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_TRUE(attachment->cleared()); // Check changing attachment - texture_manager_.SetLevelInfo(texture2.get(), + texture_manager_->SetLevelInfo(texture2.get(), GL_TEXTURE_2D, kLevel3, kFormat3, @@ -550,7 +551,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_FALSE(framebuffer_->IsCleared()); // Set to size 0 - texture_manager_.SetLevelInfo(texture2.get(), + texture_manager_->SetLevelInfo(texture2.get(), GL_TEXTURE_2D, kLevel3, kFormat3, @@ -574,6 +575,158 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_TRUE(framebuffer_->IsCleared()); } +TEST_F(FramebufferInfoTest, DrawBuffers) { + const GLuint kTextureClientId[] = { 33, 34 }; + const GLuint kTextureServiceId[] = { 333, 334 }; + + for (GLenum i = GL_COLOR_ATTACHMENT0; + i < GL_COLOR_ATTACHMENT0 + kMaxColorAttachments; ++i) { + EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(i)); + } + EXPECT_FALSE(framebuffer_->HasUnclearedColorAttachments()); + + EXPECT_EQ(static_cast<GLenum>(GL_COLOR_ATTACHMENT0), + framebuffer_->GetDrawBuffer(GL_DRAW_BUFFER0_ARB)); + for (GLenum i = GL_DRAW_BUFFER1_ARB; + i < GL_DRAW_BUFFER0_ARB + kMaxDrawBuffers; ++i) { + EXPECT_EQ(static_cast<GLenum>(GL_NONE), + framebuffer_->GetDrawBuffer(i)); + } + + for (size_t ii = 0; ii < arraysize(kTextureClientId); ++ii) { + texture_manager_->CreateTexture( + kTextureClientId[ii], kTextureServiceId[ii]); + scoped_refptr<TextureRef> texture( + texture_manager_->GetTexture(kTextureClientId[ii])); + ASSERT_TRUE(texture.get() != NULL); + + framebuffer_->AttachTexture( + GL_COLOR_ATTACHMENT0 + ii, texture.get(), GL_TEXTURE_2D, 0, 0); + EXPECT_FALSE( + framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0 + ii)); + + const Framebuffer::Attachment* attachment = + framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0 + ii); + ASSERT_TRUE(attachment != NULL); + EXPECT_TRUE(attachment->cleared()); + } + EXPECT_TRUE(framebuffer_->IsCleared()); + EXPECT_FALSE(framebuffer_->HasUnclearedColorAttachments()); + + // Set a texture as uncleared. + scoped_refptr<TextureRef> texture1( + texture_manager_->GetTexture(kTextureClientId[1])); + texture_manager_->SetTarget(texture1.get(), GL_TEXTURE_2D); + texture_manager_->SetLevelInfo( + texture1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false); + + const Framebuffer::Attachment* attachment1 = + framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT1); + ASSERT_TRUE(attachment1 != NULL); + EXPECT_FALSE(attachment1->cleared()); + EXPECT_FALSE(framebuffer_->IsCleared()); + EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT1)); + EXPECT_TRUE(framebuffer_->HasUnclearedColorAttachments()); + + GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; + framebuffer_->SetDrawBuffers(2, buffers); + EXPECT_EQ(static_cast<GLenum>(GL_COLOR_ATTACHMENT0), + framebuffer_->GetDrawBuffer(GL_DRAW_BUFFER0_ARB)); + EXPECT_EQ(static_cast<GLenum>(GL_COLOR_ATTACHMENT1), + framebuffer_->GetDrawBuffer(GL_DRAW_BUFFER1_ARB)); + for (GLenum i = GL_DRAW_BUFFER2_ARB; + i < GL_DRAW_BUFFER0_ARB + kMaxDrawBuffers; ++i) { + EXPECT_EQ(static_cast<GLenum>(GL_NONE), + framebuffer_->GetDrawBuffer(i)); + } + + // Nothing happens. + framebuffer_->PrepareDrawBuffersForClear(); + framebuffer_->RestoreDrawBuffersAfterClear(); + + // Now we disable a draw buffer 1. + buffers[1] = GL_NONE; + framebuffer_->SetDrawBuffers(2, buffers); + // We will enable the disabled draw buffer for clear(), and disable it + // after the clear. + EXPECT_CALL(*gl_, DrawBuffersARB(kMaxDrawBuffers, _)) + .Times(1) + .RetiresOnSaturation(); + framebuffer_->PrepareDrawBuffersForClear(); + EXPECT_CALL(*gl_, DrawBuffersARB(kMaxDrawBuffers, _)) + .Times(1) + .RetiresOnSaturation(); + framebuffer_->RestoreDrawBuffersAfterClear(); + + // Now remove draw buffer 1's attachment. + framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT1, NULL, 0, 0, 0); + EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT1) == NULL); + + // Nothing happens. + framebuffer_->PrepareDrawBuffersForClear(); + framebuffer_->RestoreDrawBuffersAfterClear(); +} + +class FramebufferInfoFloatTest : public FramebufferInfoTest { + public: + FramebufferInfoFloatTest() + : FramebufferInfoTest() { + } + virtual ~FramebufferInfoFloatTest() { + } + + protected: + virtual void SetUp() { + InitializeContext("OpenGL ES 3.0", + "GL_OES_texture_float GL_EXT_color_buffer_float"); + } +}; + +TEST_F(FramebufferInfoFloatTest, AttachFloatTexture) { + const GLuint kTextureClientId = 33; + const GLuint kTextureServiceId = 333; + const GLint kDepth = 1; + const GLint kBorder = 0; + const GLenum kType = GL_FLOAT; + const GLsizei kWidth = 16; + const GLsizei kHeight = 32; + const GLint kLevel = 0; + const GLenum kFormat = GL_RGBA; + const GLenum kInternalFormat = GL_RGBA32F; + const GLenum kTarget = GL_TEXTURE_2D; + const GLsizei kSamples = 0; + EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); + EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT)); + EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT)); + + texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId); + scoped_refptr<TextureRef> texture( + texture_manager_->GetTexture(kTextureClientId)); + ASSERT_TRUE(texture.get() != NULL); + + framebuffer_->AttachTexture( + GL_COLOR_ATTACHMENT0, texture.get(), kTarget, kLevel, kSamples); + EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat()); + + texture_manager_->SetTarget(texture.get(), GL_TEXTURE_2D); + texture_manager_->SetLevelInfo(texture.get(), + GL_TEXTURE_2D, + kLevel, + kInternalFormat, + kWidth, + kHeight, + kDepth, + kBorder, + kFormat, + kType, + false); + // Texture with a sized float internalformat is allowed as an attachment + // since float color attachment extension is present. + EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), + framebuffer_->IsPossiblyComplete()); +} + TEST_F(FramebufferInfoTest, UnbindRenderbuffer) { const GLuint kRenderbufferClient1Id = 33; const GLuint kRenderbufferService1Id = 333; @@ -618,13 +771,13 @@ TEST_F(FramebufferInfoTest, UnbindTexture) { const GLint kLevel1 = 0; const GLint kSamples1 = 0; - texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id); + texture_manager_->CreateTexture(kTextureClient1Id, kTextureService1Id); scoped_refptr<TextureRef> texture1( - texture_manager_.GetTexture(kTextureClient1Id)); + texture_manager_->GetTexture(kTextureClient1Id)); ASSERT_TRUE(texture1.get() != NULL); - texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id); + texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id); scoped_refptr<TextureRef> texture2( - texture_manager_.GetTexture(kTextureClient2Id)); + texture_manager_->GetTexture(kTextureClient2Id)); ASSERT_TRUE(texture2.get() != NULL); // Attach to 2 attachment points. @@ -661,9 +814,9 @@ TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) { Renderbuffer* renderbuffer1 = renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id); ASSERT_TRUE(renderbuffer1 != NULL); - texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id); + texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id); scoped_refptr<TextureRef> texture2( - texture_manager_.GetTexture(kTextureClient2Id)); + texture_manager_->GetTexture(kTextureClient2Id)); ASSERT_TRUE(texture2.get() != NULL); // Check MarkAsComlete marks as complete. @@ -681,7 +834,7 @@ TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) { // Check MarkAttachmentsAsCleared marks as complete. manager_.MarkAttachmentsAsCleared( - framebuffer_, &renderbuffer_manager_, &texture_manager_); + framebuffer_, &renderbuffer_manager_, texture_manager_.get()); EXPECT_TRUE(manager_.IsComplete(framebuffer_)); // Check Unbind marks as not complete. @@ -707,16 +860,16 @@ TEST_F(FramebufferInfoTest, GetStatus) { Renderbuffer* renderbuffer1 = renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id); ASSERT_TRUE(renderbuffer1 != NULL); - texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id); + texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id); scoped_refptr<TextureRef> texture2( - texture_manager_.GetTexture(kTextureClient2Id)); + texture_manager_->GetTexture(kTextureClient2Id)); ASSERT_TRUE(texture2.get() != NULL); - texture_manager_.SetTarget(texture2.get(), GL_TEXTURE_2D); + texture_manager_->SetTarget(texture2.get(), GL_TEXTURE_2D); EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); - framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check a second call for the same type does not call anything if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { @@ -724,14 +877,14 @@ TEST_F(FramebufferInfoTest, GetStatus) { .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); } - framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check changing the attachments calls CheckFramebufferStatus. framebuffer_->AttachTexture( GL_COLOR_ATTACHMENT0, texture2.get(), kTarget1, kLevel1, kSamples1); EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)).RetiresOnSaturation(); - framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check a second call for the same type does not call anything. if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { @@ -739,13 +892,13 @@ TEST_F(FramebufferInfoTest, GetStatus) { .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); } - framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER); // Check a second call with a different target calls CheckFramebufferStatus. EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check a second call for the same type does not call anything. if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { @@ -753,14 +906,14 @@ TEST_F(FramebufferInfoTest, GetStatus) { .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); } - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check adding another attachment calls CheckFramebufferStatus. framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer1); EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check a second call for the same type does not call anything. if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { @@ -768,26 +921,26 @@ TEST_F(FramebufferInfoTest, GetStatus) { .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); } - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check changing the format calls CheckFramebuffferStatus. - TestHelper::SetTexParameterWithExpectations(gl_.get(), - error_state_.get(), - &texture_manager_, - texture2.get(), - GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE, - GL_NO_ERROR); + TestHelper::SetTexParameteriWithExpectations(gl_.get(), + error_state_.get(), + texture_manager_.get(), + texture2.get(), + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE, + GL_NO_ERROR); EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)) .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check since it did not return FRAMEBUFFER_COMPLETE that it calls // CheckFramebufferStatus - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check putting it back does not call CheckFramebufferStatus. if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) { @@ -795,14 +948,14 @@ TEST_F(FramebufferInfoTest, GetStatus) { .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); } - TestHelper::SetTexParameterWithExpectations(gl_.get(), - error_state_.get(), - &texture_manager_, - texture2.get(), - GL_TEXTURE_WRAP_S, - GL_REPEAT, - GL_NO_ERROR); - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + TestHelper::SetTexParameteriWithExpectations(gl_.get(), + error_state_.get(), + texture_manager_.get(), + texture2.get(), + GL_TEXTURE_WRAP_S, + GL_REPEAT, + GL_NO_ERROR); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); // Check Unbinding does not call CheckFramebufferStatus framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer1); @@ -811,7 +964,7 @@ TEST_F(FramebufferInfoTest, GetStatus) { .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) .RetiresOnSaturation(); } - framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER); + framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER); } } // namespace gles2 diff --git a/chromium/gpu/command_buffer/service/gl_state_restorer_impl.cc b/chromium/gpu/command_buffer/service/gl_state_restorer_impl.cc index 7b3c5ed3841..5fbd425f695 100644 --- a/chromium/gpu/command_buffer/service/gl_state_restorer_impl.cc +++ b/chromium/gpu/command_buffer/service/gl_state_restorer_impl.cc @@ -21,14 +21,22 @@ bool GLStateRestorerImpl::IsInitialized() { return decoder_->initialized(); } -void GLStateRestorerImpl::RestoreState() { +void GLStateRestorerImpl::RestoreState(const gfx::GLStateRestorer* prev_state) { DCHECK(decoder_.get()); - decoder_->RestoreState(); + const GLStateRestorerImpl* restorer_impl = + static_cast<const GLStateRestorerImpl*>(prev_state); + decoder_->RestoreState( + restorer_impl ? restorer_impl->GetContextState() : NULL); } void GLStateRestorerImpl::RestoreAllTextureUnitBindings() { DCHECK(decoder_.get()); - decoder_->RestoreAllTextureUnitBindings(); + decoder_->RestoreAllTextureUnitBindings(NULL); +} + +void GLStateRestorerImpl::RestoreActiveTextureUnitBinding(unsigned int target) { + DCHECK(decoder_.get()); + decoder_->RestoreActiveTextureUnitBinding(target); } void GLStateRestorerImpl::RestoreFramebufferBindings() { @@ -36,4 +44,9 @@ void GLStateRestorerImpl::RestoreFramebufferBindings() { decoder_->RestoreFramebufferBindings(); } +const gles2::ContextState* GLStateRestorerImpl::GetContextState() const { + DCHECK(decoder_.get()); + return decoder_->GetContextState(); +} + } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gl_state_restorer_impl.h b/chromium/gpu/command_buffer/service/gl_state_restorer_impl.h index 032bf725186..73534b81ad3 100644 --- a/chromium/gpu/command_buffer/service/gl_state_restorer_impl.h +++ b/chromium/gpu/command_buffer/service/gl_state_restorer_impl.h @@ -15,6 +15,7 @@ namespace gpu { namespace gles2 { class GLES2Decoder; +struct ContextState; } // This class implements a GLStateRestorer that forwards to a GLES2Decoder. @@ -24,11 +25,13 @@ class GPU_EXPORT GLStateRestorerImpl : public gfx::GLStateRestorer { virtual ~GLStateRestorerImpl(); virtual bool IsInitialized() OVERRIDE; - virtual void RestoreState() OVERRIDE; + virtual void RestoreState(const gfx::GLStateRestorer* prev_state) OVERRIDE; virtual void RestoreAllTextureUnitBindings() OVERRIDE; + virtual void RestoreActiveTextureUnitBinding(unsigned int target) OVERRIDE; virtual void RestoreFramebufferBindings() OVERRIDE; private: + const gles2::ContextState* GetContextState() const; base::WeakPtr<gles2::GLES2Decoder> decoder_; DISALLOW_COPY_AND_ASSIGN(GLStateRestorerImpl); diff --git a/chromium/gpu/command_buffer/service/gl_surface_mock.h b/chromium/gpu/command_buffer/service/gl_surface_mock.h index 372a9b3f41d..0652be64de3 100644 --- a/chromium/gpu/command_buffer/service/gl_surface_mock.h +++ b/chromium/gpu/command_buffer/service/gl_surface_mock.h @@ -20,7 +20,7 @@ class GLSurfaceMock : public gfx::GLSurface { MOCK_METHOD0(IsOffscreen, bool()); MOCK_METHOD0(SwapBuffers, bool()); MOCK_METHOD4(PostSubBuffer, bool(int x, int y, int width, int height)); - MOCK_METHOD0(GetExtensions, std::string()); + MOCK_METHOD0(SupportsPostSubBuffer, bool()); MOCK_METHOD0(GetSize, gfx::Size()); MOCK_METHOD0(GetHandle, void*()); MOCK_METHOD0(GetBackingFrameBufferObject, unsigned int()); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc index 36f2b42bd6c..bda65ac6a60 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc @@ -4,214 +4,186 @@ #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" -#include <string.h> +#include <algorithm> + #include "base/basictypes.h" -#include "gpu/command_buffer/common/types.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" -#define SHADER0(src) \ - "#ifdef GL_ES\n"\ - "precision mediump float;\n"\ - "#endif\n"\ - #src -#define SHADER(src) { false, SHADER0(src), } -#define SHADER_EXTERNAL_OES0(src) \ - "#extension GL_OES_EGL_image_external : require\n"\ - "#ifdef GL_ES\n"\ - "precision mediump float;\n"\ - "#endif\n"\ - #src -#define SHADER_EXTERNAL_OES(src) { true, SHADER_EXTERNAL_OES0(src), } +#define SHADER(src) \ + "#ifdef GL_ES\n" \ + "precision mediump float;\n" \ + "#define TexCoordPrecision mediump\n" \ + "#else\n" \ + "#define TexCoordPrecision\n" \ + "#endif\n" #src +#define SHADER_2D(src) \ + "#define SamplerType sampler2D\n" \ + "#define TextureLookup texture2D\n" SHADER(src) +#define SHADER_RECTANGLE_ARB(src) \ + "#define SamplerType samplerRect\n" \ + "#define TextureLookup textureRect\n" SHADER(src) +#define SHADER_EXTERNAL_OES(src) \ + "#extension GL_OES_EGL_image_external : require\n" \ + "#define SamplerType samplerExternalOES\n" \ + "#define TextureLookup texture2D\n" SHADER(src) +#define FRAGMENT_SHADERS(src) \ + SHADER_2D(src), SHADER_RECTANGLE_ARB(src), SHADER_EXTERNAL_OES(src) namespace { -const GLfloat kQuadVertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 1.0f }; - -enum ProgramId { - PROGRAM_COPY_TEXTURE, - PROGRAM_COPY_TEXTURE_FLIP_Y, - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA, - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY, - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY, - PROGRAM_COPY_TEXTURE_OES, - PROGRAM_COPY_TEXTURE_OES_FLIP_Y, - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA, - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA, - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA_FLIPY, - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA_FLIPY, +enum VertexShaderId { + VERTEX_SHADER_COPY_TEXTURE, + VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, + NUM_VERTEX_SHADERS, }; -struct ShaderInfo { - bool needs_egl_image_external; - const char* source; +enum FragmentShaderId { + FRAGMENT_SHADER_COPY_TEXTURE_2D, + FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, + FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, + FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, + FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, + FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, + FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, + FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, + FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, + NUM_FRAGMENT_SHADERS, }; -const ShaderInfo shader_infos[] = { - // VERTEX_SHADER_POS_TEX +const char* vertex_shader_source[NUM_VERTEX_SHADERS] = { + // VERTEX_SHADER_COPY_TEXTURE SHADER( uniform mat4 u_matrix; + uniform vec2 u_half_size; attribute vec4 a_position; - varying vec2 v_uv; + varying TexCoordPrecision vec2 v_uv; void main(void) { gl_Position = u_matrix * a_position; - v_uv = a_position.xy * 0.5 + vec2(0.5, 0.5); + v_uv = a_position.xy * vec2(u_half_size.s, u_half_size.t) + + vec2(u_half_size.s, u_half_size.t); }), - // FRAGMENT_SHADER_TEX + // VERTEX_SHADER_COPY_TEXTURE_FLIP_Y SHADER( - uniform sampler2D u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = texture2D(u_texSampler, v_uv.st); - }), - // FRAGMENT_SHADER_TEX_FLIP_Y - SHADER( - uniform sampler2D u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); - }), - // FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA - SHADER( - uniform sampler2D u_texSampler; - varying vec2 v_uv; + uniform mat4 u_matrix; + uniform vec2 u_half_size; + attribute vec4 a_position; + varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_FragColor = texture2D(u_texSampler, v_uv.st); - gl_FragColor.rgb *= gl_FragColor.a; + gl_Position = u_matrix * a_position; + v_uv = a_position.xy * vec2(u_half_size.s, -u_half_size.t) + + vec2(u_half_size.s, u_half_size.t); }), - // FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA - SHADER( - uniform sampler2D u_texSampler; - varying vec2 v_uv; +}; + +const char* fragment_shader_source[NUM_FRAGMENT_SHADERS] = { + // FRAGMENT_SHADER_COPY_TEXTURE_* + FRAGMENT_SHADERS( + uniform SamplerType u_sampler; + varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_FragColor = texture2D(u_texSampler, v_uv.st); - if (gl_FragColor.a > 0.0) - gl_FragColor.rgb /= gl_FragColor.a; + gl_FragColor = TextureLookup(u_sampler, v_uv.st); }), - // FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA_FLIP_Y - SHADER( - uniform sampler2D u_texSampler; - varying vec2 v_uv; + // FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_* + FRAGMENT_SHADERS( + uniform SamplerType u_sampler; + varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_FragColor = texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); + gl_FragColor = TextureLookup(u_sampler, v_uv.st); gl_FragColor.rgb *= gl_FragColor.a; }), - // FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA_FLIP_Y - SHADER( - uniform sampler2D u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); - if (gl_FragColor.a > 0.0) - gl_FragColor.rgb /= gl_FragColor.a; - }), - // FRAGMENT_SHADER_TEX_OES - SHADER_EXTERNAL_OES( - precision mediump float; - uniform samplerExternalOES u_texSampler; - varying vec2 v_uv; + // FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_* + FRAGMENT_SHADERS( + uniform SamplerType u_sampler; + varying TexCoordPrecision vec2 v_uv; void main(void) { - gl_FragColor = texture2D(u_texSampler, v_uv.st); - }), - // FRAGMENT_SHADER_TEX_OES_FLIP_Y - SHADER_EXTERNAL_OES( - precision mediump float; - uniform samplerExternalOES u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = - texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); - }), - // FRAGMENT_SHADER_TEX_OES_PREMULTIPLY_ALPHA - SHADER_EXTERNAL_OES( - precision mediump float; - uniform samplerExternalOES u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = texture2D(u_texSampler, v_uv.st); - gl_FragColor.rgb *= gl_FragColor.a; - }), - // FRAGMENT_SHADER_TEX_OES_UNPREMULTIPLY_ALPHA - SHADER_EXTERNAL_OES( - precision mediump float; - uniform samplerExternalOES u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = texture2D(u_texSampler, v_uv.st); + gl_FragColor = TextureLookup(u_sampler, v_uv.st); if (gl_FragColor.a > 0.0) gl_FragColor.rgb /= gl_FragColor.a; }), - // FRAGMENT_SHADER_TEX_OES_PREMULTIPLY_ALPHA_FLIP_Y - SHADER_EXTERNAL_OES( - precision mediump float; - uniform samplerExternalOES u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = - texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); - gl_FragColor.rgb *= gl_FragColor.a; - }), - // FRAGMENT_SHADER_TEX_OES_UNPREMULTIPLY_ALPHA_FLIP_Y - SHADER_EXTERNAL_OES( - precision mediump float; - uniform samplerExternalOES u_texSampler; - varying vec2 v_uv; - void main(void) { - gl_FragColor = - texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); - if (gl_FragColor.a > 0.0) - gl_FragColor.rgb /= gl_FragColor.a; - }), }; -const int kNumShaders = arraysize(shader_infos); +// Returns the correct vertex shader id to evaluate the copy operation for +// the CHROMIUM_flipy setting. +VertexShaderId GetVertexShaderId(bool flip_y) { + // bit 0: flip y + static VertexShaderId shader_ids[] = { + VERTEX_SHADER_COPY_TEXTURE, + VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, + }; -// Returns the correct program to evaluate the copy operation for -// the CHROMIUM_flipy and premultiply alpha pixel store settings. -ProgramId GetProgram( - bool flip_y, - bool premultiply_alpha, - bool unpremultiply_alpha, - bool is_source_external_oes) { - // If both pre-multiply and unpremultiply are requested, then perform no - // alpha manipulation. - if (premultiply_alpha && unpremultiply_alpha) { - premultiply_alpha = false; - unpremultiply_alpha = false; - } + unsigned index = flip_y ? 1 : 0; + return shader_ids[index]; +} - // bit 0: Flip_y - // bit 1: Premult - // bit 2: Unpremult - // bit 3: External_oes - static ProgramId program_ids[] = { - PROGRAM_COPY_TEXTURE, - PROGRAM_COPY_TEXTURE_FLIP_Y, // F - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA, // P - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY, // F P - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, // U - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY, // F U - PROGRAM_COPY_TEXTURE, // P U - PROGRAM_COPY_TEXTURE, // F P U - PROGRAM_COPY_TEXTURE_OES, // E - PROGRAM_COPY_TEXTURE_OES_FLIP_Y, // F E - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA, // P E - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA_FLIPY, // F P E - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA, // U E - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA_FLIPY, // F U E - PROGRAM_COPY_TEXTURE_OES, // P U E - PROGRAM_COPY_TEXTURE_OES, // F P U E +// Returns the correct fragment shader id to evaluate the copy operation for +// the premultiply alpha pixel store settings and target. +FragmentShaderId GetFragmentShaderId(bool premultiply_alpha, + bool unpremultiply_alpha, + GLenum target) { + enum { + SAMPLER_2D, + SAMPLER_RECTANGLE_ARB, + SAMPLER_EXTERNAL_OES, + NUM_SAMPLERS }; - unsigned index = (flip_y ? (1 << 0) : 0) | - (premultiply_alpha ? (1 << 1) : 0) | - (unpremultiply_alpha ? (1 << 2) : 0) | - (is_source_external_oes ? (1 << 3) : 0); - return program_ids[index]; + // bit 0: premultiply alpha + // bit 1: unpremultiply alpha + static FragmentShaderId shader_ids[][NUM_SAMPLERS] = { + { + FRAGMENT_SHADER_COPY_TEXTURE_2D, + FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, + FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, + }, + { + FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, + FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, + FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, + }, + { + FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, + FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, + FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, + }, + { + FRAGMENT_SHADER_COPY_TEXTURE_2D, + FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, + FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, + }}; + + unsigned index = (premultiply_alpha ? (1 << 0) : 0) | + (unpremultiply_alpha ? (1 << 1) : 0); + + switch (target) { + case GL_TEXTURE_2D: + return shader_ids[index][SAMPLER_2D]; + case GL_TEXTURE_RECTANGLE_ARB: + return shader_ids[index][SAMPLER_RECTANGLE_ARB]; + case GL_TEXTURE_EXTERNAL_OES: + return shader_ids[index][SAMPLER_EXTERNAL_OES]; + default: + break; + } + + NOTREACHED(); + return shader_ids[index][SAMPLER_2D]; +} + +void CompileShader(GLuint shader, const char* shader_source) { + glShaderSource(shader, 1, &shader_source, 0); + glCompileShader(shader); +#ifndef NDEBUG + GLint compile_status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); + if (GL_TRUE != compile_status) + DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure."; +#endif +} + +void DeleteShader(GLuint shader) { + if (shader) + glDeleteShader(shader); } } // namespace @@ -219,15 +191,13 @@ ProgramId GetProgram( namespace gpu { CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() - : initialized_(false), - buffer_id_(0), - framebuffer_(0) { - for (int i = 0; i < kNumPrograms; ++i) { - programs_[i] = 0; - matrix_handle_[i] = 0; - sampler_locations_[i] = 0; - } -} + : initialized_(false), + vertex_shaders_(NUM_VERTEX_SHADERS, 0u), + fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), + buffer_id_(0u), + framebuffer_(0u) {} + +CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() {} void CopyTextureCHROMIUMResourceManager::Initialize( const gles2::GLES2Decoder* decoder) { @@ -235,70 +205,18 @@ void CopyTextureCHROMIUMResourceManager::Initialize( kVertexPositionAttrib == 0u, Position_attribs_must_be_0); - const char* extensions = - reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); - bool have_egl_image_external = extensions && - strstr(extensions, "GL_OES_EGL_image_external"); - // Initialize all of the GPU resources required to perform the copy. glGenBuffersARB(1, &buffer_id_); glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); - glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, - GL_STATIC_DRAW); + const GLfloat kQuadVertices[] = {-1.0f, -1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, 1.0f}; + glBufferData( + GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW); glGenFramebuffersEXT(1, &framebuffer_); - // TODO(gman): Init these on demand. - GLuint shaders[kNumShaders]; - for (int shader = 0; shader < kNumShaders; ++shader) { - shaders[shader] = glCreateShader( - shader == 0 ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER); - const ShaderInfo& info = shader_infos[shader]; - if (info.needs_egl_image_external && !have_egl_image_external) { - continue; - } - const char* shader_source = shader_infos[shader].source; - glShaderSource(shaders[shader], 1, &shader_source, 0); - glCompileShader(shaders[shader]); -#ifndef NDEBUG - GLint compile_status; - glGetShaderiv(shaders[shader], GL_COMPILE_STATUS, &compile_status); - if (GL_TRUE != compile_status) - DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure."; -#endif - } - - // TODO(gman): Init these on demand. - for (int program = 0; program < kNumPrograms; ++program) { - const ShaderInfo& info = shader_infos[program + 1]; - if (info.needs_egl_image_external && !have_egl_image_external) { - continue; - } - programs_[program] = glCreateProgram(); - glAttachShader(programs_[program], shaders[0]); - glAttachShader(programs_[program], shaders[program + 1]); - - glBindAttribLocation(programs_[program], kVertexPositionAttrib, - "a_position"); - - glLinkProgram(programs_[program]); -#ifndef NDEBUG - GLint linked; - glGetProgramiv(programs_[program], GL_LINK_STATUS, &linked); - if (!linked) - DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; -#endif - - sampler_locations_[program] = glGetUniformLocation(programs_[program], - "u_texSampler"); - - matrix_handle_[program] = glGetUniformLocation(programs_[program], - "u_matrix"); - } - - for (int shader = 0; shader < kNumShaders; ++shader) - glDeleteShader(shaders[shader]); - decoder->RestoreBufferBindings(); initialized_ = true; @@ -310,9 +228,14 @@ void CopyTextureCHROMIUMResourceManager::Destroy() { glDeleteFramebuffersEXT(1, &framebuffer_); - for (int program = 0; program < kNumPrograms; ++program) { - if (programs_[program]) - glDeleteProgram(programs_[program]); + std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader); + std::for_each( + fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); + + for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); + ++it) { + const ProgramInfo& info = it->second; + glDeleteProgram(info.program); } glDeleteBuffersARB(1, &buffer_id_); @@ -354,28 +277,66 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( bool unpremultiply_alpha, const GLfloat transform_matrix[16]) { DCHECK(source_target == GL_TEXTURE_2D || + source_target == GL_TEXTURE_RECTANGLE_ARB || source_target == GL_TEXTURE_EXTERNAL_OES); if (!initialized_) { DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; return; } - GLuint program = GetProgram( - flip_y, premultiply_alpha, unpremultiply_alpha, - source_target == GL_TEXTURE_EXTERNAL_OES); - glUseProgram(programs_[program]); + VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y); + DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size()); + GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id]; + if (!*vertex_shader) { + *vertex_shader = glCreateShader(GL_VERTEX_SHADER); + CompileShader(*vertex_shader, vertex_shader_source[vertex_shader_id]); + } + + FragmentShaderId fragment_shader_id = GetFragmentShaderId( + premultiply_alpha, unpremultiply_alpha, source_target); + DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); + GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; + if (!*fragment_shader) { + *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + CompileShader(*fragment_shader, fragment_shader_source[fragment_shader_id]); + } + ProgramMapKey key(vertex_shader_id, fragment_shader_id); + ProgramInfo* info = &programs_[key]; + // Create program if necessary. + if (!info->program) { + info->program = glCreateProgram(); + glAttachShader(info->program, *vertex_shader); + glAttachShader(info->program, *fragment_shader); + glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); + glLinkProgram(info->program); #ifndef NDEBUG - glValidateProgram(programs_[program]); + GLint linked; + glGetProgramiv(info->program, GL_LINK_STATUS, &linked); + if (!linked) + DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; +#endif + info->matrix_handle = glGetUniformLocation(info->program, "u_matrix"); + info->half_size_handle = glGetUniformLocation(info->program, "u_half_size"); + info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); + } + glUseProgram(info->program); + +#ifndef NDEBUG + glValidateProgram(info->program); GLint validation_status; - glGetProgramiv(programs_[program], GL_VALIDATE_STATUS, &validation_status); + glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); if (GL_TRUE != validation_status) { DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; return; } #endif - glUniformMatrix4fv(matrix_handle_[program], 1, GL_FALSE, transform_matrix); + glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix); + if (source_target == GL_TEXTURE_RECTANGLE_ARB) + glUniform2f(info->half_size_handle, width / 2.0f, height / 2.0f); + else + glUniform2f(info->half_size_handle, 0.5f, 0.5f); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, dest_id); // NVidia drivers require texture settings to be a certain way @@ -395,13 +356,13 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( } else #endif { + decoder->ClearAllAttributes(); glEnableVertexAttribArray(kVertexPositionAttrib); glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); - glVertexAttribPointer(kVertexPositionAttrib, 4, GL_FLOAT, GL_FALSE, - 4 * sizeof(GLfloat), 0); + glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); - glUniform1i(sampler_locations_[program], 0); + glUniform1i(info->sampler_handle, 0); glBindTexture(source_target, source_id); glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -421,7 +382,7 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - decoder->RestoreAttribute(kVertexPositionAttrib); + decoder->RestoreAllAttributes(); decoder->RestoreTextureState(source_id); decoder->RestoreTextureState(dest_id); decoder->RestoreTextureUnitBindings(0); @@ -432,5 +393,4 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( decoder->RestoreGlobalState(); } -} // namespace - +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h index 097eb2ce46e..17290f8ed22 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h @@ -5,6 +5,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_ +#include <vector> + +#include "base/containers/hash_tables.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" @@ -21,6 +24,7 @@ class GLES2Decoder; class GPU_EXPORT CopyTextureCHROMIUMResourceManager { public: CopyTextureCHROMIUMResourceManager(); + ~CopyTextureCHROMIUMResourceManager(); void Initialize(const gles2::GLES2Decoder* decoder); void Destroy(); @@ -45,14 +49,28 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { static const GLuint kVertexPositionAttrib = 0; private: - bool initialized_; + struct ProgramInfo { + ProgramInfo() + : program(0u), + matrix_handle(0u), + half_size_handle(0u), + sampler_handle(0u) {} + + GLuint program; + GLuint matrix_handle; + GLuint half_size_handle; + GLuint sampler_handle; + }; - static const int kNumPrograms = 12; - GLuint programs_[kNumPrograms]; + bool initialized_; + typedef std::vector<GLuint> ShaderVector; + ShaderVector vertex_shaders_; + ShaderVector fragment_shaders_; + typedef std::pair<int, int> ProgramMapKey; + typedef base::hash_map<ProgramMapKey, ProgramInfo> ProgramMap; + ProgramMap programs_; GLuint buffer_id_; GLuint framebuffer_; - GLuint matrix_handle_[kNumPrograms]; - GLuint sampler_locations_[kNumPrograms]; DISALLOW_COPY_AND_ASSIGN(CopyTextureCHROMIUMResourceManager); }; @@ -60,5 +78,3 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { } // namespace gpu. #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_ - - diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc index c2fcee2933a..02ac2f68eff 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -15,9 +15,12 @@ #include "base/at_exit.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/debug/trace_event.h" +#include "base/debug/trace_event_synthetic_delay.h" #include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "build/build_config.h" @@ -51,11 +54,10 @@ #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/shader_translator.h" #include "gpu/command_buffer/service/shader_translator_cache.h" -#include "gpu/command_buffer/service/stream_texture.h" -#include "gpu/command_buffer/service/stream_texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h" +#include "third_party/smhasher/src/City.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_fence.h" #include "ui/gl/gl_image.h" @@ -63,16 +65,15 @@ #include "ui/gl/gl_surface.h" #if defined(OS_MACOSX) -#include "ui/gl/io_surface_support_mac.h" +#include <IOSurface/IOSurfaceAPI.h> +// Note that this must be included after gl_bindings.h to avoid conflicts. +#include <OpenGL/CGLIOSurface.h> #endif #if defined(OS_WIN) #include "base/win/win_util.h" #endif -// TODO(zmo): we can't include "City.h" due to type def conflicts. -extern uint64 CityHash64(const char*, size_t); - namespace gpu { namespace gles2 { @@ -81,6 +82,7 @@ namespace { static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives"; static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth"; static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers"; +static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod"; #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) { @@ -229,15 +231,18 @@ bool ComputeDataSize( // A struct to hold info about each command. struct CommandInfo { - int arg_flags; // How to handle the arguments for this command - int arg_count; // How many arguments are expected for this command. + uint8 arg_flags; // How to handle the arguments for this command + uint8 cmd_flags; // How to handle this command + uint16 arg_count; // How many arguments are expected for this command. }; +// cmds::name::cmd_flags, // A table of CommandInfo for all the commands. const CommandInfo g_command_info[] = { #define GLES2_CMD_OP(name) { \ cmds::name::kArgFlags, \ - sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \ + cmds::name::cmd_flags, \ + sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ GLES2_COMMAND_LIST(GLES2_CMD_OP) @@ -275,15 +280,6 @@ static bool StringIsValidForGLES(const char* str) { return true; } -// Wrapper for glEnable/glDisable that doesn't suck. -static void EnableDisable(GLenum pname, bool enable) { - if (enable) { - glEnable(pname); - } else { - glDisable(pname); - } -} - // This class prevents any GL errors that occur when it is in scope from // being reported to the client. class ScopedGLErrorSuppressor { @@ -297,24 +293,25 @@ class ScopedGLErrorSuppressor { DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor); }; -// Temporarily changes a decoder's bound 2D texture and restore it when this +// Temporarily changes a decoder's bound texture and restore it when this // object goes out of scope. Also temporarily switches to using active texture // unit zero in case the client has changed that to something invalid. -class ScopedTexture2DBinder { +class ScopedTextureBinder { public: - ScopedTexture2DBinder(ContextState* state, GLuint id); - ~ScopedTexture2DBinder(); + explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target); + ~ScopedTextureBinder(); private: ContextState* state_; - DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder); + GLenum target_; + DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder); }; // Temporarily changes a decoder's bound render buffer and restore it when this // object goes out of scope. class ScopedRenderBufferBinder { public: - ScopedRenderBufferBinder(ContextState* state, GLuint id); + explicit ScopedRenderBufferBinder(ContextState* state, GLuint id); ~ScopedRenderBufferBinder(); private: @@ -326,7 +323,7 @@ class ScopedRenderBufferBinder { // object goes out of scope. class ScopedFrameBufferBinder { public: - ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id); + explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id); ~ScopedFrameBufferBinder(); private: @@ -340,9 +337,9 @@ class ScopedFrameBufferBinder { // true, the resolved framebuffer is not visible to the parent. class ScopedResolvedFrameBufferBinder { public: - ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder, - bool enforce_internal_framebuffer, - bool internal); + explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder, + bool enforce_internal_framebuffer, + bool internal); ~ScopedResolvedFrameBufferBinder(); private: @@ -351,6 +348,45 @@ class ScopedResolvedFrameBufferBinder { DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder); }; +class ScopedModifyPixels { + public: + explicit ScopedModifyPixels(TextureRef* ref); + ~ScopedModifyPixels(); + + private: + TextureRef* ref_; +}; + +ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) { + if (ref_) + ref_->texture()->OnWillModifyPixels(); +} + +ScopedModifyPixels::~ScopedModifyPixels() { + if (ref_) + ref_->texture()->OnDidModifyPixels(); +} + +class ScopedRenderTo { + public: + explicit ScopedRenderTo(Framebuffer* framebuffer); + ~ScopedRenderTo(); + + private: + const Framebuffer* framebuffer_; +}; + +ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer) + : framebuffer_(framebuffer) { + if (framebuffer) + framebuffer_->OnWillRenderTo(); +} + +ScopedRenderTo::~ScopedRenderTo() { + if (framebuffer_) + framebuffer_->OnDidRenderTo(); +} + // Encapsulates an OpenGL texture. class BackTexture { public: @@ -382,10 +418,6 @@ class BackTexture { return size_; } - size_t estimated_size() const { - return memory_tracker_.GetMemRepresented(); - } - private: MemoryTypeTracker memory_tracker_; ContextState* state_; @@ -425,10 +457,6 @@ class BackRenderbuffer { return id_; } - size_t estimated_size() const { - return memory_tracker_.GetMemRepresented(); - } - private: RenderbufferManager* renderbuffer_manager_; MemoryTypeTracker memory_tracker_; @@ -480,13 +508,32 @@ struct FenceCallback { : fence(gfx::GLFence::Create()) { DCHECK(fence); } - void AddCallback(base::Closure cb) { - callbacks.push_back(cb); - } std::vector<base::Closure> callbacks; scoped_ptr<gfx::GLFence> fence; }; +class AsyncUploadTokenCompletionObserver + : public AsyncPixelTransferCompletionObserver { + public: + explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token) + : async_upload_token_(async_upload_token) { + } + + virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE { + DCHECK(mem_params.buffer()); + void* data = mem_params.GetDataAddress(); + AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data); + sync->SetAsyncUploadToken(async_upload_token_); + } + + private: + virtual ~AsyncUploadTokenCompletionObserver() { + } + + uint32 async_upload_token_; + + DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver); +}; // } // anonymous namespace. @@ -504,17 +551,16 @@ GLES2Decoder::GLES2Decoder() GLES2Decoder::~GLES2Decoder() { } +void GLES2Decoder::BeginDecoding() {} + +void GLES2Decoder::EndDecoding() {} + // This class implements GLES2Decoder so we don't have to expose all the GLES2 // cmd stuff to outside this class. class GLES2DecoderImpl : public GLES2Decoder, - public FramebufferManager::TextureDetachObserver { + public FramebufferManager::TextureDetachObserver, + public ErrorStateClient { public: - // Used by PrepForSetUniformByLocation to validate types. - struct BaseUniformInfo { - const GLenum* const valid_types; - size_t num_valid_types; - }; - explicit GLES2DecoderImpl(ContextGroup* group); virtual ~GLES2DecoderImpl(); @@ -536,44 +582,45 @@ class GLES2DecoderImpl : public GLES2Decoder, virtual void Destroy(bool have_context) OVERRIDE; virtual void SetSurface( const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE; - virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE; + virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE; virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE; void UpdateParentTextureInfo(); virtual bool MakeCurrent() OVERRIDE; - virtual void ReleaseCurrent() OVERRIDE; virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; } virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); } virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); } virtual Capabilities GetCapabilities() OVERRIDE; - virtual void RestoreState() const OVERRIDE; + virtual void RestoreState(const ContextState* prev_state) const OVERRIDE; virtual void RestoreActiveTexture() const OVERRIDE { state_.RestoreActiveTexture(); } - virtual void RestoreAllTextureUnitBindings() const OVERRIDE { - state_.RestoreAllTextureUnitBindings(); + virtual void RestoreAllTextureUnitBindings( + const ContextState* prev_state) const OVERRIDE { + state_.RestoreAllTextureUnitBindings(prev_state); } - virtual void RestoreAttribute(unsigned index) const OVERRIDE { - state_.RestoreAttribute(index); + virtual void RestoreActiveTextureUnitBinding( + unsigned int target) const OVERRIDE { + state_.RestoreActiveTextureUnitBinding(target); } virtual void RestoreBufferBindings() const OVERRIDE { state_.RestoreBufferBindings(); } virtual void RestoreGlobalState() const OVERRIDE { - state_.RestoreGlobalState(); + state_.RestoreGlobalState(NULL); } virtual void RestoreProgramBindings() const OVERRIDE { state_.RestoreProgramBindings(); } - virtual void RestoreRenderbufferBindings() const OVERRIDE { - state_.RestoreRenderbufferBindings(); - } virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE { - state_.RestoreTextureUnitBindings(unit); + state_.RestoreTextureUnitBindings(unit, NULL); } virtual void RestoreFramebufferBindings() const OVERRIDE; virtual void RestoreTextureState(unsigned service_id) const OVERRIDE; + virtual void ClearAllAttributes() const OVERRIDE; + virtual void RestoreAllAttributes() const OVERRIDE; + virtual QueryManager* GetQueryManager() OVERRIDE { return query_manager_.get(); } @@ -590,7 +637,12 @@ class GLES2DecoderImpl : public GLES2Decoder, const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE; virtual Logger* GetLogger() OVERRIDE; + + virtual void BeginDecoding() OVERRIDE; + virtual void EndDecoding() OVERRIDE; + virtual ErrorState* GetErrorState() OVERRIDE; + virtual const ContextState* GetContextState() OVERRIDE { return &state_; } virtual void SetShaderCacheCallback( const ShaderCacheCallback& callback) OVERRIDE; @@ -602,6 +654,7 @@ class GLES2DecoderImpl : public GLES2Decoder, virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE; virtual void SetAsyncPixelTransferManagerForTest( AsyncPixelTransferManager* manager) OVERRIDE; + virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE; void ProcessFinishedAsyncTransfers(); virtual bool GetServiceTextureId(uint32 client_texture_id, @@ -632,6 +685,9 @@ class GLES2DecoderImpl : public GLES2Decoder, virtual void OnTextureRefDetachedFromFramebuffer( TextureRef* texture) OVERRIDE; + // Overriden from ErrorStateClient. + virtual void OnOutOfMemoryError() OVERRIDE; + // Helpers to facilitate calling into compatible extensions. static void RenderbufferStorageMultisampleHelper( const FeatureInfo* feature_info, @@ -676,6 +732,13 @@ class GLES2DecoderImpl : public GLES2Decoder, bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids); void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids); + // Helper for async upload token completion notification callback. + base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token, + uint32 sync_data_shm_id, + uint32 sync_data_shm_offset); + + + // Workarounds void OnFboChanged() const; void OnUseFramebuffer() const; @@ -701,6 +764,10 @@ class GLES2DecoderImpl : public GLES2Decoder, return group_->shader_manager(); } + ShaderTranslatorCache* shader_translator_cache() { + return group_->shader_translator_cache(); + } + const TextureManager* texture_manager() const { return group_->texture_manager(); } @@ -725,10 +792,6 @@ class GLES2DecoderImpl : public GLES2Decoder, return group_->memory_tracker(); } - StreamTextureManager* stream_texture_manager() const { - return group_->stream_texture_manager(); - } - bool EnsureGPUMemoryAvailable(size_t estimated_size) { MemoryTracker* tracker = memory_tracker(); if (tracker) { @@ -874,7 +937,14 @@ class GLES2DecoderImpl : public GLES2Decoder, GLsizei height); void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key); + void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target, + const GLbyte* key); + void ProduceTextureRef(std::string func_name, TextureRef* texture_ref, + GLenum target, const GLbyte* data); + void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key); + void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key, + GLuint client_id); void DoBindTexImage2DCHROMIUM( GLenum target, @@ -887,6 +957,8 @@ class GLES2DecoderImpl : public GLES2Decoder, void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs); + void DoLoseContextCHROMIUM(GLenum current, GLenum other); + // Creates a Program for the given program. Program* CreateProgram( GLuint client_id, GLuint service_id) { @@ -1036,9 +1108,12 @@ class GLES2DecoderImpl : public GLES2Decoder, } // Creates a vertex attrib manager for the given vertex array. - void CreateVertexAttribManager(GLuint client_id, GLuint service_id) { + scoped_refptr<VertexAttribManager> CreateVertexAttribManager( + GLuint client_id, + GLuint service_id, + bool client_visible) { return vertex_array_manager()->CreateVertexAttribManager( - client_id, service_id, group_->max_vertex_attribs()); + client_id, service_id, group_->max_vertex_attribs(), client_visible); } void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name); @@ -1060,10 +1135,6 @@ class GLES2DecoderImpl : public GLES2Decoder, // Clear any textures used by the current program. bool ClearUnclearedTextures(); - // Clear any uncleared level in texture. - // Returns false if there was a generated GL error. - bool ClearTexture(Texture* texture); - // Clears any uncleared attachments attached to the given frame buffer. // Returns false if there was a generated GL error. void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer); @@ -1073,6 +1144,7 @@ class GLES2DecoderImpl : public GLES2Decoder, unsigned bind_target, unsigned target, int level, + unsigned internal_format, unsigned format, unsigned type, int width, @@ -1111,10 +1183,12 @@ class GLES2DecoderImpl : public GLES2Decoder, // errors if the current program is not valid. Returns true if the current // program is valid and the location exists. Adjusts count so it // does not overflow the uniform. - bool PrepForSetUniformByLocation( - GLint fake_location, const char* function_name, - const BaseUniformInfo& base_info, - GLint* real_location, GLenum* type, GLsizei* count); + bool PrepForSetUniformByLocation(GLint fake_location, + const char* function_name, + Program::UniformApiType api_type, + GLint* real_location, + GLenum* type, + GLsizei* count); // Gets the service id for any simulated backbuffer fbo. GLuint GetBackbufferServiceId() const; @@ -1272,6 +1346,11 @@ class GLES2DecoderImpl : public GLES2Decoder, // Wrapper for glGetShaderiv void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params); + // Wrappers for glGetTexParameter. + void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); + void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params); + void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname); + // Wrappers for glGetVertexAttrib. void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params); void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params); @@ -1393,11 +1472,7 @@ class GLES2DecoderImpl : public GLES2Decoder, // simulated. bool SimulateAttrib0( const char* function_name, GLuint max_vertex_accessed, bool* simulated); - void RestoreStateForAttrib(GLuint attrib); - - // If texture is a stream texture, this will update the stream to the newest - // buffer and bind the texture implicitly. - void UpdateStreamTextureIfNeeded(Texture* texture, GLuint texture_unit_index); + void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding); // If an image is bound to texture, this will call Will/DidUseTexImage // if needed. @@ -1484,10 +1559,6 @@ class GLES2DecoderImpl : public GLES2Decoder, error::Error* error, GLint* real_location, GLuint* service_id, void** result, GLenum* result_type); - // Computes the estimated memory used for the backbuffer and passes it to - // the tracing system. - size_t GetBackbufferMemoryTotal(); - virtual bool WasContextLost() OVERRIDE; virtual bool WasContextLostByRobustnessExtension() OVERRIDE; virtual void LoseContext(uint32 reset_status) OVERRIDE; @@ -1496,13 +1567,6 @@ class GLES2DecoderImpl : public GLES2Decoder, void ReleaseIOSurfaceForTexture(GLuint texture_id); #endif - // Validates the combination of texture parameters. For example validates that - // for a given format the specific type, level and targets are valid. - // Synthesizes the correct GL error if invalid. Returns true if valid. - bool ValidateTextureParameters( - const char* function_name, - GLenum target, GLenum format, GLenum type, GLint level); - bool ValidateCompressedTexDimensions( const char* function_name, GLint level, GLsizei width, GLsizei height, GLenum format); @@ -1599,9 +1663,6 @@ class GLES2DecoderImpl : public GLES2Decoder, bool unpack_premultiply_alpha_; bool unpack_unpremultiply_alpha_; - // Default vertex attribs manager, used when no VAOs are bound. - scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_; - // The buffer we bind to attrib 0 since OpenGL requires it (ES does not). GLuint attrib_0_buffer_id_; @@ -1666,7 +1727,9 @@ class GLES2DecoderImpl : public GLES2Decoder, // Backbuffer attachments that are currently undefined. uint32 backbuffer_needs_clear_bits_; - // The current decoder error. + // The current decoder error communicates the decoder error through command + // processing functions that do not return the error value. Should be set only + // if not returning an error. error::Error current_decoder_error_; bool use_shader_translator_; @@ -1684,6 +1747,7 @@ class GLES2DecoderImpl : public GLES2Decoder, bool has_robustness_extension_; GLenum reset_status_; bool reset_by_robustness_extension_; + bool supports_post_sub_buffer_; // These flags are used to override the state of the shared feature_info_ // member. Because the same FeatureInfo instance may be shared among many @@ -1694,14 +1758,18 @@ class GLES2DecoderImpl : public GLES2Decoder, bool derivatives_explicitly_enabled_; bool frag_depth_explicitly_enabled_; bool draw_buffers_explicitly_enabled_; + bool shader_texture_lod_explicitly_enabled_; bool compile_shader_always_succeeds_; + // An optional behaviour to lose the context and group when OOM. + bool lose_context_when_out_of_memory_; + // Log extra info. bool service_logging_; #if defined(OS_MACOSX) - typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap; + typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap; TextureToIOSurfaceMap texture_to_io_surface_map_; #endif @@ -1720,6 +1788,8 @@ class GLES2DecoderImpl : public GLES2Decoder, scoped_ptr<GPUTracer> gpu_tracer_; scoped_ptr<GPUStateTracer> gpu_state_tracer_; + int gpu_trace_level_; + bool gpu_trace_commands_; std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_; @@ -1742,35 +1812,55 @@ ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() { ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_); } -static void RestoreCurrentTexture2DBindings(ContextState* state) { +static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) { TextureUnit& info = state->texture_units[0]; GLuint last_id; - if (info.bound_texture_2d.get()) { - last_id = info.bound_texture_2d->service_id(); + scoped_refptr<TextureRef> texture_ref; + switch (target) { + case GL_TEXTURE_2D: + texture_ref = info.bound_texture_2d; + break; + case GL_TEXTURE_CUBE_MAP: + texture_ref = info.bound_texture_cube_map; + break; + case GL_TEXTURE_EXTERNAL_OES: + texture_ref = info.bound_texture_external_oes; + break; + case GL_TEXTURE_RECTANGLE_ARB: + texture_ref = info.bound_texture_rectangle_arb; + break; + default: + NOTREACHED(); + break; + } + if (texture_ref.get()) { + last_id = texture_ref->service_id(); } else { last_id = 0; } - glBindTexture(GL_TEXTURE_2D, last_id); + glBindTexture(target, last_id); glActiveTexture(GL_TEXTURE0 + state->active_texture_unit); } -ScopedTexture2DBinder::ScopedTexture2DBinder(ContextState* state, - GLuint id) - : state_(state) { +ScopedTextureBinder::ScopedTextureBinder(ContextState* state, + GLuint id, + GLenum target) + : state_(state), + target_(target) { ScopedGLErrorSuppressor suppressor( - "ScopedTexture2DBinder::ctor", state_->GetErrorState()); + "ScopedTextureBinder::ctor", state_->GetErrorState()); // TODO(apatrick): Check if there are any other states that need to be reset // before binding a new texture. glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, id); + glBindTexture(target, id); } -ScopedTexture2DBinder::~ScopedTexture2DBinder() { +ScopedTextureBinder::~ScopedTextureBinder() { ScopedGLErrorSuppressor suppressor( - "ScopedTexture2DBinder::dtor", state_->GetErrorState()); - RestoreCurrentTexture2DBindings(state_); + "ScopedTextureBinder::dtor", state_->GetErrorState()); + RestoreCurrentTextureBindings(state_, target_); } ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state, @@ -1847,7 +1937,7 @@ ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder( glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid); const int width = decoder_->offscreen_size_.width(); const int height = decoder_->offscreen_size_.height(); - glDisable(GL_SCISSOR_TEST); + decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); decoder->BlitFramebufferHelper(0, 0, width, @@ -1869,7 +1959,7 @@ ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() { "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState()); decoder_->RestoreCurrentFramebufferBindings(); if (decoder_->state_.enable_flags.scissor_test) { - glEnable(GL_SCISSOR_TEST); + decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true); } } @@ -1894,7 +1984,7 @@ void BackTexture::Create() { state_->GetErrorState()); Destroy(); glGenTextures(1, &id_); - ScopedTexture2DBinder binder(state_, id_); + ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -1918,7 +2008,7 @@ bool BackTexture::AllocateStorage( DCHECK_NE(id_, 0u); ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage", state_->GetErrorState()); - ScopedTexture2DBinder binder(state_, id_); + ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D); uint32 image_size = 0; GLES2Util::ComputeImageDataSizes( size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size, @@ -1959,7 +2049,7 @@ void BackTexture::Copy(const gfx::Size& size, GLenum format) { DCHECK_NE(id_, 0u); ScopedGLErrorSuppressor suppressor("BackTexture::Copy", state_->GetErrorState()); - ScopedTexture2DBinder binder(state_, id_); + ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D); glCopyTexImage2D(GL_TEXTURE_2D, 0, // level format, @@ -2140,7 +2230,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) : GLES2Decoder(), group_(group), logger_(&debug_marker_manager_), - state_(group_->feature_info(), &logger_), + state_(group_->feature_info(), this, &logger_), unpack_flip_y_(false), unpack_premultiply_alpha_(false), unpack_unpremultiply_alpha_(false), @@ -2167,11 +2257,14 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) has_robustness_extension_(false), reset_status_(GL_NO_ERROR), reset_by_robustness_extension_(false), + supports_post_sub_buffer_(false), force_webgl_glsl_validation_(false), derivatives_explicitly_enabled_(false), frag_depth_explicitly_enabled_(false), draw_buffers_explicitly_enabled_(false), + shader_texture_lod_explicitly_enabled_(false), compile_shader_always_succeeds_(false), + lose_context_when_out_of_memory_(false), service_logging_(CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUServiceLoggingGPU)), viewport_max_width_(0), @@ -2216,8 +2309,11 @@ bool GLES2DecoderImpl::Initialize( DCHECK(!context_.get()); set_initialized(); - gpu_tracer_ = GPUTracer::Create(); + gpu_tracer_ = GPUTracer::Create(this); gpu_state_tracer_ = GPUStateTracer::Create(&state_); + // TODO(vmiura): Enable changing gpu_trace_level_ at runtime + gpu_trace_level_ = 2; + gpu_trace_commands_ = false; if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUDebugging)) { @@ -2242,6 +2338,10 @@ bool GLES2DecoderImpl::Initialize( if (!attrib_parser.Parse(attribs)) return false; + // Save the loseContextWhenOutOfMemory context creation attribute. + lose_context_when_out_of_memory_ = + attrib_parser.lose_context_when_out_of_memory_; + // If the failIfMajorPerformanceCaveat context creation attribute was true // and we are using a software renderer, fail. if (attrib_parser.fail_if_major_perf_caveat_ && @@ -2263,14 +2363,25 @@ bool GLES2DecoderImpl::Initialize( disallowed_features_ = disallowed_features; state_.attrib_values.resize(group_->max_vertex_attribs()); - default_vertex_attrib_manager_ = new VertexAttribManager(); - default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs()); + vertex_array_manager_.reset(new VertexArrayManager()); - // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call + GLuint default_vertex_attrib_service_id = 0; + if (features().native_vertex_array_object) { + glGenVertexArraysOES(1, &default_vertex_attrib_service_id); + glBindVertexArrayOES(default_vertex_attrib_service_id); + } + + state_.default_vertex_attrib_manager = + CreateVertexAttribManager(0, default_vertex_attrib_service_id, false); + + state_.default_vertex_attrib_manager->Initialize( + group_->max_vertex_attribs(), + feature_info_->workarounds().init_vertex_attributes); + + // vertex_attrib_manager is set to default_vertex_attrib_manager by this call DoBindVertexArrayOES(0); query_manager_.reset(new QueryManager(this, feature_info_.get())); - vertex_array_manager_.reset(new VertexArrayManager()); util_.set_num_compressed_texture_formats( validators_->compressed_texture_format.GetValues().size()); @@ -2295,20 +2406,20 @@ bool GLES2DecoderImpl::Initialize( ref = texture_manager()->GetDefaultTextureInfo( GL_TEXTURE_EXTERNAL_OES); state_.texture_units[tt].bound_texture_external_oes = ref; - glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id()); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0); } if (features().arb_texture_rectangle) { ref = texture_manager()->GetDefaultTextureInfo( GL_TEXTURE_RECTANGLE_ARB); state_.texture_units[tt].bound_texture_rectangle_arb = ref; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id()); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0); } ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP); state_.texture_units[tt].bound_texture_cube_map = ref; - glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id()); + glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0); ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D); state_.texture_units[tt].bound_texture_2d = ref; - glBindTexture(GL_TEXTURE_2D, ref->service_id()); + glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0); } glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR(); @@ -2499,8 +2610,8 @@ bool GLES2DecoderImpl::Initialize( state_.scissor_height = state_.viewport_height; // Set all the default state because some GL drivers get it wrong. - state_.InitCapabilities(); - state_.InitState(); + state_.InitCapabilities(NULL); + state_.InitState(NULL); glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit); DoBindBuffer(GL_ARRAY_BUFFER, 0); @@ -2522,6 +2633,12 @@ bool GLES2DecoderImpl::Initialize( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + supports_post_sub_buffer_ = surface->SupportsPostSubBuffer(); + if (feature_info_->workarounds() + .disable_post_sub_buffers_for_onscreen_surfaces && + !surface->IsOffscreen()) + supports_post_sub_buffer_ = false; + if (feature_info_->workarounds().reverse_point_sprite_coord_origin) { glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); } @@ -2568,19 +2685,15 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { caps.texture_storage = feature_info_->feature_flags().ext_texture_storage; caps.discard_framebuffer = feature_info_->feature_flags().ext_discard_framebuffer; + caps.sync_query = feature_info_->feature_flags().chromium_sync_query; #if defined(OS_MACOSX) // This is unconditionally true on mac, no need to test for it at runtime. caps.iosurface = true; #endif - // TODO(boliu): Expose this directly from GLSurface. - std::vector<std::string> extension_list; - base::SplitString(surface_->GetExtensions(), ' ', &extension_list); - std::set<std::string> extension_set(extension_list.begin(), - extension_list.end()); - caps.post_sub_buffer = - extension_set.count("GL_CHROMIUM_post_sub_buffer") > 0; + caps.post_sub_buffer = supports_post_sub_buffer_; + caps.map_image = !!image_manager(); return caps; } @@ -2629,6 +2742,9 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_; if (!draw_buffers_explicitly_enabled_) resources.MaxDrawBuffers = 1; +#if (ANGLE_SH_VERSION >= 123) + resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_; +#endif } else { resources.OES_standard_derivatives = features().oes_standard_derivatives ? 1 : 0; @@ -2640,6 +2756,10 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { features().ext_draw_buffers ? 1 : 0; resources.EXT_frag_depth = features().ext_frag_depth ? 1 : 0; +#if (ANGLE_SH_VERSION >= 123) + resources.EXT_shader_texture_lod = + features().ext_shader_texture_lod ? 1 : 0; +#endif } ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC @@ -2662,10 +2782,15 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { driver_bug_workarounds |= SH_INIT_GL_POSITION; if (workarounds().unfold_short_circuit_as_ternary_operation) driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT; - - ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance(); - vertex_translator_ = cache->GetTranslator( - SH_VERTEX_SHADER, shader_spec, &resources, + if (workarounds().init_varyings_without_static_use) + driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE; + if (workarounds().unroll_for_loop_with_sampler_array_index) + driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX; + + vertex_translator_ = shader_translator_cache()->GetTranslator( + SH_VERTEX_SHADER, + shader_spec, + &resources, implementation_type, static_cast<ShCompileOptions>(driver_bug_workarounds)); if (!vertex_translator_.get()) { @@ -2674,8 +2799,10 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { return false; } - fragment_translator_ = cache->GetTranslator( - SH_FRAGMENT_SHADER, shader_spec, &resources, + fragment_translator_ = shader_translator_cache()->GetTranslator( + SH_FRAGMENT_SHADER, + shader_spec, + &resources, implementation_type, static_cast<ShCompileOptions>(driver_bug_workarounds)); if (!fragment_translator_.get()) { @@ -2908,11 +3035,6 @@ void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() { async_pixel_transfer_manager_->BindCompletedAsyncTransfers(); } -void GLES2DecoderImpl::ReleaseCurrent() { - if (context_.get()) - context_->ReleaseCurrent(surface_.get()); -} - static void RebindCurrentFramebuffer( GLenum target, Framebuffer* framebuffer, @@ -2954,13 +3076,27 @@ bool GLES2DecoderImpl::CheckFramebufferValid( if (backbuffer_needs_clear_bits_) { glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat( offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearStencil(0); - glStencilMask(-1); + state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1); + state_.SetDeviceStencilMaskSeparate(GL_BACK, -1); glClearDepth(1.0f); - glDepthMask(true); - glDisable(GL_SCISSOR_TEST); + state_.SetDeviceDepthMask(GL_TRUE); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); + bool reset_draw_buffer = false; + if ((backbuffer_needs_clear_bits_ | GL_COLOR_BUFFER_BIT) != 0 && + group_->draw_buffer() == GL_NONE) { + reset_draw_buffer = true; + GLenum buf = GL_BACK; + if (GetBackbufferServiceId() != 0) // emulated backbuffer + buf = GL_COLOR_ATTACHMENT0; + glDrawBuffersARB(1, &buf); + } glClear(backbuffer_needs_clear_bits_); + if (reset_draw_buffer) { + GLenum buf = GL_NONE; + glDrawBuffersARB(1, &buf); + } backbuffer_needs_clear_bits_ = 0; RestoreClearState(); } @@ -3097,25 +3233,25 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() { GL_RGBA, GL_UNSIGNED_BYTE, true); - texture_manager()->SetParameter( + texture_manager()->SetParameteri( "UpdateParentTextureInfo", GetErrorState(), offscreen_saved_color_texture_info_.get(), GL_TEXTURE_MAG_FILTER, GL_NEAREST); - texture_manager()->SetParameter( + texture_manager()->SetParameteri( "UpdateParentTextureInfo", GetErrorState(), offscreen_saved_color_texture_info_.get(), GL_TEXTURE_MIN_FILTER, GL_NEAREST); - texture_manager()->SetParameter( + texture_manager()->SetParameteri( "UpdateParentTextureInfo", GetErrorState(), offscreen_saved_color_texture_info_.get(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - texture_manager()->SetParameter( + texture_manager()->SetParameteri( "UpdateParentTextureInfo", GetErrorState(), offscreen_saved_color_texture_info_.get(), @@ -3135,6 +3271,15 @@ Logger* GLES2DecoderImpl::GetLogger() { return &logger_; } +void GLES2DecoderImpl::BeginDecoding() { + gpu_tracer_->BeginDecoding(); + gpu_trace_commands_ = gpu_tracer_->IsTracing(); +} + +void GLES2DecoderImpl::EndDecoding() { + gpu_tracer_->EndDecoding(); +} + ErrorState* GLES2DecoderImpl::GetErrorState() { return state_.GetErrorState(); } @@ -3199,10 +3344,10 @@ void GLES2DecoderImpl::Destroy(bool have_context) { // Unbind everything. state_.vertex_attrib_manager = NULL; - default_vertex_attrib_manager_ = NULL; + state_.default_vertex_attrib_manager = NULL; state_.texture_units.clear(); state_.bound_array_buffer = NULL; - state_.current_query = NULL; + state_.current_queries.clear(); framebuffer_state_.bound_read_framebuffer = NULL; framebuffer_state_.bound_draw_framebuffer = NULL; state_.bound_renderbuffer = NULL; @@ -3306,6 +3451,11 @@ void GLES2DecoderImpl::Destroy(bool have_context) { offscreen_resolved_frame_buffer_.reset(); offscreen_resolved_color_texture_.reset(); + // Need to release these before releasing |group_| which may own the + // ShaderTranslatorCache. + fragment_translator_ = NULL; + vertex_translator_ = NULL; + // Should destroy the transfer manager before the texture manager held // by the context group. async_pixel_transfer_manager_.reset(); @@ -3338,9 +3488,11 @@ void GLES2DecoderImpl::SetSurface( RestoreCurrentFramebufferBindings(); } -bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) { - if (!offscreen_saved_color_texture_.get()) - return false; +void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) { + if (!offscreen_saved_color_texture_.get()) { + LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context"; + return; + } if (!offscreen_saved_color_texture_info_.get()) { GLuint service_id = offscreen_saved_color_texture_->id(); offscreen_saved_color_texture_info_ = TextureRef::Create( @@ -3349,39 +3501,8 @@ bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) { GL_TEXTURE_2D); UpdateParentTextureInfo(); } - gpu::gles2::MailboxName name; - memcpy(name.key, mailbox.name, sizeof(mailbox.name)); - return mailbox_manager()->ProduceTexture( - GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture()); -} - -size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() { - size_t total = 0; - if (offscreen_target_frame_buffer_.get()) { - if (offscreen_target_color_texture_.get()) { - total += offscreen_target_color_texture_->estimated_size(); - } - if (offscreen_target_color_render_buffer_.get()) { - total += offscreen_target_color_render_buffer_->estimated_size(); - } - if (offscreen_target_depth_render_buffer_.get()) { - total += offscreen_target_depth_render_buffer_->estimated_size(); - } - if (offscreen_target_stencil_render_buffer_.get()) { - total += offscreen_target_stencil_render_buffer_->estimated_size(); - } - if (offscreen_saved_color_texture_.get()) { - total += offscreen_saved_color_texture_->estimated_size(); - } - if (offscreen_resolved_color_texture_.get()) { - total += offscreen_resolved_color_texture_->estimated_size(); - } - } else { - gfx::Size size = surface_->GetSize(); - total += size.width() * size.height() * - GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_); - } - return total; + mailbox_manager()->ProduceTexture( + GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture()); } bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { @@ -3477,13 +3598,13 @@ bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id()); glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat( offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearStencil(0); - glStencilMaskSeparate(GL_FRONT, -1); - glStencilMaskSeparate(GL_BACK, -1); + state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1); + state_.SetDeviceStencilMaskSeparate(GL_BACK, -1); glClearDepth(0); - glDepthMask(GL_TRUE); - glDisable(GL_SCISSOR_TEST); + state_.SetDeviceDepthMask(GL_TRUE); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); RestoreClearState(); } @@ -3567,6 +3688,14 @@ error::Error GLES2DecoderImpl::DoCommand( unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count); if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) || (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) { + bool doing_gpu_trace = false; + if (gpu_trace_commands_) { + if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) { + doing_gpu_trace = true; + gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder); + } + } + uint32 immediate_data_size = (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT switch (command) { @@ -3580,6 +3709,10 @@ error::Error GLES2DecoderImpl::DoCommand( GLES2_COMMAND_LIST(GLES2_CMD_OP) #undef GLES2_CMD_OP } + + if (doing_gpu_trace) + gpu_tracer_->End(kTraceDecoder); + if (debug()) { GLenum error; while ((error = glGetError()) != GL_NO_ERROR) { @@ -3657,8 +3790,9 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) { buffer = GetBuffer(client_id); if (!buffer) { if (!group_->bind_generates_resource()) { - LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers"; - current_decoder_error_ = error::kGenericError; + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glBindBuffer", + "id not generated by glGenBuffers"); return; } @@ -3733,23 +3867,25 @@ bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() { void GLES2DecoderImpl::ApplyDirtyState() { if (framebuffer_state_.clear_state_dirty) { - glColorMask( - state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue, - state_.color_mask_alpha && - BoundFramebufferHasColorAttachmentWithAlpha(true)); + bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true); + state_.SetDeviceColorMask(state_.color_mask_red, + state_.color_mask_green, + state_.color_mask_blue, + state_.color_mask_alpha && have_alpha); + bool have_depth = BoundFramebufferHasDepthAttachment(); - glDepthMask(state_.depth_mask && have_depth); - EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth); + state_.SetDeviceDepthMask(state_.depth_mask && have_depth); + bool have_stencil = BoundFramebufferHasStencilAttachment(); - glStencilMaskSeparate( + state_.SetDeviceStencilMaskSeparate( GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0); - glStencilMaskSeparate( + state_.SetDeviceStencilMaskSeparate( GL_BACK, have_stencil ? state_.stencil_back_writemask : 0); - EnableDisable( + + state_.SetDeviceCapabilityState( + GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth); + state_.SetDeviceCapabilityState( GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil); - EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face); - EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test); - EnableDisable(GL_BLEND, state_.enable_flags.blend); framebuffer_state_.clear_state_dirty = false; } } @@ -3760,14 +3896,14 @@ GLuint GLES2DecoderImpl::GetBackbufferServiceId() const { : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0); } -void GLES2DecoderImpl::RestoreState() const { +void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const { TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState", "context", logger_.GetLogPrefix()); // Restore the Framebuffer first because of bugs in Intel drivers. // Intel drivers incorrectly clip the viewport settings to // the size of the current framebuffer object. RestoreFramebufferBindings(); - state_.RestoreState(); + state_.RestoreState(prev_state); } void GLES2DecoderImpl::RestoreFramebufferBindings() const { @@ -3804,6 +3940,28 @@ void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const { } } +void GLES2DecoderImpl::ClearAllAttributes() const { + // Must use native VAO 0, as RestoreAllAttributes can't fully restore + // other VAOs. + if (feature_info_->feature_flags().native_vertex_array_object) + glBindVertexArrayOES(0); + + for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) { + if (i != 0) // Never disable attribute 0 + glDisableVertexAttribArray(i); + if(features().angle_instanced_arrays) + glVertexAttribDivisorANGLE(i, 0); + } +} + +void GLES2DecoderImpl::RestoreAllAttributes() const { + state_.RestoreVertexAttribs(); +} + +void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) { + state_.SetIgnoreCachedStateForTest(ignore); +} + void GLES2DecoderImpl::OnFboChanged() const { if (workarounds().restore_scissor_on_fbo_change) state_.fbo_binding_for_scissor_workaround_dirty_ = true; @@ -3832,10 +3990,10 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { framebuffer = GetFramebuffer(client_id); if (!framebuffer) { if (!group_->bind_generates_resource()) { - LOG(ERROR) - << "glBindFramebuffer: id not generated by glGenFramebuffers"; - current_decoder_error_ = error::kGenericError; - return; + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glBindFramebuffer", + "id not generated by glGenFramebuffers"); + return; } // It's a new id so make a framebuffer framebuffer for it. @@ -3855,6 +4013,8 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) { framebuffer_state_.bound_draw_framebuffer = framebuffer; } + + // vmiura: This looks like dup code if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) { framebuffer_state_.bound_read_framebuffer = framebuffer; } @@ -3878,9 +4038,9 @@ void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) { renderbuffer = GetRenderbuffer(client_id); if (!renderbuffer) { if (!group_->bind_generates_resource()) { - LOG(ERROR) - << "glBindRenderbuffer: id not generated by glGenRenderbuffers"; - current_decoder_error_ = error::kGenericError; + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glBindRenderbuffer", + "id not generated by glGenRenderbuffers"); return; } @@ -3896,7 +4056,7 @@ void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) { } renderbuffer->MarkAsValid(); } - LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer"); + LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer"); state_.bound_renderbuffer = renderbuffer; glBindRenderbufferEXT(target, service_id); } @@ -3908,9 +4068,10 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) { texture_ref = GetTexture(client_id); if (!texture_ref) { if (!group_->bind_generates_resource()) { - LOG(ERROR) << "glBindTexture: id not generated by glGenTextures"; - current_decoder_error_ = error::kGenericError; - return; + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glBindTexture", + "id not generated by glGenTextures"); + return; } // It's a new id so make a texture texture for it. @@ -3925,27 +4086,25 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) { } else { texture_ref = texture_manager()->GetDefaultTextureInfo(target); } - Texture* texture = texture_ref->texture(); // Check the texture exists - // Check that we are not trying to bind it to a different target. - if (texture->target() != 0 && texture->target() != target) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glBindTexture", "texture bound to more than 1 target."); - return; - } - if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glBindTexture", "illegal target for stream texture."); - return; - } - LogClientServiceForInfo(texture, client_id, "glBindTexture"); - if (texture->target() == 0) { - texture_manager()->SetTarget(texture_ref, target); + if (texture_ref) { + Texture* texture = texture_ref->texture(); + // Check that we are not trying to bind it to a different target. + if (texture->target() != 0 && texture->target() != target) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glBindTexture", + "texture bound to more than 1 target."); + return; + } + LogClientServiceForInfo(texture, client_id, "glBindTexture"); + if (texture->target() == 0) { + texture_manager()->SetTarget(texture_ref, target); + } + glBindTexture(target, texture->service_id()); + } else { + glBindTexture(target, 0); } - glBindTexture(target, texture->service_id()); TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; unit.bind_target = target; @@ -3984,13 +4143,6 @@ void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) { void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum* attachments) { - if (!features().ext_discard_framebuffer) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, - "glDiscardFramebufferEXT", - "function not available"); - return; - } - Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER); @@ -4123,7 +4275,25 @@ bool GLES2DecoderImpl::GetHelper( switch (pname) { case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *num_written = 1; + // Return the GL implementation's preferred format and (see below type) + // if we have the GL extension that exposes this. This allows the GPU + // client to use the implementation's preferred format for glReadPixels + // for optimisation. + // + // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error + // case when requested on integer/floating point buffers but which is + // acceptable on GLES2 and with the GL_OES_read_format extension. + // + // Therefore if an error occurs we swallow the error and use the + // internal implementation. if (params) { + if (context_->HasExtension("GL_OES_read_format")) { + ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper", + GetErrorState()); + glGetIntegerv(pname, params); + if (glGetError() == GL_NO_ERROR) + return true; + } *params = GLES2Util::GetPreferredGLReadPixelsFormat( GetBoundReadFrameBufferInternalFormat()); } @@ -4131,6 +4301,13 @@ bool GLES2DecoderImpl::GetHelper( case GL_IMPLEMENTATION_COLOR_READ_TYPE: *num_written = 1; if (params) { + if (context_->HasExtension("GL_OES_read_format")) { + ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper", + GetErrorState()); + glGetIntegerv(pname, params); + if (glGetError() == GL_NO_ERROR) + return true; + } *params = GLES2Util::GetPreferredGLReadPixelsType( GetBoundReadFrameBufferInternalFormat(), GetBoundReadFrameBufferTextureType()); @@ -4348,7 +4525,7 @@ bool GLES2DecoderImpl::GetHelper( *num_written = 1; if (params) { if (state_.vertex_attrib_manager.get() != - default_vertex_attrib_manager_.get()) { + state_.default_vertex_attrib_manager.get()) { GLuint client_id = 0; vertex_array_manager_->GetClientId( state_.vertex_attrib_manager->service_id(), &client_id); @@ -4420,6 +4597,12 @@ bool GLES2DecoderImpl::GetHelper( params[0] = unpack_unpremultiply_alpha_; } return true; + case GL_BIND_GENERATES_RESOURCE_CHROMIUM: + *num_written = 1; + if (params) { + params[0] = group_->bind_generates_resource() ? 1 : 0; + } + return true; default: if (pname >= GL_DRAW_BUFFER0_ARB && pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) { @@ -4545,21 +4728,6 @@ void GLES2DecoderImpl::DoBindAttribLocation( glBindAttribLocation(program->service_id(), index, name); } -error::Error GLES2DecoderImpl::HandleBindAttribLocation( - uint32 immediate_data_size, const cmds::BindAttribLocation& c) { - GLuint program = static_cast<GLuint>(c.program); - GLuint index = static_cast<GLuint>(c.index); - uint32 name_size = c.data_size; - const char* name = GetSharedMemoryAs<const char*>( - c.name_shm_id, c.name_shm_offset, name_size); - if (name == NULL) { - return error::kOutOfBounds; - } - String name_str(name, name_size); - DoBindAttribLocation(program, index, name_str.c_str()); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket( uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) { GLuint program = static_cast<GLuint>(c.program); @@ -4610,21 +4778,6 @@ void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM( } } -error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM( - uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) { - GLuint program = static_cast<GLuint>(c.program); - GLint location = static_cast<GLint>(c.location); - uint32 name_size = c.data_size; - const char* name = GetSharedMemoryAs<const char*>( - c.name_shm_id, c.name_shm_offset, name_size); - if (name == NULL) { - return error::kOutOfBounds; - } - String name_str(name, name_size); - DoBindUniformLocationCHROMIUM(program, location, name_str.c_str()); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket( uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUMBucket& c) { @@ -4859,33 +5012,38 @@ void GLES2DecoderImpl::ClearUnclearedAttachments( glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id()); } GLbitfield clear_bits = 0; - if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) { + if (framebuffer->HasUnclearedColorAttachments()) { glClearColor( 0.0f, 0.0f, 0.0f, (GLES2Util::GetChannelsForFormat( framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f); - glColorMask(true, true, true, true); + state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); clear_bits |= GL_COLOR_BUFFER_BIT; + framebuffer->PrepareDrawBuffersForClear(); } if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) || framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) { glClearStencil(0); - glStencilMask(-1); + state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1); + state_.SetDeviceStencilMaskSeparate(GL_BACK, -1); clear_bits |= GL_STENCIL_BUFFER_BIT; } if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) || framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) { glClearDepth(1.0f); - glDepthMask(true); + state_.SetDeviceDepthMask(GL_TRUE); clear_bits |= GL_DEPTH_BUFFER_BIT; } - glDisable(GL_SCISSOR_TEST); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); glClear(clear_bits); + if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0) + framebuffer->RestoreDrawBuffersAfterClear(); + framebuffer_manager()->MarkAttachmentsAsCleared( framebuffer, renderbuffer_manager(), texture_manager()); @@ -4909,7 +5067,7 @@ void GLES2DecoderImpl::RestoreClearState() { glClearStencil(state_.stencil_clear); glClearDepth(state_.depth_clear); if (state_.enable_flags.scissor_test) { - glEnable(GL_SCISSOR_TEST); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true); } } @@ -4937,12 +5095,6 @@ void GLES2DecoderImpl::DoFramebufferTexture2D( void GLES2DecoderImpl::DoFramebufferTexture2DMultisample( GLenum target, GLenum attachment, GLenum textarget, GLuint client_texture_id, GLint level, GLsizei samples) { - if (!features().multisampled_render_to_texture) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glFramebufferTexture2DMultisample", "function not available"); - return; - } DoFramebufferTexture2DCommon( "glFramebufferTexture2DMultisample", target, attachment, textarget, client_texture_id, level, samples); @@ -5020,7 +5172,7 @@ void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv( if (!framebuffer) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, - "glFramebufferAttachmentParameteriv", "no framebuffer bound"); + "glGetFramebufferAttachmentParameteriv", "no framebuffer bound"); return; } if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) { @@ -5075,21 +5227,16 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM( GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { DCHECK(!ShouldDeferReads() && !ShouldDeferDraws()); - if (!features().chromium_framebuffer_multisample) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glBlitFramebufferCHROMIUM", "function not available"); - return; - } if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) { return; } - glDisable(GL_SCISSOR_TEST); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); BlitFramebufferHelper( srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, + state_.enable_flags.scissor_test); } void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper( @@ -5162,14 +5309,14 @@ bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample( width, height, samples, internalformat, &estimated_size)) { LOCAL_SET_GL_ERROR( GL_OUT_OF_MEMORY, - "glRenderbufferStorageMultsample", "dimensions too large"); + "glRenderbufferStorageMultisample", "dimensions too large"); return false; } if (!EnsureGPUMemoryAvailable(estimated_size)) { LOCAL_SET_GL_ERROR( GL_OUT_OF_MEMORY, - "glRenderbufferStorageMultsample", "out of memory"); + "glRenderbufferStorageMultisample", "out of memory"); return false; } @@ -5179,13 +5326,6 @@ bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample( void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - if (!features().chromium_framebuffer_multisample) { - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, - "glRenderbufferStorageMultisampleCHROMIUM", - "function not available"); - return; - } - Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER); if (!renderbuffer) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, @@ -5232,13 +5372,6 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM( void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - if (!features().multisampled_render_to_texture) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glRenderbufferStorageMultisampleEXT", "function not available"); - return; - } - Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER); if (!renderbuffer) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, @@ -5328,11 +5461,11 @@ bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity( GLboolean scissor_enabled = false; glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled); if (scissor_enabled) - glDisable(GL_SCISSOR_TEST); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); - GLboolean color_mask[4] = {true, true, true, true}; + GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); - glColorMask(true, true, true, true); + state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color); @@ -5361,9 +5494,10 @@ bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity( // Restore cached state. if (scissor_enabled) - glEnable(GL_SCISSOR_TEST); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true); - glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]); + state_.SetDeviceColorMask( + color_mask[0], color_mask[1], color_mask[2], color_mask[3]); glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer); @@ -5462,9 +5596,8 @@ void GLES2DecoderImpl::DoTexParameterf( return; } - texture_manager()->SetParameter( - "glTexParameterf", GetErrorState(), texture, pname, - static_cast<GLint>(param)); + texture_manager()->SetParameterf( + "glTexParameterf", GetErrorState(), texture, pname, param); } void GLES2DecoderImpl::DoTexParameteri( @@ -5476,7 +5609,7 @@ void GLES2DecoderImpl::DoTexParameteri( return; } - texture_manager()->SetParameter( + texture_manager()->SetParameteri( "glTexParameteri", GetErrorState(), texture, pname, param); } @@ -5489,9 +5622,8 @@ void GLES2DecoderImpl::DoTexParameterfv( return; } - texture_manager()->SetParameter( - "glTexParameterfv", GetErrorState(), texture, pname, - static_cast<GLint>(params[0])); + texture_manager()->SetParameterf( + "glTexParameterfv", GetErrorState(), texture, pname, *params); } void GLES2DecoderImpl::DoTexParameteriv( @@ -5504,7 +5636,7 @@ void GLES2DecoderImpl::DoTexParameteriv( return; } - texture_manager()->SetParameter( + texture_manager()->SetParameteri( "glTexParameteriv", GetErrorState(), texture, pname, *params); } @@ -5531,125 +5663,13 @@ bool GLES2DecoderImpl::CheckCurrentProgramForUniform( return location != -1; } -namespace { - -static const GLenum valid_int_vec1_types_list[] = { - GL_INT, - GL_BOOL, - GL_SAMPLER_2D, - GL_SAMPLER_2D_RECT_ARB, - GL_SAMPLER_CUBE, - GL_SAMPLER_EXTERNAL_OES, -}; - -static const GLenum valid_int_vec2_types_list[] = { - GL_INT_VEC2, - GL_BOOL_VEC2, -}; - -static const GLenum valid_int_vec3_types_list[] = { - GL_INT_VEC3, - GL_BOOL_VEC3, -}; - -static const GLenum valid_int_vec4_types_list[] = { - GL_INT_VEC4, - GL_BOOL_VEC4, -}; - -static const GLenum valid_float_vec1_types_list[] = { - GL_FLOAT, - GL_BOOL, -}; - -static const GLenum valid_float_vec2_types_list[] = { - GL_FLOAT_VEC2, - GL_BOOL_VEC2, -}; - -static const GLenum valid_float_vec3_types_list[] = { - GL_FLOAT_VEC3, - GL_BOOL_VEC3, -}; - -static const GLenum valid_float_vec4_types_list[] = { - GL_FLOAT_VEC4, - GL_BOOL_VEC4, -}; - -static const GLenum valid_float_mat2_types_list[] = { - GL_FLOAT_MAT2, -}; - -static const GLenum valid_float_mat3_types_list[] = { - GL_FLOAT_MAT3, -}; - -static const GLenum valid_float_mat4_types_list[] = { - GL_FLOAT_MAT4, -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = { - valid_int_vec1_types_list, - arraysize(valid_int_vec1_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = { - valid_int_vec2_types_list, - arraysize(valid_int_vec2_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = { - valid_int_vec3_types_list, - arraysize(valid_int_vec3_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = { - valid_int_vec4_types_list, - arraysize(valid_int_vec4_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = { - valid_float_vec1_types_list, - arraysize(valid_float_vec1_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = { - valid_float_vec2_types_list, - arraysize(valid_float_vec2_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = { - valid_float_vec3_types_list, - arraysize(valid_float_vec3_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = { - valid_float_vec4_types_list, - arraysize(valid_float_vec4_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = { - valid_float_mat2_types_list, - arraysize(valid_float_mat2_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = { - valid_float_mat3_types_list, - arraysize(valid_float_mat3_types_list), -}; - -static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = { - valid_float_mat4_types_list, - arraysize(valid_float_mat4_types_list), -}; - -} // anonymous namespace. - bool GLES2DecoderImpl::PrepForSetUniformByLocation( - GLint fake_location, const char* function_name, - const GLES2DecoderImpl::BaseUniformInfo& base_info, - GLint* real_location, GLenum* type, GLsizei* count) { + GLint fake_location, + const char* function_name, + Program::UniformApiType api_type, + GLint* real_location, + GLenum* type, + GLsizei* count) { DCHECK(type); DCHECK(count); DCHECK(real_location); @@ -5666,14 +5686,8 @@ bool GLES2DecoderImpl::PrepForSetUniformByLocation( GL_INVALID_OPERATION, function_name, "unknown location"); return false; } - bool okay = false; - for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) { - if (base_info.valid_types[ii] == info->type) { - okay = true; - break; - } - } - if (!okay) { + + if ((api_type & info->accepts_api_type) == 0) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, function_name, "wrong uniform function for type"); @@ -5696,9 +5710,12 @@ void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) { GLenum type = 0; GLsizei count = 1; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform1iv", valid_int_vec1_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform1i", + Program::kUniform1i, + &real_location, + &type, + &count)) { return; } if (!state_.current_program->SetSamplers( @@ -5714,9 +5731,12 @@ void GLES2DecoderImpl::DoUniform1iv( GLint fake_location, GLsizei count, const GLint *value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform1iv", valid_int_vec1_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform1iv", + Program::kUniform1i, + &real_location, + &type, + &count)) { return; } if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB || @@ -5735,9 +5755,12 @@ void GLES2DecoderImpl::DoUniform1fv( GLint fake_location, GLsizei count, const GLfloat* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform1fv", valid_float_vec1_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform1fv", + Program::kUniform1f, + &real_location, + &type, + &count)) { return; } if (type == GL_BOOL) { @@ -5755,9 +5778,12 @@ void GLES2DecoderImpl::DoUniform2fv( GLint fake_location, GLsizei count, const GLfloat* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform2fv", valid_float_vec2_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform2fv", + Program::kUniform2f, + &real_location, + &type, + &count)) { return; } if (type == GL_BOOL_VEC2) { @@ -5776,9 +5802,12 @@ void GLES2DecoderImpl::DoUniform3fv( GLint fake_location, GLsizei count, const GLfloat* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform3fv", valid_float_vec3_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform3fv", + Program::kUniform3f, + &real_location, + &type, + &count)) { return; } if (type == GL_BOOL_VEC3) { @@ -5797,9 +5826,12 @@ void GLES2DecoderImpl::DoUniform4fv( GLint fake_location, GLsizei count, const GLfloat* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform4fv", valid_float_vec4_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform4fv", + Program::kUniform4f, + &real_location, + &type, + &count)) { return; } if (type == GL_BOOL_VEC4) { @@ -5818,9 +5850,12 @@ void GLES2DecoderImpl::DoUniform2iv( GLint fake_location, GLsizei count, const GLint* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform2iv", valid_int_vec2_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform2iv", + Program::kUniform2i, + &real_location, + &type, + &count)) { return; } glUniform2iv(real_location, count, value); @@ -5830,9 +5865,12 @@ void GLES2DecoderImpl::DoUniform3iv( GLint fake_location, GLsizei count, const GLint* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform3iv", valid_int_vec3_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform3iv", + Program::kUniform3i, + &real_location, + &type, + &count)) { return; } glUniform3iv(real_location, count, value); @@ -5842,9 +5880,12 @@ void GLES2DecoderImpl::DoUniform4iv( GLint fake_location, GLsizei count, const GLint* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniform4iv", valid_int_vec4_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniform4iv", + Program::kUniform4i, + &real_location, + &type, + &count)) { return; } glUniform4iv(real_location, count, value); @@ -5855,9 +5896,12 @@ void GLES2DecoderImpl::DoUniformMatrix2fv( const GLfloat* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniformMatrix2fv", + Program::kUniformMatrix2f, + &real_location, + &type, + &count)) { return; } glUniformMatrix2fv(real_location, count, transpose, value); @@ -5868,9 +5912,12 @@ void GLES2DecoderImpl::DoUniformMatrix3fv( const GLfloat* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniformMatrix3fv", + Program::kUniformMatrix3f, + &real_location, + &type, + &count)) { return; } glUniformMatrix3fv(real_location, count, transpose, value); @@ -5881,9 +5928,12 @@ void GLES2DecoderImpl::DoUniformMatrix4fv( const GLfloat* value) { GLenum type = 0; GLint real_location = -1; - if (!PrepForSetUniformByLocation( - fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info, - &real_location, &type, &count)) { + if (!PrepForSetUniformByLocation(fake_location, + "glUniformMatrix4fv", + Program::kUniformMatrix4f, + &real_location, + &type, + &count)) { return; } glUniformMatrix4fv(real_location, count, transpose, value); @@ -5930,24 +5980,8 @@ void GLES2DecoderImpl::PerformanceWarning( std::string("PERFORMANCE WARNING: ") + msg); } -void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture, - GLuint texture_unit_index) { - if (texture && texture->IsStreamTexture()) { - DCHECK(stream_texture_manager()); - StreamTexture* stream_tex = - stream_texture_manager()->LookupStreamTexture(texture->service_id()); - if (stream_tex) { - glActiveTexture(GL_TEXTURE0 + texture_unit_index); - stream_tex->Update(); - } - } -} - void GLES2DecoderImpl::DoWillUseTexImageIfNeeded( Texture* texture, GLenum textarget) { - // This might be supported in the future. - if (textarget != GL_TEXTURE_2D) - return; // Image is already in use if texture is attached to a framebuffer. if (texture && !texture->IsAttachedToFramebuffer()) { gfx::GLImage* image = texture->GetLevelImage(textarget, 0); @@ -5957,16 +5991,13 @@ void GLES2DecoderImpl::DoWillUseTexImageIfNeeded( GetErrorState()); glBindTexture(textarget, texture->service_id()); image->WillUseTexImage(); - RestoreCurrentTexture2DBindings(&state_); + RestoreCurrentTextureBindings(&state_, textarget); } } } void GLES2DecoderImpl::DoDidUseTexImageIfNeeded( Texture* texture, GLenum textarget) { - // This might be supported in the future. - if (textarget != GL_TEXTURE_2D) - return; // Image is still in use if texture is attached to a framebuffer. if (texture && !texture->IsAttachedToFramebuffer()) { gfx::GLImage* image = texture->GetLevelImage(textarget, 0); @@ -5976,7 +6007,7 @@ void GLES2DecoderImpl::DoDidUseTexImageIfNeeded( GetErrorState()); glBindTexture(textarget, texture->service_id()); image->DidUseTexImage(); - RestoreCurrentTexture2DBindings(&state_); + RestoreCurrentTextureBindings(&state_, textarget); } } } @@ -5984,8 +6015,7 @@ void GLES2DecoderImpl::DoDidUseTexImageIfNeeded( bool GLES2DecoderImpl::PrepareTexturesForRender() { DCHECK(state_.current_program.get()); if (!texture_manager()->HaveUnrenderableTextures() && - !texture_manager()->HaveImages() && - !features().oes_egl_image_external) { + !texture_manager()->HaveImages()) { return true; } @@ -6018,8 +6048,8 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() { continue; } - Texture* texture = texture_ref->texture(); - if (textarget == GL_TEXTURE_2D) { + if (textarget != GL_TEXTURE_CUBE_MAP) { + Texture* texture = texture_ref->texture(); gfx::GLImage* image = texture->GetLevelImage(textarget, 0); if (image && !texture->IsAttachedToFramebuffer()) { ScopedGLErrorSuppressor suppressor( @@ -6030,8 +6060,6 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() { continue; } } - - UpdateStreamTextureIfNeeded(texture, texture_unit_index); } // else: should this be an error? } @@ -6064,10 +6092,10 @@ void GLES2DecoderImpl::RestoreStateForTextures() { continue; } - Texture* texture = texture_ref->texture(); - if (texture_unit.bind_target == GL_TEXTURE_2D) { - gfx::GLImage* image = texture->GetLevelImage( - texture_unit.bind_target, 0); + if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) { + Texture* texture = texture_ref->texture(); + gfx::GLImage* image = + texture->GetLevelImage(texture_unit.bind_target, 0); if (image && !texture->IsAttachedToFramebuffer()) { ScopedGLErrorSuppressor suppressor( "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState()); @@ -6208,21 +6236,23 @@ bool GLES2DecoderImpl::SimulateAttrib0( return true; } -void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) { +void GLES2DecoderImpl::RestoreStateForAttrib( + GLuint attrib_index, bool restore_array_binding) { const VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(attrib_index); - const void* ptr = reinterpret_cast<const void*>(attrib->offset()); - Buffer* buffer = attrib->buffer(); - glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0); - glVertexAttribPointer( - attrib_index, attrib->size(), attrib->type(), attrib->normalized(), - attrib->gl_stride(), ptr); + if (restore_array_binding) { + const void* ptr = reinterpret_cast<const void*>(attrib->offset()); + Buffer* buffer = attrib->buffer(); + glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0); + glVertexAttribPointer( + attrib_index, attrib->size(), attrib->type(), attrib->normalized(), + attrib->gl_stride(), ptr); + } if (attrib->divisor()) glVertexAttribDivisorANGLE(attrib_index, attrib->divisor()); glBindBuffer( - GL_ARRAY_BUFFER, - state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id() - : 0); + GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ? + state_.bound_array_buffer->service_id() : 0); // Never touch vertex attribute 0's state (in particular, never // disable it) when running on desktop GL because it will never be @@ -6411,12 +6441,12 @@ error::Error GLES2DecoderImpl::DoDrawArrays( primcount)) { bool textures_set = !PrepareTexturesForRender(); ApplyDirtyState(); + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get()); if (!instanced) { glDrawArrays(mode, first, count); } else { glDrawArraysInstancedANGLE(mode, first, count, primcount); } - ProcessPendingQueries(); if (textures_set) { RestoreStateForTextures(); } @@ -6425,7 +6455,11 @@ error::Error GLES2DecoderImpl::DoDrawArrays( } } if (simulated_attrib_0) { - RestoreStateForAttrib(0); + // We don't have to restore attrib 0 generic data at the end of this + // function even if it is simulated. This is because we will simulate + // it in each draw call, and attrib 0 generic data queries use cached + // values instead of passing down to the underlying driver. + RestoreStateForAttrib(0, false); } } return error::kNoError; @@ -6540,6 +6574,7 @@ error::Error GLES2DecoderImpl::DoDrawElements( indices = element_array_buffer->GetRange(offset, 0); } + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get()); if (!instanced) { glDrawElements(mode, count, type, indices); } else { @@ -6551,7 +6586,6 @@ error::Error GLES2DecoderImpl::DoDrawElements( element_array_buffer->service_id()); } - ProcessPendingQueries(); if (textures_set) { RestoreStateForTextures(); } @@ -6560,7 +6594,11 @@ error::Error GLES2DecoderImpl::DoDrawElements( } } if (simulated_attrib_0) { - RestoreStateForAttrib(0); + // We don't have to restore attrib 0 generic data at the end of this + // function even if it is simulated. This is because we will simulate + // it in each draw call, and attrib 0 generic data queries use cached + // values instead of passing down to the underlying driver. + RestoreStateForAttrib(0, false); } } return error::kNoError; @@ -6631,17 +6669,6 @@ error::Error GLES2DecoderImpl::ShaderSourceHelper( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleShaderSource( - uint32 immediate_data_size, const cmds::ShaderSource& c) { - uint32 data_size = c.data_size; - const char* data = GetSharedMemoryAs<const char*>( - c.data_shm_id, c.data_shm_offset, data_size); - if (!data) { - return error::kOutOfBounds; - } - return ShaderSourceHelper(c.shader, data, data_size); -} - error::Error GLES2DecoderImpl::HandleShaderSourceBucket( uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) { Bucket* bucket = GetBucket(c.data_bucket_id); @@ -6719,7 +6746,7 @@ error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE( uint32 bucket_id = static_cast<uint32>(c.bucket_id); Bucket* bucket = CreateBucket(bucket_id); Shader* shader = GetShaderInfoNotProgram( - shader_id, "glTranslatedGetShaderSourceANGLE"); + shader_id, "glGetTranslatedShaderSourceANGLE"); if (!shader) { bucket->SetSize(0); return error::kNoError; @@ -6885,6 +6912,39 @@ void GLES2DecoderImpl::GetVertexAttribHelper( } } +void GLES2DecoderImpl::DoGetTexParameterfv( + GLenum target, GLenum pname, GLfloat* params) { + InitTextureMaxAnisotropyIfNeeded(target, pname); + glGetTexParameterfv(target, pname, params); +} + +void GLES2DecoderImpl::DoGetTexParameteriv( + GLenum target, GLenum pname, GLint* params) { + InitTextureMaxAnisotropyIfNeeded(target, pname); + glGetTexParameteriv(target, pname, params); +} + +void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded( + GLenum target, GLenum pname) { + if (!workarounds().init_texture_max_anisotropy) + return; + if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT || + !validators_->texture_parameter.IsValid(pname)) { + return; + } + + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); + if (!texture_ref) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glGetTexParamter{fi}v", "unknown texture for target"); + return; + } + Texture* texture = texture_ref->texture(); + texture->InitTextureMaxAnisotropyIfNeeded(target); +} + void GLES2DecoderImpl::DoGetVertexAttribfv( GLuint index, GLenum pname, GLfloat* params) { VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index); @@ -7011,7 +7071,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttribPointer( if (!state_.bound_array_buffer.get() || state_.bound_array_buffer->IsDeleted()) { if (state_.vertex_attrib_manager.get() == - default_vertex_attrib_manager_.get()) { + state_.default_vertex_attrib_manager.get()) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound"); return error::kNoError; @@ -7103,6 +7163,7 @@ error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE( LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glVertexAttribDivisorANGLE", "function not available"); + return error::kNoError; } GLuint index = c.index; GLuint divisor = c.divisor; @@ -7251,6 +7312,7 @@ void GLES2DecoderImpl::FinishReadPixels( error::Error GLES2DecoderImpl::HandleReadPixels( uint32 immediate_data_size, const cmds::ReadPixels& c) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels"); error::Error fbo_error = WillAccessBoundFramebufferForRead(); if (fbo_error != error::kNoError) return fbo_error; @@ -7329,7 +7391,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( return error::kNoError; } - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel"); + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels"); ScopedResolvedFrameBufferBinder binder(this, false, true); @@ -7393,6 +7455,9 @@ error::Error GLES2DecoderImpl::HandleReadPixels( c, buffer)); glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); return error::kNoError; + } else { + // On error, unbind pack buffer and fall through to sync readpixels + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); } } glReadPixels(x, y, width, height, format, type, pixels); @@ -7421,7 +7486,7 @@ error::Error GLES2DecoderImpl::HandlePixelStorei( case GL_UNPACK_ALIGNMENT: if (!validators_->pixel_store_alignment.IsValid(param)) { LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE"); + GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE"); return error::kNoError; } break; @@ -7459,7 +7524,10 @@ error::Error GLES2DecoderImpl::HandlePixelStorei( error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM( uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM"); - if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) { + { + TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame"); + } + if (!supports_post_sub_buffer_) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glPostSubBufferCHROMIUM", "command not supported by surface"); @@ -7482,6 +7550,16 @@ error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM( } } +error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM( + uint32 immediate_data_size, + const cmds::ScheduleOverlayPlaneCHROMIUM& c) { + NOTIMPLEMENTED() << "Overlay supported isn't finished."; + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glScheduleOverlayPlaneCHROMIUM", + "function not implemented"); + return error::kNoError; +} + error::Error GLES2DecoderImpl::GetAttribLocationHelper( GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, const std::string& name_str) { @@ -7516,19 +7594,6 @@ error::Error GLES2DecoderImpl::GetAttribLocationHelper( error::Error GLES2DecoderImpl::HandleGetAttribLocation( uint32 immediate_data_size, const cmds::GetAttribLocation& c) { - uint32 name_size = c.data_size; - const char* name = GetSharedMemoryAs<const char*>( - c.name_shm_id, c.name_shm_offset, name_size); - if (!name) { - return error::kOutOfBounds; - } - String name_str(name, name_size); - return GetAttribLocationHelper( - c.program, c.location_shm_id, c.location_shm_offset, name_str); -} - -error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket( - uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) { Bucket* bucket = GetBucket(c.name_bucket_id); if (!bucket) { return error::kInvalidArguments; @@ -7550,7 +7615,7 @@ error::Error GLES2DecoderImpl::GetUniformLocationHelper( return error::kNoError; } Program* program = GetProgramInfoNotShader( - client_id, "glUniformLocation"); + client_id, "glGetUniformLocation"); if (!program) { return error::kNoError; } @@ -7575,19 +7640,6 @@ error::Error GLES2DecoderImpl::GetUniformLocationHelper( error::Error GLES2DecoderImpl::HandleGetUniformLocation( uint32 immediate_data_size, const cmds::GetUniformLocation& c) { - uint32 name_size = c.data_size; - const char* name = GetSharedMemoryAs<const char*>( - c.name_shm_id, c.name_shm_offset, name_size); - if (!name) { - return error::kOutOfBounds; - } - String name_str(name, name_size); - return GetUniformLocationHelper( - c.program, c.location_shm_id, c.location_shm_offset, name_str); -} - -error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket( - uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) { Bucket* bucket = GetBucket(c.name_bucket_id); if (!bucket) { return error::kInvalidArguments; @@ -7650,12 +7702,19 @@ error::Error GLES2DecoderImpl::HandleGetString( std::string()); } } + if (!shader_texture_lod_explicitly_enabled_) { + size_t offset = extensions.find(kEXTShaderTextureLodExtension); + if (std::string::npos != offset) { + extensions.replace(offset, + arraysize(kEXTShaderTextureLodExtension), + std::string()); + } + } } else { extensions = feature_info_->extensions().c_str(); } - std::string surface_extensions = surface_->GetExtensions(); - if (!surface_extensions.empty()) - extensions += " " + surface_extensions; + if (supports_post_sub_buffer_) + extensions += " GL_CHROMIUM_post_sub_buffer"; str = extensions.c_str(); } break; @@ -7697,6 +7756,7 @@ bool GLES2DecoderImpl::ClearLevel( unsigned bind_target, unsigned target, int level, + unsigned internal_format, unsigned format, unsigned type, int width, @@ -7723,10 +7783,11 @@ bool GLES2DecoderImpl::ClearLevel( return false; } glClearStencil(0); - glStencilMask(-1); + state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1); + state_.SetDeviceStencilMaskSeparate(GL_BACK, -1); glClearDepth(1.0f); - glDepthMask(true); - glDisable(GL_SCISSOR_TEST); + state_.SetDeviceDepthMask(GL_TRUE); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0)); RestoreClearState(); @@ -7783,7 +7844,8 @@ bool GLES2DecoderImpl::ClearLevel( glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get()); } else { glTexImage2D( - target, level, format, width, h, 0, format, type, zero.get()); + target, level, internal_format, width, h, 0, format, type, + zero.get()); } y += tile_height; } @@ -7799,15 +7861,17 @@ const int kS3TCBlockWidth = 4; const int kS3TCBlockHeight = 4; const int kS3TCDXT1BlockSize = 8; const int kS3TCDXT3AndDXT5BlockSize = 16; -const int kETC1BlockWidth = 4; -const int kETC1BlockHeight = 4; -const int kETC1BlockSize = 8; bool IsValidDXTSize(GLint level, GLsizei size) { return (size == 1) || (size == 2) || !(size % kS3TCBlockWidth); } +bool IsValidPVRTCSize(GLint level, GLsizei size) { + // Ensure that the size is a power of two + return (size & (size - 1)) == 0; +} + } // anonymous namespace. bool GLES2DecoderImpl::ValidateCompressedTexFuncData( @@ -7816,8 +7880,10 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData( unsigned int bytes_required = 0; switch (format) { + case GL_ATC_RGB_AMD: case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: { + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_ETC1_RGB8_OES: { int num_blocks_across = (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth; int num_blocks_down = @@ -7826,6 +7892,8 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData( bytes_required = num_blocks * kS3TCDXT1BlockSize; break; } + case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: { int num_blocks_across = @@ -7836,13 +7904,14 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData( bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize; break; } - case GL_ETC1_RGB8_OES: { - int num_blocks_across = - (width + kETC1BlockWidth - 1) / kETC1BlockWidth; - int num_blocks_down = - (height + kETC1BlockHeight - 1) / kETC1BlockHeight; - int num_blocks = num_blocks_across * num_blocks_down; - bytes_required = num_blocks * kETC1BlockSize; + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: { + bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8; + break; + } + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8; break; } default: @@ -7875,7 +7944,10 @@ bool GLES2DecoderImpl::ValidateCompressedTexDimensions( } return true; } - case GL_ETC1_RGB8_OES: + case GL_ATC_RGB_AMD: + case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + case GL_ETC1_RGB8_OES: { if (width <= 0 || height <= 0) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, function_name, @@ -7883,6 +7955,20 @@ bool GLES2DecoderImpl::ValidateCompressedTexDimensions( return false; } return true; + } + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + if (!IsValidPVRTCSize(level, width) || + !IsValidPVRTCSize(level, height)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, function_name, + "width or height invalid for level"); + return false; + } + return true; + } default: return false; } @@ -7924,12 +8010,43 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions( return ValidateCompressedTexDimensions( function_name, level, width, height, format); } + case GL_ATC_RGB_AMD: + case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, function_name, + "not supported for ATC textures"); + return false; + } case GL_ETC1_RGB8_OES: { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, function_name, - "TexsubImage2d not supported for ECT1_RGB8_OES textures"); + "not supported for ECT1_RGB8_OES textures"); return false; } + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + if ((xoffset != 0) || (yoffset != 0)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, function_name, + "xoffset and yoffset must be zero"); + return false; + } + GLsizei tex_width = 0; + GLsizei tex_height = 0; + if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) || + width != tex_width || + height != tex_height) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, function_name, + "dimensions must match existing texture level dimensions"); + return false; + } + return ValidateCompressedTexDimensions( + function_name, level, width, height, format); + } default: return false; } @@ -8112,7 +8229,8 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket( error::Error GLES2DecoderImpl::HandleTexImage2D( uint32 immediate_data_size, const cmds::TexImage2D& c) { - TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D"); + TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D", + "width", c.width, "height", c.height); // Set as failed for now, but if it successed, this will be set to not failed. texture_state_.tex_image_2d_failed = true; GLenum target = static_cast<GLenum>(c.target); @@ -8184,7 +8302,7 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D( return; } if (!texture->ValidForTexture( - target, level, xoffset, yoffset, width, height, format, type)) { + target, level, xoffset, yoffset, width, height, type)) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions."); return; @@ -8246,6 +8364,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D( if (texture->IsImmutable()) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable"); + return; } if (!texture_manager()->ValidForTarget(target, level, width, height, 1) || border != 0) { @@ -8253,9 +8372,9 @@ void GLES2DecoderImpl::DoCopyTexImage2D( GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range"); return; } - if (!texture_manager()->ValidateTextureParameters( - state_.GetErrorState(), "glCopyTexImage2D", target, internal_format, - GL_UNSIGNED_BYTE, level)) { + if (!texture_manager()->ValidateFormatAndTypeCombination( + state_.GetErrorState(), "glCopyTexImage2D", internal_format, + GL_UNSIGNED_BYTE)) { return; } @@ -8318,8 +8437,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D( // some part was clipped so clear the texture. if (!ClearLevel( texture->service_id(), texture->target(), - target, level, internal_format, GL_UNSIGNED_BYTE, width, height, - texture->IsImmutable())) { + target, level, internal_format, internal_format, GL_UNSIGNED_BYTE, + width, height, texture->IsImmutable())) { LOCAL_SET_GL_ERROR( GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big"); return; @@ -8329,11 +8448,13 @@ void GLES2DecoderImpl::DoCopyTexImage2D( GLint dy = copyY - y; GLint destX = dx; GLint destY = dy; + ScopedModifyPixels modify(texture_ref); glCopyTexSubImage2D(target, level, destX, destY, copyX, copyY, copyWidth, copyHeight); } } else { + ScopedModifyPixels modify(texture_ref); glCopyTexImage2D(target, level, internal_format, copyX, copyY, copyWidth, copyHeight, border); } @@ -8368,7 +8489,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( GLenum format = 0; if (!texture->GetLevelType(target, level, &type, &format) || !texture->ValidForTexture( - target, level, xoffset, yoffset, width, height, format, type)) { + target, level, xoffset, yoffset, width, height, type)) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions."); return; @@ -8433,6 +8554,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( } scoped_ptr<char[]> zero(new char[pixels_size]); memset(zero.get(), 0, pixels_size); + ScopedModifyPixels modify(texture_ref); glTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, zero.get()); @@ -8443,6 +8565,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( GLint dy = copyY - y; GLint destX = xoffset + dx; GLint destY = yoffset + dy; + ScopedModifyPixels modify(texture_ref); glCopyTexSubImage2D(target, level, destX, destY, copyX, copyY, copyWidth, copyHeight); @@ -8474,14 +8597,6 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D( LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0"); return false; } - if (!validators_->texture_format.IsValid(format)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format"); - return false; - } - if (!validators_->pixel_type.IsValid(type)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type"); - return false; - } TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( &state_, target); if (!texture_ref) { @@ -8498,10 +8613,8 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D( GL_INVALID_OPERATION, function_name, "level does not exist."); return false; } - if (format != internal_format) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - function_name, "format does not match internal format."); + if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(), + function_name, format, type, internal_format, level)) { return false; } if (type != current_type) { @@ -8517,7 +8630,7 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D( return false; } if (!texture->ValidForTexture( - target, level, xoffset, yoffset, width, height, format, type)) { + target, level, xoffset, yoffset, width, height, type)) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions."); return false; } @@ -8574,10 +8687,13 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( if (!texture_state_.texsubimage2d_faster_than_teximage2d && !texture->IsImmutable()) { ScopedTextureUploadTimer timer(&texture_state_); - // NOTE: In OpenGL ES 2.0 border is always zero and format is always the - // same as internal_foramt. If that changes we'll need to look them up. + GLenum internal_format; + GLenum tex_type; + texture->GetLevelType(target, level, &tex_type, &internal_format); + // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need + // to look it up. glTexImage2D( - target, level, format, width, height, 0, format, type, data); + target, level, internal_format, width, height, 0, format, type, data); } else { ScopedTextureUploadTimer timer(&texture_state_); glTexSubImage2D( @@ -8589,7 +8705,8 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( error::Error GLES2DecoderImpl::HandleTexSubImage2D( uint32 immediate_data_size, const cmds::TexSubImage2D& c) { - TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D"); + TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", + "width", c.width, "height", c.height); GLboolean internal = static_cast<GLboolean>(c.internal); if (internal == GL_TRUE && texture_state_.tex_image_2d_failed) return error::kNoError; @@ -8923,7 +9040,7 @@ error::Error GLES2DecoderImpl::HandleShaderBinary( if (shaders == NULL || binary == NULL) { return error::kOutOfBounds; } - scoped_array<GLuint> service_ids(new GLuint[n]); + scoped_ptr<GLuint[]> service_ids(new GLuint[n]); for (GLsizei ii = 0; ii < n; ++ii) { Shader* shader = GetShader(shaders[ii]); if (!shader) { @@ -8950,6 +9067,10 @@ void GLES2DecoderImpl::DoSwapBuffers() { TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers", "offscreen", is_offscreen, "frame", this_frame_number); + { + TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame"); + } + bool is_tracing; TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"), &is_tracing); @@ -8995,8 +9116,8 @@ void GLES2DecoderImpl::DoSwapBuffers() { ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id()); glClearColor(0, 0, 0, 0); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDisable(GL_SCISSOR_TEST); + state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); glClear(GL_COLOR_BUFFER_BIT); RestoreClearState(); } @@ -9040,9 +9161,6 @@ void GLES2DecoderImpl::DoSwapBuffers() { glFlush(); } } else { - TRACE_EVENT2("gpu", "Onscreen", - "width", surface_->GetSize().width(), - "height", surface_->GetSize().height()); if (!surface_->SwapBuffers()) { LOG(ERROR) << "Context lost because SwapBuffers failed."; LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB); @@ -9123,6 +9241,7 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM( bool desire_standard_derivatives = false; bool desire_frag_depth = false; bool desire_draw_buffers = false; + bool desire_shader_texture_lod = false; if (force_webgl_glsl_validation_) { desire_standard_derivatives = feature_str.find("GL_OES_standard_derivatives") != std::string::npos; @@ -9130,6 +9249,8 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM( feature_str.find("GL_EXT_frag_depth") != std::string::npos; desire_draw_buffers = feature_str.find("GL_EXT_draw_buffers") != std::string::npos; + desire_shader_texture_lod = + feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos; } if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ || @@ -9140,6 +9261,7 @@ error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM( derivatives_explicitly_enabled_ |= desire_standard_derivatives; frag_depth_explicitly_enabled_ |= desire_frag_depth; draw_buffers_explicitly_enabled_ |= desire_draw_buffers; + shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod; InitializeShaderTranslator(); } @@ -9173,7 +9295,7 @@ error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM( uint32 num = util_.GLGetNumValuesReturned(enums[ii]); if (num == 0) { LOCAL_SET_GL_ERROR_INVALID_ENUM( - "glGetMulitpleCHROMIUM", enums[ii], "pname"); + "glGetMultipleCHROMIUM", enums[ii], "pname"); return error::kNoError; } // Num will never be more than 4. @@ -9191,7 +9313,7 @@ error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM( if (result_size != static_cast<uint32>(c.size)) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, - "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE"); + "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE"); return error::kNoError; } @@ -9296,23 +9418,6 @@ void GLES2DecoderImpl::LoseContext(uint32 reset_status) { current_decoder_error_ = error::kLostContext; } -error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM( - uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) { - GLenum current = static_cast<GLenum>(c.current); - GLenum other = static_cast<GLenum>(c.other); - if (!validators_->reset_status.IsValid(current)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM( - "glLoseContextCHROMIUM", current, "current"); - } - if (!validators_->reset_status.IsValid(other)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other"); - } - group_->LoseContexts(other); - reset_status_ = current; - current_decoder_error_ = error::kLostContext; - return error::kLostContext; -} - error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM( uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) { return error::kUnknownCommand; @@ -9320,6 +9425,7 @@ error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM( error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM( uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) { + group_->mailbox_manager()->PullTextureUpdates(); if (wait_sync_point_callback_.is_null()) return error::kNoError; @@ -9346,7 +9452,7 @@ bool GLES2DecoderImpl::GenQueriesEXTHelper( return false; } } - // NOTE: We don't generate Query objects here. Only in BeginQueryEXT + query_manager_->GenQueries(n, client_ids); return true; } @@ -9355,12 +9461,14 @@ void GLES2DecoderImpl::DeleteQueriesEXTHelper( for (GLsizei ii = 0; ii < n; ++ii) { QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]); if (query && !query->IsDeleted()) { - if (query == state_.current_query.get()) { - state_.current_query = NULL; - } + ContextState::QueryMap::iterator it = + state_.current_queries.find(query->target()); + if (it != state_.current_queries.end()) + state_.current_queries.erase(it); + query->Destroy(true); - query_manager_->RemoveQuery(client_ids[ii]); } + query_manager_->RemoveQuery(client_ids[ii]); } } @@ -9423,6 +9531,14 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT( case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: case GL_GET_ERROR_QUERY_CHROMIUM: break; + case GL_COMMANDS_COMPLETED_CHROMIUM: + if (!features().chromium_sync_query) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, "glBeginQueryEXT", + "not enabled for commands completed queries"); + return error::kNoError; + } + break; default: if (!features().occlusion_query_boolean) { LOCAL_SET_GL_ERROR( @@ -9433,9 +9549,7 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT( break; } - // TODO(hubbe): Make it possible to have one query per type running at the - // same time. - if (state_.current_query.get()) { + if (state_.current_queries.find(target) != state_.current_queries.end()) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress"); return error::kNoError; @@ -9448,24 +9562,12 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT( QueryManager::Query* query = query_manager_->GetQuery(client_id); if (!query) { - // TODO(gman): Decide if we need this check. - // - // Checks id was made by glGenQueries - // - // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT - // for all Query ids but from the POV of the command buffer service maybe - // you don't. - // - // The client can enforce this. I don't think the service cares. - // - // IdAllocatorInterface* id_allocator = - // group_->GetIdAllocator(id_namespaces::kQueries); - // if (!id_allocator->InUse(client_id)) { - // LOCAL_SET_GL_ERROR( - // GL_INVALID_OPERATION, - // "glBeginQueryEXT", "id not made by glGenQueriesEXT"); - // return error::kNoError; - // } + if (!query_manager_->IsValidQuery(client_id)) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glBeginQueryEXT", + "id not made by glGenQueriesEXT"); + return error::kNoError; + } query = query_manager_->CreateQuery( target, client_id, sync_shm_id, sync_shm_offset); } @@ -9484,7 +9586,7 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT( return error::kOutOfBounds; } - state_.current_query = query; + state_.current_queries[target] = query; return error::kNoError; } @@ -9492,26 +9594,22 @@ error::Error GLES2DecoderImpl::HandleEndQueryEXT( uint32 immediate_data_size, const cmds::EndQueryEXT& c) { GLenum target = static_cast<GLenum>(c.target); uint32 submit_count = static_cast<GLuint>(c.submit_count); + ContextState::QueryMap::iterator it = state_.current_queries.find(target); - if (!state_.current_query.get()) { + if (it == state_.current_queries.end()) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glEndQueryEXT", "No active query"); return error::kNoError; } - if (state_.current_query->target() != target) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glEndQueryEXT", "target does not match active query"); - return error::kNoError; - } - if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) { + QueryManager::Query* query = it->second.get(); + if (!query_manager_->EndQuery(query, submit_count)) { return error::kOutOfBounds; } query_manager_->ProcessPendingTransferQueries(); - state_.current_query = NULL; + state_.current_queries.erase(it); return error::kNoError; } @@ -9526,14 +9624,14 @@ bool GLES2DecoderImpl::GenVertexArraysOESHelper( if (!features().native_vertex_array_object) { // Emulated VAO for (GLsizei ii = 0; ii < n; ++ii) { - CreateVertexAttribManager(client_ids[ii], 0); + CreateVertexAttribManager(client_ids[ii], 0, true); } } else { scoped_ptr<GLuint[]> service_ids(new GLuint[n]); glGenVertexArraysOES(n, service_ids.get()); for (GLsizei ii = 0; ii < n; ++ii) { - CreateVertexAttribManager(client_ids[ii], service_ids[ii]); + CreateVertexAttribManager(client_ids[ii], service_ids[ii], true); } } @@ -9547,7 +9645,7 @@ void GLES2DecoderImpl::DeleteVertexArraysOESHelper( GetVertexAttribManager(client_ids[ii]); if (vao && !vao->IsDeleted()) { if (state_.vertex_attrib_manager.get() == vao) { - state_.vertex_attrib_manager = default_vertex_attrib_manager_; + DoBindVertexArrayOES(0); } RemoveVertexAttribManager(client_ids[ii]); } @@ -9556,7 +9654,6 @@ void GLES2DecoderImpl::DeleteVertexArraysOESHelper( void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) { VertexAttribManager* vao = NULL; - GLuint service_id = 0; if (client_id != 0) { vao = GetVertexAttribManager(client_id); if (!vao) { @@ -9568,11 +9665,9 @@ void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) { "glBindVertexArrayOES", "bad vertex array id."); current_decoder_error_ = error::kNoError; return; - } else { - service_id = vao->service_id(); } } else { - vao = default_vertex_attrib_manager_.get(); + vao = state_.default_vertex_attrib_manager.get(); } // Only set the VAO state if it's changed @@ -9581,6 +9676,7 @@ void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) { if (!features().native_vertex_array_object) { EmulateVertexArrayState(); } else { + GLuint service_id = vao->service_id(); glBindVertexArrayOES(service_id); } } @@ -9590,7 +9686,7 @@ void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) { void GLES2DecoderImpl::EmulateVertexArrayState() { // Setup the Vertex attribute state for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) { - RestoreStateForAttrib(vv); + RestoreStateForAttrib(vv, true); } // Setup the element buffer @@ -9606,93 +9702,13 @@ bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) { return vao && vao->IsValid() && !vao->IsDeleted(); } -error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM( - uint32 immediate_data_size, - const cmds::CreateStreamTextureCHROMIUM& c) { - if (!features().chromium_stream_texture) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glOpenStreamTextureCHROMIUM", "not supported."); - return error::kNoError; - } - - uint32 client_id = c.client_id; - typedef cmds::CreateStreamTextureCHROMIUM::Result Result; - Result* result = GetSharedMemoryAs<Result*>( - c.result_shm_id, c.result_shm_offset, sizeof(*result)); - - if (!result) - return error::kOutOfBounds; - *result = GL_ZERO; - TextureRef* texture_ref = texture_manager()->GetTexture(client_id); - if (!texture_ref) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, - "glCreateStreamTextureCHROMIUM", "bad texture id."); - return error::kNoError; - } - - Texture* texture = texture_ref->texture(); - if (texture->IsStreamTexture()) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glCreateStreamTextureCHROMIUM", "is already a stream texture."); - return error::kNoError; - } - - if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glCreateStreamTextureCHROMIUM", - "is already bound to incompatible target."); - return error::kNoError; - } - - if (!stream_texture_manager()) - return error::kInvalidArguments; - - GLuint object_id = stream_texture_manager()->CreateStreamTexture( - texture->service_id(), client_id); - - if (object_id) { - texture_manager()->SetStreamTexture(texture_ref, true); - } else { - LOCAL_SET_GL_ERROR( - GL_OUT_OF_MEMORY, - "glCreateStreamTextureCHROMIUM", "failed to create platform texture."); - } - - *result = object_id; - return error::kNoError; -} - -error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM( - uint32 immediate_data_size, - const cmds::DestroyStreamTextureCHROMIUM& c) { - GLuint client_id = c.texture; - TextureRef* texture_ref = texture_manager()->GetTexture(client_id); - if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) { - if (!stream_texture_manager()) - return error::kInvalidArguments; - - stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id()); - texture_manager()->SetStreamTexture(texture_ref, false); - } else { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, - "glDestroyStreamTextureCHROMIUM", "bad texture id."); - } - - return error::kNoError; -} - #if defined(OS_MACOSX) void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) { TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find( texture_id); if (it != texture_to_io_surface_map_.end()) { // Found a previous IOSurface bound to this texture; release it. - CFTypeRef surface = it->second; + IOSurfaceRef surface = it->second; CFRelease(surface); texture_to_io_surface_map_.erase(it); } @@ -9710,14 +9726,6 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( return; } - IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize(); - if (!surface_support) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6."); - return; - } - if (target != GL_TEXTURE_RECTANGLE_ARB) { // This might be supported in the future, and if we could require // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we @@ -9746,7 +9754,7 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( // plugin process might allocate and release an IOSurface before // this process gets a chance to look it up. Hold on to any old // IOSurface in this case. - CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id); + IOSurfaceRef surface = IOSurfaceLookup(io_surface_id); if (!surface) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -9764,7 +9772,7 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( CGLContextObj context = static_cast<CGLContextObj>(context_->GetHandle()); - CGLError err = surface_support->CGLTexImageIOSurface2D( + CGLError err = CGLTexImageIOSurface2D( context, target, GL_RGBA, @@ -9840,6 +9848,8 @@ static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) { void GLES2DecoderImpl::DoCopyTextureCHROMIUM( GLenum target, GLuint source_id, GLuint dest_id, GLint level, GLenum internal_format, GLenum dest_type) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM"); + TextureRef* dest_texture_ref = GetTexture(dest_id); TextureRef* source_texture_ref = GetTexture(source_id); @@ -9859,7 +9869,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( Texture* dest_texture = dest_texture_ref->texture(); if (dest_texture->target() != GL_TEXTURE_2D || (source_texture->target() != GL_TEXTURE_2D && - source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) { + source_texture->target() != GL_TEXTURE_RECTANGLE_ARB && + source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target binding"); @@ -9868,26 +9879,16 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( int source_width, source_height, dest_width, dest_height; - if (source_texture->IsStreamTexture()) { - DCHECK_EQ(source_texture->target(), - static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES)); - DCHECK(stream_texture_manager()); - StreamTexture* stream_tex = - stream_texture_manager()->LookupStreamTexture( - source_texture->service_id()); - if (!stream_tex) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, - "glCopyTextureChromium", "Stream texture lookup failed"); - return; - } - gfx::Size size = stream_tex->GetSize(); + gfx::GLImage* image = + source_texture->GetLevelImage(source_texture->target(), 0); + if (image) { + gfx::Size size = image->GetSize(); source_width = size.width(); source_height = size.height(); if (source_width <= 0 || source_height <= 0) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, - "glCopyTextureChromium", "invalid streamtexture size"); + "glCopyTextureChromium", "invalid image size"); return; } } else { @@ -9950,7 +9951,7 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( 0, internal_format, dest_type, NULL); GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM"); if (error != GL_NO_ERROR) { - RestoreCurrentTexture2DBindings(&state_); + RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D); return; } @@ -9963,6 +9964,7 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( } DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); + ScopedModifyPixels modify(dest_texture_ref); // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix // before presenting. @@ -10051,7 +10053,8 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( GLenum internal_format, GLsizei width, GLsizei height) { - TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT"); + TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT", + "width", width, "height", height); if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) || TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) { LOCAL_SET_GL_ERROR( @@ -10127,44 +10130,64 @@ error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM( } void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target, - const GLbyte* mailbox) { + const GLbyte* data) { TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM", "context", logger_.GetLogPrefix(), - "mailbox[0]", static_cast<unsigned char>(mailbox[0])); + "mailbox[0]", static_cast<unsigned char>(data[0])); TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( &state_, target); + ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data); +} + +void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id, + GLenum target, const GLbyte* data) { + TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM", + "context", logger_.GetLogPrefix(), + "mailbox[0]", static_cast<unsigned char>(data[0])); + + ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id), + target, data); +} + +void GLES2DecoderImpl::ProduceTextureRef(std::string func_name, + TextureRef* texture_ref, GLenum target, const GLbyte* data) { + const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data); + DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a " + "mailbox that was not generated by " + "GenMailboxCHROMIUM."; + if (!texture_ref) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glProduceTextureCHROMIUM", "unknown texture for target"); + GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target"); return; } Texture* produced = texture_manager()->Produce(texture_ref); if (!produced) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glProduceTextureCHROMIUM", "invalid texture"); + GL_INVALID_OPERATION, func_name.c_str(), "invalid texture"); return; } - if (!group_->mailbox_manager()->ProduceTexture( - target, - *reinterpret_cast<const MailboxName*>(mailbox), - produced)) { + if (produced->target() != target) { LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - "glProduceTextureCHROMIUM", "invalid mailbox name"); + GL_INVALID_OPERATION, func_name.c_str(), "invalid target"); return; } + + group_->mailbox_manager()->ProduceTexture(target, mailbox, produced); } void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target, - const GLbyte* mailbox) { + const GLbyte* data) { TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM", "context", logger_.GetLogPrefix(), - "mailbox[0]", static_cast<unsigned char>(mailbox[0])); + "mailbox[0]", static_cast<unsigned char>(data[0])); + const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data); + DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a " + "mailbox that was not generated by " + "GenMailboxCHROMIUM."; scoped_refptr<TextureRef> texture_ref = texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); @@ -10181,10 +10204,7 @@ void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target, "glConsumeTextureCHROMIUM", "unknown texture for target"); return; } - Texture* texture = - group_->mailbox_manager()->ConsumeTexture( - target, - *reinterpret_cast<const MailboxName*>(mailbox)); + Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox); if (!texture) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -10223,6 +10243,70 @@ void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target, } } +error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate( + uint32_t immediate_data_size, + const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c) { + GLenum target = static_cast<GLenum>(c.target); + uint32_t data_size; + if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + return error::kOutOfBounds; + } + if (data_size > immediate_data_size) { + return error::kOutOfBounds; + } + const GLbyte* mailbox = + GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size); + if (!validators_->texture_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glCreateAndConsumeTextureCHROMIUM", target, "target"); + return error::kNoError; + } + if (mailbox == NULL) { + return error::kOutOfBounds; + } + uint32_t client_id = c.client_id; + DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id); + return error::kNoError; +} + +void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target, + const GLbyte* data, GLuint client_id) { + TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM", + "context", logger_.GetLogPrefix(), + "mailbox[0]", static_cast<unsigned char>(data[0])); + const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data); + DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was " + "passed a mailbox that was not " + "generated by GenMailboxCHROMIUM."; + + TextureRef* texture_ref = GetTexture(client_id); + if (texture_ref) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glCreateAndConsumeTextureCHROMIUM", "client id already in use"); + return; + } + Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox); + if (!texture) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name"); + return; + } + if (texture->target() != target) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glCreateAndConsumeTextureCHROMIUM", "invalid target"); + return; + } + + IdAllocatorInterface* id_allocator = + group_->GetIdAllocator(id_namespaces::kTextures); + id_allocator->MarkAsUsed(client_id); + + texture_ref = texture_manager()->Consume(client_id, texture); +} + void GLES2DecoderImpl::DoInsertEventMarkerEXT( GLsizei length, const GLchar* marker) { if (!marker) { @@ -10237,18 +10321,27 @@ void GLES2DecoderImpl::DoPushGroupMarkerEXT( if (!marker) { marker = ""; } - debug_marker_manager_.PushGroup( - length ? std::string(marker, length) : std::string(marker)); + std::string name = length ? std::string(marker, length) : std::string(marker); + debug_marker_manager_.PushGroup(name); + gpu_tracer_->Begin(name, kTraceGroupMarker); } void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) { debug_marker_manager_.PopGroup(); + gpu_tracer_->End(kTraceGroupMarker); } void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM( GLenum target, GLint image_id) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM"); + if (target == GL_TEXTURE_CUBE_MAP) { + LOCAL_SET_GL_ERROR( + GL_INVALID_ENUM, + "glBindTexImage2DCHROMIUM", "invalid target"); + return; + } + // Default target might be conceptually valid, but disallow it to avoid // accidents. TextureRef* texture_ref = @@ -10335,7 +10428,7 @@ error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM( return error::kInvalidArguments; } TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this); - if (!gpu_tracer_->Begin(command_name)) { + if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glTraceBeginCHROMIUM", "unable to create begin trace"); @@ -10352,7 +10445,7 @@ void GLES2DecoderImpl::DoTraceEndCHROMIUM() { return; } TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this); - gpu_tracer_->End(); + gpu_tracer_->End(kTraceCHROMIUM); } void GLES2DecoderImpl::DoDrawBuffersEXT( @@ -10397,6 +10490,12 @@ void GLES2DecoderImpl::DoDrawBuffersEXT( } } +void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) { + group_->LoseContexts(other); + reset_status_ = current; + current_decoder_error_ = error::kLostContext; +} + bool GLES2DecoderImpl::ValidateAsyncTransfer( const char* function_name, TextureRef* texture_ref, @@ -10429,13 +10528,34 @@ bool GLES2DecoderImpl::ValidateAsyncTransfer( return true; } +base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure( + uint32 async_upload_token, + uint32 sync_data_shm_id, + uint32 sync_data_shm_offset) { + scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id); + if (!buffer || !buffer->GetDataAddress(sync_data_shm_offset, + sizeof(AsyncUploadSync))) + return base::Closure(); + + AsyncMemoryParams mem_params(buffer, + sync_data_shm_offset, + sizeof(AsyncUploadSync)); + + scoped_refptr<AsyncUploadTokenCompletionObserver> observer( + new AsyncUploadTokenCompletionObserver(async_upload_token)); + + return base::Bind( + &AsyncPixelTransferManager::AsyncNotifyCompletion, + base::Unretained(GetAsyncPixelTransferManager()), + mem_params, + observer); +} + error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM"); GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); - // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use - // unsigned integer for internalformat. GLenum internal_format = static_cast<GLenum>(c.internalformat); GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); @@ -10445,6 +10565,21 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id); uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset); uint32 pixels_size; + uint32 async_upload_token = static_cast<uint32>(c.async_upload_token); + uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id); + uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset); + + base::ScopedClosureRunner scoped_completion_callback; + if (async_upload_token) { + base::Closure completion_closure = + AsyncUploadTokenCompletionClosure(async_upload_token, + sync_data_shm_id, + sync_data_shm_offset); + if (completion_closure.is_null()) + return error::kInvalidArguments; + + scoped_completion_callback.Reset(completion_closure); + } // TODO(epenner): Move this and copies of this memory validation // into ValidateTexImage2D step. @@ -10492,20 +10627,12 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( return error::kNoError; } - // We know the memory/size is safe, so get the real shared memory since - // it might need to be duped to prevent use-after-free of the memory. - gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id); - base::SharedMemory* shared_memory = buffer.shared_memory; - uint32 shm_size = buffer.size; - uint32 shm_data_offset = c.pixels_shm_offset; - uint32 shm_data_size = pixels_size; - // Setup the parameters. AsyncTexImage2DParams tex_params = { target, level, static_cast<GLenum>(internal_format), width, height, border, format, type}; - AsyncMemoryParams mem_params = { - shared_memory, shm_size, shm_data_offset, shm_data_size}; + AsyncMemoryParams mem_params( + GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size); // Set up the async state if needed, and make the texture // immutable so the async state stays valid. The level info @@ -10539,6 +10666,21 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( GLsizei height = static_cast<GLsizei>(c.height); GLenum format = static_cast<GLenum>(c.format); GLenum type = static_cast<GLenum>(c.type); + uint32 async_upload_token = static_cast<uint32>(c.async_upload_token); + uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id); + uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset); + + base::ScopedClosureRunner scoped_completion_callback; + if (async_upload_token) { + base::Closure completion_closure = + AsyncUploadTokenCompletionClosure(async_upload_token, + sync_data_shm_id, + sync_data_shm_offset); + if (completion_closure.is_null()) + return error::kInvalidArguments; + + scoped_completion_callback.Reset(completion_closure); + } // TODO(epenner): Move this and copies of this memory validation // into ValidateTexSubImage2D step. @@ -10582,19 +10724,11 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( } } - // We know the memory/size is safe, so get the real shared memory since - // it might need to be duped to prevent use-after-free of the memory. - gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id); - base::SharedMemory* shared_memory = buffer.shared_memory; - uint32 shm_size = buffer.size; - uint32 shm_data_offset = c.data_shm_offset; - uint32 shm_data_size = data_size; - // Setup the parameters. AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset, width, height, format, type}; - AsyncMemoryParams mem_params = {shared_memory, shm_size, - shm_data_offset, shm_data_size}; + AsyncMemoryParams mem_params( + GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size); AsyncPixelTransferDelegate* delegate = async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref); if (!delegate) { @@ -10649,12 +10783,28 @@ error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM( + uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM"); + + GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D(); + ProcessFinishedAsyncTransfers(); + return error::kNoError; +} + void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer( TextureRef* texture_ref) { Texture* texture = texture_ref->texture(); DoDidUseTexImageIfNeeded(texture, texture->target()); } +void GLES2DecoderImpl::OnOutOfMemoryError() { + if (lose_context_when_out_of_memory_) { + group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB); + LoseContext(GL_GUILTY_CONTEXT_RESET_ARB); + } +} + // Include the auto-generated part of this file. We split this because it means // we can easily edit the non-auto generated parts right here in this file // instead of having to edit some template or the code generator. diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h index 87c93350415..ad06a6e95bf 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -28,7 +28,6 @@ namespace gpu { class AsyncPixelTransferDelegate; class AsyncPixelTransferManager; -class StreamTextureManager; struct Mailbox; namespace gles2 { @@ -39,14 +38,13 @@ class GLES2Util; class Logger; class QueryManager; class VertexArrayManager; +struct ContextState; struct DisallowedFeatures { DisallowedFeatures() - : multisampling(false), - gpu_memory_manager(false) { + : gpu_memory_manager(false) { } - bool multisampling; bool gpu_memory_manager; }; @@ -117,7 +115,7 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, // Set the surface associated with the default FBO. virtual void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) = 0; - virtual bool ProduceFrontBuffer(const Mailbox& mailbox) = 0; + virtual void ProduceFrontBuffer(const Mailbox& mailbox) = 0; // Resize an offscreen frame buffer. virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) = 0; @@ -125,9 +123,6 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, // Make this decoder's GL context current. virtual bool MakeCurrent() = 0; - // Have the decoder release the context. - virtual void ReleaseCurrent() = 0; - // Gets the GLES2 Util which holds info. virtual GLES2Util* GetGLES2Util() = 0; @@ -140,20 +135,25 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, virtual Capabilities GetCapabilities() = 0; // Restores all of the decoder GL state. - virtual void RestoreState() const = 0; + virtual void RestoreState(const ContextState* prev_state) const = 0; // Restore States. virtual void RestoreActiveTexture() const = 0; - virtual void RestoreAllTextureUnitBindings() const = 0; - virtual void RestoreAttribute(unsigned index) const = 0; + virtual void RestoreAllTextureUnitBindings( + const ContextState* prev_state) const = 0; + virtual void RestoreActiveTextureUnitBinding(unsigned int target) const = 0; virtual void RestoreBufferBindings() const = 0; virtual void RestoreFramebufferBindings() const = 0; virtual void RestoreGlobalState() const = 0; virtual void RestoreProgramBindings() const = 0; - virtual void RestoreRenderbufferBindings() const = 0; virtual void RestoreTextureState(unsigned service_id) const = 0; virtual void RestoreTextureUnitBindings(unsigned unit) const = 0; + virtual void ClearAllAttributes() const = 0; + virtual void RestoreAllAttributes() const = 0; + + virtual void SetIgnoreCachedStateForTest(bool ignore) = 0; + // Gets the QueryManager for this context. virtual QueryManager* GetQueryManager() = 0; @@ -194,6 +194,7 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, unsigned bind_target, unsigned target, int level, + unsigned internal_format, unsigned format, unsigned type, int width, @@ -228,6 +229,11 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, virtual Logger* GetLogger() = 0; + virtual void BeginDecoding(); + virtual void EndDecoding(); + + virtual const ContextState* GetContextState() = 0; + protected: GLES2Decoder(); @@ -241,4 +247,5 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, } // namespace gles2 } // namespace gpu + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_H_ diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index ddc00fcc4fb..8011ab19990 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -1,9 +1,11 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! // It is included by gles2_cmd_decoder.cc @@ -11,14 +13,16 @@ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_AUTOGEN_H_ error::Error GLES2DecoderImpl::HandleActiveTexture( - uint32 immediate_data_size, const gles2::cmds::ActiveTexture& c) { + uint32_t immediate_data_size, + const gles2::cmds::ActiveTexture& c) { GLenum texture = static_cast<GLenum>(c.texture); DoActiveTexture(texture); return error::kNoError; } error::Error GLES2DecoderImpl::HandleAttachShader( - uint32 immediate_data_size, const gles2::cmds::AttachShader& c) { + uint32_t immediate_data_size, + const gles2::cmds::AttachShader& c) { GLuint program = c.program; GLuint shader = c.shader; DoAttachShader(program, shader); @@ -26,7 +30,8 @@ error::Error GLES2DecoderImpl::HandleAttachShader( } error::Error GLES2DecoderImpl::HandleBindBuffer( - uint32 immediate_data_size, const gles2::cmds::BindBuffer& c) { + uint32_t immediate_data_size, + const gles2::cmds::BindBuffer& c) { GLenum target = static_cast<GLenum>(c.target); GLuint buffer = c.buffer; if (!validators_->buffer_target.IsValid(target)) { @@ -38,7 +43,8 @@ error::Error GLES2DecoderImpl::HandleBindBuffer( } error::Error GLES2DecoderImpl::HandleBindFramebuffer( - uint32 immediate_data_size, const gles2::cmds::BindFramebuffer& c) { + uint32_t immediate_data_size, + const gles2::cmds::BindFramebuffer& c) { GLenum target = static_cast<GLenum>(c.target); GLuint framebuffer = c.framebuffer; if (!validators_->frame_buffer_target.IsValid(target)) { @@ -50,7 +56,8 @@ error::Error GLES2DecoderImpl::HandleBindFramebuffer( } error::Error GLES2DecoderImpl::HandleBindRenderbuffer( - uint32 immediate_data_size, const gles2::cmds::BindRenderbuffer& c) { + uint32_t immediate_data_size, + const gles2::cmds::BindRenderbuffer& c) { GLenum target = static_cast<GLenum>(c.target); GLuint renderbuffer = c.renderbuffer; if (!validators_->render_buffer_target.IsValid(target)) { @@ -62,7 +69,8 @@ error::Error GLES2DecoderImpl::HandleBindRenderbuffer( } error::Error GLES2DecoderImpl::HandleBindTexture( - uint32 immediate_data_size, const gles2::cmds::BindTexture& c) { + uint32_t immediate_data_size, + const gles2::cmds::BindTexture& c) { GLenum target = static_cast<GLenum>(c.target); GLuint texture = c.texture; if (!validators_->texture_bind_target.IsValid(target)) { @@ -74,15 +82,14 @@ error::Error GLES2DecoderImpl::HandleBindTexture( } error::Error GLES2DecoderImpl::HandleBlendColor( - uint32 immediate_data_size, const gles2::cmds::BlendColor& c) { + uint32_t immediate_data_size, + const gles2::cmds::BlendColor& c) { GLclampf red = static_cast<GLclampf>(c.red); GLclampf green = static_cast<GLclampf>(c.green); GLclampf blue = static_cast<GLclampf>(c.blue); GLclampf alpha = static_cast<GLclampf>(c.alpha); - if (state_.blend_color_red != red || - state_.blend_color_green != green || - state_.blend_color_blue != blue || - state_.blend_color_alpha != alpha) { + if (state_.blend_color_red != red || state_.blend_color_green != green || + state_.blend_color_blue != blue || state_.blend_color_alpha != alpha) { state_.blend_color_red = red; state_.blend_color_green = green; state_.blend_color_blue = blue; @@ -93,7 +100,8 @@ error::Error GLES2DecoderImpl::HandleBlendColor( } error::Error GLES2DecoderImpl::HandleBlendEquation( - uint32 immediate_data_size, const gles2::cmds::BlendEquation& c) { + uint32_t immediate_data_size, + const gles2::cmds::BlendEquation& c) { GLenum mode = static_cast<GLenum>(c.mode); if (!validators_->equation.IsValid(mode)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glBlendEquation", mode, "mode"); @@ -109,17 +117,18 @@ error::Error GLES2DecoderImpl::HandleBlendEquation( } error::Error GLES2DecoderImpl::HandleBlendEquationSeparate( - uint32 immediate_data_size, const gles2::cmds::BlendEquationSeparate& c) { + uint32_t immediate_data_size, + const gles2::cmds::BlendEquationSeparate& c) { GLenum modeRGB = static_cast<GLenum>(c.modeRGB); GLenum modeAlpha = static_cast<GLenum>(c.modeAlpha); if (!validators_->equation.IsValid(modeRGB)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glBlendEquationSeparate", modeRGB, - "modeRGB"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBlendEquationSeparate", modeRGB, "modeRGB"); return error::kNoError; } if (!validators_->equation.IsValid(modeAlpha)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glBlendEquationSeparate", modeAlpha, - "modeAlpha"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBlendEquationSeparate", modeAlpha, "modeAlpha"); return error::kNoError; } if (state_.blend_equation_rgb != modeRGB || @@ -132,7 +141,8 @@ error::Error GLES2DecoderImpl::HandleBlendEquationSeparate( } error::Error GLES2DecoderImpl::HandleBlendFunc( - uint32 immediate_data_size, const gles2::cmds::BlendFunc& c) { + uint32_t immediate_data_size, + const gles2::cmds::BlendFunc& c) { GLenum sfactor = static_cast<GLenum>(c.sfactor); GLenum dfactor = static_cast<GLenum>(c.dfactor); if (!validators_->src_blend_factor.IsValid(sfactor)) { @@ -143,8 +153,7 @@ error::Error GLES2DecoderImpl::HandleBlendFunc( LOCAL_SET_GL_ERROR_INVALID_ENUM("glBlendFunc", dfactor, "dfactor"); return error::kNoError; } - if (state_.blend_source_rgb != sfactor || - state_.blend_dest_rgb != dfactor || + if (state_.blend_source_rgb != sfactor || state_.blend_dest_rgb != dfactor || state_.blend_source_alpha != sfactor || state_.blend_dest_alpha != dfactor) { state_.blend_source_rgb = sfactor; @@ -157,7 +166,8 @@ error::Error GLES2DecoderImpl::HandleBlendFunc( } error::Error GLES2DecoderImpl::HandleBlendFuncSeparate( - uint32 immediate_data_size, const gles2::cmds::BlendFuncSeparate& c) { + uint32_t immediate_data_size, + const gles2::cmds::BlendFuncSeparate& c) { GLenum srcRGB = static_cast<GLenum>(c.srcRGB); GLenum dstRGB = static_cast<GLenum>(c.dstRGB); GLenum srcAlpha = static_cast<GLenum>(c.srcAlpha); @@ -171,17 +181,16 @@ error::Error GLES2DecoderImpl::HandleBlendFuncSeparate( return error::kNoError; } if (!validators_->src_blend_factor.IsValid(srcAlpha)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glBlendFuncSeparate", srcAlpha, - "srcAlpha"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBlendFuncSeparate", srcAlpha, "srcAlpha"); return error::kNoError; } if (!validators_->dst_blend_factor.IsValid(dstAlpha)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glBlendFuncSeparate", dstAlpha, - "dstAlpha"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBlendFuncSeparate", dstAlpha, "dstAlpha"); return error::kNoError; } - if (state_.blend_source_rgb != srcRGB || - state_.blend_dest_rgb != dstRGB || + if (state_.blend_source_rgb != srcRGB || state_.blend_dest_rgb != dstRGB || state_.blend_source_alpha != srcAlpha || state_.blend_dest_alpha != dstAlpha) { state_.blend_source_rgb = srcRGB; @@ -194,11 +203,12 @@ error::Error GLES2DecoderImpl::HandleBlendFuncSeparate( } error::Error GLES2DecoderImpl::HandleBufferSubData( - uint32 immediate_data_size, const gles2::cmds::BufferSubData& c) { + uint32_t immediate_data_size, + const gles2::cmds::BufferSubData& c) { GLenum target = static_cast<GLenum>(c.target); GLintptr offset = static_cast<GLintptr>(c.offset); GLsizeiptr size = static_cast<GLsizeiptr>(c.size); - uint32 data_size = size; + uint32_t data_size = size; const void* data = GetSharedMemoryAs<const void*>( c.data_shm_id, c.data_shm_offset, data_size); if (!validators_->buffer_target.IsValid(target)) { @@ -217,7 +227,8 @@ error::Error GLES2DecoderImpl::HandleBufferSubData( } error::Error GLES2DecoderImpl::HandleCheckFramebufferStatus( - uint32 immediate_data_size, const gles2::cmds::CheckFramebufferStatus& c) { + uint32_t immediate_data_size, + const gles2::cmds::CheckFramebufferStatus& c) { GLenum target = static_cast<GLenum>(c.target); typedef cmds::CheckFramebufferStatus::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -226,16 +237,16 @@ error::Error GLES2DecoderImpl::HandleCheckFramebufferStatus( return error::kOutOfBounds; } if (!validators_->frame_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glCheckFramebufferStatus", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glCheckFramebufferStatus", target, "target"); return error::kNoError; } *result_dst = DoCheckFramebufferStatus(target); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleClear( - uint32 immediate_data_size, const gles2::cmds::Clear& c) { +error::Error GLES2DecoderImpl::HandleClear(uint32_t immediate_data_size, + const gles2::cmds::Clear& c) { error::Error error; error = WillAccessBoundFramebufferForDraw(); if (error != error::kNoError) @@ -246,15 +257,14 @@ error::Error GLES2DecoderImpl::HandleClear( } error::Error GLES2DecoderImpl::HandleClearColor( - uint32 immediate_data_size, const gles2::cmds::ClearColor& c) { + uint32_t immediate_data_size, + const gles2::cmds::ClearColor& c) { GLclampf red = static_cast<GLclampf>(c.red); GLclampf green = static_cast<GLclampf>(c.green); GLclampf blue = static_cast<GLclampf>(c.blue); GLclampf alpha = static_cast<GLclampf>(c.alpha); - if (state_.color_clear_red != red || - state_.color_clear_green != green || - state_.color_clear_blue != blue || - state_.color_clear_alpha != alpha) { + if (state_.color_clear_red != red || state_.color_clear_green != green || + state_.color_clear_blue != blue || state_.color_clear_alpha != alpha) { state_.color_clear_red = red; state_.color_clear_green = green; state_.color_clear_blue = blue; @@ -265,7 +275,8 @@ error::Error GLES2DecoderImpl::HandleClearColor( } error::Error GLES2DecoderImpl::HandleClearDepthf( - uint32 immediate_data_size, const gles2::cmds::ClearDepthf& c) { + uint32_t immediate_data_size, + const gles2::cmds::ClearDepthf& c) { GLclampf depth = static_cast<GLclampf>(c.depth); if (state_.depth_clear != depth) { state_.depth_clear = depth; @@ -275,7 +286,8 @@ error::Error GLES2DecoderImpl::HandleClearDepthf( } error::Error GLES2DecoderImpl::HandleClearStencil( - uint32 immediate_data_size, const gles2::cmds::ClearStencil& c) { + uint32_t immediate_data_size, + const gles2::cmds::ClearStencil& c) { GLint s = static_cast<GLint>(c.s); if (state_.stencil_clear != s) { state_.stencil_clear = s; @@ -285,15 +297,14 @@ error::Error GLES2DecoderImpl::HandleClearStencil( } error::Error GLES2DecoderImpl::HandleColorMask( - uint32 immediate_data_size, const gles2::cmds::ColorMask& c) { + uint32_t immediate_data_size, + const gles2::cmds::ColorMask& c) { GLboolean red = static_cast<GLboolean>(c.red); GLboolean green = static_cast<GLboolean>(c.green); GLboolean blue = static_cast<GLboolean>(c.blue); GLboolean alpha = static_cast<GLboolean>(c.alpha); - if (state_.color_mask_red != red || - state_.color_mask_green != green || - state_.color_mask_blue != blue || - state_.color_mask_alpha != alpha) { + if (state_.color_mask_red != red || state_.color_mask_green != green || + state_.color_mask_blue != blue || state_.color_mask_alpha != alpha) { state_.color_mask_red = red; state_.color_mask_green = green; state_.color_mask_blue = blue; @@ -304,14 +315,15 @@ error::Error GLES2DecoderImpl::HandleColorMask( } error::Error GLES2DecoderImpl::HandleCompileShader( - uint32 immediate_data_size, const gles2::cmds::CompileShader& c) { + uint32_t immediate_data_size, + const gles2::cmds::CompileShader& c) { GLuint shader = c.shader; DoCompileShader(shader); return error::kNoError; } error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2D( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::CompressedTexSubImage2D& c) { GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); @@ -321,12 +333,12 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2D( GLsizei height = static_cast<GLsizei>(c.height); GLenum format = static_cast<GLenum>(c.format); GLsizei imageSize = static_cast<GLsizei>(c.imageSize); - uint32 data_size = imageSize; + uint32_t data_size = imageSize; const void* data = GetSharedMemoryAs<const void*>( c.data_shm_id, c.data_shm_offset, data_size); if (!validators_->texture_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glCompressedTexSubImage2D", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glCompressedTexSubImage2D", target, "target"); return error::kNoError; } if (width < 0) { @@ -340,8 +352,8 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2D( return error::kNoError; } if (!validators_->compressed_texture_format.IsValid(format)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glCompressedTexSubImage2D", format, - "format"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glCompressedTexSubImage2D", format, "format"); return error::kNoError; } if (imageSize < 0) { @@ -358,7 +370,8 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2D( } error::Error GLES2DecoderImpl::HandleCopyTexImage2D( - uint32 immediate_data_size, const gles2::cmds::CopyTexImage2D& c) { + uint32_t immediate_data_size, + const gles2::cmds::CopyTexImage2D& c) { error::Error error; error = WillAccessBoundFramebufferForRead(); if (error != error::kNoError) @@ -376,8 +389,8 @@ error::Error GLES2DecoderImpl::HandleCopyTexImage2D( return error::kNoError; } if (!validators_->texture_internal_format.IsValid(internalformat)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glCopyTexImage2D", internalformat, - "internalformat"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glCopyTexImage2D", internalformat, "internalformat"); return error::kNoError; } if (width < 0) { @@ -388,17 +401,13 @@ error::Error GLES2DecoderImpl::HandleCopyTexImage2D( LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyTexImage2D", "height < 0"); return error::kNoError; } - if (!validators_->texture_border.IsValid(border)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glCopyTexImage2D", "border GL_INVALID_VALUE"); - return error::kNoError; - } DoCopyTexImage2D(target, level, internalformat, x, y, width, height, border); return error::kNoError; } error::Error GLES2DecoderImpl::HandleCopyTexSubImage2D( - uint32 immediate_data_size, const gles2::cmds::CopyTexSubImage2D& c) { + uint32_t immediate_data_size, + const gles2::cmds::CopyTexSubImage2D& c) { error::Error error; error = WillAccessBoundFramebufferForRead(); if (error != error::kNoError) @@ -428,8 +437,9 @@ error::Error GLES2DecoderImpl::HandleCopyTexSubImage2D( } error::Error GLES2DecoderImpl::HandleCreateProgram( - uint32 immediate_data_size, const gles2::cmds::CreateProgram& c) { - uint32 client_id = c.client_id; + uint32_t immediate_data_size, + const gles2::cmds::CreateProgram& c) { + uint32_t client_id = c.client_id; if (!CreateProgramHelper(client_id)) { return error::kInvalidArguments; } @@ -437,21 +447,22 @@ error::Error GLES2DecoderImpl::HandleCreateProgram( } error::Error GLES2DecoderImpl::HandleCreateShader( - uint32 immediate_data_size, const gles2::cmds::CreateShader& c) { + uint32_t immediate_data_size, + const gles2::cmds::CreateShader& c) { GLenum type = static_cast<GLenum>(c.type); if (!validators_->shader_type.IsValid(type)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glCreateShader", type, "type"); return error::kNoError; } - uint32 client_id = c.client_id; + uint32_t client_id = c.client_id; if (!CreateShaderHelper(type, client_id)) { return error::kInvalidArguments; } return error::kNoError; } -error::Error GLES2DecoderImpl::HandleCullFace( - uint32 immediate_data_size, const gles2::cmds::CullFace& c) { +error::Error GLES2DecoderImpl::HandleCullFace(uint32_t immediate_data_size, + const gles2::cmds::CullFace& c) { GLenum mode = static_cast<GLenum>(c.mode); if (!validators_->face_type.IsValid(mode)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glCullFace", mode, "mode"); @@ -464,31 +475,16 @@ error::Error GLES2DecoderImpl::HandleCullFace( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDeleteBuffers( - uint32 immediate_data_size, const gles2::cmds::DeleteBuffers& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - const GLuint* buffers = GetSharedMemoryAs<const GLuint*>( - c.buffers_shm_id, c.buffers_shm_offset, data_size); - if (buffers == NULL) { - return error::kOutOfBounds; - } - DeleteBuffersHelper(n, buffers); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleDeleteBuffersImmediate( - uint32 immediate_data_size, const gles2::cmds::DeleteBuffersImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::DeleteBuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - const GLuint* buffers = GetImmediateDataAs<const GLuint*>( - c, data_size, immediate_data_size); + const GLuint* buffers = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); if (buffers == NULL) { return error::kOutOfBounds; } @@ -496,32 +492,16 @@ error::Error GLES2DecoderImpl::HandleDeleteBuffersImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDeleteFramebuffers( - uint32 immediate_data_size, const gles2::cmds::DeleteFramebuffers& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - const GLuint* framebuffers = GetSharedMemoryAs<const GLuint*>( - c.framebuffers_shm_id, c.framebuffers_shm_offset, data_size); - if (framebuffers == NULL) { - return error::kOutOfBounds; - } - DeleteFramebuffersHelper(n, framebuffers); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleDeleteFramebuffersImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::DeleteFramebuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - const GLuint* framebuffers = GetImmediateDataAs<const GLuint*>( - c, data_size, immediate_data_size); + const GLuint* framebuffers = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); if (framebuffers == NULL) { return error::kOutOfBounds; } @@ -529,32 +509,16 @@ error::Error GLES2DecoderImpl::HandleDeleteFramebuffersImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDeleteRenderbuffers( - uint32 immediate_data_size, const gles2::cmds::DeleteRenderbuffers& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - const GLuint* renderbuffers = GetSharedMemoryAs<const GLuint*>( - c.renderbuffers_shm_id, c.renderbuffers_shm_offset, data_size); - if (renderbuffers == NULL) { - return error::kOutOfBounds; - } - DeleteRenderbuffersHelper(n, renderbuffers); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleDeleteRenderbuffersImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::DeleteRenderbuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - const GLuint* renderbuffers = GetImmediateDataAs<const GLuint*>( - c, data_size, immediate_data_size); + const GLuint* renderbuffers = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); if (renderbuffers == NULL) { return error::kOutOfBounds; } @@ -562,32 +526,16 @@ error::Error GLES2DecoderImpl::HandleDeleteRenderbuffersImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDeleteTextures( - uint32 immediate_data_size, const gles2::cmds::DeleteTextures& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - const GLuint* textures = GetSharedMemoryAs<const GLuint*>( - c.textures_shm_id, c.textures_shm_offset, data_size); - if (textures == NULL) { - return error::kOutOfBounds; - } - DeleteTexturesHelper(n, textures); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleDeleteTexturesImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::DeleteTexturesImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - const GLuint* textures = GetImmediateDataAs<const GLuint*>( - c, data_size, immediate_data_size); + const GLuint* textures = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); if (textures == NULL) { return error::kOutOfBounds; } @@ -596,7 +544,8 @@ error::Error GLES2DecoderImpl::HandleDeleteTexturesImmediate( } error::Error GLES2DecoderImpl::HandleDepthFunc( - uint32 immediate_data_size, const gles2::cmds::DepthFunc& c) { + uint32_t immediate_data_size, + const gles2::cmds::DepthFunc& c) { GLenum func = static_cast<GLenum>(c.func); if (!validators_->cmp_function.IsValid(func)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glDepthFunc", func, "func"); @@ -610,7 +559,8 @@ error::Error GLES2DecoderImpl::HandleDepthFunc( } error::Error GLES2DecoderImpl::HandleDepthMask( - uint32 immediate_data_size, const gles2::cmds::DepthMask& c) { + uint32_t immediate_data_size, + const gles2::cmds::DepthMask& c) { GLboolean flag = static_cast<GLboolean>(c.flag); if (state_.depth_mask != flag) { state_.depth_mask = flag; @@ -620,7 +570,8 @@ error::Error GLES2DecoderImpl::HandleDepthMask( } error::Error GLES2DecoderImpl::HandleDepthRangef( - uint32 immediate_data_size, const gles2::cmds::DepthRangef& c) { + uint32_t immediate_data_size, + const gles2::cmds::DepthRangef& c) { GLclampf zNear = static_cast<GLclampf>(c.zNear); GLclampf zFar = static_cast<GLclampf>(c.zFar); DoDepthRangef(zNear, zFar); @@ -628,15 +579,16 @@ error::Error GLES2DecoderImpl::HandleDepthRangef( } error::Error GLES2DecoderImpl::HandleDetachShader( - uint32 immediate_data_size, const gles2::cmds::DetachShader& c) { + uint32_t immediate_data_size, + const gles2::cmds::DetachShader& c) { GLuint program = c.program; GLuint shader = c.shader; DoDetachShader(program, shader); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDisable( - uint32 immediate_data_size, const gles2::cmds::Disable& c) { +error::Error GLES2DecoderImpl::HandleDisable(uint32_t immediate_data_size, + const gles2::cmds::Disable& c) { GLenum cap = static_cast<GLenum>(c.cap); if (!validators_->capability.IsValid(cap)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glDisable", cap, "cap"); @@ -647,15 +599,15 @@ error::Error GLES2DecoderImpl::HandleDisable( } error::Error GLES2DecoderImpl::HandleDisableVertexAttribArray( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::DisableVertexAttribArray& c) { GLuint index = static_cast<GLuint>(c.index); DoDisableVertexAttribArray(index); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleEnable( - uint32 immediate_data_size, const gles2::cmds::Enable& c) { +error::Error GLES2DecoderImpl::HandleEnable(uint32_t immediate_data_size, + const gles2::cmds::Enable& c) { GLenum cap = static_cast<GLenum>(c.cap); if (!validators_->capability.IsValid(cap)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glEnable", cap, "cap"); @@ -666,15 +618,15 @@ error::Error GLES2DecoderImpl::HandleEnable( } error::Error GLES2DecoderImpl::HandleEnableVertexAttribArray( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::EnableVertexAttribArray& c) { GLuint index = static_cast<GLuint>(c.index); DoEnableVertexAttribArray(index); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleFinish( - uint32 immediate_data_size, const gles2::cmds::Finish& c) { +error::Error GLES2DecoderImpl::HandleFinish(uint32_t immediate_data_size, + const gles2::cmds::Finish& c) { error::Error error; error = WillAccessBoundFramebufferForRead(); if (error != error::kNoError) @@ -683,31 +635,32 @@ error::Error GLES2DecoderImpl::HandleFinish( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleFlush( - uint32 immediate_data_size, const gles2::cmds::Flush& c) { +error::Error GLES2DecoderImpl::HandleFlush(uint32_t immediate_data_size, + const gles2::cmds::Flush& c) { DoFlush(); return error::kNoError; } error::Error GLES2DecoderImpl::HandleFramebufferRenderbuffer( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::FramebufferRenderbuffer& c) { GLenum target = static_cast<GLenum>(c.target); GLenum attachment = static_cast<GLenum>(c.attachment); GLenum renderbuffertarget = static_cast<GLenum>(c.renderbuffertarget); GLuint renderbuffer = c.renderbuffer; if (!validators_->frame_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferRenderbuffer", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferRenderbuffer", target, "target"); return error::kNoError; } if (!validators_->attachment.IsValid(attachment)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferRenderbuffer", attachment, - "attachment"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferRenderbuffer", attachment, "attachment"); return error::kNoError; } if (!validators_->render_buffer_target.IsValid(renderbuffertarget)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferRenderbuffer", renderbuffertarget, "renderbuffertarget"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferRenderbuffer", renderbuffertarget, "renderbuffertarget"); return error::kNoError; } DoFramebufferRenderbuffer( @@ -716,30 +669,25 @@ error::Error GLES2DecoderImpl::HandleFramebufferRenderbuffer( } error::Error GLES2DecoderImpl::HandleFramebufferTexture2D( - uint32 immediate_data_size, const gles2::cmds::FramebufferTexture2D& c) { + uint32_t immediate_data_size, + const gles2::cmds::FramebufferTexture2D& c) { GLenum target = static_cast<GLenum>(c.target); GLenum attachment = static_cast<GLenum>(c.attachment); GLenum textarget = static_cast<GLenum>(c.textarget); GLuint texture = c.texture; GLint level = static_cast<GLint>(c.level); if (!validators_->frame_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTexture2D", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTexture2D", target, "target"); return error::kNoError; } if (!validators_->attachment.IsValid(attachment)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTexture2D", attachment, - "attachment"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferTexture2D", attachment, "attachment"); return error::kNoError; } if (!validators_->texture_target.IsValid(textarget)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTexture2D", textarget, - "textarget"); - return error::kNoError; - } - if (!validators_->zero_only.IsValid(level)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glFramebufferTexture2D", "level GL_INVALID_VALUE"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferTexture2D", textarget, "textarget"); return error::kNoError; } DoFramebufferTexture2D(target, attachment, textarget, texture, level); @@ -747,7 +695,8 @@ error::Error GLES2DecoderImpl::HandleFramebufferTexture2D( } error::Error GLES2DecoderImpl::HandleFrontFace( - uint32 immediate_data_size, const gles2::cmds::FrontFace& c) { + uint32_t immediate_data_size, + const gles2::cmds::FrontFace& c) { GLenum mode = static_cast<GLenum>(c.mode); if (!validators_->face_mode.IsValid(mode)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glFrontFace", mode, "mode"); @@ -760,33 +709,16 @@ error::Error GLES2DecoderImpl::HandleFrontFace( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGenBuffers( - uint32 immediate_data_size, const gles2::cmds::GenBuffers& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - GLuint* buffers = GetSharedMemoryAs<GLuint*>( - c.buffers_shm_id, c.buffers_shm_offset, data_size); - if (buffers == NULL) { - return error::kOutOfBounds; - } - if (!GenBuffersHelper(n, buffers)) { - return error::kInvalidArguments; - } - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleGenBuffersImmediate( - uint32 immediate_data_size, const gles2::cmds::GenBuffersImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::GenBuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - GLuint* buffers = GetImmediateDataAs<GLuint*>( - c, data_size, immediate_data_size); + GLuint* buffers = + GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); if (buffers == NULL) { return error::kOutOfBounds; } @@ -797,7 +729,8 @@ error::Error GLES2DecoderImpl::HandleGenBuffersImmediate( } error::Error GLES2DecoderImpl::HandleGenerateMipmap( - uint32 immediate_data_size, const gles2::cmds::GenerateMipmap& c) { + uint32_t immediate_data_size, + const gles2::cmds::GenerateMipmap& c) { GLenum target = static_cast<GLenum>(c.target); if (!validators_->texture_bind_target.IsValid(target)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glGenerateMipmap", target, "target"); @@ -807,34 +740,16 @@ error::Error GLES2DecoderImpl::HandleGenerateMipmap( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGenFramebuffers( - uint32 immediate_data_size, const gles2::cmds::GenFramebuffers& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - GLuint* framebuffers = GetSharedMemoryAs<GLuint*>( - c.framebuffers_shm_id, c.framebuffers_shm_offset, data_size); - if (framebuffers == NULL) { - return error::kOutOfBounds; - } - if (!GenFramebuffersHelper(n, framebuffers)) { - return error::kInvalidArguments; - } - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleGenFramebuffersImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::GenFramebuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - GLuint* framebuffers = GetImmediateDataAs<GLuint*>( - c, data_size, immediate_data_size); + GLuint* framebuffers = + GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); if (framebuffers == NULL) { return error::kOutOfBounds; } @@ -844,34 +759,16 @@ error::Error GLES2DecoderImpl::HandleGenFramebuffersImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGenRenderbuffers( - uint32 immediate_data_size, const gles2::cmds::GenRenderbuffers& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - GLuint* renderbuffers = GetSharedMemoryAs<GLuint*>( - c.renderbuffers_shm_id, c.renderbuffers_shm_offset, data_size); - if (renderbuffers == NULL) { - return error::kOutOfBounds; - } - if (!GenRenderbuffersHelper(n, renderbuffers)) { - return error::kInvalidArguments; - } - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleGenRenderbuffersImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::GenRenderbuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - GLuint* renderbuffers = GetImmediateDataAs<GLuint*>( - c, data_size, immediate_data_size); + GLuint* renderbuffers = + GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); if (renderbuffers == NULL) { return error::kOutOfBounds; } @@ -881,33 +778,16 @@ error::Error GLES2DecoderImpl::HandleGenRenderbuffersImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGenTextures( - uint32 immediate_data_size, const gles2::cmds::GenTextures& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - GLuint* textures = GetSharedMemoryAs<GLuint*>( - c.textures_shm_id, c.textures_shm_offset, data_size); - if (textures == NULL) { - return error::kOutOfBounds; - } - if (!GenTexturesHelper(n, textures)) { - return error::kInvalidArguments; - } - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleGenTexturesImmediate( - uint32 immediate_data_size, const gles2::cmds::GenTexturesImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::GenTexturesImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - GLuint* textures = GetImmediateDataAs<GLuint*>( - c, data_size, immediate_data_size); + GLuint* textures = + GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); if (textures == NULL) { return error::kOutOfBounds; } @@ -918,7 +798,8 @@ error::Error GLES2DecoderImpl::HandleGenTexturesImmediate( } error::Error GLES2DecoderImpl::HandleGetBooleanv( - uint32 immediate_data_size, const gles2::cmds::GetBooleanv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetBooleanv& c) { GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetBooleanv::Result Result; GLsizei num_values = 0; @@ -949,7 +830,8 @@ error::Error GLES2DecoderImpl::HandleGetBooleanv( } error::Error GLES2DecoderImpl::HandleGetBufferParameteriv( - uint32 immediate_data_size, const gles2::cmds::GetBufferParameteriv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetBufferParameteriv& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetBufferParameteriv::Result Result; @@ -959,8 +841,7 @@ error::Error GLES2DecoderImpl::HandleGetBufferParameteriv( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLint* params = result ? result->GetData() : NULL; if (!validators_->buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetBufferParameteriv", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetBufferParameteriv", target, "target"); return error::kNoError; } if (!validators_->buffer_parameter.IsValid(pname)) { @@ -978,8 +859,8 @@ error::Error GLES2DecoderImpl::HandleGetBufferParameteriv( result->SetNumResults(num_values); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGetError( - uint32 immediate_data_size, const gles2::cmds::GetError& c) { +error::Error GLES2DecoderImpl::HandleGetError(uint32_t immediate_data_size, + const gles2::cmds::GetError& c) { typedef cmds::GetError::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); @@ -991,7 +872,8 @@ error::Error GLES2DecoderImpl::HandleGetError( } error::Error GLES2DecoderImpl::HandleGetFloatv( - uint32 immediate_data_size, const gles2::cmds::GetFloatv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetFloatv& c) { GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetFloatv::Result Result; GLsizei num_values = 0; @@ -1022,7 +904,7 @@ error::Error GLES2DecoderImpl::HandleGetFloatv( } error::Error GLES2DecoderImpl::HandleGetFramebufferAttachmentParameteriv( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::GetFramebufferAttachmentParameteriv& c) { GLenum target = static_cast<GLenum>(c.target); GLenum attachment = static_cast<GLenum>(c.attachment); @@ -1034,15 +916,18 @@ error::Error GLES2DecoderImpl::HandleGetFramebufferAttachmentParameteriv( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLint* params = result ? result->GetData() : NULL; if (!validators_->frame_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetFramebufferAttachmentParameteriv", target, "target"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glGetFramebufferAttachmentParameteriv", target, "target"); return error::kNoError; } if (!validators_->attachment.IsValid(attachment)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetFramebufferAttachmentParameteriv", attachment, "attachment"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glGetFramebufferAttachmentParameteriv", attachment, "attachment"); return error::kNoError; } if (!validators_->frame_buffer_parameter.IsValid(pname)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetFramebufferAttachmentParameteriv", pname, "pname"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glGetFramebufferAttachmentParameteriv", pname, "pname"); return error::kNoError; } if (params == NULL) { @@ -1064,7 +949,8 @@ error::Error GLES2DecoderImpl::HandleGetFramebufferAttachmentParameteriv( } error::Error GLES2DecoderImpl::HandleGetIntegerv( - uint32 immediate_data_size, const gles2::cmds::GetIntegerv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetIntegerv& c) { GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetIntegerv::Result Result; GLsizei num_values = 0; @@ -1095,7 +981,8 @@ error::Error GLES2DecoderImpl::HandleGetIntegerv( } error::Error GLES2DecoderImpl::HandleGetProgramiv( - uint32 immediate_data_size, const gles2::cmds::GetProgramiv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetProgramiv& c) { GLuint program = c.program; GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetProgramiv::Result Result; @@ -1127,7 +1014,7 @@ error::Error GLES2DecoderImpl::HandleGetProgramiv( } error::Error GLES2DecoderImpl::HandleGetRenderbufferParameteriv( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::GetRenderbufferParameteriv& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); @@ -1138,13 +1025,13 @@ error::Error GLES2DecoderImpl::HandleGetRenderbufferParameteriv( c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); GLint* params = result ? result->GetData() : NULL; if (!validators_->render_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetRenderbufferParameteriv", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glGetRenderbufferParameteriv", target, "target"); return error::kNoError; } if (!validators_->render_buffer_parameter.IsValid(pname)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetRenderbufferParameteriv", pname, - "pname"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glGetRenderbufferParameteriv", pname, "pname"); return error::kNoError; } if (params == NULL) { @@ -1166,7 +1053,8 @@ error::Error GLES2DecoderImpl::HandleGetRenderbufferParameteriv( } error::Error GLES2DecoderImpl::HandleGetShaderiv( - uint32 immediate_data_size, const gles2::cmds::GetShaderiv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetShaderiv& c) { GLuint shader = c.shader; GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetShaderiv::Result Result; @@ -1198,7 +1086,8 @@ error::Error GLES2DecoderImpl::HandleGetShaderiv( } error::Error GLES2DecoderImpl::HandleGetTexParameterfv( - uint32 immediate_data_size, const gles2::cmds::GetTexParameterfv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetTexParameterfv& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetTexParameterfv::Result Result; @@ -1223,7 +1112,7 @@ error::Error GLES2DecoderImpl::HandleGetTexParameterfv( if (result->size != 0) { return error::kInvalidArguments; } - glGetTexParameterfv(target, pname, params); + DoGetTexParameterfv(target, pname, params); GLenum error = glGetError(); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); @@ -1234,7 +1123,8 @@ error::Error GLES2DecoderImpl::HandleGetTexParameterfv( } error::Error GLES2DecoderImpl::HandleGetTexParameteriv( - uint32 immediate_data_size, const gles2::cmds::GetTexParameteriv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetTexParameteriv& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetTexParameteriv::Result Result; @@ -1259,7 +1149,7 @@ error::Error GLES2DecoderImpl::HandleGetTexParameteriv( if (result->size != 0) { return error::kInvalidArguments; } - glGetTexParameteriv(target, pname, params); + DoGetTexParameteriv(target, pname, params); GLenum error = glGetError(); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); @@ -1270,7 +1160,8 @@ error::Error GLES2DecoderImpl::HandleGetTexParameteriv( } error::Error GLES2DecoderImpl::HandleGetVertexAttribfv( - uint32 immediate_data_size, const gles2::cmds::GetVertexAttribfv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetVertexAttribfv& c) { GLuint index = static_cast<GLuint>(c.index); GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetVertexAttribfv::Result Result; @@ -1302,7 +1193,8 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribfv( } error::Error GLES2DecoderImpl::HandleGetVertexAttribiv( - uint32 immediate_data_size, const gles2::cmds::GetVertexAttribiv& c) { + uint32_t immediate_data_size, + const gles2::cmds::GetVertexAttribiv& c) { GLuint index = static_cast<GLuint>(c.index); GLenum pname = static_cast<GLenum>(c.pname); typedef cmds::GetVertexAttribiv::Result Result; @@ -1333,8 +1225,8 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribiv( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleHint( - uint32 immediate_data_size, const gles2::cmds::Hint& c) { +error::Error GLES2DecoderImpl::HandleHint(uint32_t immediate_data_size, + const gles2::cmds::Hint& c) { GLenum target = static_cast<GLenum>(c.target); GLenum mode = static_cast<GLenum>(c.mode); if (!validators_->hint_target.IsValid(target)) { @@ -1364,8 +1256,8 @@ error::Error GLES2DecoderImpl::HandleHint( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleIsBuffer( - uint32 immediate_data_size, const gles2::cmds::IsBuffer& c) { +error::Error GLES2DecoderImpl::HandleIsBuffer(uint32_t immediate_data_size, + const gles2::cmds::IsBuffer& c) { GLuint buffer = c.buffer; typedef cmds::IsBuffer::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -1378,7 +1270,8 @@ error::Error GLES2DecoderImpl::HandleIsBuffer( } error::Error GLES2DecoderImpl::HandleIsEnabled( - uint32 immediate_data_size, const gles2::cmds::IsEnabled& c) { + uint32_t immediate_data_size, + const gles2::cmds::IsEnabled& c) { GLenum cap = static_cast<GLenum>(c.cap); typedef cmds::IsEnabled::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -1395,7 +1288,8 @@ error::Error GLES2DecoderImpl::HandleIsEnabled( } error::Error GLES2DecoderImpl::HandleIsFramebuffer( - uint32 immediate_data_size, const gles2::cmds::IsFramebuffer& c) { + uint32_t immediate_data_size, + const gles2::cmds::IsFramebuffer& c) { GLuint framebuffer = c.framebuffer; typedef cmds::IsFramebuffer::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -1408,7 +1302,8 @@ error::Error GLES2DecoderImpl::HandleIsFramebuffer( } error::Error GLES2DecoderImpl::HandleIsProgram( - uint32 immediate_data_size, const gles2::cmds::IsProgram& c) { + uint32_t immediate_data_size, + const gles2::cmds::IsProgram& c) { GLuint program = c.program; typedef cmds::IsProgram::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -1421,7 +1316,8 @@ error::Error GLES2DecoderImpl::HandleIsProgram( } error::Error GLES2DecoderImpl::HandleIsRenderbuffer( - uint32 immediate_data_size, const gles2::cmds::IsRenderbuffer& c) { + uint32_t immediate_data_size, + const gles2::cmds::IsRenderbuffer& c) { GLuint renderbuffer = c.renderbuffer; typedef cmds::IsRenderbuffer::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -1433,8 +1329,8 @@ error::Error GLES2DecoderImpl::HandleIsRenderbuffer( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleIsShader( - uint32 immediate_data_size, const gles2::cmds::IsShader& c) { +error::Error GLES2DecoderImpl::HandleIsShader(uint32_t immediate_data_size, + const gles2::cmds::IsShader& c) { GLuint shader = c.shader; typedef cmds::IsShader::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -1447,7 +1343,8 @@ error::Error GLES2DecoderImpl::HandleIsShader( } error::Error GLES2DecoderImpl::HandleIsTexture( - uint32 immediate_data_size, const gles2::cmds::IsTexture& c) { + uint32_t immediate_data_size, + const gles2::cmds::IsTexture& c) { GLuint texture = c.texture; typedef cmds::IsTexture::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -1460,7 +1357,8 @@ error::Error GLES2DecoderImpl::HandleIsTexture( } error::Error GLES2DecoderImpl::HandleLineWidth( - uint32 immediate_data_size, const gles2::cmds::LineWidth& c) { + uint32_t immediate_data_size, + const gles2::cmds::LineWidth& c) { GLfloat width = static_cast<GLfloat>(c.width); if (width <= 0.0f) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "LineWidth", "width out of range"); @@ -1474,14 +1372,16 @@ error::Error GLES2DecoderImpl::HandleLineWidth( } error::Error GLES2DecoderImpl::HandleLinkProgram( - uint32 immediate_data_size, const gles2::cmds::LinkProgram& c) { + uint32_t immediate_data_size, + const gles2::cmds::LinkProgram& c) { GLuint program = c.program; DoLinkProgram(program); return error::kNoError; } error::Error GLES2DecoderImpl::HandlePolygonOffset( - uint32 immediate_data_size, const gles2::cmds::PolygonOffset& c) { + uint32_t immediate_data_size, + const gles2::cmds::PolygonOffset& c) { GLfloat factor = static_cast<GLfloat>(c.factor); GLfloat units = static_cast<GLfloat>(c.units); if (state_.polygon_offset_factor != factor || @@ -1494,13 +1394,15 @@ error::Error GLES2DecoderImpl::HandlePolygonOffset( } error::Error GLES2DecoderImpl::HandleReleaseShaderCompiler( - uint32 immediate_data_size, const gles2::cmds::ReleaseShaderCompiler& c) { + uint32_t immediate_data_size, + const gles2::cmds::ReleaseShaderCompiler& c) { DoReleaseShaderCompiler(); return error::kNoError; } error::Error GLES2DecoderImpl::HandleRenderbufferStorage( - uint32 immediate_data_size, const gles2::cmds::RenderbufferStorage& c) { + uint32_t immediate_data_size, + const gles2::cmds::RenderbufferStorage& c) { GLenum target = static_cast<GLenum>(c.target); GLenum internalformat = static_cast<GLenum>(c.internalformat); GLsizei width = static_cast<GLsizei>(c.width); @@ -1510,8 +1412,8 @@ error::Error GLES2DecoderImpl::HandleRenderbufferStorage( return error::kNoError; } if (!validators_->render_buffer_format.IsValid(internalformat)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glRenderbufferStorage", internalformat, - "internalformat"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glRenderbufferStorage", internalformat, "internalformat"); return error::kNoError; } if (width < 0) { @@ -1519,8 +1421,7 @@ error::Error GLES2DecoderImpl::HandleRenderbufferStorage( return error::kNoError; } if (height < 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glRenderbufferStorage", "height < 0"); + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glRenderbufferStorage", "height < 0"); return error::kNoError; } DoRenderbufferStorage(target, internalformat, width, height); @@ -1528,15 +1429,16 @@ error::Error GLES2DecoderImpl::HandleRenderbufferStorage( } error::Error GLES2DecoderImpl::HandleSampleCoverage( - uint32 immediate_data_size, const gles2::cmds::SampleCoverage& c) { + uint32_t immediate_data_size, + const gles2::cmds::SampleCoverage& c) { GLclampf value = static_cast<GLclampf>(c.value); GLboolean invert = static_cast<GLboolean>(c.invert); DoSampleCoverage(value, invert); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleScissor( - uint32 immediate_data_size, const gles2::cmds::Scissor& c) { +error::Error GLES2DecoderImpl::HandleScissor(uint32_t immediate_data_size, + const gles2::cmds::Scissor& c) { GLint x = static_cast<GLint>(c.x); GLint y = static_cast<GLint>(c.y); GLsizei width = static_cast<GLsizei>(c.width); @@ -1549,10 +1451,8 @@ error::Error GLES2DecoderImpl::HandleScissor( LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScissor", "height < 0"); return error::kNoError; } - if (state_.scissor_x != x || - state_.scissor_y != y || - state_.scissor_width != width || - state_.scissor_height != height) { + if (state_.scissor_x != x || state_.scissor_y != y || + state_.scissor_width != width || state_.scissor_height != height) { state_.scissor_x = x; state_.scissor_y = y; state_.scissor_width = width; @@ -1563,7 +1463,8 @@ error::Error GLES2DecoderImpl::HandleScissor( } error::Error GLES2DecoderImpl::HandleStencilFunc( - uint32 immediate_data_size, const gles2::cmds::StencilFunc& c) { + uint32_t immediate_data_size, + const gles2::cmds::StencilFunc& c) { GLenum func = static_cast<GLenum>(c.func); GLint ref = static_cast<GLint>(c.ref); GLuint mask = static_cast<GLuint>(c.mask); @@ -1571,12 +1472,9 @@ error::Error GLES2DecoderImpl::HandleStencilFunc( LOCAL_SET_GL_ERROR_INVALID_ENUM("glStencilFunc", func, "func"); return error::kNoError; } - if (state_.stencil_front_func != func || - state_.stencil_front_ref != ref || - state_.stencil_front_mask != mask || - state_.stencil_back_func != func || - state_.stencil_back_ref != ref || - state_.stencil_back_mask != mask) { + if (state_.stencil_front_func != func || state_.stencil_front_ref != ref || + state_.stencil_front_mask != mask || state_.stencil_back_func != func || + state_.stencil_back_ref != ref || state_.stencil_back_mask != mask) { state_.stencil_front_func = func; state_.stencil_front_ref = ref; state_.stencil_front_mask = mask; @@ -1589,7 +1487,8 @@ error::Error GLES2DecoderImpl::HandleStencilFunc( } error::Error GLES2DecoderImpl::HandleStencilFuncSeparate( - uint32 immediate_data_size, const gles2::cmds::StencilFuncSeparate& c) { + uint32_t immediate_data_size, + const gles2::cmds::StencilFuncSeparate& c) { GLenum face = static_cast<GLenum>(c.face); GLenum func = static_cast<GLenum>(c.func); GLint ref = static_cast<GLint>(c.ref); @@ -1605,13 +1504,13 @@ error::Error GLES2DecoderImpl::HandleStencilFuncSeparate( bool changed = false; if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { changed |= state_.stencil_front_func != func || - state_.stencil_front_ref != ref || - state_.stencil_front_mask != mask; + state_.stencil_front_ref != ref || + state_.stencil_front_mask != mask; } if (face == GL_BACK || face == GL_FRONT_AND_BACK) { changed |= state_.stencil_back_func != func || - state_.stencil_back_ref != ref || - state_.stencil_back_mask != mask; + state_.stencil_back_ref != ref || + state_.stencil_back_mask != mask; } if (changed) { if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { @@ -1630,7 +1529,8 @@ error::Error GLES2DecoderImpl::HandleStencilFuncSeparate( } error::Error GLES2DecoderImpl::HandleStencilMask( - uint32 immediate_data_size, const gles2::cmds::StencilMask& c) { + uint32_t immediate_data_size, + const gles2::cmds::StencilMask& c) { GLuint mask = static_cast<GLuint>(c.mask); if (state_.stencil_front_writemask != mask || state_.stencil_back_writemask != mask) { @@ -1642,7 +1542,8 @@ error::Error GLES2DecoderImpl::HandleStencilMask( } error::Error GLES2DecoderImpl::HandleStencilMaskSeparate( - uint32 immediate_data_size, const gles2::cmds::StencilMaskSeparate& c) { + uint32_t immediate_data_size, + const gles2::cmds::StencilMaskSeparate& c) { GLenum face = static_cast<GLenum>(c.face); GLuint mask = static_cast<GLuint>(c.mask); if (!validators_->face_type.IsValid(face)) { @@ -1669,7 +1570,8 @@ error::Error GLES2DecoderImpl::HandleStencilMaskSeparate( } error::Error GLES2DecoderImpl::HandleStencilOp( - uint32 immediate_data_size, const gles2::cmds::StencilOp& c) { + uint32_t immediate_data_size, + const gles2::cmds::StencilOp& c) { GLenum fail = static_cast<GLenum>(c.fail); GLenum zfail = static_cast<GLenum>(c.zfail); GLenum zpass = static_cast<GLenum>(c.zpass); @@ -1703,7 +1605,8 @@ error::Error GLES2DecoderImpl::HandleStencilOp( } error::Error GLES2DecoderImpl::HandleStencilOpSeparate( - uint32 immediate_data_size, const gles2::cmds::StencilOpSeparate& c) { + uint32_t immediate_data_size, + const gles2::cmds::StencilOpSeparate& c) { GLenum face = static_cast<GLenum>(c.face); GLenum fail = static_cast<GLenum>(c.fail); GLenum zfail = static_cast<GLenum>(c.zfail); @@ -1727,13 +1630,13 @@ error::Error GLES2DecoderImpl::HandleStencilOpSeparate( bool changed = false; if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { changed |= state_.stencil_front_fail_op != fail || - state_.stencil_front_z_fail_op != zfail || - state_.stencil_front_z_pass_op != zpass; + state_.stencil_front_z_fail_op != zfail || + state_.stencil_front_z_pass_op != zpass; } if (face == GL_BACK || face == GL_FRONT_AND_BACK) { changed |= state_.stencil_back_fail_op != fail || - state_.stencil_back_z_fail_op != zfail || - state_.stencil_back_z_pass_op != zpass; + state_.stencil_back_z_fail_op != zfail || + state_.stencil_back_z_pass_op != zpass; } if (changed) { if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { @@ -1752,7 +1655,8 @@ error::Error GLES2DecoderImpl::HandleStencilOpSeparate( } error::Error GLES2DecoderImpl::HandleTexParameterf( - uint32 immediate_data_size, const gles2::cmds::TexParameterf& c) { + uint32_t immediate_data_size, + const gles2::cmds::TexParameterf& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); GLfloat param = static_cast<GLfloat>(c.param); @@ -1768,45 +1672,20 @@ error::Error GLES2DecoderImpl::HandleTexParameterf( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleTexParameterfv( - uint32 immediate_data_size, const gles2::cmds::TexParameterfv& c) { - GLenum target = static_cast<GLenum>(c.target); - GLenum pname = static_cast<GLenum>(c.pname); - uint32 data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* params = GetSharedMemoryAs<const GLfloat*>( - c.params_shm_id, c.params_shm_offset, data_size); - if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexParameterfv", target, "target"); - return error::kNoError; - } - if (!validators_->texture_parameter.IsValid(pname)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexParameterfv", pname, "pname"); - return error::kNoError; - } - if (params == NULL) { - return error::kOutOfBounds; - } - DoTexParameterfv(target, pname, params); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleTexParameterfvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::TexParameterfvImmediate& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* params = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* params = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (!validators_->texture_bind_target.IsValid(target)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexParameterfv", target, "target"); return error::kNoError; @@ -1823,7 +1702,8 @@ error::Error GLES2DecoderImpl::HandleTexParameterfvImmediate( } error::Error GLES2DecoderImpl::HandleTexParameteri( - uint32 immediate_data_size, const gles2::cmds::TexParameteri& c) { + uint32_t immediate_data_size, + const gles2::cmds::TexParameteri& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); GLint param = static_cast<GLint>(c.param); @@ -1839,45 +1719,20 @@ error::Error GLES2DecoderImpl::HandleTexParameteri( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleTexParameteriv( - uint32 immediate_data_size, const gles2::cmds::TexParameteriv& c) { - GLenum target = static_cast<GLenum>(c.target); - GLenum pname = static_cast<GLenum>(c.pname); - uint32 data_size; - if (!ComputeDataSize(1, sizeof(GLint), 1, &data_size)) { - return error::kOutOfBounds; - } - const GLint* params = GetSharedMemoryAs<const GLint*>( - c.params_shm_id, c.params_shm_offset, data_size); - if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexParameteriv", target, "target"); - return error::kNoError; - } - if (!validators_->texture_parameter.IsValid(pname)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexParameteriv", pname, "pname"); - return error::kNoError; - } - if (params == NULL) { - return error::kOutOfBounds; - } - DoTexParameteriv(target, pname, params); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleTexParameterivImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::TexParameterivImmediate& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLint), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLint* params = GetImmediateDataAs<const GLint*>( - c, data_size, immediate_data_size); + const GLint* params = + GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); if (!validators_->texture_bind_target.IsValid(target)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexParameteriv", target, "target"); return error::kNoError; @@ -1894,44 +1749,31 @@ error::Error GLES2DecoderImpl::HandleTexParameterivImmediate( } error::Error GLES2DecoderImpl::HandleUniform1f( - uint32 immediate_data_size, const gles2::cmds::Uniform1f& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform1f& c) { GLint location = static_cast<GLint>(c.location); GLfloat x = static_cast<GLfloat>(c.x); - GLfloat temp[1] = { x, }; + GLfloat temp[1] = { + x, + }; DoUniform1fv(location, 1, &temp[0]); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform1fv( - uint32 immediate_data_size, const gles2::cmds::Uniform1fv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 1, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform1fv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform1fvImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform1fvImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform1fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLfloat), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* v = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* v = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -1940,43 +1782,28 @@ error::Error GLES2DecoderImpl::HandleUniform1fvImmediate( } error::Error GLES2DecoderImpl::HandleUniform1i( - uint32 immediate_data_size, const gles2::cmds::Uniform1i& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform1i& c) { GLint location = static_cast<GLint>(c.location); GLint x = static_cast<GLint>(c.x); DoUniform1i(location, x); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform1iv( - uint32 immediate_data_size, const gles2::cmds::Uniform1iv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLint), 1, &data_size)) { - return error::kOutOfBounds; - } - const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform1iv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform1ivImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform1ivImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform1ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLint), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLint* v = GetImmediateDataAs<const GLint*>( - c, data_size, immediate_data_size); + const GLint* v = + GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -1985,45 +1812,32 @@ error::Error GLES2DecoderImpl::HandleUniform1ivImmediate( } error::Error GLES2DecoderImpl::HandleUniform2f( - uint32 immediate_data_size, const gles2::cmds::Uniform2f& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform2f& c) { GLint location = static_cast<GLint>(c.location); GLfloat x = static_cast<GLfloat>(c.x); GLfloat y = static_cast<GLfloat>(c.y); - GLfloat temp[2] = { x, y, }; + GLfloat temp[2] = { + x, y, + }; DoUniform2fv(location, 1, &temp[0]); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform2fv( - uint32 immediate_data_size, const gles2::cmds::Uniform2fv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 2, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform2fv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform2fvImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform2fvImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform2fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLfloat), 2, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* v = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* v = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -2032,45 +1846,32 @@ error::Error GLES2DecoderImpl::HandleUniform2fvImmediate( } error::Error GLES2DecoderImpl::HandleUniform2i( - uint32 immediate_data_size, const gles2::cmds::Uniform2i& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform2i& c) { GLint location = static_cast<GLint>(c.location); GLint x = static_cast<GLint>(c.x); GLint y = static_cast<GLint>(c.y); - GLint temp[2] = { x, y, }; + GLint temp[2] = { + x, y, + }; DoUniform2iv(location, 1, &temp[0]); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform2iv( - uint32 immediate_data_size, const gles2::cmds::Uniform2iv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLint), 2, &data_size)) { - return error::kOutOfBounds; - } - const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform2iv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform2ivImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform2ivImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform2ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLint), 2, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLint* v = GetImmediateDataAs<const GLint*>( - c, data_size, immediate_data_size); + const GLint* v = + GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -2079,46 +1880,33 @@ error::Error GLES2DecoderImpl::HandleUniform2ivImmediate( } error::Error GLES2DecoderImpl::HandleUniform3f( - uint32 immediate_data_size, const gles2::cmds::Uniform3f& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform3f& c) { GLint location = static_cast<GLint>(c.location); GLfloat x = static_cast<GLfloat>(c.x); GLfloat y = static_cast<GLfloat>(c.y); GLfloat z = static_cast<GLfloat>(c.z); - GLfloat temp[3] = { x, y, z, }; + GLfloat temp[3] = { + x, y, z, + }; DoUniform3fv(location, 1, &temp[0]); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform3fv( - uint32 immediate_data_size, const gles2::cmds::Uniform3fv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 3, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform3fv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform3fvImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform3fvImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform3fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLfloat), 3, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* v = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* v = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -2127,46 +1915,33 @@ error::Error GLES2DecoderImpl::HandleUniform3fvImmediate( } error::Error GLES2DecoderImpl::HandleUniform3i( - uint32 immediate_data_size, const gles2::cmds::Uniform3i& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform3i& c) { GLint location = static_cast<GLint>(c.location); GLint x = static_cast<GLint>(c.x); GLint y = static_cast<GLint>(c.y); GLint z = static_cast<GLint>(c.z); - GLint temp[3] = { x, y, z, }; + GLint temp[3] = { + x, y, z, + }; DoUniform3iv(location, 1, &temp[0]); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform3iv( - uint32 immediate_data_size, const gles2::cmds::Uniform3iv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLint), 3, &data_size)) { - return error::kOutOfBounds; - } - const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform3iv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform3ivImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform3ivImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform3ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLint), 3, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLint* v = GetImmediateDataAs<const GLint*>( - c, data_size, immediate_data_size); + const GLint* v = + GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -2175,47 +1950,34 @@ error::Error GLES2DecoderImpl::HandleUniform3ivImmediate( } error::Error GLES2DecoderImpl::HandleUniform4f( - uint32 immediate_data_size, const gles2::cmds::Uniform4f& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform4f& c) { GLint location = static_cast<GLint>(c.location); GLfloat x = static_cast<GLfloat>(c.x); GLfloat y = static_cast<GLfloat>(c.y); GLfloat z = static_cast<GLfloat>(c.z); GLfloat w = static_cast<GLfloat>(c.w); - GLfloat temp[4] = { x, y, z, w, }; + GLfloat temp[4] = { + x, y, z, w, + }; DoUniform4fv(location, 1, &temp[0]); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform4fv( - uint32 immediate_data_size, const gles2::cmds::Uniform4fv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform4fv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform4fvImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform4fvImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform4fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* v = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* v = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -2224,47 +1986,34 @@ error::Error GLES2DecoderImpl::HandleUniform4fvImmediate( } error::Error GLES2DecoderImpl::HandleUniform4i( - uint32 immediate_data_size, const gles2::cmds::Uniform4i& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform4i& c) { GLint location = static_cast<GLint>(c.location); GLint x = static_cast<GLint>(c.x); GLint y = static_cast<GLint>(c.y); GLint z = static_cast<GLint>(c.z); GLint w = static_cast<GLint>(c.w); - GLint temp[4] = { x, y, z, w, }; + GLint temp[4] = { + x, y, z, w, + }; DoUniform4iv(location, 1, &temp[0]); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniform4iv( - uint32 immediate_data_size, const gles2::cmds::Uniform4iv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLint), 4, &data_size)) { - return error::kOutOfBounds; - } - const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, data_size); - if (v == NULL) { - return error::kOutOfBounds; - } - DoUniform4iv(location, count, v); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniform4ivImmediate( - uint32 immediate_data_size, const gles2::cmds::Uniform4ivImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::Uniform4ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLint), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLint* v = GetImmediateDataAs<const GLint*>( - c, data_size, immediate_data_size); + const GLint* v = + GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); if (v == NULL) { return error::kOutOfBounds; } @@ -2272,49 +2021,21 @@ error::Error GLES2DecoderImpl::HandleUniform4ivImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniformMatrix2fv( - uint32 immediate_data_size, const gles2::cmds::UniformMatrix2fv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* value = GetSharedMemoryAs<const GLfloat*>( - c.value_shm_id, c.value_shm_offset, data_size); - if (!validators_->false_only.IsValid(transpose)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glUniformMatrix2fv", "transpose GL_INVALID_VALUE"); - return error::kNoError; - } - if (value == NULL) { - return error::kOutOfBounds; - } - DoUniformMatrix2fv(location, count, transpose, value); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniformMatrix2fvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::UniformMatrix2fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLfloat), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* value = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); - if (!validators_->false_only.IsValid(transpose)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glUniformMatrix2fv", "transpose GL_INVALID_VALUE"); - return error::kNoError; - } + const GLfloat* value = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (value == NULL) { return error::kOutOfBounds; } @@ -2322,49 +2043,21 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2fvImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniformMatrix3fv( - uint32 immediate_data_size, const gles2::cmds::UniformMatrix3fv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 9, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* value = GetSharedMemoryAs<const GLfloat*>( - c.value_shm_id, c.value_shm_offset, data_size); - if (!validators_->false_only.IsValid(transpose)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glUniformMatrix3fv", "transpose GL_INVALID_VALUE"); - return error::kNoError; - } - if (value == NULL) { - return error::kOutOfBounds; - } - DoUniformMatrix3fv(location, count, transpose, value); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniformMatrix3fvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::UniformMatrix3fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLfloat), 9, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* value = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); - if (!validators_->false_only.IsValid(transpose)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glUniformMatrix3fv", "transpose GL_INVALID_VALUE"); - return error::kNoError; - } + const GLfloat* value = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (value == NULL) { return error::kOutOfBounds; } @@ -2372,49 +2065,21 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3fvImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleUniformMatrix4fv( - uint32 immediate_data_size, const gles2::cmds::UniformMatrix4fv& c) { - GLint location = static_cast<GLint>(c.location); - GLsizei count = static_cast<GLsizei>(c.count); - GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLfloat), 16, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* value = GetSharedMemoryAs<const GLfloat*>( - c.value_shm_id, c.value_shm_offset, data_size); - if (!validators_->false_only.IsValid(transpose)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glUniformMatrix4fv", "transpose GL_INVALID_VALUE"); - return error::kNoError; - } - if (value == NULL) { - return error::kOutOfBounds; - } - DoUniformMatrix4fv(location, count, transpose, value); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleUniformMatrix4fvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::UniformMatrix4fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLfloat), 16, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* value = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); - if (!validators_->false_only.IsValid(transpose)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glUniformMatrix4fv", "transpose GL_INVALID_VALUE"); - return error::kNoError; - } + const GLfloat* value = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (value == NULL) { return error::kOutOfBounds; } @@ -2423,56 +2088,43 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4fvImmediate( } error::Error GLES2DecoderImpl::HandleUseProgram( - uint32 immediate_data_size, const gles2::cmds::UseProgram& c) { + uint32_t immediate_data_size, + const gles2::cmds::UseProgram& c) { GLuint program = c.program; DoUseProgram(program); return error::kNoError; } error::Error GLES2DecoderImpl::HandleValidateProgram( - uint32 immediate_data_size, const gles2::cmds::ValidateProgram& c) { + uint32_t immediate_data_size, + const gles2::cmds::ValidateProgram& c) { GLuint program = c.program; DoValidateProgram(program); return error::kNoError; } error::Error GLES2DecoderImpl::HandleVertexAttrib1f( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib1f& c) { + uint32_t immediate_data_size, + const gles2::cmds::VertexAttrib1f& c) { GLuint indx = static_cast<GLuint>(c.indx); GLfloat x = static_cast<GLfloat>(c.x); DoVertexAttrib1f(indx, x); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleVertexAttrib1fv( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib1fv& c) { - GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, data_size); - if (values == NULL) { - return error::kOutOfBounds; - } - DoVertexAttrib1fv(indx, values); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleVertexAttrib1fvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::VertexAttrib1fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* values = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* values = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (values == NULL) { return error::kOutOfBounds; } @@ -2481,7 +2133,8 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib1fvImmediate( } error::Error GLES2DecoderImpl::HandleVertexAttrib2f( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib2f& c) { + uint32_t immediate_data_size, + const gles2::cmds::VertexAttrib2f& c) { GLuint indx = static_cast<GLuint>(c.indx); GLfloat x = static_cast<GLfloat>(c.x); GLfloat y = static_cast<GLfloat>(c.y); @@ -2489,35 +2142,19 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib2f( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleVertexAttrib2fv( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib2fv& c) { - GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 2, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, data_size); - if (values == NULL) { - return error::kOutOfBounds; - } - DoVertexAttrib2fv(indx, values); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleVertexAttrib2fvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::VertexAttrib2fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLfloat), 2, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* values = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* values = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (values == NULL) { return error::kOutOfBounds; } @@ -2526,7 +2163,8 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib2fvImmediate( } error::Error GLES2DecoderImpl::HandleVertexAttrib3f( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib3f& c) { + uint32_t immediate_data_size, + const gles2::cmds::VertexAttrib3f& c) { GLuint indx = static_cast<GLuint>(c.indx); GLfloat x = static_cast<GLfloat>(c.x); GLfloat y = static_cast<GLfloat>(c.y); @@ -2535,35 +2173,19 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib3f( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleVertexAttrib3fv( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib3fv& c) { - GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 3, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, data_size); - if (values == NULL) { - return error::kOutOfBounds; - } - DoVertexAttrib3fv(indx, values); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleVertexAttrib3fvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::VertexAttrib3fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLfloat), 3, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* values = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* values = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (values == NULL) { return error::kOutOfBounds; } @@ -2572,7 +2194,8 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib3fvImmediate( } error::Error GLES2DecoderImpl::HandleVertexAttrib4f( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib4f& c) { + uint32_t immediate_data_size, + const gles2::cmds::VertexAttrib4f& c) { GLuint indx = static_cast<GLuint>(c.indx); GLfloat x = static_cast<GLfloat>(c.x); GLfloat y = static_cast<GLfloat>(c.y); @@ -2582,35 +2205,19 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib4f( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleVertexAttrib4fv( - uint32 immediate_data_size, const gles2::cmds::VertexAttrib4fv& c) { - GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; - if (!ComputeDataSize(1, sizeof(GLfloat), 4, &data_size)) { - return error::kOutOfBounds; - } - const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, data_size); - if (values == NULL) { - return error::kOutOfBounds; - } - DoVertexAttrib4fv(indx, values); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleVertexAttrib4fvImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::VertexAttrib4fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLfloat), 4, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLfloat* values = GetImmediateDataAs<const GLfloat*>( - c, data_size, immediate_data_size); + const GLfloat* values = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); if (values == NULL) { return error::kOutOfBounds; } @@ -2618,8 +2225,8 @@ error::Error GLES2DecoderImpl::HandleVertexAttrib4fvImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleViewport( - uint32 immediate_data_size, const gles2::cmds::Viewport& c) { +error::Error GLES2DecoderImpl::HandleViewport(uint32_t immediate_data_size, + const gles2::cmds::Viewport& c) { GLint x = static_cast<GLint>(c.x); GLint y = static_cast<GLint>(c.y); GLsizei width = static_cast<GLsizei>(c.width); @@ -2637,8 +2244,15 @@ error::Error GLES2DecoderImpl::HandleViewport( } error::Error GLES2DecoderImpl::HandleBlitFramebufferCHROMIUM( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::BlitFramebufferCHROMIUM& c) { + if (!features().chromium_framebuffer_multisample) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glBlitFramebufferCHROMIUM", + "function not available"); + return error::kNoError; + } + error::Error error; error = WillAccessBoundFramebufferForDraw(); if (error != error::kNoError) @@ -2657,8 +2271,8 @@ error::Error GLES2DecoderImpl::HandleBlitFramebufferCHROMIUM( GLbitfield mask = static_cast<GLbitfield>(c.mask); GLenum filter = static_cast<GLenum>(c.filter); if (!validators_->blit_filter.IsValid(filter)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glBlitFramebufferCHROMIUM", filter, - "filter"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBlitFramebufferCHROMIUM", filter, "filter"); return error::kNoError; } DoBlitFramebufferCHROMIUM( @@ -2667,34 +2281,47 @@ error::Error GLES2DecoderImpl::HandleBlitFramebufferCHROMIUM( } error::Error GLES2DecoderImpl::HandleRenderbufferStorageMultisampleCHROMIUM( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::RenderbufferStorageMultisampleCHROMIUM& c) { + if (!features().chromium_framebuffer_multisample) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glRenderbufferStorageMultisampleCHROMIUM", + "function not available"); + return error::kNoError; + } + GLenum target = static_cast<GLenum>(c.target); GLsizei samples = static_cast<GLsizei>(c.samples); GLenum internalformat = static_cast<GLenum>(c.internalformat); GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); if (!validators_->render_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glRenderbufferStorageMultisampleCHROMIUM", target, "target"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glRenderbufferStorageMultisampleCHROMIUM", target, "target"); return error::kNoError; } if (samples < 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glRenderbufferStorageMultisampleCHROMIUM", "samples < 0"); // NOLINT + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, + "glRenderbufferStorageMultisampleCHROMIUM", + "samples < 0"); return error::kNoError; } if (!validators_->render_buffer_format.IsValid(internalformat)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glRenderbufferStorageMultisampleCHROMIUM", internalformat, "internalformat"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM("glRenderbufferStorageMultisampleCHROMIUM", + internalformat, + "internalformat"); return error::kNoError; } if (width < 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glRenderbufferStorageMultisampleCHROMIUM", "width < 0"); // NOLINT + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, + "glRenderbufferStorageMultisampleCHROMIUM", + "width < 0"); return error::kNoError; } if (height < 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glRenderbufferStorageMultisampleCHROMIUM", "height < 0"); // NOLINT + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, + "glRenderbufferStorageMultisampleCHROMIUM", + "height < 0"); return error::kNoError; } DoRenderbufferStorageMultisampleCHROMIUM( @@ -2703,15 +2330,23 @@ error::Error GLES2DecoderImpl::HandleRenderbufferStorageMultisampleCHROMIUM( } error::Error GLES2DecoderImpl::HandleRenderbufferStorageMultisampleEXT( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::RenderbufferStorageMultisampleEXT& c) { + if (!features().multisampled_render_to_texture) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glRenderbufferStorageMultisampleEXT", + "function not available"); + return error::kNoError; + } + GLenum target = static_cast<GLenum>(c.target); GLsizei samples = static_cast<GLsizei>(c.samples); GLenum internalformat = static_cast<GLenum>(c.internalformat); GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); if (!validators_->render_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glRenderbufferStorageMultisampleEXT", target, "target"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glRenderbufferStorageMultisampleEXT", target, "target"); return error::kNoError; } if (samples < 0) { @@ -2720,7 +2355,9 @@ error::Error GLES2DecoderImpl::HandleRenderbufferStorageMultisampleEXT( return error::kNoError; } if (!validators_->render_buffer_format.IsValid(internalformat)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glRenderbufferStorageMultisampleEXT", internalformat, "internalformat"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM("glRenderbufferStorageMultisampleEXT", + internalformat, + "internalformat"); return error::kNoError; } if (width < 0) { @@ -2739,8 +2376,15 @@ error::Error GLES2DecoderImpl::HandleRenderbufferStorageMultisampleEXT( } error::Error GLES2DecoderImpl::HandleFramebufferTexture2DMultisampleEXT( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::FramebufferTexture2DMultisampleEXT& c) { + if (!features().multisampled_render_to_texture) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glFramebufferTexture2DMultisampleEXT", + "function not available"); + return error::kNoError; + } + GLenum target = static_cast<GLenum>(c.target); GLenum attachment = static_cast<GLenum>(c.attachment); GLenum textarget = static_cast<GLenum>(c.textarget); @@ -2748,25 +2392,24 @@ error::Error GLES2DecoderImpl::HandleFramebufferTexture2DMultisampleEXT( GLint level = static_cast<GLint>(c.level); GLsizei samples = static_cast<GLsizei>(c.samples); if (!validators_->frame_buffer_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTexture2DMultisampleEXT", target, "target"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferTexture2DMultisampleEXT", target, "target"); return error::kNoError; } if (!validators_->attachment.IsValid(attachment)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTexture2DMultisampleEXT", attachment, "attachment"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferTexture2DMultisampleEXT", attachment, "attachment"); return error::kNoError; } if (!validators_->texture_target.IsValid(textarget)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glFramebufferTexture2DMultisampleEXT", textarget, "textarget"); // NOLINT - return error::kNoError; - } - if (!validators_->zero_only.IsValid(level)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glFramebufferTexture2DMultisampleEXT", "level GL_INVALID_VALUE"); // NOLINT + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glFramebufferTexture2DMultisampleEXT", textarget, "textarget"); return error::kNoError; } if (samples < 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glFramebufferTexture2DMultisampleEXT", "samples < 0"); // NOLINT + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, + "glFramebufferTexture2DMultisampleEXT", + "samples < 0"); return error::kNoError; } DoFramebufferTexture2DMultisample( @@ -2775,7 +2418,8 @@ error::Error GLES2DecoderImpl::HandleFramebufferTexture2DMultisampleEXT( } error::Error GLES2DecoderImpl::HandleTexStorage2DEXT( - uint32 immediate_data_size, const gles2::cmds::TexStorage2DEXT& c) { + uint32_t immediate_data_size, + const gles2::cmds::TexStorage2DEXT& c) { GLenum target = static_cast<GLenum>(c.target); GLsizei levels = static_cast<GLsizei>(c.levels); GLenum internalFormat = static_cast<GLenum>(c.internalFormat); @@ -2790,8 +2434,8 @@ error::Error GLES2DecoderImpl::HandleTexStorage2DEXT( return error::kNoError; } if (!validators_->texture_internal_format_storage.IsValid(internalFormat)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage2DEXT", internalFormat, - "internalFormat"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glTexStorage2DEXT", internalFormat, "internalFormat"); return error::kNoError; } if (width < 0) { @@ -2806,33 +2450,16 @@ error::Error GLES2DecoderImpl::HandleTexStorage2DEXT( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGenQueriesEXT( - uint32 immediate_data_size, const gles2::cmds::GenQueriesEXT& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - GLuint* queries = GetSharedMemoryAs<GLuint*>( - c.queries_shm_id, c.queries_shm_offset, data_size); - if (queries == NULL) { - return error::kOutOfBounds; - } - if (!GenQueriesEXTHelper(n, queries)) { - return error::kInvalidArguments; - } - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleGenQueriesEXTImmediate( - uint32 immediate_data_size, const gles2::cmds::GenQueriesEXTImmediate& c) { + uint32_t immediate_data_size, + const gles2::cmds::GenQueriesEXTImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - GLuint* queries = GetImmediateDataAs<GLuint*>( - c, data_size, immediate_data_size); + GLuint* queries = + GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); if (queries == NULL) { return error::kOutOfBounds; } @@ -2842,32 +2469,16 @@ error::Error GLES2DecoderImpl::HandleGenQueriesEXTImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDeleteQueriesEXT( - uint32 immediate_data_size, const gles2::cmds::DeleteQueriesEXT& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - const GLuint* queries = GetSharedMemoryAs<const GLuint*>( - c.queries_shm_id, c.queries_shm_offset, data_size); - if (queries == NULL) { - return error::kOutOfBounds; - } - DeleteQueriesEXTHelper(n, queries); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleDeleteQueriesEXTImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::DeleteQueriesEXTImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - const GLuint* queries = GetImmediateDataAs<const GLuint*>( - c, data_size, immediate_data_size); + const GLuint* queries = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); if (queries == NULL) { return error::kOutOfBounds; } @@ -2876,7 +2487,8 @@ error::Error GLES2DecoderImpl::HandleDeleteQueriesEXTImmediate( } error::Error GLES2DecoderImpl::HandleInsertEventMarkerEXT( - uint32 immediate_data_size, const gles2::cmds::InsertEventMarkerEXT& c) { + uint32_t immediate_data_size, + const gles2::cmds::InsertEventMarkerEXT& c) { GLuint bucket_id = static_cast<GLuint>(c.bucket_id); Bucket* bucket = GetBucket(bucket_id); if (!bucket || bucket->size() == 0) { @@ -2891,7 +2503,8 @@ error::Error GLES2DecoderImpl::HandleInsertEventMarkerEXT( } error::Error GLES2DecoderImpl::HandlePushGroupMarkerEXT( - uint32 immediate_data_size, const gles2::cmds::PushGroupMarkerEXT& c) { + uint32_t immediate_data_size, + const gles2::cmds::PushGroupMarkerEXT& c) { GLuint bucket_id = static_cast<GLuint>(c.bucket_id); Bucket* bucket = GetBucket(bucket_id); if (!bucket || bucket->size() == 0) { @@ -2906,39 +2519,22 @@ error::Error GLES2DecoderImpl::HandlePushGroupMarkerEXT( } error::Error GLES2DecoderImpl::HandlePopGroupMarkerEXT( - uint32 immediate_data_size, const gles2::cmds::PopGroupMarkerEXT& c) { + uint32_t immediate_data_size, + const gles2::cmds::PopGroupMarkerEXT& c) { DoPopGroupMarkerEXT(); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleGenVertexArraysOES( - uint32 immediate_data_size, const gles2::cmds::GenVertexArraysOES& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - GLuint* arrays = GetSharedMemoryAs<GLuint*>( - c.arrays_shm_id, c.arrays_shm_offset, data_size); - if (arrays == NULL) { - return error::kOutOfBounds; - } - if (!GenVertexArraysOESHelper(n, arrays)) { - return error::kInvalidArguments; - } - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleGenVertexArraysOESImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::GenVertexArraysOESImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - GLuint* arrays = GetImmediateDataAs<GLuint*>( - c, data_size, immediate_data_size); + GLuint* arrays = + GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); if (arrays == NULL) { return error::kOutOfBounds; } @@ -2948,32 +2544,16 @@ error::Error GLES2DecoderImpl::HandleGenVertexArraysOESImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDeleteVertexArraysOES( - uint32 immediate_data_size, const gles2::cmds::DeleteVertexArraysOES& c) { - GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; - if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { - return error::kOutOfBounds; - } - const GLuint* arrays = GetSharedMemoryAs<const GLuint*>( - c.arrays_shm_id, c.arrays_shm_offset, data_size); - if (arrays == NULL) { - return error::kOutOfBounds; - } - DeleteVertexArraysOESHelper(n, arrays); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleDeleteVertexArraysOESImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::DeleteVertexArraysOESImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - uint32 data_size; + uint32_t data_size; if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { return error::kOutOfBounds; } - const GLuint* arrays = GetImmediateDataAs<const GLuint*>( - c, data_size, immediate_data_size); + const GLuint* arrays = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); if (arrays == NULL) { return error::kOutOfBounds; } @@ -2982,7 +2562,8 @@ error::Error GLES2DecoderImpl::HandleDeleteVertexArraysOESImmediate( } error::Error GLES2DecoderImpl::HandleIsVertexArrayOES( - uint32 immediate_data_size, const gles2::cmds::IsVertexArrayOES& c) { + uint32_t immediate_data_size, + const gles2::cmds::IsVertexArrayOES& c) { GLuint array = c.array; typedef cmds::IsVertexArrayOES::Result Result; Result* result_dst = GetSharedMemoryAs<Result*>( @@ -2995,20 +2576,22 @@ error::Error GLES2DecoderImpl::HandleIsVertexArrayOES( } error::Error GLES2DecoderImpl::HandleBindVertexArrayOES( - uint32 immediate_data_size, const gles2::cmds::BindVertexArrayOES& c) { + uint32_t immediate_data_size, + const gles2::cmds::BindVertexArrayOES& c) { GLuint array = c.array; DoBindVertexArrayOES(array); return error::kNoError; } error::Error GLES2DecoderImpl::HandleSwapBuffers( - uint32 immediate_data_size, const gles2::cmds::SwapBuffers& c) { + uint32_t immediate_data_size, + const gles2::cmds::SwapBuffers& c) { DoSwapBuffers(); return error::kNoError; } error::Error GLES2DecoderImpl::HandleGetMaxValueInBufferCHROMIUM( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::GetMaxValueInBufferCHROMIUM& c) { GLuint buffer_id = c.buffer_id; GLsizei count = static_cast<GLsizei>(c.count); @@ -3026,8 +2609,8 @@ error::Error GLES2DecoderImpl::HandleGetMaxValueInBufferCHROMIUM( return error::kNoError; } if (!validators_->get_max_index_type.IsValid(type)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetMaxValueInBufferCHROMIUM", type, - "type"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glGetMaxValueInBufferCHROMIUM", type, "type"); return error::kNoError; } *result_dst = DoGetMaxValueInBufferCHROMIUM(buffer_id, count, type, offset); @@ -3035,7 +2618,7 @@ error::Error GLES2DecoderImpl::HandleGetMaxValueInBufferCHROMIUM( } error::Error GLES2DecoderImpl::HandleTexImageIOSurface2DCHROMIUM( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::TexImageIOSurface2DCHROMIUM& c) { GLenum target = static_cast<GLenum>(c.target); GLsizei width = static_cast<GLsizei>(c.width); @@ -3043,8 +2626,8 @@ error::Error GLES2DecoderImpl::HandleTexImageIOSurface2DCHROMIUM( GLuint ioSurfaceId = static_cast<GLuint>(c.ioSurfaceId); GLuint plane = static_cast<GLuint>(c.plane); if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexImageIOSurface2DCHROMIUM", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glTexImageIOSurface2DCHROMIUM", target, "target"); return error::kNoError; } if (width < 0) { @@ -3062,7 +2645,8 @@ error::Error GLES2DecoderImpl::HandleTexImageIOSurface2DCHROMIUM( } error::Error GLES2DecoderImpl::HandleCopyTextureCHROMIUM( - uint32 immediate_data_size, const gles2::cmds::CopyTextureCHROMIUM& c) { + uint32_t immediate_data_size, + const gles2::cmds::CopyTextureCHROMIUM& c) { GLenum target = static_cast<GLenum>(c.target); GLenum source_id = static_cast<GLenum>(c.source_id); GLenum dest_id = static_cast<GLenum>(c.dest_id); @@ -3070,13 +2654,14 @@ error::Error GLES2DecoderImpl::HandleCopyTextureCHROMIUM( GLint internalformat = static_cast<GLint>(c.internalformat); GLenum dest_type = static_cast<GLenum>(c.dest_type); if (!validators_->texture_internal_format.IsValid(internalformat)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "internalformat GL_INVALID_VALUE"); // NOLINT + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, + "glCopyTextureCHROMIUM", + "internalformat GL_INVALID_VALUE"); return error::kNoError; } if (!validators_->pixel_type.IsValid(dest_type)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glCopyTextureCHROMIUM", dest_type, - "dest_type"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glCopyTextureCHROMIUM", dest_type, "dest_type"); return error::kNoError; } DoCopyTextureCHROMIUM( @@ -3084,43 +2669,22 @@ error::Error GLES2DecoderImpl::HandleCopyTextureCHROMIUM( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleProduceTextureCHROMIUM( - uint32 immediate_data_size, const gles2::cmds::ProduceTextureCHROMIUM& c) { - GLenum target = static_cast<GLenum>(c.target); - uint32 data_size; - if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { - return error::kOutOfBounds; - } - const GLbyte* mailbox = GetSharedMemoryAs<const GLbyte*>( - c.mailbox_shm_id, c.mailbox_shm_offset, data_size); - if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glProduceTextureCHROMIUM", target, - "target"); - return error::kNoError; - } - if (mailbox == NULL) { - return error::kOutOfBounds; - } - DoProduceTextureCHROMIUM(target, mailbox); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleProduceTextureCHROMIUMImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::ProduceTextureCHROMIUMImmediate& c) { GLenum target = static_cast<GLenum>(c.target); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLbyte* mailbox = GetImmediateDataAs<const GLbyte*>( - c, data_size, immediate_data_size); + const GLbyte* mailbox = + GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size); if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glProduceTextureCHROMIUM", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glProduceTextureCHROMIUM", target, "target"); return error::kNoError; } if (mailbox == NULL) { @@ -3130,43 +2694,48 @@ error::Error GLES2DecoderImpl::HandleProduceTextureCHROMIUMImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUM( - uint32 immediate_data_size, const gles2::cmds::ConsumeTextureCHROMIUM& c) { +error::Error GLES2DecoderImpl::HandleProduceTextureDirectCHROMIUMImmediate( + uint32_t immediate_data_size, + const gles2::cmds::ProduceTextureDirectCHROMIUMImmediate& c) { + GLuint texture = c.texture; GLenum target = static_cast<GLenum>(c.target); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { return error::kOutOfBounds; } - const GLbyte* mailbox = GetSharedMemoryAs<const GLbyte*>( - c.mailbox_shm_id, c.mailbox_shm_offset, data_size); + if (data_size > immediate_data_size) { + return error::kOutOfBounds; + } + const GLbyte* mailbox = + GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size); if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glConsumeTextureCHROMIUM", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glProduceTextureDirectCHROMIUM", target, "target"); return error::kNoError; } if (mailbox == NULL) { return error::kOutOfBounds; } - DoConsumeTextureCHROMIUM(target, mailbox); + DoProduceTextureDirectCHROMIUM(texture, target, mailbox); return error::kNoError; } error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUMImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::ConsumeTextureCHROMIUMImmediate& c) { GLenum target = static_cast<GLenum>(c.target); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLbyte* mailbox = GetImmediateDataAs<const GLbyte*>( - c, data_size, immediate_data_size); + const GLbyte* mailbox = + GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size); if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glConsumeTextureCHROMIUM", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glConsumeTextureCHROMIUM", target, "target"); return error::kNoError; } if (mailbox == NULL) { @@ -3177,12 +2746,13 @@ error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUMImmediate( } error::Error GLES2DecoderImpl::HandleBindTexImage2DCHROMIUM( - uint32 immediate_data_size, const gles2::cmds::BindTexImage2DCHROMIUM& c) { + uint32_t immediate_data_size, + const gles2::cmds::BindTexImage2DCHROMIUM& c) { GLenum target = static_cast<GLenum>(c.target); GLint imageId = static_cast<GLint>(c.imageId); if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glBindTexImage2DCHROMIUM", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBindTexImage2DCHROMIUM", target, "target"); return error::kNoError; } DoBindTexImage2DCHROMIUM(target, imageId); @@ -3190,13 +2760,13 @@ error::Error GLES2DecoderImpl::HandleBindTexImage2DCHROMIUM( } error::Error GLES2DecoderImpl::HandleReleaseTexImage2DCHROMIUM( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::ReleaseTexImage2DCHROMIUM& c) { GLenum target = static_cast<GLenum>(c.target); GLint imageId = static_cast<GLint>(c.imageId); if (!validators_->texture_bind_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM("glReleaseTexImage2DCHROMIUM", target, - "target"); + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glReleaseTexImage2DCHROMIUM", target, "target"); return error::kNoError; } DoReleaseTexImage2DCHROMIUM(target, imageId); @@ -3204,47 +2774,33 @@ error::Error GLES2DecoderImpl::HandleReleaseTexImage2DCHROMIUM( } error::Error GLES2DecoderImpl::HandleTraceEndCHROMIUM( - uint32 immediate_data_size, const gles2::cmds::TraceEndCHROMIUM& c) { + uint32_t immediate_data_size, + const gles2::cmds::TraceEndCHROMIUM& c) { DoTraceEndCHROMIUM(); return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXT( - uint32 immediate_data_size, const gles2::cmds::DiscardFramebufferEXT& c) { - GLenum target = static_cast<GLenum>(c.target); - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { - return error::kOutOfBounds; - } - const GLenum* attachments = GetSharedMemoryAs<const GLenum*>( - c.attachments_shm_id, c.attachments_shm_offset, data_size); - if (count < 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glDiscardFramebufferEXT", "count < 0"); +error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXTImmediate( + uint32_t immediate_data_size, + const gles2::cmds::DiscardFramebufferEXTImmediate& c) { + if (!features().ext_discard_framebuffer) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glDiscardFramebufferEXT", + "function not available"); return error::kNoError; } - if (attachments == NULL) { - return error::kOutOfBounds; - } - DoDiscardFramebufferEXT(target, count, attachments); - return error::kNoError; -} -error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXTImmediate( - uint32 immediate_data_size, - const gles2::cmds::DiscardFramebufferEXTImmediate& c) { GLenum target = static_cast<GLenum>(c.target); GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLenum* attachments = GetImmediateDataAs<const GLenum*>( - c, data_size, immediate_data_size); + const GLenum* attachments = + GetImmediateDataAs<const GLenum*>(c, data_size, immediate_data_size); if (count < 0) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, "glDiscardFramebufferEXT", "count < 0"); @@ -3257,39 +2813,37 @@ error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXTImmediate( return error::kNoError; } -error::Error GLES2DecoderImpl::HandleDrawBuffersEXT( - uint32 immediate_data_size, const gles2::cmds::DrawBuffersEXT& c) { - GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; - if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { - return error::kOutOfBounds; - } - const GLenum* bufs = GetSharedMemoryAs<const GLenum*>( - c.bufs_shm_id, c.bufs_shm_offset, data_size); - if (count < 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDrawBuffersEXT", "count < 0"); +error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM( + uint32_t immediate_data_size, + const gles2::cmds::LoseContextCHROMIUM& c) { + GLenum current = static_cast<GLenum>(c.current); + GLenum other = static_cast<GLenum>(c.other); + if (!validators_->reset_status.IsValid(current)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glLoseContextCHROMIUM", current, "current"); return error::kNoError; } - if (bufs == NULL) { - return error::kOutOfBounds; + if (!validators_->reset_status.IsValid(other)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other"); + return error::kNoError; } - DoDrawBuffersEXT(count, bufs); + DoLoseContextCHROMIUM(current, other); return error::kNoError; } error::Error GLES2DecoderImpl::HandleDrawBuffersEXTImmediate( - uint32 immediate_data_size, + uint32_t immediate_data_size, const gles2::cmds::DrawBuffersEXTImmediate& c) { GLsizei count = static_cast<GLsizei>(c.count); - uint32 data_size; + uint32_t data_size; if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { return error::kOutOfBounds; } if (data_size > immediate_data_size) { return error::kOutOfBounds; } - const GLenum* bufs = GetImmediateDataAs<const GLenum*>( - c, data_size, immediate_data_size); + const GLenum* bufs = + GetImmediateDataAs<const GLenum*>(c, data_size, immediate_data_size); if (count < 0) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDrawBuffersEXT", "count < 0"); return error::kNoError; @@ -3301,42 +2855,75 @@ error::Error GLES2DecoderImpl::HandleDrawBuffersEXTImmediate( return error::kNoError; } - bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { switch (cap) { case GL_BLEND: state_.enable_flags.blend = enabled; - return true; + if (state_.enable_flags.cached_blend != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_blend = enabled; + return true; + } + return false; case GL_CULL_FACE: state_.enable_flags.cull_face = enabled; - return true; + if (state_.enable_flags.cached_cull_face != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_cull_face = enabled; + return true; + } + return false; case GL_DEPTH_TEST: - if (state_.enable_flags.depth_test != enabled) { - state_.enable_flags.depth_test = enabled; + state_.enable_flags.depth_test = enabled; + if (state_.enable_flags.cached_depth_test != enabled || + state_.ignore_cached_state) { framebuffer_state_.clear_state_dirty = true; } return false; case GL_DITHER: state_.enable_flags.dither = enabled; - return true; + if (state_.enable_flags.cached_dither != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_dither = enabled; + return true; + } + return false; case GL_POLYGON_OFFSET_FILL: state_.enable_flags.polygon_offset_fill = enabled; - return true; + if (state_.enable_flags.cached_polygon_offset_fill != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_polygon_offset_fill = enabled; + return true; + } + return false; case GL_SAMPLE_ALPHA_TO_COVERAGE: state_.enable_flags.sample_alpha_to_coverage = enabled; - return true; + if (state_.enable_flags.cached_sample_alpha_to_coverage != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_sample_alpha_to_coverage = enabled; + return true; + } + return false; case GL_SAMPLE_COVERAGE: state_.enable_flags.sample_coverage = enabled; - return true; + if (state_.enable_flags.cached_sample_coverage != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_sample_coverage = enabled; + return true; + } + return false; case GL_SCISSOR_TEST: - if (state_.enable_flags.scissor_test != enabled) { - state_.enable_flags.scissor_test = enabled; - framebuffer_state_.clear_state_dirty = true; + state_.enable_flags.scissor_test = enabled; + if (state_.enable_flags.cached_scissor_test != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_scissor_test = enabled; + return true; } return false; case GL_STENCIL_TEST: - if (state_.enable_flags.stencil_test != enabled) { - state_.enable_flags.stencil_test = enabled; + state_.enable_flags.stencil_test = enabled; + if (state_.enable_flags.cached_stencil_test != enabled || + state_.ignore_cached_state) { framebuffer_state_.clear_state_dirty = true; } return false; @@ -3346,4 +2933,3 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { } } #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_AUTOGEN_H_ - diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index f52c2217040..94bf3aa27f8 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -21,13 +21,12 @@ class GLSurface; } namespace gpu { -class StreamTextureManager; - namespace gles2 { class ContextGroup; class ErrorState; class QueryManager; +struct ContextState; class MockGLES2Decoder : public GLES2Decoder { public: @@ -43,23 +42,25 @@ class MockGLES2Decoder : public GLES2Decoder { const std::vector<int32>& attribs)); MOCK_METHOD1(Destroy, void(bool have_context)); MOCK_METHOD1(SetSurface, void(const scoped_refptr<gfx::GLSurface>& surface)); - MOCK_METHOD1(ProduceFrontBuffer, bool(const Mailbox& mailbox)); + MOCK_METHOD1(ProduceFrontBuffer, void(const Mailbox& mailbox)); MOCK_METHOD1(ResizeOffscreenFrameBuffer, bool(const gfx::Size& size)); MOCK_METHOD0(MakeCurrent, bool()); - MOCK_METHOD0(ReleaseCurrent, void()); MOCK_METHOD1(GetServiceIdForTesting, uint32(uint32 client_id)); MOCK_METHOD0(GetGLES2Util, GLES2Util*()); MOCK_METHOD0(GetGLSurface, gfx::GLSurface*()); MOCK_METHOD0(GetGLContext, gfx::GLContext*()); MOCK_METHOD0(GetContextGroup, ContextGroup*()); + MOCK_METHOD0(GetContextState, const ContextState*()); MOCK_METHOD0(GetCapabilities, Capabilities()); MOCK_METHOD0(ProcessPendingQueries, bool()); MOCK_METHOD0(HasMoreIdleWork, bool()); MOCK_METHOD0(PerformIdleWork, void()); - MOCK_CONST_METHOD0(RestoreState, void()); + MOCK_CONST_METHOD1(RestoreState, void(const ContextState* prev_state)); MOCK_CONST_METHOD0(RestoreActiveTexture, void()); - MOCK_CONST_METHOD0(RestoreAllTextureUnitBindings, void()); - MOCK_CONST_METHOD1(RestoreAttribute, void(unsigned index)); + MOCK_CONST_METHOD1( + RestoreAllTextureUnitBindings, void(const ContextState* state)); + MOCK_CONST_METHOD1( + RestoreActiveTextureUnitBinding, void(unsigned int target)); MOCK_CONST_METHOD0(RestoreBufferBindings, void()); MOCK_CONST_METHOD0(RestoreFramebufferBindings, void()); MOCK_CONST_METHOD0(RestoreGlobalState, void()); @@ -67,6 +68,8 @@ class MockGLES2Decoder : public GLES2Decoder { MOCK_CONST_METHOD0(RestoreRenderbufferBindings, void()); MOCK_CONST_METHOD1(RestoreTextureState, void(unsigned service_id)); MOCK_CONST_METHOD1(RestoreTextureUnitBindings, void(unsigned unit)); + MOCK_CONST_METHOD0(ClearAllAttributes, void()); + MOCK_CONST_METHOD0(RestoreAllAttributes, void()); MOCK_METHOD0(GetQueryManager, gpu::gles2::QueryManager*()); MOCK_METHOD0(GetVertexArrayManager, gpu::gles2::VertexArrayManager*()); MOCK_METHOD1( @@ -78,6 +81,7 @@ class MockGLES2Decoder : public GLES2Decoder { MOCK_METHOD0(ResetAsyncPixelTransferManagerForTest, void()); MOCK_METHOD1(SetAsyncPixelTransferManagerForTest, void(AsyncPixelTransferManager*)); + MOCK_METHOD1(SetIgnoreCachedStateForTest, void(bool ignore)); MOCK_METHOD3(DoCommand, error::Error(unsigned int command, unsigned int arg_count, const void* cmd_data)); @@ -85,11 +89,12 @@ class MockGLES2Decoder : public GLES2Decoder { uint32* service_texture_id)); MOCK_METHOD0(GetContextLostReason, error::ContextLostReason()); MOCK_CONST_METHOD1(GetCommandName, const char*(unsigned int command_id)); - MOCK_METHOD9(ClearLevel, bool( + MOCK_METHOD10(ClearLevel, bool( unsigned service_id, unsigned bind_target, unsigned target, int level, + unsigned internal_format, unsigned format, unsigned type, int width, diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index ec8ff6ccb2f..f97a6dc5b95 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" #include "base/command_line.h" #include "base/strings/string_number_conversions.h" @@ -14,15 +14,14 @@ #include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" #include "gpu/command_buffer/service/gl_surface_mock.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/mocks.h" #include "gpu/command_buffer/service/program_manager.h" -#include "gpu/command_buffer/service/stream_texture_manager_mock.h" -#include "gpu/command_buffer/service/stream_texture_mock.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_implementation.h" @@ -36,10 +35,12 @@ using ::gfx::MockGLInterface; using ::testing::_; +using ::testing::AtLeast; using ::testing::DoAll; using ::testing::InSequence; using ::testing::Invoke; using ::testing::MatcherCast; +using ::testing::Mock; using ::testing::Pointee; using ::testing::Return; using ::testing::SaveArg; @@ -54,1592 +55,58 @@ namespace gles2 { using namespace cmds; -class GLES2DecoderTest : public GLES2DecoderTestBase { - public: - GLES2DecoderTest() { } - - protected: - void CheckReadPixelsOutOfRange( - GLint in_read_x, GLint in_read_y, - GLsizei in_read_width, GLsizei in_read_height, - bool init); -}; - -class GLES2DecoderTestWithExtensions - : public GLES2DecoderTest, - public ::testing::WithParamInterface<const char*> { - public: - GLES2DecoderTestWithExtensions() {} - - virtual void SetUp() { - InitDecoder(GetParam(), // extensions - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - false); // bind generates resource - } -}; - -class GLES2DecoderWithShaderTest : public GLES2DecoderWithShaderTestBase { - public: - GLES2DecoderWithShaderTest() - : GLES2DecoderWithShaderTestBase() { - } - - void CheckTextureChangesMarkFBOAsNotComplete(bool bound_fbo); - void CheckRenderbufferChangesMarkFBOAsNotComplete(bool bound_fbo); -}; - -class GLES2DecoderGeometryInstancingTest : public GLES2DecoderWithShaderTest { - public: - GLES2DecoderGeometryInstancingTest() - : GLES2DecoderWithShaderTest() { - } - - virtual void SetUp() { - InitDecoder( - "GL_ANGLE_instanced_arrays", // extensions - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource - SetupDefaultProgram(); - } -}; - -class GLES2DecoderRGBBackbufferTest : public GLES2DecoderWithShaderTest { - public: - GLES2DecoderRGBBackbufferTest() { } - - virtual void SetUp() { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - SetupDefaultProgram(); - } -}; - -class GLES2DecoderManualInitTest : public GLES2DecoderWithShaderTest { - public: - GLES2DecoderManualInitTest() { } - - // Override default setup so nothing gets setup. - virtual void SetUp() { - } -}; - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysNoAttributesSucceeds) { - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -// Tests when the math overflows (0x40000000 * sizeof GLfloat) -TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OverflowFails) { - const GLsizei kLargeCount = 0x40000000; - SetupTexture(); - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kLargeCount); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); -} - -// Tests when the math overflows (0x7FFFFFFF + 1 = 0x8000000 verts) -TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0PosToNegFails) { - const GLsizei kLargeCount = 0x7FFFFFFF; - SetupTexture(); - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kLargeCount); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); +void GLES2DecoderRGBBackbufferTest::SetUp() { + // Test codepath with workaround clear_alpha_in_readpixels because + // ReadPixelsEmulator emulates the incorrect driver behavior. + CommandLine command_line(0, NULL); + command_line.AppendSwitchASCII( + switches::kGpuDriverBugWorkarounds, + base::IntToString(gpu::CLEAR_ALPHA_IN_READPIXELS)); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); + SetupDefaultProgram(); } -// Tests when the driver returns an error -TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OOMFails) { - const GLsizei kFakeLargeCount = 0x1234; - SetupTexture(); - AddExpectationsForSimulatedAttrib0WithError( - kFakeLargeCount, 0, GL_OUT_OF_MEMORY); - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); +// Override default setup so nothing gets setup. +void GLES2DecoderManualInitTest::SetUp() { } -TEST_F(GLES2DecoderWithShaderTest, DrawArraysBadTextureUsesBlack) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - // This is an NPOT texture. As the default filtering requires mips - // this should trigger replacing with black textures before rendering. - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - { - InSequence sequence; - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture( - GL_TEXTURE_2D, TestHelper::kServiceBlackTexture2dId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) - .Times(1) - .RetiresOnSaturation(); +void GLES2DecoderManualInitTest::EnableDisableTest(GLenum cap, + bool enable, + bool expect_set) { + if (expect_set) { + SetupExpectationsForEnableDisable(cap, enable); + } + if (enable) { + Enable cmd; + cmd.Init(cap); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } else { + Disable cmd; + cmd.Init(cap); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); } - SetupExpectationsForApplyingDefaultDirtyState(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysMissingAttributesFails) { - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, - DrawArraysMissingAttributesZeroCountSucceeds) { - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysValidAttributesSucceeds) { - SetupTexture(); - SetupVertexBuffer(); - DoEnableVertexAttribArray(1); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); - SetupExpectationsForApplyingDefaultDirtyState(); - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysDeletedBufferFails) { - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - DeleteVertexBuffer(); - - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysDeletedProgramSucceeds) { - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - DoDeleteProgram(client_program_id_, kServiceProgramId); - - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)) - .Times(1); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysWithInvalidModeFails) { - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0); - DrawArrays cmd; - cmd.Init(GL_QUADS, 0, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_POLYGON, 0, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysInvalidCountFails) { - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - // Try start > 0 - EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 1, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Try with count > size - cmd.Init(GL_TRIANGLES, 0, kNumVertices + 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Try with attrib offset > 0 - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 4); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Try with size > 2 (ie, vec3 instead of vec2) - DoVertexAttribPointer(1, 3, GL_FLOAT, 0, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Try with stride > 8 (vec2 + vec2 byte) - DoVertexAttribPointer(1, 2, GL_FLOAT, sizeof(GLfloat) * 3, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysInstancedANGLEFails) { - SetupTexture(); - SetupVertexBuffer(); - DoEnableVertexAttribArray(1); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLENoAttributesFails) { - SetupTexture(); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLESimulatedAttrib0) { - SetupTexture(); - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); - SetupExpectationsForApplyingDefaultDirtyState(); - - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, 3)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 1)) - .Times(1) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, 3); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLEMissingAttributesFails) { - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLEMissingAttributesZeroCountSucceeds) { - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, 0, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLEValidAttributesSucceeds) { - SetupTexture(); - SetupVertexBuffer(); - DoEnableVertexAttribArray(1); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); - SetupExpectationsForApplyingDefaultDirtyState(); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, 1)) - .Times(1) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLEWithInvalidModeFails) { - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_QUADS, 0, 1, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_POLYGON, 0, 1, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLEInvalidPrimcountFails) { - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, 1, -1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -// Per-instance data is twice as large, but number of instances is half -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLELargeInstanceSucceeds) { - SetupTexture(); - SetupVertexBuffer(); - SetupExpectationsForApplyingDefaultDirtyState(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, - kNumVertices / 2)) - .Times(1) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices / 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -// Per-instance data is twice as large, but divisor is twice -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLELargeDivisorSucceeds) { - SetupTexture(); - SetupVertexBuffer(); - SetupExpectationsForApplyingDefaultDirtyState(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 2); - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, - kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, DrawArraysInstancedANGLELargeFails) { - SetupTexture(); - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices + 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - cmd.Init(GL_TRIANGLES, 0, kNumVertices + 1, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -// Per-index data is twice as large, but number of indices is half -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLELargeIndexSucceeds) { - SetupTexture(); - SetupVertexBuffer(); - SetupExpectationsForApplyingDefaultDirtyState(); - DoVertexAttribPointer(1, 4, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices / 2, - kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices / 2, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawArraysInstancedANGLENoDivisor0Fails) { - SetupTexture(); - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - DoVertexAttribDivisorANGLE(1, 1); - EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArraysInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsNoAttributesSucceeds) { - SetupTexture(); - SetupIndexBuffer(); - AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - EXPECT_CALL(*gl_, DrawElements(GL_TRIANGLES, kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2))) - .Times(1) - .RetiresOnSaturation(); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsMissingAttributesFails) { - SetupIndexBuffer(); - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) - .Times(0); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, - DrawElementsMissingAttributesZeroCountSucceeds) { - SetupIndexBuffer(); - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) - .Times(0); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsExtraAttributesFails) { - SetupIndexBuffer(); - DoEnableVertexAttribArray(6); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) - .Times(0); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsValidAttributesSucceeds) { - SetupTexture(); - SetupVertexBuffer(); - SetupIndexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId); - SetupExpectationsForApplyingDefaultDirtyState(); - - EXPECT_CALL(*gl_, DrawElements(GL_TRIANGLES, kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2))) - .Times(1) - .RetiresOnSaturation(); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsDeletedBufferFails) { - SetupVertexBuffer(); - SetupIndexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - DeleteIndexBuffer(); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) - .Times(0); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsDeletedProgramSucceeds) { - SetupTexture(); - SetupIndexBuffer(); - AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - DoDeleteProgram(client_program_id_, kServiceProgramId); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) - .Times(1); - EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)) - .Times(1); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsWithInvalidModeFails) { - SetupVertexBuffer(); - SetupIndexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) - .Times(0); - DrawElements cmd; - cmd.Init(GL_QUADS, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_POLYGON, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsInvalidCountFails) { - SetupVertexBuffer(); - SetupIndexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - // Try start > 0 - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kNumIndices, GL_UNSIGNED_SHORT, 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Try with count > size - cmd.Init(GL_TRIANGLES, kNumIndices + 1, GL_UNSIGNED_SHORT, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsOutOfRangeIndicesFails) { - SetupVertexBuffer(); - SetupIndexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kInvalidIndexRangeCount, GL_UNSIGNED_SHORT, - kInvalidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsOddOffsetForUint16Fails) { - SetupVertexBuffer(); - SetupIndexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kInvalidIndexRangeCount, GL_UNSIGNED_SHORT, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsInstancedANGLEFails) { - SetupTexture(); - SetupVertexBuffer(); - SetupIndexBuffer(); - DoEnableVertexAttribArray(1); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLENoAttributesFails) { - SetupTexture(); - SetupIndexBuffer(); - - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLESimulatedAttrib0) { - SetupTexture(); - SetupVertexBuffer(); - SetupIndexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId); - SetupExpectationsForApplyingDefaultDirtyState(); - - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE( - GL_TRIANGLES, - kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2), - 3)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 1)) - .Times(1) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 3); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLEMissingAttributesFails) { - SetupIndexBuffer(); - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLEMissingAttributesZeroCountSucceeds) { - SetupIndexBuffer(); - DoEnableVertexAttribArray(1); - - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLEValidAttributesSucceeds) { - SetupIndexBuffer(); - SetupTexture(); - SetupVertexBuffer(); - DoEnableVertexAttribArray(1); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId); - SetupExpectationsForApplyingDefaultDirtyState(); - - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE( - GL_TRIANGLES, - kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2), - 1)) - .Times(1) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLEWithInvalidModeFails) { - SetupIndexBuffer(); - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_QUADS, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_INVALID_ENUM, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -// Per-instance data is twice as large, but number of instances is half -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLELargeInstanceSucceeds) { - SetupTexture(); - SetupIndexBuffer(); - SetupVertexBuffer(); - SetupExpectationsForApplyingDefaultDirtyState(); - //Add offset so we're sure we're accessing data near the end of the buffer. - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, - (kNumVertices - kMaxValidIndex - 1) * 2 * - sizeof(GLfloat)); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE( - GL_TRIANGLES, - kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2), - kNumVertices / 2)) - .Times(1) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kNumVertices / 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -// Per-instance data is twice as large, but divisor is twice -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLELargeDivisorSucceeds) { - SetupTexture(); - SetupIndexBuffer(); - SetupVertexBuffer(); - SetupExpectationsForApplyingDefaultDirtyState(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 2); - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE( - GL_TRIANGLES, - kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2), - kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLELargeFails) { - SetupTexture(); - SetupIndexBuffer(); - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kNumVertices + 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - cmd.Init(GL_TRIANGLES, kInvalidIndexRangeCount, GL_UNSIGNED_SHORT, - kInvalidIndexRangeStart * 2, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLEInvalidPrimcountFails) { - SetupTexture(); - SetupIndexBuffer(); - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, -1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -// Per-index data is twice as large, but values of indices are smaller -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLELargeIndexSucceeds) { - SetupTexture(); - SetupIndexBuffer(); - SetupVertexBuffer(); - SetupExpectationsForApplyingDefaultDirtyState(); - DoVertexAttribPointer(1, 4, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE( - GL_TRIANGLES, - kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2), - kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderGeometryInstancingTest, - DrawElementsInstancedANGLENoDivisor0Fails) { - SetupTexture(); - SetupIndexBuffer(); - SetupVertexBuffer(); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoVertexAttribDivisorANGLE(0, 1); - DoVertexAttribDivisorANGLE(1, 1); - EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawElementsInstancedANGLE cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervSucceeds) { - const float dummy = 0; - const GLuint kOffsetToTestFor = sizeof(dummy) * 4; - const GLuint kIndexToTest = 1; - GetVertexAttribPointerv::Result* result = - static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_); - result->size = 0; - const GLuint* result_value = result->GetData(); - // Test that initial value is 0. - GetVertexAttribPointerv cmd; - cmd.Init(kIndexToTest, GL_VERTEX_ATTRIB_ARRAY_POINTER, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(sizeof(*result_value), result->size); - EXPECT_EQ(0u, *result_value); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Set the value and see that we get it. - SetupVertexBuffer(); - DoVertexAttribPointer(kIndexToTest, 2, GL_FLOAT, 0, kOffsetToTestFor); - result->size = 0; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(sizeof(*result_value), result->size); - EXPECT_EQ(kOffsetToTestFor, *result_value); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervBadArgsFails) { - const GLuint kIndexToTest = 1; - GetVertexAttribPointerv::Result* result = - static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_); - result->size = 0; - const GLuint* result_value = result->GetData(); - // Test pname invalid fails. - GetVertexAttribPointerv cmd; - cmd.Init(kIndexToTest, GL_VERTEX_ATTRIB_ARRAY_POINTER + 1, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0u, result->size); - EXPECT_EQ(kInitialResult, *result_value); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - - // Test index out of range fails. - result->size = 0; - cmd.Init(kNumVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_POINTER, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0u, result->size); - EXPECT_EQ(kInitialResult, *result_value); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - - // Test memory id bad fails. - cmd.Init(kIndexToTest, GL_VERTEX_ATTRIB_ARRAY_POINTER, - kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - - // Test memory offset bad fails. - cmd.Init(kIndexToTest, GL_VERTEX_ATTRIB_ARRAY_POINTER, - shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformivSucceeds) { - GetUniformiv::Result* result = - static_cast<GetUniformiv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformiv cmd; - cmd.Init(client_program_id_, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformiv(kServiceProgramId, kUniform2RealLocation, _)) - .Times(1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), - result->size); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformivArrayElementSucceeds) { - GetUniformiv::Result* result = - static_cast<GetUniformiv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformiv cmd; - cmd.Init(client_program_id_, - kUniform2ElementFakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, - GetUniformiv(kServiceProgramId, kUniform2ElementRealLocation, _)) - .Times(1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), - result->size); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadProgramFails) { - GetUniformiv::Result* result = - static_cast<GetUniformiv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformiv cmd; - // non-existant program - cmd.Init(kInvalidClientId, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformiv(_, _, _)) - .Times(0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - // Valid id that is not a program. The GL spec requires a different error for - // this case. -#if GLES2_TEST_SHADER_VS_PROGRAM_IDS - result->size = kInitialResult; - cmd.Init(client_shader_id_, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS - // Unlinked program - EXPECT_CALL(*gl_, CreateProgram()) - .Times(1) - .WillOnce(Return(kNewServiceId)) - .RetiresOnSaturation(); - CreateProgram cmd2; - cmd2.Init(kNewClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - result->size = kInitialResult; - cmd.Init(kNewClientId, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadLocationFails) { - GetUniformiv::Result* result = - static_cast<GetUniformiv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformiv cmd; - // invalid location - cmd.Init(client_program_id_, kInvalidUniformLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformiv(_, _, _)) - .Times(0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadSharedMemoryFails) { - GetUniformiv cmd; - cmd.Init(client_program_id_, - kUniform2FakeLocation, - kInvalidSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformiv(_, _, _)) - .Times(0); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kUniform2FakeLocation, - kSharedMemoryId, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -}; - -TEST_F(GLES2DecoderWithShaderTest, GetUniformfvSucceeds) { - GetUniformfv::Result* result = - static_cast<GetUniformfv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformfv cmd; - cmd.Init(client_program_id_, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformfv(kServiceProgramId, kUniform2RealLocation, _)) - .Times(1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), - result->size); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformfvArrayElementSucceeds) { - GetUniformfv::Result* result = - static_cast<GetUniformfv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformfv cmd; - cmd.Init(client_program_id_, - kUniform2ElementFakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, - GetUniformfv(kServiceProgramId, kUniform2ElementRealLocation, _)) - .Times(1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), - result->size); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadProgramFails) { - GetUniformfv::Result* result = - static_cast<GetUniformfv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformfv cmd; - // non-existant program - cmd.Init(kInvalidClientId, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformfv(_, _, _)) - .Times(0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - // Valid id that is not a program. The GL spec requires a different error for - // this case. -#if GLES2_TEST_SHADER_VS_PROGRAM_IDS - result->size = kInitialResult; - cmd.Init(client_shader_id_, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS - // Unlinked program - EXPECT_CALL(*gl_, CreateProgram()) - .Times(1) - .WillOnce(Return(kNewServiceId)) - .RetiresOnSaturation(); - CreateProgram cmd2; - cmd2.Init(kNewClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - result->size = kInitialResult; - cmd.Init(kNewClientId, - kUniform2FakeLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadLocationFails) { - GetUniformfv::Result* result = - static_cast<GetUniformfv::Result*>(shared_memory_address_); - result->size = 0; - GetUniformfv cmd; - // invalid location - cmd.Init(client_program_id_, kInvalidUniformLocation, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformfv(_, _, _)) - .Times(0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadSharedMemoryFails) { - GetUniformfv cmd; - cmd.Init(client_program_id_, - kUniform2FakeLocation, - kInvalidSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, GetUniformfv(_, _, _)) - .Times(0); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kUniform2FakeLocation, - kSharedMemoryId, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -}; - -TEST_F(GLES2DecoderWithShaderTest, GetAttachedShadersSucceeds) { - GetAttachedShaders cmd; - typedef GetAttachedShaders::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 0; - EXPECT_CALL(*gl_, GetAttachedShaders(kServiceProgramId, 1, _, _)) - .WillOnce(DoAll(SetArgumentPointee<2>(1), - SetArgumentPointee<3>(kServiceShaderId))); - cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_, - Result::ComputeSize(1)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(1, result->GetNumResults()); - EXPECT_EQ(client_shader_id_, result->GetData()[0]); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetAttachedShadersResultNotInitFail) { - GetAttachedShaders cmd; - typedef GetAttachedShaders::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 1; - EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)) - .Times(0); - cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_, - Result::ComputeSize(1)); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetAttachedShadersBadProgramFails) { - GetAttachedShaders cmd; - typedef GetAttachedShaders::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 0; - EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)) - .Times(0); - cmd.Init(kInvalidClientId, shared_memory_id_, shared_memory_offset_, - Result::ComputeSize(1)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0U, result->size); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetAttachedShadersBadSharedMemoryFails) { - GetAttachedShaders cmd; - typedef GetAttachedShaders::Result Result; - cmd.Init(client_program_id_, kInvalidSharedMemoryId, shared_memory_offset_, - Result::ComputeSize(1)); - EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)) - .Times(0); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, shared_memory_id_, kInvalidSharedMemoryOffset, - Result::ComputeSize(1)); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatSucceeds) { - ScopedGLImplementationSetter gl_impl(::gfx::kGLImplementationEGLGLES2); - GetShaderPrecisionFormat cmd; - typedef GetShaderPrecisionFormat::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - const GLint range[2] = { 62, 62 }; - const GLint precision = 16; - EXPECT_CALL(*gl_,GetShaderPrecisionFormat(_, _, _, _)) - .WillOnce(DoAll(SetArrayArgument<2>(range,range+2), - SetArgumentPointee<3>(precision))) - .RetiresOnSaturation(); - cmd.Init(GL_VERTEX_SHADER, GL_HIGH_FLOAT, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_NE(0, result->success); - EXPECT_EQ(range[0], result->min_range); - EXPECT_EQ(range[1], result->max_range); - EXPECT_EQ(precision, result->precision); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatResultNotInitFails) { - GetShaderPrecisionFormat cmd; - typedef GetShaderPrecisionFormat::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 1; - // NOTE: GL might not be called. There is no Desktop OpenGL equivalent - cmd.Init(GL_VERTEX_SHADER, GL_HIGH_FLOAT, - shared_memory_id_, shared_memory_offset_); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatBadArgsFails) { - typedef GetShaderPrecisionFormat::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - GetShaderPrecisionFormat cmd; - cmd.Init(GL_TEXTURE_2D, GL_HIGH_FLOAT, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - result->success = 0; - cmd.Init(GL_VERTEX_SHADER, GL_TEXTURE_2D, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, - GetShaderPrecisionFormatBadSharedMemoryFails) { - GetShaderPrecisionFormat cmd; - cmd.Init(GL_VERTEX_SHADER, GL_HIGH_FLOAT, - kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(GL_VERTEX_SHADER, GL_TEXTURE_2D, - shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformSucceeds) { - const GLuint kUniformIndex = 1; - const uint32 kBucketId = 123; - GetActiveUniform cmd; - typedef GetActiveUniform::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - cmd.Init(client_program_id_, kUniformIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_NE(0, result->success); - EXPECT_EQ(kUniform2Size, result->size); - EXPECT_EQ(kUniform2Type, result->type); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); - ASSERT_TRUE(bucket != NULL); - EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kUniform2Name, - bucket->size())); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformResultNotInitFails) { - const GLuint kUniformIndex = 1; - const uint32 kBucketId = 123; - GetActiveUniform cmd; - typedef GetActiveUniform::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 1; - cmd.Init(client_program_id_, kUniformIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformBadProgramFails) { - const GLuint kUniformIndex = 1; - const uint32 kBucketId = 123; - GetActiveUniform cmd; - typedef GetActiveUniform::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - cmd.Init(kInvalidClientId, kUniformIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result->success); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -#if GLES2_TEST_SHADER_VS_PROGRAM_IDS - result->success = 0; - cmd.Init(client_shader_id_, kUniformIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result->success); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformBadIndexFails) { - const uint32 kBucketId = 123; - GetActiveUniform cmd; - typedef GetActiveUniform::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - cmd.Init(client_program_id_, kBadUniformIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result->success); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformBadSharedMemoryFails) { - const GLuint kUniformIndex = 1; - const uint32 kBucketId = 123; - GetActiveUniform cmd; - typedef GetActiveUniform::Result Result; - cmd.Init(client_program_id_, kUniformIndex, kBucketId, - kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kUniformIndex, kBucketId, - shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribSucceeds) { - const GLuint kAttribIndex = 1; - const uint32 kBucketId = 123; - GetActiveAttrib cmd; - typedef GetActiveAttrib::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - cmd.Init(client_program_id_, kAttribIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_NE(0, result->success); - EXPECT_EQ(kAttrib2Size, result->size); - EXPECT_EQ(kAttrib2Type, result->type); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); - ASSERT_TRUE(bucket != NULL); - EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kAttrib2Name, - bucket->size())); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribResultNotInitFails) { - const GLuint kAttribIndex = 1; - const uint32 kBucketId = 123; - GetActiveAttrib cmd; - typedef GetActiveAttrib::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 1; - cmd.Init(client_program_id_, kAttribIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribBadProgramFails) { - const GLuint kAttribIndex = 1; - const uint32 kBucketId = 123; - GetActiveAttrib cmd; - typedef GetActiveAttrib::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - cmd.Init(kInvalidClientId, kAttribIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result->success); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -#if GLES2_TEST_SHADER_VS_PROGRAM_IDS - result->success = 0; - cmd.Init(client_shader_id_, kAttribIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result->success); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribBadIndexFails) { - const uint32 kBucketId = 123; - GetActiveAttrib cmd; - typedef GetActiveAttrib::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->success = 0; - cmd.Init(client_program_id_, kBadAttribIndex, kBucketId, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result->success); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribBadSharedMemoryFails) { - const GLuint kAttribIndex = 1; - const uint32 kBucketId = 123; - GetActiveAttrib cmd; - typedef GetActiveAttrib::Result Result; - cmd.Init(client_program_id_, kAttribIndex, kBucketId, - kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kAttribIndex, kBucketId, - shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetShaderInfoLogValidArgs) { - const char* kInfo = "hello"; - const uint32 kBucketId = 123; - CompileShader compile_cmd; - GetShaderInfoLog cmd; - EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _)); - EXPECT_CALL(*gl_, CompileShader(kServiceShaderId)); - EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _)) - .WillOnce(SetArgumentPointee<2>(GL_FALSE)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_INFO_LOG_LENGTH, _)) - .WillOnce(SetArgumentPointee<2>(strlen(kInfo) + 1)) - .RetiresOnSaturation(); - EXPECT_CALL( - *gl_, GetShaderInfoLog(kServiceShaderId, strlen(kInfo) + 1, _, _)) - .WillOnce(DoAll(SetArgumentPointee<2>(strlen(kInfo)), - SetArrayArgument<3>(kInfo, kInfo + strlen(kInfo) + 1))); - compile_cmd.Init(client_shader_id_); - cmd.Init(client_shader_id_, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(compile_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); - ASSERT_TRUE(bucket != NULL); - EXPECT_EQ(strlen(kInfo) + 1, bucket->size()); - EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kInfo, - bucket->size())); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetShaderInfoLogInvalidArgs) { - const uint32 kBucketId = 123; - GetShaderInfoLog cmd; - cmd.Init(kInvalidClientId, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_F(GLES2DecoderTest, GetIntegervCached) { +TEST_P(GLES2DecoderTest, GetIntegervCached) { struct TestInfo { GLenum pname; GLint expected; }; TestInfo tests[] = { - { GL_MAX_TEXTURE_SIZE, TestHelper::kMaxTextureSize, }, - { GL_MAX_CUBE_MAP_TEXTURE_SIZE, TestHelper::kMaxCubeMapTextureSize, }, - { GL_MAX_RENDERBUFFER_SIZE, TestHelper::kMaxRenderbufferSize, }, + { + GL_MAX_TEXTURE_SIZE, TestHelper::kMaxTextureSize, + }, + { + GL_MAX_CUBE_MAP_TEXTURE_SIZE, TestHelper::kMaxCubeMapTextureSize, + }, + { + GL_MAX_RENDERBUFFER_SIZE, TestHelper::kMaxRenderbufferSize, + }, }; typedef GetIntegerv::Result Result; for (size_t ii = 0; ii < sizeof(tests) / sizeof(tests[0]); ++ii) { @@ -1649,1243 +116,100 @@ TEST_F(GLES2DecoderTest, GetIntegervCached) { .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetIntegerv(test.pname, _)) - .Times(0); + EXPECT_CALL(*gl_, GetIntegerv(test.pname, _)).Times(0); result->size = 0; GetIntegerv cmd2; cmd2.Init(test.pname, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(test.pname), - result->GetNumResults()); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(test.pname), + result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_EQ(test.expected, result->GetData()[0]); } } -TEST_F(GLES2DecoderTest, CompileShaderValidArgs) { - EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _)); - EXPECT_CALL(*gl_, CompileShader(kServiceShaderId)); - EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _)) - .WillOnce(SetArgumentPointee<2>(GL_TRUE)) - .RetiresOnSaturation(); - CompileShader cmd; - cmd.Init(client_shader_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, CompileShaderInvalidArgs) { - CompileShader cmd; - cmd.Init(kInvalidClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -#if GLES2_TEST_SHADER_VS_PROGRAM_IDS - cmd.Init(client_program_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS -} - -TEST_F(GLES2DecoderTest, ShaderSourceAndGetShaderSourceValidArgs) { - const uint32 kBucketId = 123; - const char kSource[] = "hello"; - const uint32 kSourceSize = sizeof(kSource) - 1; - memcpy(shared_memory_address_, kSource, kSourceSize); - ShaderSource cmd; - cmd.Init(client_shader_id_, - kSharedMemoryId, kSharedMemoryOffset, kSourceSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - memset(shared_memory_address_, 0, kSourceSize); - GetShaderSource get_cmd; - get_cmd.Init(client_shader_id_, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(get_cmd)); - CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); - ASSERT_TRUE(bucket != NULL); - EXPECT_EQ(kSourceSize + 1, bucket->size()); - EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kSource, - bucket->size())); -} - -TEST_F(GLES2DecoderTest, ShaderSourceInvalidArgs) { - const char kSource[] = "hello"; - const uint32 kSourceSize = sizeof(kSource) - 1; - memcpy(shared_memory_address_, kSource, kSourceSize); - ShaderSource cmd; - cmd.Init(kInvalidClientId, - kSharedMemoryId, kSharedMemoryOffset, kSourceSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -#if GLES2_TEST_SHADER_VS_PROGRAM_IDS - cmd.Init(client_program_id_, - kSharedMemoryId, kSharedMemoryOffset, kSourceSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS - cmd.Init(client_shader_id_, - kInvalidSharedMemoryId, kSharedMemoryOffset, kSourceSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_shader_id_, - kSharedMemoryId, kInvalidSharedMemoryOffset, kSourceSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_shader_id_, - kSharedMemoryId, kSharedMemoryOffset, kSharedBufferSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, ShaderSourceBucketAndGetShaderSourceValidArgs) { - const uint32 kInBucketId = 123; - const uint32 kOutBucketId = 125; - const char kSource[] = "hello"; - const uint32 kSourceSize = sizeof(kSource) - 1; - SetBucketAsCString(kInBucketId, kSource); - ShaderSourceBucket cmd; - cmd.Init(client_shader_id_, kInBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - ClearSharedMemory(); - GetShaderSource get_cmd; - get_cmd.Init(client_shader_id_, kOutBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(get_cmd)); - CommonDecoder::Bucket* bucket = decoder_->GetBucket(kOutBucketId); - ASSERT_TRUE(bucket != NULL); - EXPECT_EQ(kSourceSize + 1, bucket->size()); - EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kSource, - bucket->size())); -} - -TEST_F(GLES2DecoderTest, ShaderSourceBucketInvalidArgs) { - const uint32 kBucketId = 123; - const char kSource[] = "hello"; - const uint32 kSourceSize = sizeof(kSource) - 1; - memcpy(shared_memory_address_, kSource, kSourceSize); - ShaderSourceBucket cmd; - // Test no bucket. - cmd.Init(client_texture_id_, kBucketId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - // Test invalid client. - SetBucketAsCString(kBucketId, kSource); - cmd.Init(kInvalidClientId, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest, ShaderSourceStripComments) { - const uint32 kInBucketId = 123; - const char kSource[] = "hello/*te\ast*/world//a\ab"; - SetBucketAsCString(kInBucketId, kSource); - ShaderSourceBucket cmd; - cmd.Init(client_shader_id_, kInBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, GenerateMipmapWrongFormatsFails) { - EXPECT_CALL(*gl_, GenerateMipmapEXT(_)) - .Times(0); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - GenerateMipmap cmd; - cmd.Init(GL_TEXTURE_2D); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, GenerateMipmapHandlesOutOfMemory) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - TextureManager* manager = group().texture_manager(); - TextureRef* texture_ref = manager->GetTexture(client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - GLint width = 0; - GLint height = 0; - EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 2, &width, &height)); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GenerateMipmapEXT(GL_TEXTURE_2D)) - .Times(1); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - GenerateMipmap cmd; - cmd.Init(GL_TEXTURE_2D); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); - EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 2, &width, &height)); -} - -TEST_F(GLES2DecoderTest, GenerateMipmapClearsUnclearedTexture) { - EXPECT_CALL(*gl_, GenerateMipmapEXT(_)) - .Times(0); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 2, 2); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GenerateMipmapEXT(GL_TEXTURE_2D)); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - GenerateMipmap cmd; - cmd.Init(GL_TEXTURE_2D); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1iValidArgs) { - EXPECT_CALL(*gl_, Uniform1i(kUniform1RealLocation, 2)); - Uniform1i cmd; - cmd.Init(kUniform1FakeLocation, 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1ivValidArgs) { - EXPECT_CALL( - *gl_, Uniform1iv(kUniform1RealLocation, 1, - reinterpret_cast<const GLint*>(shared_memory_address_))); - Uniform1iv cmd; - cmd.Init(kUniform1FakeLocation, - 1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1ivInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); - Uniform1iv cmd; - cmd.Init(kUniform1FakeLocation, - 1, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1ivInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); - Uniform1iv cmd; - cmd.Init(kUniform1FakeLocation, - 1, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1ivImmediateValidArgs) { - Uniform1ivImmediate& cmd = *GetImmediateAs<Uniform1ivImmediate>(); - EXPECT_CALL( - *gl_, - Uniform1iv(kUniform1RealLocation, 1, - reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); - GLint temp[1 * 2] = { 0, }; - cmd.Init(kUniform1FakeLocation, 1, - &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1ivInvalidValidArgs) { - EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); - Uniform1iv cmd; - cmd.Init(kUniform1FakeLocation, - 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1ivZeroCount) { - EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); - Uniform1iv cmd; - cmd.Init(kUniform1FakeLocation, - 0, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1iSamplerIsLmited) { - EXPECT_CALL(*gl_, Uniform1i(_, _)).Times(0); - Uniform1i cmd; - cmd.Init( - kUniform1FakeLocation, - kNumTextureUnits); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, Uniform1ivSamplerIsLimited) { - EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); - Uniform1ivImmediate& cmd = *GetImmediateAs<Uniform1ivImmediate>(); - GLint temp[] = { kNumTextureUnits }; - cmd.Init(kUniform1FakeLocation, 1, - &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, BindBufferToDifferentTargetFails) { - // Bind the buffer to GL_ARRAY_BUFFER - DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); - // Attempt to rebind to GL_ELEMENT_ARRAY_BUFFER - // NOTE: Real GLES2 does not have this restriction but WebGL and we do. - // This can be restriction can be removed at runtime. - EXPECT_CALL(*gl_, BindBuffer(_, _)) - .Times(0); - BindBuffer cmd; - cmd.Init(GL_ELEMENT_ARRAY_BUFFER, client_buffer_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, ActiveTextureValidArgs) { - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE1)); - SpecializedSetup<ActiveTexture, 0>(true); - ActiveTexture cmd; - cmd.Init(GL_TEXTURE1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, ActiveTextureInvalidArgs) { - EXPECT_CALL(*gl_, ActiveTexture(_)).Times(0); - SpecializedSetup<ActiveTexture, 0>(false); - ActiveTexture cmd; - cmd.Init(GL_TEXTURE0 - 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(kNumTextureUnits); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest, CheckFramebufferStatusWithNoBoundTarget) { - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)) - .Times(0); - CheckFramebufferStatus::Result* result = - static_cast<CheckFramebufferStatus::Result*>(shared_memory_address_); - *result = 0; - CheckFramebufferStatus cmd; - cmd.Init(GL_FRAMEBUFFER, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), *result); -} - -TEST_F(GLES2DecoderWithShaderTest, BindAndDeleteFramebuffer) { - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - DoDeleteFramebuffer( - client_framebuffer_id_, kServiceFramebufferId, - true, GL_FRAMEBUFFER, 0, - true, GL_FRAMEBUFFER, 0); - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, FramebufferRenderbufferWithNoBoundTarget) { - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)) - .Times(0); - FramebufferRenderbuffer cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, FramebufferTexture2DWithNoBoundTarget) { - EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)) - .Times(0); - FramebufferTexture2D cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_, - 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithNoBoundTarget) { - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)) - .Times(0); - GetFramebufferAttachmentParameteriv cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, shared_memory_id_, - shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithRenderbuffer) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - GetFramebufferAttachmentParameteriv::Result* result = - static_cast<GetFramebufferAttachmentParameteriv::Result*>( - shared_memory_address_); - result->size = 0; - const GLint* result_value = result->GetData(); - FramebufferRenderbuffer fbrb_cmd; - GetFramebufferAttachmentParameteriv cmd; - fbrb_cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, shared_memory_id_, - shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(static_cast<GLuint>(*result_value), client_renderbuffer_id_); -} - -TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithTexture) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferTexture2DEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kServiceTextureId, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - GetFramebufferAttachmentParameteriv::Result* result = - static_cast<GetFramebufferAttachmentParameteriv::Result*>( - shared_memory_address_); - result->SetNumResults(0); - const GLint* result_value = result->GetData(); - FramebufferTexture2D fbtex_cmd; - GetFramebufferAttachmentParameteriv cmd; - fbtex_cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_, - 0); - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, shared_memory_id_, - shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(static_cast<GLuint>(*result_value), client_texture_id_); -} - -TEST_F(GLES2DecoderTest, GetRenderbufferParameterivWithNoBoundTarget) { - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetRenderbufferParameterivEXT(_, _, _)) - .Times(0); - GetRenderbufferParameteriv cmd; - cmd.Init( - GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, shared_memory_id_, - shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, RenderbufferStorageWithNoBoundTarget) { - EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)) - .Times(0); - RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 3, 4); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -namespace { - -// A class to emulate glReadPixels -class ReadPixelsEmulator { - public: - // pack_alignment is the alignment you want ReadPixels to use - // when copying. The actual data passed in pixels should be contiguous. - ReadPixelsEmulator(GLsizei width, GLsizei height, GLint bytes_per_pixel, - const void* src_pixels, const void* expected_pixels, - GLint pack_alignment) - : width_(width), - height_(height), - pack_alignment_(pack_alignment), - bytes_per_pixel_(bytes_per_pixel), - src_pixels_(reinterpret_cast<const int8*>(src_pixels)), - expected_pixels_(reinterpret_cast<const int8*>(expected_pixels)) { - } - - void ReadPixels( - GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, void* pixels) const { - DCHECK_GE(x, 0); - DCHECK_GE(y, 0); - DCHECK_LE(x + width, width_); - DCHECK_LE(y + height, height_); - for (GLint yy = 0; yy < height; ++yy) { - const int8* src = GetPixelAddress(src_pixels_, x, y + yy); - const void* dst = ComputePackAlignmentAddress(0, yy, width, pixels); - memcpy(const_cast<void*>(dst), src, width * bytes_per_pixel_); - } - } - - bool CompareRowSegment( - GLint x, GLint y, GLsizei width, const void* data) const { - DCHECK(x + width <= width_ || width == 0); - return memcmp(data, GetPixelAddress(expected_pixels_, x, y), - width * bytes_per_pixel_) == 0; - } - - // Helper to compute address of pixel in pack aligned data. - const void* ComputePackAlignmentAddress( - GLint x, GLint y, GLsizei width, const void* address) const { - GLint unpadded_row_size = ComputeImageDataSize(width, 1); - GLint two_rows_size = ComputeImageDataSize(width, 2); - GLsizei padded_row_size = two_rows_size - unpadded_row_size; - GLint offset = y * padded_row_size + x * bytes_per_pixel_; - return static_cast<const int8*>(address) + offset; - } - - GLint ComputeImageDataSize(GLint width, GLint height) const { - GLint row_size = width * bytes_per_pixel_; - if (height > 1) { - GLint temp = row_size + pack_alignment_ - 1; - GLint padded_row_size = (temp / pack_alignment_) * pack_alignment_; - GLint size_of_all_but_last_row = (height - 1) * padded_row_size; - return size_of_all_but_last_row + row_size; - } else { - return height * row_size; - } - } - - private: - const int8* GetPixelAddress(const int8* base, GLint x, GLint y) const { - return base + (width_ * y + x) * bytes_per_pixel_; - } - - GLsizei width_; - GLsizei height_; - GLint pack_alignment_; - GLint bytes_per_pixel_; - const int8* src_pixels_; - const int8* expected_pixels_; -}; - -} // anonymous namespace - -void GLES2DecoderTest::CheckReadPixelsOutOfRange( - GLint in_read_x, GLint in_read_y, - GLsizei in_read_width, GLsizei in_read_height, - bool init) { - const GLsizei kWidth = 5; - const GLsizei kHeight = 3; - const GLint kBytesPerPixel = 3; - const GLint kPackAlignment = 4; - const GLenum kFormat = GL_RGB; - static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { - 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13, - 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28, - 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34, - }; - - ClearSharedMemory(); - - // We need to setup an FBO so we can know the max size that ReadPixels will - // access - if (init) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, kFormat, kWidth, kHeight, 0, - kFormat, GL_UNSIGNED_BYTE, kSharedMemoryId, - kSharedMemoryOffset); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_, kServiceTextureId, 0, GL_NO_ERROR); - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - } - - ReadPixelsEmulator emu( - kWidth, kHeight, kBytesPerPixel, kSrcPixels, kSrcPixels, kPackAlignment); - typedef ReadPixels::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - uint32 result_shm_id = kSharedMemoryId; - uint32 result_shm_offset = kSharedMemoryOffset; - uint32 pixels_shm_id = kSharedMemoryId; - uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); - void* dest = &result[1]; - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - // ReadPixels will be called for valid size only even though the command - // is requesting a larger size. - GLint read_x = std::max(0, in_read_x); - GLint read_y = std::max(0, in_read_y); - GLint read_end_x = std::max(0, std::min(kWidth, in_read_x + in_read_width)); - GLint read_end_y = std::max(0, std::min(kHeight, in_read_y + in_read_height)); - GLint read_width = read_end_x - read_x; - GLint read_height = read_end_y - read_y; - if (read_width > 0 && read_height > 0) { - for (GLint yy = read_y; yy < read_end_y; ++yy) { - EXPECT_CALL( - *gl_, ReadPixels(read_x, yy, read_width, 1, - kFormat, GL_UNSIGNED_BYTE, _)) - .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels)) - .RetiresOnSaturation(); - } - } - ReadPixels cmd; - cmd.Init(in_read_x, in_read_y, in_read_width, in_read_height, - kFormat, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - - GLint unpadded_row_size = emu.ComputeImageDataSize(in_read_width, 1); - scoped_ptr<int8[]> zero(new int8[unpadded_row_size]); - scoped_ptr<int8[]> pack(new int8[kPackAlignment]); - memset(zero.get(), 0, unpadded_row_size); - memset(pack.get(), kInitialMemoryValue, kPackAlignment); - for (GLint yy = 0; yy < in_read_height; ++yy) { - const int8* row = static_cast<const int8*>( - emu.ComputePackAlignmentAddress(0, yy, in_read_width, dest)); - GLint y = in_read_y + yy; - if (y < 0 || y >= kHeight) { - EXPECT_EQ(0, memcmp(zero.get(), row, unpadded_row_size)); - } else { - // check off left. - GLint num_left_pixels = std::max(-in_read_x, 0); - GLint num_left_bytes = num_left_pixels * kBytesPerPixel; - EXPECT_EQ(0, memcmp(zero.get(), row, num_left_bytes)); - - // check off right. - GLint num_right_pixels = std::max(in_read_x + in_read_width - kWidth, 0); - GLint num_right_bytes = num_right_pixels * kBytesPerPixel; - EXPECT_EQ(0, memcmp(zero.get(), - row + unpadded_row_size - num_right_bytes, - num_right_bytes)); - - // check middle. - GLint x = std::max(in_read_x, 0); - GLint num_middle_pixels = - std::max(in_read_width - num_left_pixels - num_right_pixels, 0); - EXPECT_TRUE(emu.CompareRowSegment( - x, y, num_middle_pixels, row + num_left_bytes)); - } - - // check padding - if (yy != in_read_height - 1) { - GLint num_padding_bytes = - (kPackAlignment - 1) - (unpadded_row_size % kPackAlignment); - EXPECT_EQ(0, - memcmp(pack.get(), row + unpadded_row_size, num_padding_bytes)); - } - } -} - -TEST_F(GLES2DecoderTest, ReadPixels) { - const GLsizei kWidth = 5; - const GLsizei kHeight = 3; - const GLint kBytesPerPixel = 3; - const GLint kPackAlignment = 4; - static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { - 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13, - 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28, - 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34, - }; - - surface_->SetSize(gfx::Size(INT_MAX, INT_MAX)); - - ReadPixelsEmulator emu( - kWidth, kHeight, kBytesPerPixel, kSrcPixels, kSrcPixels, kPackAlignment); - typedef ReadPixels::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - uint32 result_shm_id = kSharedMemoryId; - uint32 result_shm_offset = kSharedMemoryOffset; - uint32 pixels_shm_id = kSharedMemoryId; - uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); - void* dest = &result[1]; - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL( - *gl_, ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _)) - .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels)); - ReadPixels cmd; - cmd.Init(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - for (GLint yy = 0; yy < kHeight; ++yy) { - EXPECT_TRUE(emu.CompareRowSegment( - 0, yy, kWidth, - emu.ComputePackAlignmentAddress(0, yy, kWidth, dest))); - } -} - -TEST_F(GLES2DecoderRGBBackbufferTest, ReadPixelsNoAlphaBackbuffer) { - const GLsizei kWidth = 3; - const GLsizei kHeight = 3; - const GLint kBytesPerPixel = 4; - const GLint kPackAlignment = 4; - static const uint8 kExpectedPixels[kWidth * kHeight * kBytesPerPixel] = { - 12, 13, 14, 255, 19, 18, 19, 255, 13, 14, 18, 255, - 29, 28, 23, 255, 21, 22, 21, 255, 28, 23, 22, 255, - 31, 34, 39, 255, 32, 37, 32, 255, 34, 39, 37, 255, - }; - static const uint8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { - 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, - 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, - 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, - }; - - surface_->SetSize(gfx::Size(INT_MAX, INT_MAX)); - - ReadPixelsEmulator emu( - kWidth, kHeight, kBytesPerPixel, kSrcPixels, kExpectedPixels, - kPackAlignment); - typedef ReadPixels::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - uint32 result_shm_id = kSharedMemoryId; - uint32 result_shm_offset = kSharedMemoryOffset; - uint32 pixels_shm_id = kSharedMemoryId; - uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); - void* dest = &result[1]; - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL( - *gl_, ReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, _)) - .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels)); - ReadPixels cmd; - cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - for (GLint yy = 0; yy < kHeight; ++yy) { - EXPECT_TRUE(emu.CompareRowSegment( - 0, yy, kWidth, - emu.ComputePackAlignmentAddress(0, yy, kWidth, dest))); - } -} - -TEST_F(GLES2DecoderTest, ReadPixelsOutOfRange) { - static GLint tests[][4] = { - { -2, -1, 9, 5, }, // out of range on all sides - { 2, 1, 9, 5, }, // out of range on right, bottom - { -7, -4, 9, 5, }, // out of range on left, top - { 0, -5, 9, 5, }, // completely off top - { 0, 3, 9, 5, }, // completely off bottom - { -9, 0, 9, 5, }, // completely off left - { 5, 0, 9, 5, }, // completely off right - }; - - for (size_t tt = 0; tt < arraysize(tests); ++tt) { - CheckReadPixelsOutOfRange( - tests[tt][0], tests[tt][1], tests[tt][2], tests[tt][3], tt == 0); - } -} - -TEST_F(GLES2DecoderTest, ReadPixelsInvalidArgs) { - typedef ReadPixels::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - uint32 result_shm_id = kSharedMemoryId; - uint32 result_shm_offset = kSharedMemoryOffset; - uint32 pixels_shm_id = kSharedMemoryId; - uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); - EXPECT_CALL(*gl_, ReadPixels(_, _, _, _, _, _, _)).Times(0); - ReadPixels cmd; - cmd.Init(0, 0, -1, 1, GL_RGB, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(0, 0, 1, -1, GL_RGB, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(0, 0, 1, 1, GL_RGB, GL_INT, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, - kInvalidSharedMemoryId, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, - pixels_shm_id, kInvalidSharedMemoryOffset, - result_shm_id, result_shm_offset, - false); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - kInvalidSharedMemoryId, result_shm_offset, - false); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, kInvalidSharedMemoryOffset, - false); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, BindAttribLocation) { - const GLint kLocation = 2; - const char* kName = "testing"; - const uint32 kNameSize = strlen(kName); - EXPECT_CALL( - *gl_, BindAttribLocation(kServiceProgramId, kLocation, StrEq(kName))) - .Times(1); - memcpy(shared_memory_address_, kName, kNameSize); - BindAttribLocation cmd; - cmd.Init(client_program_id_, kLocation, kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, BindAttribLocationInvalidArgs) { - const GLint kLocation = 2; - const char* kName = "testing"; - const char* kBadName = "test\aing"; - const uint32 kNameSize = strlen(kName); - const uint32 kBadNameSize = strlen(kBadName); - EXPECT_CALL(*gl_, BindAttribLocation(_, _, _)).Times(0); - memcpy(shared_memory_address_, kName, kNameSize); - BindAttribLocation cmd; - cmd.Init(kInvalidClientId, kLocation, - kSharedMemoryId, kSharedMemoryOffset, kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(client_program_id_, kLocation, - kInvalidSharedMemoryId, kSharedMemoryOffset, kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kLocation, - kSharedMemoryId, kInvalidSharedMemoryOffset, kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kLocation, - kSharedMemoryId, kSharedMemoryOffset, kSharedBufferSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - memcpy(shared_memory_address_, kBadName, kBadNameSize); - cmd.Init(client_program_id_, kLocation, - kSharedMemoryId, kSharedMemoryOffset, kBadNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest, BindAttribLocationBucket) { - const uint32 kBucketId = 123; - const GLint kLocation = 2; - const char* kName = "testing"; - EXPECT_CALL( - *gl_, BindAttribLocation(kServiceProgramId, kLocation, StrEq(kName))) - .Times(1); - SetBucketAsCString(kBucketId, kName); - BindAttribLocationBucket cmd; - cmd.Init(client_program_id_, kLocation, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, BindAttribLocationBucketInvalidArgs) { - const uint32 kBucketId = 123; - const GLint kLocation = 2; - const char* kName = "testing"; - EXPECT_CALL(*gl_, BindAttribLocation(_, _, _)).Times(0); - BindAttribLocationBucket cmd; - // check bucket does not exist. - cmd.Init(client_program_id_, kLocation, kBucketId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - // check bucket is empty. - SetBucketAsCString(kBucketId, NULL); - cmd.Init(client_program_id_, kLocation, kBucketId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - // Check bad program id - SetBucketAsCString(kBucketId, kName); - cmd.Init(kInvalidClientId, kLocation, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetAttribLocation) { - const uint32 kNameSize = strlen(kAttrib2Name); - const char* kNonExistentName = "foobar"; - const uint32 kNonExistentNameSize = strlen(kNonExistentName); - typedef GetAttribLocation::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - *result = -1; - char* name = GetSharedMemoryAsWithOffset<char*>(sizeof(*result)); - const uint32 kNameOffset = kSharedMemoryOffset + sizeof(*result); - memcpy(name, kAttrib2Name, kNameSize); - GetAttribLocation cmd; - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(kAttrib2Location, *result); - *result = -1; - memcpy(name, kNonExistentName, kNonExistentNameSize); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNonExistentNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); -} - -TEST_F(GLES2DecoderWithShaderTest, GetAttribLocationInvalidArgs) { - const uint32 kNameSize = strlen(kAttrib2Name); - const char* kBadName = "foo\abar"; - const uint32 kBadNameSize = strlen(kBadName); - typedef GetAttribLocation::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - *result = -1; - char* name = GetSharedMemoryAsWithOffset<char*>(sizeof(*result)); - const uint32 kNameOffset = kSharedMemoryOffset + sizeof(*result); - memcpy(name, kAttrib2Name, kNameSize); - GetAttribLocation cmd; - cmd.Init(kInvalidClientId, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - *result = -1; - cmd.Init(client_program_id_, - kInvalidSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kInvalidSharedMemoryOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kInvalidSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kInvalidSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kSharedBufferSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - memcpy(name, kBadName, kBadNameSize); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kBadNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetAttribLocationBucket) { - const uint32 kBucketId = 123; - const char* kNonExistentName = "foobar"; - typedef GetAttribLocationBucket::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - SetBucketAsCString(kBucketId, kAttrib2Name); - *result = -1; - GetAttribLocationBucket cmd; - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(kAttrib2Location, *result); - SetBucketAsCString(kBucketId, kNonExistentName); - *result = -1; - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); -} - -TEST_F(GLES2DecoderWithShaderTest, GetAttribLocationBucketInvalidArgs) { - const uint32 kBucketId = 123; - typedef GetAttribLocationBucket::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - *result = -1; - GetAttribLocationBucket cmd; - // Check no bucket - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - // Check bad program id. - SetBucketAsCString(kBucketId, kAttrib2Name); - cmd.Init(kInvalidClientId, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - *result = -1; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - // Check bad memory - cmd.Init(client_program_id_, kBucketId, - kInvalidSharedMemoryId, kSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformLocation) { - const uint32 kNameSize = strlen(kUniform2Name); - const char* kNonExistentName = "foobar"; - const uint32 kNonExistentNameSize = strlen(kNonExistentName); - typedef GetUniformLocation::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - *result = -1; - char* name = GetSharedMemoryAsWithOffset<char*>(sizeof(*result)); - const uint32 kNameOffset = kSharedMemoryOffset + sizeof(*result); - memcpy(name, kUniform2Name, kNameSize); - GetUniformLocation cmd; - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(kUniform2FakeLocation, *result); - memcpy(name, kNonExistentName, kNonExistentNameSize); - *result = -1; - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNonExistentNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformLocationInvalidArgs) { - const uint32 kNameSize = strlen(kUniform2Name); - const char* kBadName = "foo\abar"; - const uint32 kBadNameSize = strlen(kBadName); - typedef GetUniformLocation::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - *result = -1; - char* name = GetSharedMemoryAsWithOffset<char*>(sizeof(*result)); - const uint32 kNameOffset = kSharedMemoryOffset + sizeof(*result); - memcpy(name, kUniform2Name, kNameSize); - GetUniformLocation cmd; - cmd.Init(kInvalidClientId, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - *result = -1; - cmd.Init(client_program_id_, - kInvalidSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kInvalidSharedMemoryOffset, - kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kInvalidSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kInvalidSharedMemoryOffset, - kNameSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kSharedBufferSize); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - memcpy(name, kBadName, kBadNameSize); - cmd.Init(client_program_id_, - kSharedMemoryId, kNameOffset, - kSharedMemoryId, kSharedMemoryOffset, - kBadNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformLocationBucket) { - const uint32 kBucketId = 123; - const char* kNonExistentName = "foobar"; - typedef GetUniformLocationBucket::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - SetBucketAsCString(kBucketId, kUniform2Name); - *result = -1; - GetUniformLocationBucket cmd; - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(kUniform2FakeLocation, *result); - SetBucketAsCString(kBucketId, kNonExistentName); - *result = -1; - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); -} - -TEST_F(GLES2DecoderWithShaderTest, GetUniformLocationBucketInvalidArgs) { - const uint32 kBucketId = 123; - typedef GetUniformLocationBucket::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - *result = -1; - GetUniformLocationBucket cmd; - // Check no bucket - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - // Check bad program id. - SetBucketAsCString(kBucketId, kUniform2Name); - cmd.Init(kInvalidClientId, kBucketId, - kSharedMemoryId, kSharedMemoryOffset); - *result = -1; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(-1, *result); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - // Check bad memory - cmd.Init(client_program_id_, kBucketId, - kInvalidSharedMemoryId, kSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, kBucketId, - kSharedMemoryId, kInvalidSharedMemoryOffset); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, GetMaxValueInBufferCHROMIUM) { +TEST_P(GLES2DecoderWithShaderTest, GetMaxValueInBufferCHROMIUM) { SetupIndexBuffer(); GetMaxValueInBufferCHROMIUM::Result* result = static_cast<GetMaxValueInBufferCHROMIUM::Result*>(shared_memory_address_); *result = 0; GetMaxValueInBufferCHROMIUM cmd; - cmd.Init(client_element_buffer_id_, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kSharedMemoryId, kSharedMemoryOffset); + cmd.Init(client_element_buffer_id_, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(7u, *result); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - cmd.Init(client_element_buffer_id_, kValidIndexRangeCount + 1, + cmd.Init(client_element_buffer_id_, + kValidIndexRangeCount + 1, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kSharedMemoryId, kSharedMemoryOffset); + kValidIndexRangeStart * 2, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(100u, *result); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - cmd.Init(kInvalidClientId, kValidIndexRangeCount, + cmd.Init(kInvalidClientId, + kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kSharedMemoryId, kSharedMemoryOffset); + kValidIndexRangeStart * 2, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(client_element_buffer_id_, kOutOfRangeIndexRangeEnd, + cmd.Init(client_element_buffer_id_, + kOutOfRangeIndexRangeEnd, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kSharedMemoryId, kSharedMemoryOffset); + kValidIndexRangeStart * 2, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - cmd.Init(client_element_buffer_id_, kValidIndexRangeCount + 1, + cmd.Init(client_element_buffer_id_, + kValidIndexRangeCount + 1, GL_UNSIGNED_SHORT, - kOutOfRangeIndexRangeEnd * 2, kSharedMemoryId, kSharedMemoryOffset); + kOutOfRangeIndexRangeEnd * 2, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - cmd.Init(client_element_buffer_id_, kValidIndexRangeCount + 1, + cmd.Init(client_element_buffer_id_, + kValidIndexRangeCount + 1, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kSharedMemoryId, kSharedMemoryOffset); + kValidIndexRangeStart * 2, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_buffer_id_, kValidIndexRangeCount + 1, + cmd.Init(client_buffer_id_, + kValidIndexRangeCount + 1, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2, kSharedMemoryId, kSharedMemoryOffset); + kValidIndexRangeStart * 2, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - cmd.Init(client_element_buffer_id_, kValidIndexRangeCount + 1, + cmd.Init(client_element_buffer_id_, + kValidIndexRangeCount + 1, GL_UNSIGNED_SHORT, kValidIndexRangeStart * 2, - kInvalidSharedMemoryId, kSharedMemoryOffset); + kInvalidSharedMemoryId, + kSharedMemoryOffset); EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(client_element_buffer_id_, kValidIndexRangeCount + 1, + cmd.Init(client_element_buffer_id_, + kValidIndexRangeCount + 1, GL_UNSIGNED_SHORT, kValidIndexRangeStart * 2, - kSharedMemoryId, kInvalidSharedMemoryOffset); + kSharedMemoryId, + kInvalidSharedMemoryOffset); EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest, SharedIds) { +TEST_P(GLES2DecoderTest, SharedIds) { GenSharedIdsCHROMIUM gen_cmd; RegisterSharedIdsCHROMIUM reg_cmd; DeleteSharedIdsCHROMIUM del_cmd; @@ -2956,7 +280,7 @@ TEST_F(GLES2DecoderTest, SharedIds) { EXPECT_EQ(kOffset + 1, ids[1]); } -TEST_F(GLES2DecoderTest, GenSharedIdsCHROMIUMBadArgs) { +TEST_P(GLES2DecoderTest, GenSharedIdsCHROMIUMBadArgs) { const GLuint kNamespaceId = id_namespaces::kTextures; GenSharedIdsCHROMIUM cmd; cmd.Init(kNamespaceId, 0, -1, kSharedMemoryId, kSharedMemoryOffset); @@ -2967,7 +291,7 @@ TEST_F(GLES2DecoderTest, GenSharedIdsCHROMIUMBadArgs) { EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest, RegisterSharedIdsCHROMIUMBadArgs) { +TEST_P(GLES2DecoderTest, RegisterSharedIdsCHROMIUMBadArgs) { const GLuint kNamespaceId = id_namespaces::kTextures; RegisterSharedIdsCHROMIUM cmd; cmd.Init(kNamespaceId, -1, kSharedMemoryId, kSharedMemoryOffset); @@ -2978,7 +302,7 @@ TEST_F(GLES2DecoderTest, RegisterSharedIdsCHROMIUMBadArgs) { EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest, RegisterSharedIdsCHROMIUMDuplicateIds) { +TEST_P(GLES2DecoderTest, RegisterSharedIdsCHROMIUMDuplicateIds) { const GLuint kNamespaceId = id_namespaces::kTextures; const GLuint kRegisterId = 3; RegisterSharedIdsCHROMIUM cmd; @@ -2991,7 +315,7 @@ TEST_F(GLES2DecoderTest, RegisterSharedIdsCHROMIUMDuplicateIds) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_F(GLES2DecoderTest, DeleteSharedIdsCHROMIUMBadArgs) { +TEST_P(GLES2DecoderTest, DeleteSharedIdsCHROMIUMBadArgs) { const GLuint kNamespaceId = id_namespaces::kTextures; DeleteSharedIdsCHROMIUM cmd; cmd.Init(kNamespaceId, -1, kSharedMemoryId, kSharedMemoryOffset); @@ -3002,234 +326,7 @@ TEST_F(GLES2DecoderTest, DeleteSharedIdsCHROMIUMBadArgs) { EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest, TexSubImage2DValidArgs) { - const int kWidth = 16; - const int kHeight = 8; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 1, 1, 0, kWidth - 1, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - TexSubImage2D cmd; - cmd.Init( - GL_TEXTURE_2D, 1, 1, 0, kWidth - 1, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, TexSubImage2DBadArgs) { - const int kWidth = 16; - const int kHeight = 8; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - TexSubImage2D cmd; - cmd.Init(GL_TEXTURE0, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_TRUE, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_INT, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, -1, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 1, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, -1, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 1, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth + 1, kHeight, GL_RGBA, - GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight + 1, GL_RGBA, - GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, - GL_UNSIGNED_SHORT_4_4_4_4, kSharedMemoryId, kSharedMemoryOffset, - GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kInvalidSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kInvalidSharedMemoryOffset, GL_FALSE); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, CopyTexSubImage2DValidArgs) { - const int kWidth = 16; - const int kHeight = 8; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, CopyTexSubImage2D( - GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight)) - .Times(1) - .RetiresOnSaturation(); - CopyTexSubImage2D cmd; - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, CopyTexSubImage2DBadArgs) { - const int kWidth = 16; - const int kHeight = 8; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - CopyTexSubImage2D cmd; - cmd.Init(GL_TEXTURE0, 1, 0, 0, 0, 0, kWidth, kHeight); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, -1, 0, 0, 0, kWidth, kHeight); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 1, 0, 0, 0, kWidth, kHeight); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, -1, 0, 0, kWidth, kHeight); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 1, 0, 0, kWidth, kHeight); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth + 1, kHeight); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight + 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -// Check that if a renderbuffer is attached and GL returns -// GL_FRAMEBUFFER_COMPLETE that the buffer is cleared and state is restored. -TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearColor) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - ClearColor color_cmd; - ColorMask color_mask_cmd; - Enable enable_cmd; - FramebufferRenderbuffer cmd; - color_cmd.Init(0.1f, 0.2f, 0.3f, 0.4f); - color_mask_cmd.Init(0, 1, 0, 1); - enable_cmd.Init(GL_SCISSOR_TEST); - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); - InSequence sequence; - EXPECT_CALL(*gl_, ClearColor(0.1f, 0.2f, 0.3f, 0.4f)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(color_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(color_mask_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(enable_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepth) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - ClearDepthf depth_cmd; - DepthMask depth_mask_cmd; - FramebufferRenderbuffer cmd; - depth_cmd.Init(0.5f); - depth_mask_cmd.Init(false); - cmd.Init( - GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - client_renderbuffer_id_); - InSequence sequence; - EXPECT_CALL(*gl_, ClearDepth(0.5f)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(depth_mask_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearStencil) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - ClearStencil stencil_cmd; - StencilMaskSeparate stencil_mask_separate_cmd; - FramebufferRenderbuffer cmd; - stencil_cmd.Init(123); - stencil_mask_separate_cmd.Init(GL_BACK, 0x1234u); - cmd.Init( - GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - client_renderbuffer_id_); - InSequence sequence; - EXPECT_CALL(*gl_, ClearStencil(123)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_mask_separate_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, IsBuffer) { +TEST_P(GLES2DecoderTest, IsBuffer) { EXPECT_FALSE(DoIsBuffer(client_buffer_id_)); DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); EXPECT_TRUE(DoIsBuffer(client_buffer_id_)); @@ -3237,19 +334,23 @@ TEST_F(GLES2DecoderTest, IsBuffer) { EXPECT_FALSE(DoIsBuffer(client_buffer_id_)); } -TEST_F(GLES2DecoderTest, IsFramebuffer) { +TEST_P(GLES2DecoderTest, IsFramebuffer) { EXPECT_FALSE(DoIsFramebuffer(client_framebuffer_id_)); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); EXPECT_TRUE(DoIsFramebuffer(client_framebuffer_id_)); - DoDeleteFramebuffer( - client_framebuffer_id_, kServiceFramebufferId, - true, GL_FRAMEBUFFER, 0, - true, GL_FRAMEBUFFER, 0); + DoDeleteFramebuffer(client_framebuffer_id_, + kServiceFramebufferId, + true, + GL_FRAMEBUFFER, + 0, + true, + GL_FRAMEBUFFER, + 0); EXPECT_FALSE(DoIsFramebuffer(client_framebuffer_id_)); } -TEST_F(GLES2DecoderTest, IsProgram) { +TEST_P(GLES2DecoderTest, IsProgram) { // IsProgram is true as soon as the program is created. EXPECT_TRUE(DoIsProgram(client_program_id_)); EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)) @@ -3257,26 +358,25 @@ TEST_F(GLES2DecoderTest, IsProgram) { .RetiresOnSaturation(); DoDeleteProgram(client_program_id_, kServiceProgramId); EXPECT_FALSE(DoIsProgram(client_program_id_)); - } -TEST_F(GLES2DecoderTest, IsRenderbuffer) { +TEST_P(GLES2DecoderTest, IsRenderbuffer) { EXPECT_FALSE(DoIsRenderbuffer(client_renderbuffer_id_)); - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); EXPECT_TRUE(DoIsRenderbuffer(client_renderbuffer_id_)); DoDeleteRenderbuffer(client_renderbuffer_id_, kServiceRenderbufferId); EXPECT_FALSE(DoIsRenderbuffer(client_renderbuffer_id_)); } -TEST_F(GLES2DecoderTest, IsShader) { +TEST_P(GLES2DecoderTest, IsShader) { // IsShader is true as soon as the program is created. EXPECT_TRUE(DoIsShader(client_shader_id_)); DoDeleteShader(client_shader_id_, kServiceShaderId); EXPECT_FALSE(DoIsShader(client_shader_id_)); } -TEST_F(GLES2DecoderTest, IsTexture) { +TEST_P(GLES2DecoderTest, IsTexture) { EXPECT_FALSE(DoIsTexture(client_texture_id_)); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); EXPECT_TRUE(DoIsTexture(client_texture_id_)); @@ -3284,1114 +384,7 @@ TEST_F(GLES2DecoderTest, IsTexture) { EXPECT_FALSE(DoIsTexture(client_texture_id_)); } -#if 0 // Turn this test on once we allow GL_DEPTH_STENCIL_ATTACHMENT -TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepthStencil) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - ClearDepthf depth_cmd; - ClearStencil stencil_cmd; - FramebufferRenderbuffer cmd; - depth_cmd.Init(0.5f); - stencil_cmd.Init(123); - cmd.Init( - GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - client_renderbuffer_id_); - InSequence sequence; - EXPECT_CALL(*gl_, ClearDepth(0.5f)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ClearStencil(123)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} -#endif - -TEST_F(GLES2DecoderWithShaderTest, VertexAttribPointer) { - SetupVertexBuffer(); - static const GLenum types[] = { - GL_BYTE, - GL_UNSIGNED_BYTE, - GL_SHORT, - GL_UNSIGNED_SHORT, - GL_FLOAT, - GL_FIXED, - GL_INT, - GL_UNSIGNED_INT, - }; - static const GLsizei sizes[] = { - 1, - 1, - 2, - 2, - 4, - 4, - 4, - 4, - }; - static const GLuint indices[] = { - 0, - 1, - kNumVertexAttribs - 1, - kNumVertexAttribs, - }; - static const GLsizei offset_mult[] = { - 0, - 0, - 1, - 1, - 2, - 1000, - }; - static const GLsizei offset_offset[] = { - 0, - 1, - 0, - 1, - 0, - 0, - }; - static const GLsizei stride_mult[] = { - -1, - 0, - 0, - 1, - 1, - 2, - 1000, - }; - static const GLsizei stride_offset[] = { - 0, - 0, - 1, - 0, - 1, - 0, - 0, - }; - for (size_t tt = 0; tt < arraysize(types); ++tt) { - GLenum type = types[tt]; - GLsizei num_bytes = sizes[tt]; - for (size_t ii = 0; ii < arraysize(indices); ++ii) { - GLuint index = indices[ii]; - for (GLint size = 0; size < 5; ++size) { - for (size_t oo = 0; oo < arraysize(offset_mult); ++oo) { - GLuint offset = num_bytes * offset_mult[oo] + offset_offset[oo]; - for (size_t ss = 0; ss < arraysize(stride_mult); ++ss) { - GLsizei stride = num_bytes * stride_mult[ss] + stride_offset[ss]; - for (int normalize = 0; normalize < 2; ++normalize) { - bool index_good = index < static_cast<GLuint>(kNumVertexAttribs); - bool size_good = (size > 0 && size < 5); - bool offset_good = (offset % num_bytes == 0); - bool stride_good = (stride % num_bytes == 0) && stride >= 0 && - stride <= 255; - bool type_good = (type != GL_INT && type != GL_UNSIGNED_INT && - type != GL_FIXED); - bool good = size_good && offset_good && stride_good && - type_good && index_good; - bool call = good && (type != GL_FIXED); - if (call) { - EXPECT_CALL(*gl_, VertexAttribPointer( - index, size, type, normalize, stride, - BufferOffset(offset))); - } - VertexAttribPointer cmd; - cmd.Init(index, size, type, normalize, stride, offset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - if (good) { - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - } else if (size_good && - offset_good && - stride_good && - type_good && - !index_good) { - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - } else if (size_good && - offset_good && - stride_good && - !type_good && - index_good) { - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - } else if (size_good && - offset_good && - !stride_good && - type_good && - index_good) { - if (stride < 0 || stride > 255) { - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - } else { - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - } - } else if (size_good && - !offset_good && - stride_good && - type_good && - index_good) { - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - } else if (!size_good && - offset_good && - stride_good && - type_good && - index_good) { - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - } else { - EXPECT_NE(GL_NO_ERROR, GetGLError()); - } - } - } - } - } - } - } -} - -// Test that with an RGB backbuffer if we set the color mask to 1,1,1,1 it is -// set to 1,1,1,0 at Draw time but is 1,1,1,1 at query time. -TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMask) { - ColorMask cmd; - cmd.Init(true, true, true, true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_COLOR_WRITEMASK, result->GetData())) - .Times(0); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_COLOR_WRITEMASK, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_COLOR_WRITEMASK), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(1, result->GetData()[0]); - EXPECT_EQ(1, result->GetData()[1]); - EXPECT_EQ(1, result->GetData()[2]); - EXPECT_EQ(1, result->GetData()[3]); -} - -// Test that with no depth if we set DepthMask true that it's set to false at -// draw time but querying it returns true. -TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferDepthMask) { - EXPECT_CALL(*gl_, DepthMask(true)) - .Times(0) - .RetiresOnSaturation(); - DepthMask cmd; - cmd.Init(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_WRITEMASK, result->GetData())) - .Times(0); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_DEPTH_WRITEMASK, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_WRITEMASK), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(1, result->GetData()[0]); -} - -// Test that with no stencil if we set the stencil mask it's still set to 0 at -// draw time but gets our value if we query. -TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferStencilMask) { - const GLint kMask = 123; - EXPECT_CALL(*gl_, StencilMask(kMask)) - .Times(0) - .RetiresOnSaturation(); - StencilMask cmd; - cmd.Init(kMask); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_WRITEMASK, result->GetData())) - .Times(0); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_WRITEMASK, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_WRITEMASK), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(kMask, result->GetData()[0]); -} - -// Test that if an FBO is bound we get the correct masks. -TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMaskFBO) { - ColorMask cmd; - cmd.Init(true, true, true, true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupTexture(); - SetupVertexBuffer(); - DoEnableVertexAttribArray(0); - DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); - DoEnableVertexAttribArray(1); - DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); - DoEnableVertexAttribArray(2); - DoVertexAttribPointer(2, 2, GL_FLOAT, 0, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Check that no extra calls are made on the next draw. - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Setup Frame buffer. - // needs to be 1x1 or else it's not renderable. - const GLsizei kWidth = 1; - const GLsizei kHeight = 1; - const GLenum kFormat = GL_RGB; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - // Pass some data so the texture will be marked as cleared. - DoTexImage2D( - GL_TEXTURE_2D, 0, kFormat, kWidth, kHeight, 0, - kFormat, GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_, kServiceTextureId, 0, GL_NO_ERROR); - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - - // This time state needs to be set. - SetupExpectationsForApplyingDirtyState( - false, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Check that no extra calls are made on the next draw. - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Unbind - DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); - - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) { - InitDecoder( - "", // extensions - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(8, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) { - InitDecoder( - "", // extensions - true, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(0, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) { - InitDecoder( - "", // extensions - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(24)) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(24, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) { - InitDecoder( - "", // extensions - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(24)) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(0, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - true, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(8, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(0, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, DepthEnableWithDepth) { - InitDecoder( - "", // extensions - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource - - Enable cmd; - cmd.Init(GL_DEPTH_TEST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupDefaultProgram(); - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - true, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - true, // depth mask - true, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _)) - .Times(0) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(1, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) { - InitDecoder( - "", // extensions - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - Enable cmd; - cmd.Init(GL_DEPTH_TEST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupDefaultProgram(); - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _)) - .Times(0) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(1, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, StencilEnableWithStencil) { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - true, // request stencil - true); // bind generates resource - - Enable cmd; - cmd.Init(GL_STENCIL_TEST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupDefaultProgram(); - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - true, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - -1, // front stencil mask - -1, // back stencil mask - true, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _)) - .Times(0) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(1, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - Enable cmd; - cmd.Init(GL_STENCIL_TEST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupDefaultProgram(); - SetupTexture(); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - true, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1110, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays draw_cmd; - draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _)) - .Times(0) - .RetiresOnSaturation(); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(1, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilReportsCorrectValues) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - true, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(8, result->GetData()[0]); - result->size = 0; - cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(24)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(24, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilNoRequestedStencil) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(0, result->GetData()[0]); - result->size = 0; - cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(24)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(24, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferDepth) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - - EXPECT_CALL(*gl_, RenderbufferStorageEXT( - GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50)) - .Times(1) - .RetiresOnSaturation(); - RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - FramebufferRenderbuffer fbrb_cmd; - fbrb_cmd.Init( - GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - client_renderbuffer_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); - - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(0, result->GetData()[0]); - result->size = 0; - cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(24)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(24, result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferStencil) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - - EXPECT_CALL(*gl_, RenderbufferStorageEXT( - GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50)) - .Times(1) - .RetiresOnSaturation(); - RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - FramebufferRenderbuffer fbrb_cmd; - fbrb_cmd.Init( - GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, - client_renderbuffer_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); - - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 0; - GetIntegerv cmd2; - cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(8, result->GetData()[0]); - result->size = 0; - cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); - EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(24)) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ( - decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(0, result->GetData()[0]); -} - -TEST_F(GLES2DecoderTest, GetMultipleIntegervCHROMIUMValidArgs) { +TEST_P(GLES2DecoderTest, GetMultipleIntegervCHROMIUMValidArgs) { const GLsizei kCount = 3; GLenum* pnames = GetSharedMemoryAs<GLenum*>(); pnames[0] = GL_DEPTH_WRITEMASK; @@ -4405,29 +398,31 @@ TEST_F(GLES2DecoderTest, GetMultipleIntegervCHROMIUMValidArgs) { num_results += decoder_->GetGLES2Util()->GLGetNumValuesReturned(pnames[ii]); } const GLsizei result_size = num_results * sizeof(*results); - memset(results, 0, result_size); + memset(results, 0, result_size); const GLint kSentinel = 0x12345678; results[num_results] = kSentinel; GetMultipleIntegervCHROMIUM cmd; - cmd.Init( - kSharedMemoryId, kSharedMemoryOffset, kCount, - kSharedMemoryId, kSharedMemoryOffset + sizeof(*pnames) * kCount, - result_size); + cmd.Init(kSharedMemoryId, + kSharedMemoryOffset, + kCount, + kSharedMemoryId, + kSharedMemoryOffset + sizeof(*pnames) * kCount, + result_size); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(1, results[0]); // Depth writemask - EXPECT_EQ(1, results[1]); // color writemask red - EXPECT_EQ(1, results[2]); // color writemask green - EXPECT_EQ(1, results[3]); // color writemask blue - EXPECT_EQ(1, results[4]); // color writemask alpha - EXPECT_EQ(-1, results[5]); // stencil writemask alpha + EXPECT_EQ(1, results[0]); // Depth writemask + EXPECT_EQ(1, results[1]); // color writemask red + EXPECT_EQ(1, results[2]); // color writemask green + EXPECT_EQ(1, results[3]); // color writemask blue + EXPECT_EQ(1, results[4]); // color writemask alpha + EXPECT_EQ(-1, results[5]); // stencil writemask alpha EXPECT_EQ(kSentinel, results[num_results]); // End of results } -TEST_F(GLES2DecoderTest, GetMultipleIntegervCHROMIUMInvalidArgs) { +TEST_P(GLES2DecoderTest, GetMultipleIntegervCHROMIUMInvalidArgs) { const GLsizei kCount = 3; // Offset the pnames because GLGetError will use the first uint32. const uint32 kPnameOffset = sizeof(uint32); @@ -4443,66 +438,82 @@ TEST_F(GLES2DecoderTest, GetMultipleIntegervCHROMIUMInvalidArgs) { num_results += decoder_->GetGLES2Util()->GLGetNumValuesReturned(pnames[ii]); } const GLsizei result_size = num_results * sizeof(*results); - memset(results, 0, result_size); + memset(results, 0, result_size); const GLint kSentinel = 0x12345678; results[num_results] = kSentinel; GetMultipleIntegervCHROMIUM cmd; // Check bad pnames pointer. - cmd.Init( - kInvalidSharedMemoryId, kSharedMemoryOffset + kPnameOffset, kCount, - kSharedMemoryId, kSharedMemoryOffset + kResultsOffset, - result_size); + cmd.Init(kInvalidSharedMemoryId, + kSharedMemoryOffset + kPnameOffset, + kCount, + kSharedMemoryId, + kSharedMemoryOffset + kResultsOffset, + result_size); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Check bad pnames pointer. - cmd.Init( - kSharedMemoryId, kInvalidSharedMemoryOffset, kCount, - kSharedMemoryId, kSharedMemoryOffset + kResultsOffset, - result_size); + cmd.Init(kSharedMemoryId, + kInvalidSharedMemoryOffset, + kCount, + kSharedMemoryId, + kSharedMemoryOffset + kResultsOffset, + result_size); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Check bad count. - cmd.Init( - kSharedMemoryId, kSharedMemoryOffset + kPnameOffset, -1, - kSharedMemoryId, kSharedMemoryOffset + kResultsOffset, - result_size); + cmd.Init(kSharedMemoryId, + kSharedMemoryOffset + kPnameOffset, + -1, + kSharedMemoryId, + kSharedMemoryOffset + kResultsOffset, + result_size); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Check bad results pointer. - cmd.Init( - kSharedMemoryId, kSharedMemoryOffset + kPnameOffset, kCount, - kInvalidSharedMemoryId, kSharedMemoryOffset + kResultsOffset, - result_size); + cmd.Init(kSharedMemoryId, + kSharedMemoryOffset + kPnameOffset, + kCount, + kInvalidSharedMemoryId, + kSharedMemoryOffset + kResultsOffset, + result_size); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Check bad results pointer. - cmd.Init( - kSharedMemoryId, kSharedMemoryOffset + kPnameOffset, kCount, - kSharedMemoryId, kInvalidSharedMemoryOffset, - result_size); + cmd.Init(kSharedMemoryId, + kSharedMemoryOffset + kPnameOffset, + kCount, + kSharedMemoryId, + kInvalidSharedMemoryOffset, + result_size); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Check bad size. - cmd.Init( - kSharedMemoryId, kSharedMemoryOffset + kPnameOffset, kCount, - kSharedMemoryId, kSharedMemoryOffset + kResultsOffset, - result_size + 1); + cmd.Init(kSharedMemoryId, + kSharedMemoryOffset + kPnameOffset, + kCount, + kSharedMemoryId, + kSharedMemoryOffset + kResultsOffset, + result_size + 1); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); // Check bad size. - cmd.Init( - kSharedMemoryId, kSharedMemoryOffset + kPnameOffset, kCount, - kSharedMemoryId, kSharedMemoryOffset + kResultsOffset, - result_size - 1); + cmd.Init(kSharedMemoryId, + kSharedMemoryOffset + kPnameOffset, + kCount, + kSharedMemoryId, + kSharedMemoryOffset + kResultsOffset, + result_size - 1); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); // Check bad enum. - cmd.Init( - kSharedMemoryId, kSharedMemoryOffset + kPnameOffset, kCount, - kSharedMemoryId, kSharedMemoryOffset + kResultsOffset, - result_size); + cmd.Init(kSharedMemoryId, + kSharedMemoryOffset + kPnameOffset, + kCount, + kSharedMemoryId, + kSharedMemoryOffset + kResultsOffset, + result_size); GLenum temp = pnames[2]; pnames[2] = GL_TRUE; EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -4521,2631 +532,58 @@ TEST_F(GLES2DecoderTest, GetMultipleIntegervCHROMIUMInvalidArgs) { EXPECT_EQ(kSentinel, results[num_results]); // End of results } -TEST_F(GLES2DecoderTest, TexImage2DRedefinitionSucceeds) { - const int kWidth = 16; - const int kHeight = 8; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - EXPECT_CALL(*gl_, GetError()) - .WillRepeatedly(Return(GL_NO_ERROR)); - for (int ii = 0; ii < 2; ++ii) { - TexImage2D cmd; - if (ii == 0) { - EXPECT_CALL(*gl_, TexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, - GL_UNSIGNED_BYTE, _)) - .Times(1) - .RetiresOnSaturation(); - cmd.Init( - GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, - GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); - } else { - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 0, GL_RGBA, GL_UNSIGNED_BYTE, kWidth, kHeight); - cmd.Init( - GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, - GL_UNSIGNED_BYTE, 0, 0); - } - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight - 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - // Consider this TexSubImage2D command part of the previous TexImage2D - // (last GL_TRUE argument). It will be skipped if there are bugs in the - // redefinition case. - TexSubImage2D cmd2; - cmd2.Init( - GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight - 1, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_TRUE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - } -} - -TEST_F(GLES2DecoderTest, TexImage2DGLError) { - GLenum target = GL_TEXTURE_2D; - GLint level = 0; - GLenum internal_format = GL_RGBA; - GLsizei width = 2; - GLsizei height = 4; - GLint border = 0; - GLenum format = GL_RGBA; - GLenum type = GL_UNSIGNED_BYTE; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - TextureManager* manager = group().texture_manager(); - TextureRef* texture_ref = manager->GetTexture(client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexImage2D(target, level, internal_format, - width, height, border, format, type, _)) - .Times(1) - .RetiresOnSaturation(); - TexImage2D cmd; - cmd.Init(target, level, internal_format, width, height, border, format, - type, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); - EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); -} - -TEST_F(GLES2DecoderTest, BufferDataGLError) { - GLenum target = GL_ARRAY_BUFFER; - GLsizeiptr size = 4; - DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); - BufferManager* manager = group().buffer_manager(); - Buffer* buffer = manager->GetBuffer(client_buffer_id_); - ASSERT_TRUE(buffer != NULL); - EXPECT_EQ(0, buffer->size()); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BufferData(target, size, _, GL_STREAM_DRAW)) - .Times(1) - .RetiresOnSaturation(); - BufferData cmd; - cmd.Init(target, size, 0, 0, GL_STREAM_DRAW); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); - EXPECT_EQ(0, buffer->size()); -} - -TEST_F(GLES2DecoderTest, CopyTexImage2DGLError) { - GLenum target = GL_TEXTURE_2D; - GLint level = 0; - GLenum internal_format = GL_RGBA; - GLsizei width = 2; - GLsizei height = 4; - GLint border = 0; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - TextureManager* manager = group().texture_manager(); - TextureRef* texture_ref = manager->GetTexture(client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, CopyTexImage2D( - target, level, internal_format, 0, 0, width, height, border)) - .Times(1) - .RetiresOnSaturation(); - CopyTexImage2D cmd; - cmd.Init(target, level, internal_format, 0, 0, width, height, border); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); - EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); -} - -TEST_F(GLES2DecoderTest, FramebufferRenderbufferGLError) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - FramebufferRenderbuffer cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); -} - -TEST_F(GLES2DecoderTest, FramebufferTexture2DGLError) { - const GLsizei kWidth = 5; - const GLsizei kHeight = 3; - const GLenum kFormat = GL_RGB; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, kFormat, kWidth, kHeight, 0, - kFormat, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferTexture2DEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kServiceTextureId, 0)) - .Times(1) - .RetiresOnSaturation(); - FramebufferTexture2D fbtex_cmd; - fbtex_cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_, - 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); -} - -TEST_F(GLES2DecoderTest, RenderbufferStorageGLError) { - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, RenderbufferStorageEXT( - GL_RENDERBUFFER, GL_RGBA, 100, 50)) - .Times(1) - .RetiresOnSaturation(); - RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 100, 50); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); -} - -TEST_F(GLES2DecoderTest, RenderbufferStorageBadArgs) { - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, TestHelper::kMaxRenderbufferSize + 1, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 1, TestHelper::kMaxRenderbufferSize + 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, - RenderbufferStorageMultisampleCHROMIUMGLError) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, RenderbufferStorageMultisampleEXT( - GL_RENDERBUFFER, 1, GL_RGBA, 100, 50)) - .Times(1) - .RetiresOnSaturation(); - RenderbufferStorageMultisampleCHROMIUM cmd; - cmd.Init(GL_RENDERBUFFER, 1, GL_RGBA4, 100, 50); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, - RenderbufferStorageMultisampleCHROMIUMBadArgs) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - EXPECT_CALL(*gl_, RenderbufferStorageMultisampleEXT(_, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - RenderbufferStorageMultisampleCHROMIUM cmd; - cmd.Init(GL_RENDERBUFFER, TestHelper::kMaxSamples + 1, - GL_RGBA4, TestHelper::kMaxRenderbufferSize, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA4, TestHelper::kMaxRenderbufferSize + 1, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - cmd.Init(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA4, 1, TestHelper::kMaxRenderbufferSize + 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUM) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - InSequence sequence; - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL( - *gl_, - RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, - TestHelper::kMaxSamples, - GL_RGBA, - TestHelper::kMaxRenderbufferSize, - 1)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - RenderbufferStorageMultisampleCHROMIUM cmd; - cmd.Init(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA4, TestHelper::kMaxRenderbufferSize, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, - RenderbufferStorageMultisampleEXTNotSupported) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - InSequence sequence; - // GL_EXT_framebuffer_multisample uses RenderbufferStorageMultisampleCHROMIUM. - RenderbufferStorageMultisampleEXT cmd; - cmd.Init(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA4, TestHelper::kMaxRenderbufferSize, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -class GLES2DecoderMultisampledRenderToTextureTest - : public GLES2DecoderTestWithExtensions {}; - -TEST_P(GLES2DecoderMultisampledRenderToTextureTest, - NotCompatibleWithRenderbufferStorageMultisampleCHROMIUM) { - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - RenderbufferStorageMultisampleCHROMIUM cmd; - cmd.Init(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA4, TestHelper::kMaxRenderbufferSize, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_P(GLES2DecoderMultisampledRenderToTextureTest, - RenderbufferStorageMultisampleEXT) { - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - InSequence sequence; - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - if (strstr(GetParam(), "GL_IMG_multisampled_render_to_texture")) { - EXPECT_CALL( - *gl_, - RenderbufferStorageMultisampleIMG(GL_RENDERBUFFER, - TestHelper::kMaxSamples, - GL_RGBA, - TestHelper::kMaxRenderbufferSize, - 1)) - .Times(1) - .RetiresOnSaturation(); - } else { - EXPECT_CALL( - *gl_, - RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, - TestHelper::kMaxSamples, - GL_RGBA, - TestHelper::kMaxRenderbufferSize, - 1)) - .Times(1) - .RetiresOnSaturation(); - } - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - RenderbufferStorageMultisampleEXT cmd; - cmd.Init(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA4, TestHelper::kMaxRenderbufferSize, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -INSTANTIATE_TEST_CASE_P( - GLES2DecoderMultisampledRenderToTextureTests, - GLES2DecoderMultisampledRenderToTextureTest, - ::testing::Values("GL_EXT_multisampled_render_to_texture", - "GL_IMG_multisampled_render_to_texture")); - -TEST_F(GLES2DecoderTest, ReadPixelsGLError) { - GLenum kFormat = GL_RGBA; - GLint x = 0; - GLint y = 0; - GLsizei width = 2; - GLsizei height = 4; - typedef ReadPixels::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - uint32 result_shm_id = kSharedMemoryId; - uint32 result_shm_offset = kSharedMemoryOffset; - uint32 pixels_shm_id = kSharedMemoryId; - uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_OUT_OF_MEMORY)) - .RetiresOnSaturation(); - EXPECT_CALL( - *gl_, ReadPixels(x, y, width, height, kFormat, GL_UNSIGNED_BYTE, _)) - .Times(1) - .RetiresOnSaturation(); - ReadPixels cmd; - cmd.Init(x, y, width, height, kFormat, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); -} - -static bool ValueInArray(GLint value, GLint* array, GLint count) { - for (GLint ii = 0; ii < count; ++ii) { - if (array[ii] == value) { - return true; - } - } - return false; -} - -TEST_F(GLES2DecoderManualInitTest, GetCompressedTextureFormats) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - GetIntegerv cmd; - result->size = 0; - EXPECT_CALL(*gl_, GetIntegerv(_, _)) - .Times(0) - .RetiresOnSaturation(); - cmd.Init( - GL_NUM_COMPRESSED_TEXTURE_FORMATS, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(1, result->GetNumResults()); - GLint num_formats = result->GetData()[0]; - EXPECT_EQ(4, num_formats); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - result->size = 0; - cmd.Init( - GL_COMPRESSED_TEXTURE_FORMATS, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(num_formats, result->GetNumResults()); - - EXPECT_TRUE(ValueInArray( - GL_COMPRESSED_RGB_S3TC_DXT1_EXT, - result->GetData(), result->GetNumResults())); - EXPECT_TRUE(ValueInArray( - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, - result->GetData(), result->GetNumResults())); - EXPECT_TRUE(ValueInArray( - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, - result->GetData(), result->GetNumResults())); - EXPECT_TRUE(ValueInArray( - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, - result->GetData(), result->GetNumResults())); - - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, GetNoCompressedTextureFormats) { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - GetIntegerv cmd; - result->size = 0; - EXPECT_CALL(*gl_, GetIntegerv(_, _)) - .Times(0) - .RetiresOnSaturation(); - cmd.Init( - GL_NUM_COMPRESSED_TEXTURE_FORMATS, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(1, result->GetNumResults()); - GLint num_formats = result->GetData()[0]; - EXPECT_EQ(0, num_formats); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - result->size = 0; - cmd.Init( - GL_COMPRESSED_TEXTURE_FORMATS, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(num_formats, result->GetNumResults()); - - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DBucketBadBucket) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - const uint32 kBadBucketId = 123; - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - CompressedTexImage2DBucket cmd; - cmd.Init( - GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 0, - kBadBucketId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - CompressedTexSubImage2DBucket cmd2; - cmd2.Init( - GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, - kBadBucketId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); -} - -namespace { - -struct S3TCTestData { - GLenum format; - size_t block_size; -}; - -} // anonymous namespace. - -TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DS3TC) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - const uint32 kBucketId = 123; - CommonDecoder::Bucket* bucket = decoder_->CreateBucket(kBucketId); - ASSERT_TRUE(bucket != NULL); - - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - - static const S3TCTestData test_data[] = { - { GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8, }, - { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, }, - { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16, }, - { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 16, }, - }; - - for (size_t ii = 0; ii < arraysize(test_data); ++ii) { - const S3TCTestData& test = test_data[ii]; - CompressedTexImage2DBucket cmd; - // test small width. - DoCompressedTexImage2D( - GL_TEXTURE_2D, 0, test.format, 2, 4, 0, test.block_size, - kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // test bad width. - cmd.Init( - GL_TEXTURE_2D, 0, test.format, 5, 4, 0, - kBucketId); - bucket->SetSize(test.block_size * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // test small height. - DoCompressedTexImage2D( - GL_TEXTURE_2D, 0, test.format, 4, 2, 0, test.block_size, - kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // test too bad height. - cmd.Init( - GL_TEXTURE_2D, 0, test.format, 4, 5, 0, - kBucketId); - bucket->SetSize(test.block_size * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // test small for level 0. - DoCompressedTexImage2D( - GL_TEXTURE_2D, 0, test.format, 1, 1, 0, test.block_size, - kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // test small for level 0. - DoCompressedTexImage2D( - GL_TEXTURE_2D, 0, test.format, 2, 2, 0, test.block_size, - kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // test size too large. - cmd.Init( - GL_TEXTURE_2D, 0, test.format, 4, 4, 0, - kBucketId); - bucket->SetSize(test.block_size * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - - // test size too small. - cmd.Init( - GL_TEXTURE_2D, 0, test.format, 4, 4, 0, - kBucketId); - bucket->SetSize(test.block_size / 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - - // test with 3 mips. - DoCompressedTexImage2D( - GL_TEXTURE_2D, 0, test.format, 4, 4, 0, test.block_size, kBucketId); - DoCompressedTexImage2D( - GL_TEXTURE_2D, 1, test.format, 2, 2, 0, test.block_size, kBucketId); - DoCompressedTexImage2D( - GL_TEXTURE_2D, 2, test.format, 1, 1, 0, test.block_size, kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Test a 16x16 - DoCompressedTexImage2D( - GL_TEXTURE_2D, 0, test.format, 16, 16, 0, test.block_size * 4 * 4, - kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - CompressedTexSubImage2DBucket sub_cmd; - bucket->SetSize(test.block_size); - // Test sub image bad xoffset - sub_cmd.Init( - GL_TEXTURE_2D, 0, 1, 0, 4, 4, test.format, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Test sub image bad yoffset - sub_cmd.Init( - GL_TEXTURE_2D, 0, 0, 2, 4, 4, test.format, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Test sub image bad width - bucket->SetSize(test.block_size * 2); - sub_cmd.Init( - GL_TEXTURE_2D, 0, 0, 0, 5, 4, test.format, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Test sub image bad height - sub_cmd.Init( - GL_TEXTURE_2D, 0, 0, 0, 4, 5, test.format, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Test sub image bad size - bucket->SetSize(test.block_size + 1); - sub_cmd.Init( - GL_TEXTURE_2D, 0, 0, 0, 4, 4, test.format, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - - for (GLint yoffset = 0; yoffset <= 8; yoffset += 4) { - for (GLint xoffset = 0; xoffset <= 8; xoffset += 4) { - for (GLsizei height = 4; height <= 8; height +=4 ) { - for (GLsizei width = 4; width <= 8; width += 4) { - GLsizei size = test.block_size * (width / 4) * (height / 4); - bucket->SetSize(size); - EXPECT_CALL(*gl_, CompressedTexSubImage2D( - GL_TEXTURE_2D, 0, xoffset, yoffset, width, height, test.format, - size, _)) - .Times(1) - .RetiresOnSaturation(); - sub_cmd.Init( - GL_TEXTURE_2D, 0, xoffset, yoffset, width, height, test.format, - kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - } - } - } - } - } -} - -TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DETC1) { - InitDecoder( - "GL_OES_compressed_ETC1_RGB8_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - const uint32 kBucketId = 123; - CommonDecoder::Bucket* bucket = decoder_->CreateBucket(kBucketId); - ASSERT_TRUE(bucket != NULL); - - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - - const GLenum kFormat = GL_ETC1_RGB8_OES; - const size_t kBlockSize = 8; - - CompressedTexImage2DBucket cmd; - // test small width. - DoCompressedTexImage2D(GL_TEXTURE_2D, 0, kFormat, 4, 8, 0, 16, kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // test small height. - DoCompressedTexImage2D(GL_TEXTURE_2D, 0, kFormat, 8, 4, 0, 16, kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // test size too large. - cmd.Init(GL_TEXTURE_2D, 0, kFormat, 4, 4, 0, kBucketId); - bucket->SetSize(kBlockSize * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - - // test size too small. - cmd.Init(GL_TEXTURE_2D, 0, kFormat, 4, 4, 0, kBucketId); - bucket->SetSize(kBlockSize / 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - - // Test a 16x16 - DoCompressedTexImage2D( - GL_TEXTURE_2D, 0, kFormat, 16, 16, 0, kBlockSize * 16, kBucketId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Test CompressedTexSubImage not allowed - CompressedTexSubImage2DBucket sub_cmd; - bucket->SetSize(kBlockSize); - sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 4, 4, kFormat, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Test TexSubImage not allowed for ETC1 compressed texture - TextureRef* texture_ref = GetTexture(client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - GLenum type, internal_format; - EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); - EXPECT_EQ(kFormat, internal_format); - TexSubImage2D texsub_cmd; - texsub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(texsub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Test CopyTexSubImage not allowed for ETC1 compressed texture - CopyTexSubImage2D copy_cmd; - copy_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4); - EXPECT_EQ(error::kNoError, ExecuteCmd(copy_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, GetCompressedTextureFormatsETC1) { - InitDecoder( - "GL_OES_compressed_ETC1_RGB8_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - GetIntegerv cmd; - result->size = 0; - EXPECT_CALL(*gl_, GetIntegerv(_, _)) - .Times(0) - .RetiresOnSaturation(); - cmd.Init( - GL_NUM_COMPRESSED_TEXTURE_FORMATS, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(1, result->GetNumResults()); - GLint num_formats = result->GetData()[0]; - EXPECT_EQ(1, num_formats); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - result->size = 0; - cmd.Init( - GL_COMPRESSED_TEXTURE_FORMATS, - shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(num_formats, result->GetNumResults()); - - EXPECT_TRUE(ValueInArray( - GL_ETC1_RGB8_OES, - result->GetData(), result->GetNumResults())); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, GetProgramInfoCHROMIUMValidArgs) { - const uint32 kBucketId = 123; - GetProgramInfoCHROMIUM cmd; - cmd.Init(client_program_id_, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); - EXPECT_GT(bucket->size(), 0u); -} - -TEST_F(GLES2DecoderWithShaderTest, GetProgramInfoCHROMIUMInvalidArgs) { - const uint32 kBucketId = 123; - CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); - EXPECT_TRUE(bucket == NULL); - GetProgramInfoCHROMIUM cmd; - cmd.Init(kInvalidClientId, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - bucket = decoder_->GetBucket(kBucketId); - ASSERT_TRUE(bucket != NULL); - EXPECT_EQ(sizeof(ProgramInfoHeader), bucket->size()); - ProgramInfoHeader* info = bucket->GetDataAs<ProgramInfoHeader*>( - 0, sizeof(ProgramInfoHeader)); - ASSERT_TRUE(info != 0); - EXPECT_EQ(0u, info->link_status); - EXPECT_EQ(0u, info->num_attribs); - EXPECT_EQ(0u, info->num_uniforms); -} - -TEST_F(GLES2DecoderManualInitTest, EGLImageExternalBindTexture) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kNewServiceId)); - EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - BindTexture cmd; - cmd.Init(GL_TEXTURE_EXTERNAL_OES, kNewClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - TextureRef* texture_ref = GetTexture(kNewClientId); - EXPECT_TRUE(texture_ref != NULL); - EXPECT_TRUE(texture_ref->texture()->target() == GL_TEXTURE_EXTERNAL_OES); -} - -TEST_F(GLES2DecoderManualInitTest, EGLImageExternalGetBinding) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, - result->GetData())) - .Times(0); - result->size = 0; - GetIntegerv cmd; - cmd.Init(GL_TEXTURE_BINDING_EXTERNAL_OES, - shared_memory_id_, - shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_TEXTURE_BINDING_EXTERNAL_OES), result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(client_texture_id_, (uint32)result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureDefaults) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - - TextureRef* texture_ref = GetTexture(client_texture_id_); - EXPECT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES); - EXPECT_TRUE(texture->min_filter() == GL_LINEAR); - EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); - EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); -} - -TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParam) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST)); - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_MIN_FILTER, - GL_LINEAR)); - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE)); - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE)); - TexParameteri cmd; - cmd.Init(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - cmd.Init(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_MIN_FILTER, - GL_LINEAR); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - cmd.Init(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - cmd.Init(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - TextureRef* texture_ref = GetTexture(client_texture_id_); - EXPECT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES); - EXPECT_TRUE(texture->min_filter() == GL_LINEAR); - EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); - EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); -} - -TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParamInvalid) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - - TexParameteri cmd; - cmd.Init(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST_MIPMAP_NEAREST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - - cmd.Init(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_WRAP_S, - GL_REPEAT); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - - cmd.Init(GL_TEXTURE_EXTERNAL_OES, - GL_TEXTURE_WRAP_T, - GL_REPEAT); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - - TextureRef* texture_ref = GetTexture(client_texture_id_); - EXPECT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES); - EXPECT_TRUE(texture->min_filter() == GL_LINEAR); - EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); - EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); -} - -TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTexImage2DError) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - GLenum target = GL_TEXTURE_EXTERNAL_OES; - GLint level = 0; - GLenum internal_format = GL_RGBA; - GLsizei width = 2; - GLsizei height = 4; - GLint border = 0; - GLenum format = GL_RGBA; - GLenum type = GL_UNSIGNED_BYTE; - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - ASSERT_TRUE(GetTexture(client_texture_id_) != NULL); - TexImage2D cmd; - cmd.Init(target, level, internal_format, width, height, border, format, - type, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - - // TexImage2D is not allowed with GL_TEXTURE_EXTERNAL_OES targets. - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, BindGeneratesResourceFalse) { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource +TEST_P(GLES2DecoderManualInitTest, BindGeneratesResourceFalse) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); BindTexture cmd1; cmd1.Init(GL_TEXTURE_2D, kInvalidClientId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); BindBuffer cmd2; cmd2.Init(GL_ARRAY_BUFFER, kInvalidClientId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); BindFramebuffer cmd3; cmd3.Init(GL_FRAMEBUFFER, kInvalidClientId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd3)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd3)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); BindRenderbuffer cmd4; cmd4.Init(GL_RENDERBUFFER, kInvalidClientId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd4)); -} - -TEST_F(GLES2DecoderManualInitTest, CreateStreamTextureCHROMIUM) { - const GLuint kObjectId = 123; - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*stream_texture_manager(), CreateStreamTexture( - kServiceTextureId, client_texture_id_)) - .WillOnce(Return(kObjectId)) - .RetiresOnSaturation(); - - CreateStreamTextureCHROMIUM cmd; - CreateStreamTextureCHROMIUM::Result* result = - static_cast<CreateStreamTextureCHROMIUM::Result*>(shared_memory_address_); - cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(kObjectId, *result); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - TextureRef* texture_ref = GetTexture(client_texture_id_); - EXPECT_TRUE(texture_ref != NULL); - EXPECT_TRUE(texture_ref->texture()->IsStreamTexture()); - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); -} - -TEST_F(GLES2DecoderManualInitTest, CreateStreamTextureCHROMIUMBadId) { - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - CreateStreamTextureCHROMIUM cmd; - CreateStreamTextureCHROMIUM::Result* result = - static_cast<CreateStreamTextureCHROMIUM::Result*>(shared_memory_address_); - cmd.Init(kNewClientId, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(static_cast<GLuint>(GL_ZERO), *result); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, CreateStreamTextureCHROMIUMAlreadyBound) { - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - - CreateStreamTextureCHROMIUM cmd; - CreateStreamTextureCHROMIUM::Result* result = - static_cast<CreateStreamTextureCHROMIUM::Result*>(shared_memory_address_); - cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(static_cast<GLuint>(GL_ZERO), *result); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, CreateStreamTextureCHROMIUMAlreadySet) { - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - TextureRef* texture_ref = GetTexture(client_texture_id_); - group().texture_manager()->SetStreamTexture(texture_ref, true); - - CreateStreamTextureCHROMIUM cmd; - cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); -} - -TEST_F(GLES2DecoderManualInitTest, DrawStreamTextureCHROMIUM) { - InitDecoder( - "GL_CHROMIUM_stream_texture GL_OES_EGL_image_external", // extensions - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource - - StrictMock<MockStreamTexture> stream_texture; - - TextureRef* texture_ref = GetTexture(client_texture_id_); - group().texture_manager()->SetStreamTexture(texture_ref, true); - - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - SetupSamplerExternalProgram(); - SetupIndexBuffer(); - AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - EXPECT_TRUE(group().texture_manager()->CanRender(texture_ref)); - - InSequence s; - EXPECT_CALL(*stream_texture_manager(), LookupStreamTexture(kServiceTextureId)) - .WillOnce(Return(&stream_texture)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(stream_texture, Update()) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) - .Times(1); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); -} - -TEST_F(GLES2DecoderManualInitTest, BindStreamTextureCHROMIUMInvalid) { - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - TextureRef* texture_ref = GetTexture(client_texture_id_); - group().texture_manager()->SetStreamTexture(texture_ref, true); - - BindTexture cmd; - cmd.Init(GL_TEXTURE_2D, client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - BindTexture cmd2; - cmd2.Init(GL_TEXTURE_CUBE_MAP, client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd4)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); -} - -TEST_F(GLES2DecoderManualInitTest, DestroyStreamTextureCHROMIUM) { - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - TextureRef* texture_ref = GetTexture(client_texture_id_); - group().texture_manager()->SetStreamTexture(texture_ref, true); - - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); - - DestroyStreamTextureCHROMIUM cmd; - cmd.Init(client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_FALSE(texture_ref->texture()->IsStreamTexture()); - EXPECT_EQ(0U, texture_ref->texture()->target()); -} - -TEST_F(GLES2DecoderManualInitTest, DestroyStreamTextureCHROMIUMInvalid) { - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - DestroyStreamTextureCHROMIUM cmd; - cmd.Init(client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, DestroyStreamTextureCHROMIUMBadId) { - InitDecoder( - "GL_CHROMIUM_stream_texture", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - DestroyStreamTextureCHROMIUM cmd; - cmd.Init(GL_ZERO); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, StreamTextureCHROMIUMNullMgr) { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - CreateStreamTextureCHROMIUM cmd; - cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - GetGLError(); // ignore internal error - - TextureRef* texture_ref = GetTexture(client_texture_id_); - group().texture_manager()->SetStreamTexture(texture_ref, true); - - DestroyStreamTextureCHROMIUM cmd2; - cmd2.Init(client_texture_id_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd2)); - GetGLError(); // ignore internal error -} - -TEST_F(GLES2DecoderManualInitTest, ReCreateStreamTextureCHROMIUM) { - const GLuint kObjectId = 123; - InitDecoder( - "GL_CHROMIUM_stream_texture GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*stream_texture_manager(), - CreateStreamTexture(kServiceTextureId, client_texture_id_)) - .WillOnce(Return(kObjectId)) - .RetiresOnSaturation(); - - TextureRef* texture_ref = GetTexture(client_texture_id_); - group().texture_manager()->SetStreamTexture(texture_ref, true); - - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - DestroyStreamTextureCHROMIUM cmd; - cmd.Init(client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_FALSE(texture_ref->texture()->IsStreamTexture()); - - CreateStreamTextureCHROMIUM cmd2; - cmd2.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(texture_ref->texture()->IsStreamTexture()); - - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); } -TEST_F(GLES2DecoderManualInitTest, ProduceAndConsumeStreamTextureCHROMIUM) { - InitDecoder( - "GL_CHROMIUM_stream_texture GL_OES_EGL_image_external", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - TextureRef* texture_ref = GetTexture(client_texture_id_); - group().texture_manager()->SetStreamTexture(texture_ref, true); - - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); - - GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; - group().mailbox_manager()->GenerateMailboxName( - reinterpret_cast<MailboxName*>(mailbox)); - - memcpy(shared_memory_address_, mailbox, sizeof(mailbox)); - - EXPECT_EQ(kServiceTextureId, texture_ref->service_id()); - - ProduceTextureCHROMIUM produce_cmd; - produce_cmd.Init( - GL_TEXTURE_EXTERNAL_OES, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Create new texture for consume. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)) - .RetiresOnSaturation(); - DoBindTexture(GL_TEXTURE_EXTERNAL_OES, kNewClientId, kNewServiceId); - - // Assigns and binds original service size texture ID. - EXPECT_CALL(*gl_, DeleteTextures(1, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); - - // Shared mem got clobbered from GetError() above. - memcpy(shared_memory_address_, mailbox, sizeof(mailbox)); - ConsumeTextureCHROMIUM consume_cmd; - consume_cmd.Init( - GL_TEXTURE_EXTERNAL_OES, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(consume_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Service ID is restored. - EXPECT_EQ(kServiceTextureId, texture_ref->service_id()); - - EXPECT_CALL(*stream_texture_manager(), - DestroyStreamTexture(kServiceTextureId)) - .Times(1) - .RetiresOnSaturation(); -} - -TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleBindTexture) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_RECTANGLE_ARB, kNewServiceId)); - EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - BindTexture cmd; - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, kNewClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - Texture* texture = GetTexture(kNewClientId)->texture(); - EXPECT_TRUE(texture != NULL); - EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); -} - -TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleGetBinding) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindTexture( - GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - typedef GetIntegerv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, - result->GetData())) - .Times(0); - result->size = 0; - GetIntegerv cmd; - cmd.Init(GL_TEXTURE_BINDING_RECTANGLE_ARB, - shared_memory_id_, - shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_TEXTURE_BINDING_RECTANGLE_ARB), result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ(client_texture_id_, (uint32)result->GetData()[0]); -} - -TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureDefaults) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindTexture( - GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); - - Texture* texture = GetTexture(client_texture_id_)->texture(); - EXPECT_TRUE(texture != NULL); - EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); - EXPECT_TRUE(texture->min_filter() == GL_LINEAR); - EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); - EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); -} - -TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParam) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - DoBindTexture( - GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); - - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST)); - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_MIN_FILTER, - GL_LINEAR)); - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE)); - EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE)); - TexParameteri cmd; - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_MIN_FILTER, - GL_LINEAR); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - Texture* texture = GetTexture(client_texture_id_)->texture(); - EXPECT_TRUE(texture != NULL); - EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); - EXPECT_TRUE(texture->min_filter() == GL_LINEAR); - EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); - EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); -} - -TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParamInvalid) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - DoBindTexture( - GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); - - TexParameteri cmd; - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST_MIPMAP_NEAREST); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_WRAP_S, - GL_REPEAT); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - - cmd.Init(GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_WRAP_T, - GL_REPEAT); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); - - Texture* texture = GetTexture(client_texture_id_)->texture(); - EXPECT_TRUE(texture != NULL); - EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); - EXPECT_TRUE(texture->min_filter() == GL_LINEAR); - EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); - EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); -} - -TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTexImage2DError) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - GLenum target = GL_TEXTURE_RECTANGLE_ARB; - GLint level = 0; - GLenum internal_format = GL_RGBA; - GLsizei width = 2; - GLsizei height = 4; - GLint border = 0; - GLenum format = GL_RGBA; - GLenum type = GL_UNSIGNED_BYTE; - DoBindTexture( - GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); - ASSERT_TRUE(GetTexture(client_texture_id_) != NULL); - TexImage2D cmd; - cmd.Init(target, level, internal_format, width, height, border, format, - type, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - - // TexImage2D is not allowed with GL_TEXTURE_RECTANGLE_ARB targets. - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest, EnableFeatureCHROMIUMBadBucket) { +TEST_P(GLES2DecoderTest, EnableFeatureCHROMIUMBadBucket) { const uint32 kBadBucketId = 123; EnableFeatureCHROMIUM cmd; cmd.Init(kBadBucketId, shared_memory_id_, shared_memory_offset_); EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest, RequestExtensionCHROMIUMBadBucket) { +TEST_P(GLES2DecoderTest, RequestExtensionCHROMIUMBadBucket) { const uint32 kBadBucketId = 123; RequestExtensionCHROMIUM cmd; cmd.Init(kBadBucketId); EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest, TexSubImage2DClearsAfterTexImage2DNULL) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 2, 2); - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - TexSubImage2D cmd; - cmd.Init( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - // Test if we call it again it does not clear. - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, TexSubImage2DDoesNotClearAfterTexImage2DNULLThenData) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - TexSubImage2D cmd; - cmd.Init( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - // Test if we call it again it does not clear. - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F( - GLES2DecoderManualInitTest, - TexSubImage2DDoesNotClearAfterTexImage2DNULLThenDataWithTexImage2DIsFaster) { - CommandLine command_line(0, NULL); - command_line.AppendSwitchASCII( - switches::kGpuDriverBugWorkarounds, - base::IntToString(gpu::TEXSUBIMAGE2D_FASTER_THAN_TEXIMAGE2D)); - InitDecoderWithCommandLine( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true, // bind generates resource - &command_line); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - - { - // Uses texSubimage internally because the above workaround is active and - // the update is for the full size of the texture. - EXPECT_CALL(*gl_, - TexSubImage2D( - GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, _)) - .Times(1) - .RetiresOnSaturation(); - cmds::TexImage2D cmd; - cmd.Init(GL_TEXTURE_2D, - 0, - GL_RGBA, - 2, - 2, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - kSharedMemoryId, - kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } - - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - TexSubImage2D cmd; - cmd.Init( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - // Test if we call it again it does not clear. - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, TexSubImage2DClearsAfterTexImage2DWithDataThenNULL) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - // Put in data (so it should be marked as cleared) - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - // Put in no data. - TexImage2D tex_cmd; - tex_cmd.Init( - GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - // It won't actually call TexImage2D, just mark it as uncleared. - EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); - // Next call to TexSubImage2d should clear. - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 2, 2); - EXPECT_CALL(*gl_, TexSubImage2D( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - shared_memory_address_)) - .Times(1) - .RetiresOnSaturation(); - TexSubImage2D cmd; - cmd.Init( - GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawArraysClearsAfterTexImage2DNULL) { - SetupAllNeededVertexBuffers(); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - // Create an uncleared texture with 2 levels. - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - DoTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - // Expect 2 levels will be cleared. - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 2, 2); - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, 1); - SetupExpectationsForApplyingDefaultDirtyState(); - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // But not again - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawElementsClearsAfterTexImage2DNULL) { - SetupAllNeededVertexBuffers(); - SetupIndexBuffer(); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - // Create an uncleared texture with 2 levels. - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - DoTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - // Expect 2 levels will be cleared. - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 2, 2); - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, 1); - SetupExpectationsForApplyingDefaultDirtyState(); - - EXPECT_CALL(*gl_, DrawElements(GL_TRIANGLES, kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2))) - .Times(1) - .RetiresOnSaturation(); - DrawElements cmd; - cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, - kValidIndexRangeStart * 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // But not again - EXPECT_CALL(*gl_, DrawElements(GL_TRIANGLES, kValidIndexRangeCount, - GL_UNSIGNED_SHORT, - BufferOffset(kValidIndexRangeStart * 2))) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawClearsAfterTexImage2DNULLInFBO) { - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - SetupAllNeededVertexBuffers(); - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - // Setup "render from" texture. - SetupTexture(); - - SetupExpectationsForFramebufferClearing( - GL_FRAMEBUFFER, // target - GL_COLOR_BUFFER_BIT, // clear bits - 0, 0, 0, 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test - - SetupExpectationsForApplyingDirtyState( - false, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1111, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // But not again. - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawWitFBOThatCantClearDoesNotDraw) { - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - // Setup "render from" texture. - SetupTexture(); - - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_UNSUPPORTED)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DrawArrays(_, _, _)) - .Times(0) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, CopyTexImage2DMarksTextureAsCleared) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - - TextureManager* manager = group().texture_manager(); - TextureRef* texture_ref = manager->GetTexture(client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - CopyTexImage2D cmd; - cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - - EXPECT_TRUE(texture->SafeToRenderFrom()); -} - -TEST_F(GLES2DecoderTest, CopyTexSubImage2DClearsUnclearedTexture) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_2D, GL_TEXTURE_2D, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 2, 2); - EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)) - .Times(1) - .RetiresOnSaturation(); - CopyTexSubImage2D cmd; - cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderManualInitTest, CompressedImage2DMarksTextureAsCleared) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, CompressedTexImage2D( - GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 8, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - CompressedTexImage2D cmd; - cmd.Init(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, - 8, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - TextureManager* manager = group().texture_manager(); - TextureRef* texture_ref = manager->GetTexture(client_texture_id_); - EXPECT_TRUE(texture_ref->texture()->SafeToRenderFrom()); -} - -TEST_F(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnClear) { - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - // Setup "render from" texture. - SetupTexture(); - - SetupExpectationsForFramebufferClearing( - GL_FRAMEBUFFER, // target - GL_COLOR_BUFFER_BIT, // clear bits - 0, 0, 0, 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test - SetupExpectationsForApplyingDirtyState( - false, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1111, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, Clear(GL_COLOR_BUFFER_BIT)) - .Times(1) - .RetiresOnSaturation(); - - Clear cmd; - cmd.Init(GL_COLOR_BUFFER_BIT); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnReadPixels) { - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - // Setup "render from" texture. - SetupTexture(); - - SetupExpectationsForFramebufferClearing( - GL_FRAMEBUFFER, // target - GL_COLOR_BUFFER_BIT, // clear bits - 0, 0, 0, 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, _)) - .Times(1) - .RetiresOnSaturation(); - typedef ReadPixels::Result Result; - Result* result = GetSharedMemoryAs<Result*>(); - uint32 result_shm_id = kSharedMemoryId; - uint32 result_shm_offset = kSharedMemoryOffset; - uint32 pixels_shm_id = kSharedMemoryId; - uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); - ReadPixels cmd; - cmd.Init(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, - UnClearedAttachmentsGetClearedOnReadPixelsAndDrawBufferGetsRestored) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render from" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer( - GL_READ_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - SetupExpectationsForFramebufferClearingMulti( - kServiceFramebufferId, // read framebuffer service id - 0, // backbuffer service id - GL_READ_FRAMEBUFFER, // target - GL_COLOR_BUFFER_BIT, // clear bits - 0, 0, 0, 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test - - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, _)) - .Times(1) - .RetiresOnSaturation(); - typedef ReadPixels::Result Result; - uint32 result_shm_id = kSharedMemoryId; - uint32 result_shm_offset = kSharedMemoryOffset; - uint32 pixels_shm_id = kSharedMemoryId; - uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(Result); - ReadPixels cmd; - cmd.Init(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - pixels_shm_id, pixels_shm_offset, - result_shm_id, result_shm_offset, - false); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, DrawClearsAfterRenderbufferStorageInFBO) { - SetupTexture(); - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - DoRenderbufferStorage( - GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 100, 50, GL_NO_ERROR); - DoFramebufferRenderbuffer( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR); - - SetupExpectationsForFramebufferClearing( - GL_FRAMEBUFFER, // target - GL_COLOR_BUFFER_BIT, // clear bits - 0, 0, 0, 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test - - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - false, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1111, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, DrawArraysClearsAfterTexImage2DNULLCubemap) { - static const GLenum faces[] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - }; - SetupCubemapProgram(); - DoBindTexture(GL_TEXTURE_CUBE_MAP, client_texture_id_, kServiceTextureId); - // Fill out all the faces for 2 levels, leave 2 uncleared. - for (int ii = 0; ii < 6; ++ii) { - GLenum face = faces[ii]; - int32 shm_id = - (face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ? 0 : kSharedMemoryId; - uint32 shm_offset = - (face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ? 0 : kSharedMemoryOffset; - DoTexImage2D(face, 0, GL_RGBA, 2, 2, 0, GL_RGBA, - GL_UNSIGNED_BYTE, shm_id, shm_offset); - DoTexImage2D(face, 1, GL_RGBA, 1, 1, 0, GL_RGBA, - GL_UNSIGNED_BYTE, shm_id, shm_offset); - } - // Expect 2 levels will be cleared. - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_CUBE_MAP, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 2, 2); - SetupClearTextureExpections( - kServiceTextureId, kServiceTextureId, GL_TEXTURE_CUBE_MAP, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, 1); - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest, TextureUsageAngleExtNotEnabledByDefault) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - - TexParameteri cmd; - cmd.Init(GL_TEXTURE_2D, - GL_TEXTURE_USAGE_ANGLE, - GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, - DrawClearsAfterRenderbuffersWithMultipleAttachments) { - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - DoRenderbufferStorage( - GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, - 1, 1, GL_NO_ERROR); - DoFramebufferRenderbuffer( - GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR); - - SetupTexture(); - SetupExpectationsForFramebufferClearing( - GL_FRAMEBUFFER, // target - GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, // clear bits - 0, 0, 0, 0, // color - 0, // stencil - 1.0f, // depth - false); // scissor test - - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDirtyState( - false, // Framebuffer is RGB - true, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1111, // color bits - true, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, CopyTexImageWithInCompleteFBOFails) { - GLenum target = GL_TEXTURE_2D; - GLint level = 0; - GLenum internal_format = GL_RGBA; - GLsizei width = 2; - GLsizei height = 4; - GLint border = 0; - SetupTexture(); - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - DoRenderbufferStorage( - GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 0, 0, GL_NO_ERROR); - DoFramebufferRenderbuffer( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR); - - EXPECT_CALL(*gl_, CopyTexImage2D(_, _, _, _, _, _, _, _)) - .Times(0) - .RetiresOnSaturation(); - CopyTexImage2D cmd; - cmd.Init(target, level, internal_format, 0, 0, width, height, border); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, GetGLError()); -} - -void GLES2DecoderWithShaderTest::CheckRenderbufferChangesMarkFBOAsNotComplete( - bool bound_fbo) { - FramebufferManager* framebuffer_manager = group().framebuffer_manager(); - SetupTexture(); - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - DoRenderbufferStorage( - GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 1, 1, GL_NO_ERROR); - DoFramebufferRenderbuffer( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR); - - - if (!bound_fbo) { - DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); - } - - Framebuffer* framebuffer = - framebuffer_manager->GetFramebuffer(client_framebuffer_id_); - ASSERT_TRUE(framebuffer != NULL); - framebuffer_manager->MarkAsComplete(framebuffer); - EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); - - // Test that renderbufferStorage marks fbo as not complete. - DoRenderbufferStorage( - GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 1, 1, GL_NO_ERROR); - EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); - framebuffer_manager->MarkAsComplete(framebuffer); - EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); - - // Test deleting renderbuffer marks fbo as not complete. - DoDeleteRenderbuffer(client_renderbuffer_id_, kServiceRenderbufferId); - if (bound_fbo) { - EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); - } else { - EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); - } -} - -TEST_F(GLES2DecoderWithShaderTest, - RenderbufferChangesMarkFBOAsNotCompleteBoundFBO) { - CheckRenderbufferChangesMarkFBOAsNotComplete(true); -} - -TEST_F(GLES2DecoderWithShaderTest, - RenderbufferChangesMarkFBOAsNotCompleteUnboundFBO) { - CheckRenderbufferChangesMarkFBOAsNotComplete(false); -} - -void GLES2DecoderWithShaderTest::CheckTextureChangesMarkFBOAsNotComplete( - bool bound_fbo) { - FramebufferManager* framebuffer_manager = group().framebuffer_manager(); - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - SetupTexture(); - - // Setup "render to" texture. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - DoRenderbufferStorage( - GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, - 1, 1, GL_NO_ERROR); - DoFramebufferRenderbuffer( - GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR); - - if (!bound_fbo) { - DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); - } - - Framebuffer* framebuffer = - framebuffer_manager->GetFramebuffer(client_framebuffer_id_); - ASSERT_TRUE(framebuffer != NULL); - framebuffer_manager->MarkAsComplete(framebuffer); - EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); - - // Test TexImage2D marks fbo as not complete. - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, 0, 0); - EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); - framebuffer_manager->MarkAsComplete(framebuffer); - EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); - - // Test CopyImage2D marks fbo as not complete. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1, 1, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - CopyTexImage2D cmd; - cmd.Init(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1, 1, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); - - // Test deleting texture marks fbo as not complete. - framebuffer_manager->MarkAsComplete(framebuffer); - EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); - DoDeleteTexture(kFBOClientTextureId, kFBOServiceTextureId); - - if (bound_fbo) { - EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); - } else { - EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); - } -} - -TEST_F(GLES2DecoderWithShaderTest, TextureChangesMarkFBOAsNotCompleteBoundFBO) { - CheckTextureChangesMarkFBOAsNotComplete(true); -} - -TEST_F(GLES2DecoderWithShaderTest, - TextureChangesMarkFBOAsNotCompleteUnboundFBO) { - CheckTextureChangesMarkFBOAsNotComplete(false); -} - -TEST_F(GLES2DecoderWithShaderTest, - DrawingWithFBOTwiceChecksForFBOCompleteOnce) { - const GLuint kFBOClientTextureId = 4100; - const GLuint kFBOServiceTextureId = 4101; - - SetupAllNeededVertexBuffers(); - - // Register a texture id. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) - .RetiresOnSaturation(); - GenHelper<GenTexturesImmediate>(kFBOClientTextureId); - - // Setup "render to" texture that is cleared. - DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); - DoTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); - - // Setup "render from" texture. - SetupTexture(); - - // Make sure we check for framebuffer complete. - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - - SetupExpectationsForApplyingDirtyState( - false, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1111, // color bits - false, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled - - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // But not again. - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, BeginQueryEXTDisabled) { +TEST_P(GLES2DecoderTest, BeginQueryEXTDisabled) { // Test something fails if off. } -TEST_F(GLES2DecoderManualInitTest, BeginEndQueryEXT) { - InitDecoder( - "GL_EXT_occlusion_query_boolean", // extensions - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource +TEST_P(GLES2DecoderManualInitTest, BeginEndQueryEXT) { + InitState init; + init.extensions = "GL_EXT_occlusion_query_boolean"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); // Test end fails if no begin. EndQueryEXT end_cmd; @@ -7165,20 +603,35 @@ TEST_F(GLES2DecoderManualInitTest, BeginEndQueryEXT) { // Test valid parameters work. EXPECT_CALL(*gl_, GenQueriesARB(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)) - .RetiresOnSaturation(); + .WillOnce(SetArgumentPointee<1>(kNewServiceId)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, BeginQueryARB(GL_ANY_SAMPLES_PASSED_EXT, kNewServiceId)) .Times(1) .RetiresOnSaturation(); - begin_cmd.Init( - GL_ANY_SAMPLES_PASSED_EXT, kNewClientId, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); + // Query object should not be created untill BeginQueriesEXT. QueryManager* query_manager = decoder_->GetQueryManager(); ASSERT_TRUE(query_manager != NULL); QueryManager::Query* query = query_manager->GetQuery(kNewClientId); + EXPECT_TRUE(query == NULL); + + // BeginQueryEXT should fail if id is not generated from GenQueriesEXT. + begin_cmd.Init(GL_ANY_SAMPLES_PASSED_EXT, + kInvalidClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + begin_cmd.Init(GL_ANY_SAMPLES_PASSED_EXT, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // After BeginQueriesEXT id name should have query object associated with it. + query = query_manager->GetQuery(kNewClientId); ASSERT_TRUE(query != NULL); EXPECT_FALSE(query->pending()); @@ -7200,105 +653,150 @@ TEST_F(GLES2DecoderManualInitTest, BeginEndQueryEXT) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_TRUE(query->pending()); - EXPECT_CALL(*gl_, DeleteQueriesARB(1, _)) - .Times(1) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, DeleteQueriesARB(1, _)).Times(1).RetiresOnSaturation(); } -static void CheckBeginEndQueryBadMemoryFails( - GLES2DecoderTestBase* test, - GLuint client_id, - GLuint service_id, - int32 shm_id, - uint32 shm_offset) { +struct QueryType { + GLenum type; + bool is_gl; +}; + +const QueryType kQueryTypes[] = { + {GL_COMMANDS_ISSUED_CHROMIUM, false}, + {GL_LATENCY_QUERY_CHROMIUM, false}, + {GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, false}, + {GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, false}, + {GL_GET_ERROR_QUERY_CHROMIUM, false}, + {GL_COMMANDS_COMPLETED_CHROMIUM, false}, + {GL_ANY_SAMPLES_PASSED_EXT, true}, +}; + +static void CheckBeginEndQueryBadMemoryFails(GLES2DecoderTestBase* test, + GLuint client_id, + GLuint service_id, + const QueryType& query_type, + int32 shm_id, + uint32 shm_offset) { + // We need to reset the decoder on each iteration, because we lose the + // context every time. + GLES2DecoderTestBase::InitState init; + init.extensions = "GL_EXT_occlusion_query_boolean GL_ARB_sync"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + test->InitDecoder(init); ::testing::StrictMock< ::gfx::MockGLInterface>* gl = test->GetGLMock(); BeginQueryEXT begin_cmd; test->GenHelper<GenQueriesEXTImmediate>(client_id); - EXPECT_CALL(*gl, GenQueriesARB(1, _)) - .WillOnce(SetArgumentPointee<1>(service_id)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, BeginQueryARB(GL_ANY_SAMPLES_PASSED_EXT, service_id)) - .Times(1) - .RetiresOnSaturation(); + if (query_type.is_gl) { + EXPECT_CALL(*gl, GenQueriesARB(1, _)) + .WillOnce(SetArgumentPointee<1>(service_id)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, BeginQueryARB(query_type.type, service_id)) + .Times(1) + .RetiresOnSaturation(); + } // Test bad shared memory fails - begin_cmd.Init(GL_ANY_SAMPLES_PASSED_EXT, client_id, shm_id, shm_offset); + begin_cmd.Init(query_type.type, client_id, shm_id, shm_offset); error::Error error1 = test->ExecuteCmd(begin_cmd); - EXPECT_CALL(*gl, EndQueryARB(GL_ANY_SAMPLES_PASSED_EXT)) - .Times(1) - .RetiresOnSaturation(); + if (query_type.is_gl) { + EXPECT_CALL(*gl, EndQueryARB(query_type.type)) + .Times(1) + .RetiresOnSaturation(); + } + if (query_type.type == GL_GET_ERROR_QUERY_CHROMIUM) { + EXPECT_CALL(*gl, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + } + GLsync kGlSync = reinterpret_cast<GLsync>(0xdeadbeef); + if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) { + EXPECT_CALL(*gl, Flush()).RetiresOnSaturation(); + EXPECT_CALL(*gl, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) + .WillOnce(Return(kGlSync)) + .RetiresOnSaturation(); + } EndQueryEXT end_cmd; - end_cmd.Init(GL_ANY_SAMPLES_PASSED_EXT, 1); + end_cmd.Init(query_type.type, 1); error::Error error2 = test->ExecuteCmd(end_cmd); - EXPECT_CALL(*gl, - GetQueryObjectuivARB(service_id, GL_QUERY_RESULT_AVAILABLE_EXT, _)) - .WillOnce(SetArgumentPointee<2>(1)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, - GetQueryObjectuivARB(service_id, GL_QUERY_RESULT_EXT, _)) - .WillOnce(SetArgumentPointee<2>(1)) - .RetiresOnSaturation(); + if (query_type.is_gl) { + EXPECT_CALL( + *gl, GetQueryObjectuivARB(service_id, GL_QUERY_RESULT_AVAILABLE_EXT, _)) + .WillOnce(SetArgumentPointee<2>(1)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetQueryObjectuivARB(service_id, GL_QUERY_RESULT_EXT, _)) + .WillOnce(SetArgumentPointee<2>(1)) + .RetiresOnSaturation(); + } + if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) { + EXPECT_CALL(*gl, ClientWaitSync(kGlSync, _, _)) + .WillOnce(Return(GL_ALREADY_SIGNALED)) + .RetiresOnSaturation(); + } QueryManager* query_manager = test->GetDecoder()->GetQueryManager(); ASSERT_TRUE(query_manager != NULL); bool process_success = query_manager->ProcessPendingQueries(); - EXPECT_TRUE(error1 != error::kNoError || - error2 != error::kNoError || + EXPECT_TRUE(error1 != error::kNoError || error2 != error::kNoError || !process_success); - EXPECT_CALL(*gl, DeleteQueriesARB(1, _)) - .Times(1) - .RetiresOnSaturation(); + if (query_type.is_gl) { + EXPECT_CALL(*gl, DeleteQueriesARB(1, _)).Times(1).RetiresOnSaturation(); + } + if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) + EXPECT_CALL(*gl, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation(); + test->ResetDecoder(); } -TEST_F(GLES2DecoderManualInitTest, BeginEndQueryEXTBadMemoryIdFails) { - InitDecoder( - "GL_EXT_occlusion_query_boolean", // extensions - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - CheckBeginEndQueryBadMemoryFails( - this, kNewClientId, kNewServiceId, - kInvalidSharedMemoryId, kSharedMemoryOffset); +TEST_P(GLES2DecoderManualInitTest, BeginEndQueryEXTBadMemoryIdFails) { + for (size_t i = 0; i < arraysize(kQueryTypes); ++i) { + CheckBeginEndQueryBadMemoryFails(this, + kNewClientId, + kNewServiceId, + kQueryTypes[i], + kInvalidSharedMemoryId, + kSharedMemoryOffset); + } } -TEST_F(GLES2DecoderManualInitTest, BeginEndQueryEXTBadMemoryOffsetFails) { - InitDecoder( - "GL_EXT_occlusion_query_boolean", // extensions - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - - CheckBeginEndQueryBadMemoryFails( - this, kNewClientId, kNewServiceId, - kSharedMemoryId, kInvalidSharedMemoryOffset); +TEST_P(GLES2DecoderManualInitTest, BeginEndQueryEXTBadMemoryOffsetFails) { + for (size_t i = 0; i < arraysize(kQueryTypes); ++i) { + // Out-of-bounds. + CheckBeginEndQueryBadMemoryFails(this, + kNewClientId, + kNewServiceId, + kQueryTypes[i], + kSharedMemoryId, + kInvalidSharedMemoryOffset); + // Overflow. + CheckBeginEndQueryBadMemoryFails(this, + kNewClientId, + kNewServiceId, + kQueryTypes[i], + kSharedMemoryId, + 0xfffffffcu); + } } -TEST_F(GLES2DecoderTest, BeginEndQueryEXTCommandsIssuedCHROMIUM) { +TEST_P(GLES2DecoderTest, BeginEndQueryEXTCommandsIssuedCHROMIUM) { BeginQueryEXT begin_cmd; GenHelper<GenQueriesEXTImmediate>(kNewClientId); // Test valid parameters work. - begin_cmd.Init( - GL_COMMANDS_ISSUED_CHROMIUM, kNewClientId, - kSharedMemoryId, kSharedMemoryOffset); + begin_cmd.Init(GL_COMMANDS_ISSUED_CHROMIUM, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); @@ -7316,15 +814,16 @@ TEST_F(GLES2DecoderTest, BeginEndQueryEXTCommandsIssuedCHROMIUM) { EXPECT_FALSE(query->pending()); } -TEST_F(GLES2DecoderTest, BeginEndQueryEXTGetErrorQueryCHROMIUM) { +TEST_P(GLES2DecoderTest, BeginEndQueryEXTGetErrorQueryCHROMIUM) { BeginQueryEXT begin_cmd; GenHelper<GenQueriesEXTImmediate>(kNewClientId); // Test valid parameters work. - begin_cmd.Init( - GL_GET_ERROR_QUERY_CHROMIUM, kNewClientId, - kSharedMemoryId, kSharedMemoryOffset); + begin_cmd.Init(GL_GET_ERROR_QUERY_CHROMIUM, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); @@ -7350,107 +849,70 @@ TEST_F(GLES2DecoderTest, BeginEndQueryEXTGetErrorQueryCHROMIUM) { static_cast<GLenum>(sync->result)); } -TEST_F(GLES2DecoderTest, ProduceAndConsumeTextureCHROMIUM) { - GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; - group().mailbox_manager()->GenerateMailboxName( - reinterpret_cast<MailboxName*>(mailbox)); +TEST_P(GLES2DecoderManualInitTest, BeginEndQueryEXTCommandsCompletedCHROMIUM) { + InitState init; + init.extensions = "GL_EXT_occlusion_query_boolean GL_ARB_sync"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); - memcpy(shared_memory_address_, mailbox, sizeof(mailbox)); + GenHelper<GenQueriesEXTImmediate>(kNewClientId); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - DoTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - TextureRef* texture_ref = group().texture_manager()->GetTexture( - client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_EQ(kServiceTextureId, texture->service_id()); - - ProduceTextureCHROMIUM produce_cmd; - produce_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd)); + BeginQueryEXT begin_cmd; + begin_cmd.Init(GL_COMMANDS_COMPLETED_CHROMIUM, + kNewClientId, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - // Texture didn't change. - GLsizei width; - GLsizei height; - GLenum type; - GLenum internal_format; - - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - EXPECT_EQ(3, width); - EXPECT_EQ(1, height); - EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); - EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); - EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); - - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); - EXPECT_EQ(2, width); - EXPECT_EQ(4, height); - EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); - EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); - EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); - - // Service ID has not changed. - EXPECT_EQ(kServiceTextureId, texture->service_id()); - - // Create new texture for consume. - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)) - .RetiresOnSaturation(); - DoBindTexture(GL_TEXTURE_2D, kNewClientId, kNewServiceId); + QueryManager* query_manager = decoder_->GetQueryManager(); + ASSERT_TRUE(query_manager != NULL); + QueryManager::Query* query = query_manager->GetQuery(kNewClientId); + ASSERT_TRUE(query != NULL); + EXPECT_FALSE(query->pending()); - // Assigns and binds original service size texture ID. - EXPECT_CALL(*gl_, DeleteTextures(1, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) - .Times(1) + GLsync kGlSync = reinterpret_cast<GLsync>(0xdeadbeef); + EXPECT_CALL(*gl_, Flush()).RetiresOnSaturation(); + EXPECT_CALL(*gl_, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) + .WillOnce(Return(kGlSync)) .RetiresOnSaturation(); - memcpy(shared_memory_address_, mailbox, sizeof(mailbox)); - ConsumeTextureCHROMIUM consume_cmd; - consume_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(consume_cmd)); + EndQueryEXT end_cmd; + end_cmd.Init(GL_COMMANDS_COMPLETED_CHROMIUM, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(end_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(query->pending()); - // Texture is redefined. - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - EXPECT_EQ(3, width); - EXPECT_EQ(1, height); - EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); - EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); - EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); - - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); - EXPECT_EQ(2, width); - EXPECT_EQ(4, height); - EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); - EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); - EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); - - // Service ID is restored. - EXPECT_EQ(kServiceTextureId, texture->service_id()); -} + EXPECT_CALL(*gl_, ClientWaitSync(kGlSync, _, _)) + .WillOnce(Return(GL_TIMEOUT_EXPIRED)) + .RetiresOnSaturation(); + bool process_success = query_manager->ProcessPendingQueries(); + EXPECT_TRUE(process_success); + EXPECT_TRUE(query->pending()); + + EXPECT_CALL(*gl_, ClientWaitSync(kGlSync, _, _)) + .WillOnce(Return(GL_ALREADY_SIGNALED)) + .RetiresOnSaturation(); + process_success = query_manager->ProcessPendingQueries(); -TEST_F(GLES2DecoderTest, CanChangeSurface) { - scoped_refptr<GLSurfaceMock> other_surface(new GLSurfaceMock); - EXPECT_CALL(*other_surface.get(), GetBackingFrameBufferObject()). - WillOnce(Return(7)); - EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 7)); + EXPECT_TRUE(process_success); + EXPECT_FALSE(query->pending()); + QuerySync* sync = static_cast<QuerySync*>(shared_memory_address_); + EXPECT_EQ(static_cast<GLenum>(0), static_cast<GLenum>(sync->result)); - decoder_->SetSurface(other_surface); + EXPECT_CALL(*gl_, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation(); + ResetDecoder(); } -TEST_F(GLES2DecoderTest, IsEnabledReturnsCachedValue) { +TEST_P(GLES2DecoderTest, IsEnabledReturnsCachedValue) { // NOTE: There are no expectations because no GL functions should be // called for DEPTH_TEST or STENCIL_TEST static const GLenum kStates[] = { - GL_DEPTH_TEST, - GL_STENCIL_TEST, + GL_DEPTH_TEST, GL_STENCIL_TEST, }; for (size_t ii = 0; ii < arraysize(kStates); ++ii) { Enable enable_cmd; @@ -7471,732 +933,18 @@ TEST_F(GLES2DecoderTest, IsEnabledReturnsCachedValue) { } } -TEST_F(GLES2DecoderManualInitTest, DepthTextureBadArgs) { - InitDecoder( - "GL_ANGLE_depth_texture", // extensions - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - true, // request stencil - true); // bind generates resource - - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - // Check trying to upload data fails. - TexImage2D tex_cmd; - tex_cmd.Init( - GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, - 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - kSharedMemoryId, kSharedMemoryOffset); - EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - // Try level > 0. - tex_cmd.Init( - GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT, - 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - // Make a 1 pixel depth texture. - DoTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, - 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 0); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // Check that trying to update it fails. - TexSubImage2D tex_sub_cmd; - tex_sub_cmd.Init( - GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); - EXPECT_EQ(error::kNoError, ExecuteCmd(tex_sub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Check that trying to CopyTexImage2D fails - CopyTexImage2D copy_tex_cmd; - copy_tex_cmd.Init(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 1, 1, 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(copy_tex_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - - // Check that trying to CopyTexSubImage2D fails - CopyTexSubImage2D copy_sub_cmd; - copy_sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(copy_sub_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, GenerateMipmapDepthTexture) { - InitDecoder( - "GL_ANGLE_depth_texture", // extensions - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - true, // request stencil - true); // bind generates resource - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, - 2, 2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - 0, 0); - GenerateMipmap cmd; - cmd.Init(GL_TEXTURE_2D); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, DrawClearsDepthTexture) { - InitDecoder( - "GL_ANGLE_depth_texture", // extensions - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource - - SetupDefaultProgram(); - SetupAllNeededVertexBuffers(); - const GLenum attachment = GL_DEPTH_ATTACHMENT; - const GLenum target = GL_TEXTURE_2D; - const GLint level = 0; - DoBindTexture(target, client_texture_id_, kServiceTextureId); - - // Create a depth texture. - DoTexImage2D(target, level, GL_DEPTH_COMPONENT, 1, 1, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 0); - - EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _)) - .Times(1) - .RetiresOnSaturation(); - - EXPECT_CALL(*gl_, FramebufferTexture2DEXT( - GL_DRAW_FRAMEBUFFER_EXT, attachment, target, kServiceTextureId, level)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT)) - .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) - .RetiresOnSaturation(); - - EXPECT_CALL(*gl_, ClearStencil(0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, StencilMask(-1)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ClearDepth(1.0f)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthMask(true)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST)) - .Times(1) - .RetiresOnSaturation(); - - EXPECT_CALL(*gl_, Clear(GL_DEPTH_BUFFER_BIT)) - .Times(1) - .RetiresOnSaturation(); - - SetupExpectationsForRestoreClearState( - 0.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, false); - - EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0)) - .Times(1) - .RetiresOnSaturation(); - - SetupExpectationsForApplyingDefaultDirtyState(); - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderWithShaderTest, BindUniformLocationCHROMIUM) { - const GLint kLocation = 2; - const char* kName = "testing"; - const uint32 kNameSize = strlen(kName); - const char* kBadName1 = "gl_testing"; - const uint32 kBadName1Size = strlen(kBadName1); - const char* kBadName2 = "testing[1]"; - const uint32 kBadName2Size = strlen(kBadName2); - memcpy(shared_memory_address_, kName, kNameSize); - BindUniformLocationCHROMIUM cmd; - cmd.Init(client_program_id_, kLocation, kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - // check negative location - memcpy(shared_memory_address_, kName, kNameSize); - cmd.Init(client_program_id_, -1, kSharedMemoryId, kSharedMemoryOffset, - kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - // check highest location - memcpy(shared_memory_address_, kName, kNameSize); - GLint kMaxLocation = - (kMaxFragmentUniformVectors + kMaxVertexUniformVectors) * 4 - 1; - cmd.Init(client_program_id_, kMaxLocation, kSharedMemoryId, - kSharedMemoryOffset, kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - // check too high location - memcpy(shared_memory_address_, kName, kNameSize); - cmd.Init(client_program_id_, kMaxLocation + 1, kSharedMemoryId, - kSharedMemoryOffset, kNameSize); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); - // check bad name "gl_..." - memcpy(shared_memory_address_, kBadName1, kBadName1Size); - cmd.Init(client_program_id_, kLocation, kSharedMemoryId, kSharedMemoryOffset, - kBadName1Size); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - // check bad name "name[1]" non zero - memcpy(shared_memory_address_, kBadName2, kBadName2Size); - cmd.Init(client_program_id_, kLocation, kSharedMemoryId, kSharedMemoryOffset, - kBadName2Size); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -class GLES2DecoderVertexArraysOESTest : public GLES2DecoderWithShaderTest { - public: - GLES2DecoderVertexArraysOESTest() { } - - bool vertex_array_deleted_manually_; - - virtual void SetUp() { - InitDecoder( - "GL_OES_vertex_array_object", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - SetupDefaultProgram(); - - AddExpectationsForGenVertexArraysOES(); - GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_); - - vertex_array_deleted_manually_ = false; - } - - virtual void TearDown() { - // This should only be set if the test handled deletion of the vertex array - // itself. Necessary because vertex_array_objects are not sharable, and thus - // not managed in the ContextGroup, meaning they will be destroyed during - // test tear down - if (!vertex_array_deleted_manually_) { - AddExpectationsForDeleteVertexArraysOES(); - } - - GLES2DecoderWithShaderTest::TearDown(); - } - - void GenVertexArraysOESValidArgs() { - AddExpectationsForGenVertexArraysOES(); - GetSharedMemoryAs<GLuint*>()[0] = kNewClientId; - GenVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL); - AddExpectationsForDeleteVertexArraysOES(); - } - - void GenVertexArraysOESInvalidArgs() { - EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0); - GetSharedMemoryAs<GLuint*>()[0] = client_vertexarray_id_; - GenVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - } - - void GenVertexArraysOESImmediateValidArgs() { - AddExpectationsForGenVertexArraysOES(); - GenVertexArraysOESImmediate* cmd = - GetImmediateAs<GenVertexArraysOESImmediate>(); - GLuint temp = kNewClientId; - cmd->Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(*cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL); - AddExpectationsForDeleteVertexArraysOES(); - } - - void GenVertexArraysOESImmediateInvalidArgs() { - EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0); - GenVertexArraysOESImmediate* cmd = - GetImmediateAs<GenVertexArraysOESImmediate>(); - cmd->Init(1, &client_vertexarray_id_); - EXPECT_EQ(error::kInvalidArguments, - ExecuteImmediateCmd(*cmd, sizeof(&client_vertexarray_id_))); - } - - void DeleteVertexArraysOESValidArgs() { - AddExpectationsForDeleteVertexArraysOES(); - GetSharedMemoryAs<GLuint*>()[0] = client_vertexarray_id_; - DeleteVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetVertexArrayInfo(client_vertexarray_id_) == NULL); - vertex_array_deleted_manually_ = true; - } - - void DeleteVertexArraysOESInvalidArgs() { - GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId; - DeleteVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } - - void DeleteVertexArraysOESImmediateValidArgs() { - AddExpectationsForDeleteVertexArraysOES(); - DeleteVertexArraysOESImmediate& cmd = - *GetImmediateAs<DeleteVertexArraysOESImmediate>(); - cmd.Init(1, &client_vertexarray_id_); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(client_vertexarray_id_))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetVertexArrayInfo(client_vertexarray_id_) == NULL); - vertex_array_deleted_manually_ = true; - } - - void DeleteVertexArraysOESImmediateInvalidArgs() { - DeleteVertexArraysOESImmediate& cmd = - *GetImmediateAs<DeleteVertexArraysOESImmediate>(); - GLuint temp = kInvalidClientId; - cmd.Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); - } - - void IsVertexArrayOESValidArgs() { - IsVertexArrayOES cmd; - cmd.Init(client_vertexarray_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - } - - void IsVertexArrayOESInvalidArgsBadSharedMemoryId() { - IsVertexArrayOES cmd; - cmd.Init( - client_vertexarray_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init( - client_vertexarray_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - } - - void BindVertexArrayOESValidArgs() { - AddExpectationsForBindVertexArrayOES(); - BindVertexArrayOES cmd; - cmd.Init(client_vertexarray_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - } - - void BindVertexArrayOESValidArgsNewId() { - BindVertexArrayOES cmd; - cmd.Init(kNewClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - } -}; - -class GLES2DecoderEmulatedVertexArraysOESTest - : public GLES2DecoderVertexArraysOESTest { - public: - GLES2DecoderEmulatedVertexArraysOESTest() { } - - virtual void SetUp() { - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - SetupDefaultProgram(); - - AddExpectationsForGenVertexArraysOES(); - GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_); - - vertex_array_deleted_manually_ = false; - } -}; - -// Test vertex array objects with native support -TEST_F(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESValidArgs) { - GenVertexArraysOESValidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, GenVertexArraysOESValidArgs) { - GenVertexArraysOESValidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESInvalidArgs) { - GenVertexArraysOESInvalidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, ) { - GenVertexArraysOESInvalidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESImmediateValidArgs) { - GenVertexArraysOESImmediateValidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - GenVertexArraysOESImmediateValidArgs) { - GenVertexArraysOESImmediateValidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, - GenVertexArraysOESImmediateInvalidArgs) { - GenVertexArraysOESImmediateInvalidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - GenVertexArraysOESImmediateInvalidArgs) { - GenVertexArraysOESImmediateInvalidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, DeleteVertexArraysOESValidArgs) { - DeleteVertexArraysOESValidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - DeleteVertexArraysOESValidArgs) { - DeleteVertexArraysOESValidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, DeleteVertexArraysOESInvalidArgs) { - DeleteVertexArraysOESInvalidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - DeleteVertexArraysOESInvalidArgs) { - DeleteVertexArraysOESInvalidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, - DeleteVertexArraysOESImmediateValidArgs) { - DeleteVertexArraysOESImmediateValidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - DeleteVertexArraysOESImmediateValidArgs) { - DeleteVertexArraysOESImmediateValidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, - DeleteVertexArraysOESImmediateInvalidArgs) { - DeleteVertexArraysOESImmediateInvalidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - DeleteVertexArraysOESImmediateInvalidArgs) { - DeleteVertexArraysOESImmediateInvalidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, IsVertexArrayOESValidArgs) { - IsVertexArrayOESValidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, IsVertexArrayOESValidArgs) { - IsVertexArrayOESValidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, - IsVertexArrayOESInvalidArgsBadSharedMemoryId) { - IsVertexArrayOESInvalidArgsBadSharedMemoryId(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - IsVertexArrayOESInvalidArgsBadSharedMemoryId) { - IsVertexArrayOESInvalidArgsBadSharedMemoryId(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgs) { - BindVertexArrayOESValidArgs(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, BindVertexArrayOESValidArgs) { - BindVertexArrayOESValidArgs(); -} - -TEST_F(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgsNewId) { - BindVertexArrayOESValidArgsNewId(); -} -TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, - BindVertexArrayOESValidArgsNewId) { - BindVertexArrayOESValidArgsNewId(); -} - -TEST_F(GLES2DecoderTest, BindTexImage2DCHROMIUM) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - TextureRef* texture_ref = group().texture_manager()->GetTexture( - client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_EQ(kServiceTextureId, texture->service_id()); - - group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0).get(), 1); - EXPECT_FALSE(group().image_manager()->LookupImage(1) == NULL); - - GLsizei width; - GLsizei height; - GLenum type; - GLenum internal_format; - - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - EXPECT_EQ(3, width); - EXPECT_EQ(1, height); - EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); - EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); - EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); - EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); - - // Bind image to texture. - // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; - bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - // Image should now be set. - EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); - - // Define new texture image. - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - // Image should no longer be set. - EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); -} - -TEST_F(GLES2DecoderTest, ReleaseTexImage2DCHROMIUM) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - 0, 0); - TextureRef* texture_ref = group().texture_manager()->GetTexture( - client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_EQ(kServiceTextureId, texture->service_id()); - - group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0).get(), 1); - EXPECT_FALSE(group().image_manager()->LookupImage(1) == NULL); - - GLsizei width; - GLsizei height; - GLenum type; - GLenum internal_format; - - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - EXPECT_EQ(3, width); - EXPECT_EQ(1, height); - EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); - EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); - EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); - EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); - - // Bind image to texture. - // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; - bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - // Image should now be set. - EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); - - // Release image from texture. - // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - ReleaseTexImage2DCHROMIUM release_tex_image_2d_cmd; - release_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(release_tex_image_2d_cmd)); - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - // Image should no longer be set. - EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); -} - -class MockGLImage : public gfx::GLImage { - public: - MockGLImage() {} - - // Overridden from gfx::GLImage: - MOCK_METHOD0(Destroy, void()); - MOCK_METHOD0(GetSize, gfx::Size()); - MOCK_METHOD1(BindTexImage, bool(unsigned)); - MOCK_METHOD1(ReleaseTexImage, void(unsigned)); - MOCK_METHOD0(WillUseTexImage, void()); - MOCK_METHOD0(DidUseTexImage, void()); - - protected: - virtual ~MockGLImage() {} -}; - -TEST_F(GLES2DecoderWithShaderTest, UseTexImage) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); - - TextureRef* texture_ref = group().texture_manager()->GetTexture( - client_texture_id_); - ASSERT_TRUE(texture_ref != NULL); - Texture* texture = texture_ref->texture(); - EXPECT_EQ(kServiceTextureId, texture->service_id()); - - const int32 kImageId = 1; - scoped_refptr<MockGLImage> image(new MockGLImage); - group().image_manager()->AddImage(image.get(), kImageId); - - // Bind image to texture. - EXPECT_CALL(*image, BindTexImage(GL_TEXTURE_2D)) - .Times(1) - .WillOnce(Return(true)) - .RetiresOnSaturation(); - EXPECT_CALL(*image, GetSize()) - .Times(1) - .WillOnce(Return(gfx::Size(1, 1))) - .RetiresOnSaturation(); - // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; - bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, kImageId); - EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); - - AddExpectationsForSimulatedAttrib0(kNumVertices, 0); - SetupExpectationsForApplyingDefaultDirtyState(); - - // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) - .Times(3) - .RetiresOnSaturation(); - EXPECT_CALL(*image, WillUseTexImage()) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*image, DidUseTexImage()) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kNumVertices); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) - .Times(2) - .RetiresOnSaturation(); - // Image will be 'in use' as long as bound to a framebuffer. - EXPECT_CALL(*image, WillUseTexImage()) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferTexture2DEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kServiceTextureId, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - FramebufferTexture2D fbtex_cmd; - fbtex_cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_, - 0); - EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - kServiceRenderbufferId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) - .Times(2) - .RetiresOnSaturation(); - // Image should no longer be 'in use' after being unbound from framebuffer. - EXPECT_CALL(*image, DidUseTexImage()) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - FramebufferRenderbuffer fbrb_cmd; - fbrb_cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); -} - -TEST_F(GLES2DecoderManualInitTest, GpuMemoryManagerCHROMIUM) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource +TEST_P(GLES2DecoderManualInitTest, GpuMemoryManagerCHROMIUM) { + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); Texture* texture = GetTexture(client_texture_id_)->texture(); EXPECT_TRUE(texture != NULL); EXPECT_TRUE(texture->pool() == GL_TEXTURE_POOL_UNMANAGED_CHROMIUM); - DoBindTexture( - GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); TexParameteri cmd; cmd.Init(GL_TEXTURE_2D, @@ -8213,258 +961,11 @@ TEST_F(GLES2DecoderManualInitTest, GpuMemoryManagerCHROMIUM) { EXPECT_TRUE(texture->pool() == GL_TEXTURE_POOL_MANAGED_CHROMIUM); - cmd.Init(GL_TEXTURE_2D, - GL_TEXTURE_POOL_CHROMIUM, - GL_NONE); + cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_POOL_CHROMIUM, GL_NONE); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) { - InitDecoder( - "GL_CHROMIUM_async_pixel_transfers", // extensions - false, false, false, // has alpha/depth/stencil - false, false, false, // request alpha/depth/stencil - true); // bind generates resource - - // Set up the texture. - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - TextureRef* texture_ref = GetTexture(client_texture_id_); - Texture* texture = texture_ref->texture(); - - // Set a mock Async delegate - StrictMock<gpu::MockAsyncPixelTransferManager>* manager = - new StrictMock<gpu::MockAsyncPixelTransferManager>; - manager->Initialize(group().texture_manager()); - decoder_->SetAsyncPixelTransferManagerForTest(manager); - StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate = NULL; - - // Tex(Sub)Image2D upload commands. - AsyncTexImage2DCHROMIUM teximage_cmd; - teximage_cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, - GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); - AsyncTexSubImage2DCHROMIUM texsubimage_cmd; - texsubimage_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, - GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); - WaitAsyncTexImage2DCHROMIUM wait_cmd; - wait_cmd.Init(GL_TEXTURE_2D); - - // No transfer state exists initially. - EXPECT_FALSE( - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - - base::Closure bind_callback; - - // AsyncTexImage2D - { - // Create transfer state since it doesn't exist. - EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) - .WillOnce(Return( - delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) - .RetiresOnSaturation(); - EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)) - .WillOnce(SaveArg<2>(&bind_callback)) - .RetiresOnSaturation(); - // Command succeeds. - EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ( - delegate, - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - EXPECT_TRUE(texture->IsImmutable()); - // The texture is safe but the level has not been defined yet. - EXPECT_TRUE(texture->SafeToRenderFrom()); - GLsizei width, height; - EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - } - { - // Async redefinitions are not allowed! - // Command fails. - EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ( - delegate, - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - EXPECT_TRUE(texture->IsImmutable()); - EXPECT_TRUE(texture->SafeToRenderFrom()); - } - - // Binding/defining of the async transfer - { - // TODO(epenner): We should check that the manager gets the - // BindCompletedAsyncTransfers() call, which is required to - // guarantee the delegate calls the bind callback. - - // Simulate the bind callback from the delegate. - bind_callback.Run(); - - // After the bind callback is run, the texture is safe, - // and has the right size etc. - EXPECT_TRUE(texture->SafeToRenderFrom()); - GLsizei width, height; - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - EXPECT_EQ(width, 8); - EXPECT_EQ(height, 8); - } - - // AsyncTexSubImage2D - decoder_->GetAsyncPixelTransferManager() - ->ClearPixelTransferDelegateForTest(texture_ref); - texture->SetImmutable(false); - { - // Create transfer state since it doesn't exist. - EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) - .WillOnce(Return( - delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) - .RetiresOnSaturation(); - EXPECT_CALL(*delegate, AsyncTexSubImage2D(_, _)) - .RetiresOnSaturation(); - // Command succeeds. - EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ( - delegate, - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - EXPECT_TRUE(texture->IsImmutable()); - EXPECT_TRUE(texture->SafeToRenderFrom()); - } - { - // No transfer is in progress. - EXPECT_CALL(*delegate, TransferIsInProgress()) - .WillOnce(Return(false)) // texSubImage validation - .WillOnce(Return(false)) // async validation - .RetiresOnSaturation(); - EXPECT_CALL(*delegate, AsyncTexSubImage2D(_, _)) - .RetiresOnSaturation(); - // Command succeeds. - EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ( - delegate, - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - EXPECT_TRUE(texture->IsImmutable()); - EXPECT_TRUE(texture->SafeToRenderFrom()); - } - { - // A transfer is still in progress! - EXPECT_CALL(*delegate, TransferIsInProgress()) - .WillOnce(Return(true)) - .RetiresOnSaturation(); - // No async call, command fails. - EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); - EXPECT_EQ( - delegate, - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - EXPECT_TRUE(texture->IsImmutable()); - EXPECT_TRUE(texture->SafeToRenderFrom()); - } - - // Delete delegate on DeleteTexture. - { - EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); - DoDeleteTexture(client_texture_id_, kServiceTextureId); - EXPECT_FALSE( - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - delegate = NULL; - } - - // WaitAsyncTexImage2D - { - // Get a fresh texture since the existing texture cannot be respecified - // asynchronously and AsyncTexSubImage2D does not involved binding. - EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kServiceTextureId)); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - texture_ref = GetTexture(client_texture_id_); - texture = texture_ref->texture(); - texture->SetImmutable(false); - // Create transfer state since it doesn't exist. - EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) - .WillOnce(Return( - delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) - .RetiresOnSaturation(); - EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)) - .RetiresOnSaturation(); - // Start async transfer. - EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_EQ( - delegate, - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - - EXPECT_TRUE(texture->IsImmutable()); - // Wait for completion. - EXPECT_CALL(*delegate, WaitForTransferCompletion()); - EXPECT_CALL(*manager, BindCompletedAsyncTransfers()); - EXPECT_EQ(error::kNoError, ExecuteCmd(wait_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - } -} - -TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransferManager) { - InitDecoder( - "GL_CHROMIUM_async_pixel_transfers", // extensions - false, false, false, // has alpha/depth/stencil - false, false, false, // request alpha/depth/stencil - true); // bind generates resource - - // Set up the texture. - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - TextureRef* texture_ref = GetTexture(client_texture_id_); - - // Set a mock Async delegate. - StrictMock<gpu::MockAsyncPixelTransferManager>* manager = - new StrictMock<gpu::MockAsyncPixelTransferManager>; - manager->Initialize(group().texture_manager()); - decoder_->SetAsyncPixelTransferManagerForTest(manager); - StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate = NULL; - - AsyncTexImage2DCHROMIUM teximage_cmd; - teximage_cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, - GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); - - // No transfer delegate exists initially. - EXPECT_FALSE( - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - - // Create delegate on AsyncTexImage2D. - { - EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) - .WillOnce(Return( - delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) - .RetiresOnSaturation(); - EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)).RetiresOnSaturation(); - - // Command succeeds. - EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - } - - // Delegate is cached. - EXPECT_EQ(delegate, - decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( - texture_ref)); - - // Delete delegate on manager teardown. - { - EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); - decoder_->ResetAsyncPixelTransferManagerForTest(); - - // Texture ref still valid. - EXPECT_EQ(texture_ref, GetTexture(client_texture_id_)); - } -} - namespace { class SizeOnlyMemoryTracker : public MemoryTracker { @@ -8476,15 +977,15 @@ class SizeOnlyMemoryTracker : public MemoryTracker { const size_t kInitialManagedPoolSize = 0; pool_infos_[MemoryTracker::kUnmanaged].initial_size = kInitialUnmanagedPoolSize; - pool_infos_[MemoryTracker::kManaged].initial_size = - kInitialManagedPoolSize; + pool_infos_[MemoryTracker::kManaged].initial_size = kInitialManagedPoolSize; } // Ensure a certain amount of GPU memory is free. Returns true on success. MOCK_METHOD1(EnsureGPUMemoryAvailable, bool(size_t size_needed)); - virtual void TrackMemoryAllocatedChange( - size_t old_size, size_t new_size, Pool pool) { + virtual void TrackMemoryAllocatedChange(size_t old_size, + size_t new_size, + Pool pool) { PoolInfo& info = pool_infos_[pool]; info.size += new_size - old_size; } @@ -8495,13 +996,9 @@ class SizeOnlyMemoryTracker : public MemoryTracker { } private: - virtual ~SizeOnlyMemoryTracker() { - } + virtual ~SizeOnlyMemoryTracker() {} struct PoolInfo { - PoolInfo() - : initial_size(0), - size(0) { - } + PoolInfo() : initial_size(0), size(0) {} size_t initial_size; size_t size; }; @@ -8510,78 +1007,90 @@ class SizeOnlyMemoryTracker : public MemoryTracker { } // anonymous namespace. -TEST_F(GLES2DecoderManualInitTest, MemoryTrackerInitialSize) { +TEST_P(GLES2DecoderManualInitTest, MemoryTrackerInitialSize) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); // Expect that initial size - size is 0. EXPECT_EQ(0u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); EXPECT_EQ(0u, memory_tracker->GetPoolSize(MemoryTracker::kManaged)); } -TEST_F(GLES2DecoderManualInitTest, MemoryTrackerTexImage2D) { +TEST_P(GLES2DecoderManualInitTest, MemoryTrackerTexImage2D) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(true)).RetiresOnSaturation(); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); + .WillOnce(Return(true)) + .RetiresOnSaturation(); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 8, + 4, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(64)) - .WillOnce(Return(true)).RetiresOnSaturation(); - DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); + .WillOnce(Return(true)) + .RetiresOnSaturation(); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 4, + 4, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(64u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Check we get out of memory and no call to glTexImage2D if Ensure fails. EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(64)) - .WillOnce(Return(false)).RetiresOnSaturation(); + .WillOnce(Return(false)) + .RetiresOnSaturation(); TexImage2D cmd; - cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, - kSharedMemoryId, kSharedMemoryOffset); + cmd.Init(GL_TEXTURE_2D, + 0, + GL_RGBA, + 4, + 4, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); EXPECT_EQ(64u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); } -TEST_F(GLES2DecoderManualInitTest, MemoryTrackerTexStorage2DEXT) { +TEST_P(GLES2DecoderManualInitTest, MemoryTrackerTexStorage2DEXT) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); // Check we get out of memory and no call to glTexStorage2DEXT // if Ensure fails. EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(false)).RetiresOnSaturation(); + .WillOnce(Return(false)) + .RetiresOnSaturation(); TexStorage2DEXT cmd; cmd.Init(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 4); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -8589,7 +1098,7 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerTexStorage2DEXT) { EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); } -TEST_F(GLES2DecoderManualInitTest, MemoryTrackerCopyTexImage2D) { +TEST_P(GLES2DecoderManualInitTest, MemoryTrackerCopyTexImage2D) { GLenum target = GL_TEXTURE_2D; GLint level = 0; GLenum internal_format = GL_RGBA; @@ -8599,62 +1108,57 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerCopyTexImage2D) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(true)).RetiresOnSaturation(); + .WillOnce(Return(true)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, CopyTexImage2D( - target, level, internal_format, 0, 0, width, height, border)) + EXPECT_CALL(*gl_, + CopyTexImage2D( + target, level, internal_format, 0, 0, width, height, border)) .Times(1) .RetiresOnSaturation(); CopyTexImage2D cmd; - cmd.Init(target, level, internal_format, 0, 0, width, height, border); + cmd.Init(target, level, internal_format, 0, 0, width, height); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Check we get out of memory and no call to glCopyTexImage2D if Ensure fails. EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(false)).RetiresOnSaturation(); + .WillOnce(Return(false)) + .RetiresOnSaturation(); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); } -TEST_F(GLES2DecoderManualInitTest, MemoryTrackerRenderbufferStorage) { +TEST_P(GLES2DecoderManualInitTest, MemoryTrackerRenderbufferStorage) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(true)).RetiresOnSaturation(); - EXPECT_CALL(*gl_, RenderbufferStorageEXT( - GL_RENDERBUFFER, GL_RGBA, 8, 4)) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, RenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA, 8, 4)) .Times(1) .RetiresOnSaturation(); RenderbufferStorage cmd; @@ -8665,33 +1169,29 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerRenderbufferStorage) { // Check we get out of memory and no call to glRenderbufferStorage if Ensure // fails. EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(false)).RetiresOnSaturation(); + .WillOnce(Return(false)) + .RetiresOnSaturation(); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); } -TEST_F(GLES2DecoderManualInitTest, MemoryTrackerBufferData) { +TEST_P(GLES2DecoderManualInitTest, MemoryTrackerBufferData) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, - kServiceBufferId); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(true)).RetiresOnSaturation(); + .WillOnce(Return(true)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, BufferData(GL_ARRAY_BUFFER, 128, _, GL_STREAM_DRAW)) .Times(1) .RetiresOnSaturation(); @@ -8703,206 +1203,96 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerBufferData) { // Check we get out of memory and no call to glBufferData if Ensure // fails. EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) - .WillOnce(Return(false)).RetiresOnSaturation(); + .WillOnce(Return(false)) + .RetiresOnSaturation(); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kManaged)); } -TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateSuccceeds) { - const GLsizei count = 1; - const GLenum bufs[] = { GL_COLOR_ATTACHMENT0 }; - DrawBuffersEXTImmediate& cmd = - *GetImmediateAs<DrawBuffersEXTImmediate>(); - cmd.Init(count, bufs); - - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - EXPECT_CALL(*gl_, DrawBuffersARB(count, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(bufs))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateFails) { - const GLsizei count = 1; - const GLenum bufs[] = { GL_COLOR_ATTACHMENT1_EXT }; - DrawBuffersEXTImmediate& cmd = - *GetImmediateAs<DrawBuffersEXTImmediate>(); - cmd.Init(count, bufs); - - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(bufs))); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -} - -TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateBackbuffer) { - const GLsizei count = 1; - const GLenum bufs[] = { GL_BACK }; - DrawBuffersEXTImmediate& cmd = - *GetImmediateAs<DrawBuffersEXTImmediate>(); - cmd.Init(count, bufs); - - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(bufs))); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +TEST_P(GLES2DecoderManualInitTest, ImmutableCopyTexImage2D) { + const GLenum kTarget = GL_TEXTURE_2D; + const GLint kLevel = 0; + const GLenum kInternalFormat = GL_RGBA; + const GLenum kSizedInternalFormat = GL_RGBA8; + const GLsizei kWidth = 4; + const GLsizei kHeight = 8; + const GLint kBorder = 0; + InitState init; + init.extensions = "GL_EXT_texture_storage"; + init.gl_version = "3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); // unbind + // CopyTexImage2D will call arbitrary amount of GetErrors. + EXPECT_CALL(*gl_, GetError()) + .Times(AtLeast(1)); - EXPECT_CALL(*gl_, DrawBuffersARB(count, _)) - .Times(1) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + CopyTexImage2D( + kTarget, kLevel, kInternalFormat, 0, 0, kWidth, kHeight, + kBorder)) + .Times(1); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(bufs))); + EXPECT_CALL(*gl_, + TexStorage2DEXT( + kTarget, kLevel, kSizedInternalFormat, kWidth, kHeight)) + .Times(1); + CopyTexImage2D copy_cmd; + copy_cmd.Init(kTarget, kLevel, kInternalFormat, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(copy_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderManualInitTest, DiscardFramebufferEXT) { - InitDecoder("GL_EXT_discard_framebuffer", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource - - const GLenum target = GL_FRAMEBUFFER; - const GLsizei count = 1; - const GLenum attachments[] = { GL_COLOR_ATTACHMENT0 }; - - SetupTexture(); - DoBindFramebuffer( - GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); - DoFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - client_texture_id_, - kServiceTextureId, - 0, - GL_NO_ERROR); - FramebufferManager* framebuffer_manager = group().framebuffer_manager(); - Framebuffer* framebuffer = - framebuffer_manager->GetFramebuffer(client_framebuffer_id_); - EXPECT_TRUE(framebuffer->IsCleared()); - - EXPECT_CALL(*gl_, DiscardFramebufferEXT(target, count, _)) - .Times(1) - .RetiresOnSaturation(); - DiscardFramebufferEXTImmediate& cmd = - *GetImmediateAs<DiscardFramebufferEXTImmediate>(); - cmd.Init(target, count, attachments); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(attachments))); + TexStorage2DEXT storage_cmd; + storage_cmd.Init(kTarget, kLevel, kSizedInternalFormat, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(storage_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_FALSE(framebuffer->IsCleared()); -} -TEST_F(GLES2DecoderTest, DiscardFramebufferEXTUnsupported) { - const GLenum target = GL_FRAMEBUFFER; - const GLsizei count = 1; - const GLenum attachments[] = { GL_COLOR_EXT }; - DiscardFramebufferEXTImmediate& cmd = - *GetImmediateAs<DiscardFramebufferEXTImmediate>(); - cmd.Init(target, count, attachments); - - // Should not result into a call into GL. - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(attachments))); + // This should not invoke CopyTexImage2D. + copy_cmd.Init(kTarget, kLevel, kInternalFormat, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(copy_cmd)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } -TEST_F(GLES2DecoderManualInitTest, ClearUniformsBeforeFirstProgramUse) { - CommandLine command_line(0, NULL); - command_line.AppendSwitchASCII( - switches::kGpuDriverBugWorkarounds, - base::IntToString(gpu::CLEAR_UNIFORMS_BEFORE_FIRST_PROGRAM_USE)); - InitDecoderWithCommandLine( - "", // extensions - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true, // bind generates resource - &command_line); - { - static AttribInfo attribs[] = { - { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, - { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, - { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, - }; - static UniformInfo uniforms[] = { - { kUniform1Name, kUniform1Size, kUniform1Type, - kUniform1FakeLocation, kUniform1RealLocation, - kUniform1DesiredLocation }, - { kUniform2Name, kUniform2Size, kUniform2Type, - kUniform2FakeLocation, kUniform2RealLocation, - kUniform2DesiredLocation }, - { kUniform3Name, kUniform3Size, kUniform3Type, - kUniform3FakeLocation, kUniform3RealLocation, - kUniform3DesiredLocation }, - }; - SetupShader(attribs, arraysize(attribs), uniforms, arraysize(uniforms), - client_program_id_, kServiceProgramId, - client_vertex_shader_id_, kServiceVertexShaderId, - client_fragment_shader_id_, kServiceFragmentShaderId); - TestHelper::SetupExpectationsForClearingUniforms( - gl_.get(), uniforms, arraysize(uniforms)); - } - - { - EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) - .Times(1) - .RetiresOnSaturation(); - cmds::UseProgram cmd; - cmd.Init(client_program_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } +TEST_P(GLES2DecoderTest, LoseContextCHROMIUMValidArgs) { + EXPECT_CALL(*mock_decoder_, LoseContext(GL_GUILTY_CONTEXT_RESET_ARB)) + .Times(1); + cmds::LoseContextCHROMIUM cmd; + cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_GUILTY_CONTEXT_RESET_ARB); + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -// TODO(gman): Complete this test. -// TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) { -// } - -// TODO(gman): BufferData - -// TODO(gman): BufferDataImmediate - -// TODO(gman): BufferSubData - -// TODO(gman): BufferSubDataImmediate - -// TODO(gman): CompressedTexImage2D - -// TODO(gman): CompressedTexImage2DImmediate - -// TODO(gman): CompressedTexSubImage2DImmediate - -// TODO(gman): DeleteProgram - -// TODO(gman): DeleteShader - -// TODO(gman): PixelStorei +TEST_P(GLES2DecoderTest, LoseContextCHROMIUMInvalidArgs0_0) { + EXPECT_CALL(*mock_decoder_, LoseContext(_)) + .Times(0); + cmds::LoseContextCHROMIUM cmd; + cmd.Init(GL_NONE, GL_GUILTY_CONTEXT_RESET_ARB); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} -// TODO(gman): TexImage2D +TEST_P(GLES2DecoderTest, LoseContextCHROMIUMInvalidArgs1_0) { + EXPECT_CALL(*mock_decoder_, LoseContext(_)) + .Times(0); + cmds::LoseContextCHROMIUM cmd; + cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_NONE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} -// TODO(gman): TexImage2DImmediate +INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderTest, ::testing::Bool()); -// TODO(gman): TexSubImage2DImmediate +INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderWithShaderTest, ::testing::Bool()); -// TODO(gman): UseProgram +INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderManualInitTest, ::testing::Bool()); -// TODO(gman): SwapBuffers +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderRGBBackbufferTest, + ::testing::Bool()); } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.h new file mode 100644 index 00000000000..fea20abba52 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.h @@ -0,0 +1,80 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_H_ + +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/buffer_manager.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/framebuffer_manager.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/query_manager.h" +#include "gpu/command_buffer/service/renderbuffer_manager.h" +#include "gpu/command_buffer/service/shader_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "gpu/command_buffer/service/texture_manager.h" +#include "gpu/command_buffer/service/vertex_array_manager.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_context_stub_with_extensions.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +namespace base { +class CommandLine; +} + +namespace gpu { +namespace gles2 { + +class GLES2DecoderTest : public GLES2DecoderTestBase { + public: + GLES2DecoderTest() {} + + protected: + void CheckReadPixelsOutOfRange(GLint in_read_x, + GLint in_read_y, + GLsizei in_read_width, + GLsizei in_read_height, + bool init); +}; + +class GLES2DecoderWithShaderTest : public GLES2DecoderWithShaderTestBase { + public: + GLES2DecoderWithShaderTest() : GLES2DecoderWithShaderTestBase() {} + + void CheckTextureChangesMarkFBOAsNotComplete(bool bound_fbo); + void CheckRenderbufferChangesMarkFBOAsNotComplete(bool bound_fbo); +}; + +class GLES2DecoderRGBBackbufferTest : public GLES2DecoderWithShaderTest { + public: + GLES2DecoderRGBBackbufferTest() {} + + virtual void SetUp(); +}; + +class GLES2DecoderManualInitTest : public GLES2DecoderWithShaderTest { + public: + GLES2DecoderManualInitTest() {} + + // Override default setup so nothing gets setup. + virtual void SetUp(); + + void DirtyStateMaskTest(GLuint color_bits, + bool depth_mask, + GLuint front_stencil_mask, + GLuint back_stencil_mask); + void EnableDisableTest(GLenum cap, bool enable, bool expect_set); +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_H_ diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h index ac8a8f206ef..3eb5acb7279 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h @@ -1,9 +1,11 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! // It is included by gles2_cmd_decoder_unittest_base.cc @@ -35,50 +37,30 @@ void GLES2DecoderTestBase::SetupInitStateExpectations() { EXPECT_CALL(*gl_, ClearColor(0.0f, 0.0f, 0.0f, 0.0f)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ClearDepth(1.0f)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ClearStencil(0)) - .Times(1) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ClearDepth(1.0f)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, ClearStencil(0)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, ColorMask(true, true, true, true)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, CullFace(GL_BACK)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthFunc(GL_LESS)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthMask(true)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthRange(0.0f, 1.0f)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, FrontFace(GL_CCW)) - .Times(1) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, CullFace(GL_BACK)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, DepthFunc(GL_LESS)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, DepthMask(true)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, DepthRange(0.0f, 1.0f)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, FrontFace(GL_CCW)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, Hint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, LineWidth(1.0f)) - .Times(1) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, LineWidth(1.0f)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, PixelStorei(GL_PACK_ALIGNMENT, 4)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ALIGNMENT, 4)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, PolygonOffset(0.0f, 0.0f)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, SampleCoverage(1.0f, false)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL( - *gl_, Scissor(kViewportX, kViewportY, kViewportWidth, kViewportHeight)) + EXPECT_CALL(*gl_, PolygonOffset(0.0f, 0.0f)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, SampleCoverage(1.0f, false)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, + Scissor(kViewportX, kViewportY, kViewportWidth, kViewportHeight)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, StencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 0xFFFFFFFFU)) @@ -99,10 +81,9 @@ void GLES2DecoderTestBase::SetupInitStateExpectations() { EXPECT_CALL(*gl_, StencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL( - *gl_, Viewport(kViewportX, kViewportY, kViewportWidth, kViewportHeight)) + EXPECT_CALL(*gl_, + Viewport(kViewportX, kViewportY, kViewportWidth, kViewportHeight)) .Times(1) .RetiresOnSaturation(); } #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_0_AUTOGEN_H_ - diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc index 9c3d7339afe..10f6af17389 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc @@ -37,6 +37,8 @@ class GLES2DecoderTest1 : public GLES2DecoderTestBase { GLES2DecoderTest1() { } }; +INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderTest1, ::testing::Bool()); + template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::GenerateMipmap, 0>( bool valid) { @@ -45,14 +47,6 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::GenerateMipmap, 0>( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); if (valid) { - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR)) - .Times(1) - .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -281,6 +275,26 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::GetVertexAttribiv, 0>( } }; +template <> +void GLES2DecoderTestBase::SpecializedSetup<cmds::RenderbufferStorage, 0>( + bool valid) { + DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, + kServiceRenderbufferId); + if (valid) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + RenderbufferStorageEXT(GL_RENDERBUFFER, _, 3, 4)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + } +} + + #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h" } // namespace gles2 diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index d89779b1f3e..32e20d82720 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h @@ -1,9 +1,11 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! // It is included by gles2_cmd_decoder_unittest_1.cc @@ -12,7 +14,7 @@ // TODO(gman): ActiveTexture -TEST_F(GLES2DecoderTest1, AttachShaderValidArgs) { +TEST_P(GLES2DecoderTest1, AttachShaderValidArgs) { EXPECT_CALL(*gl_, AttachShader(kServiceProgramId, kServiceShaderId)); SpecializedSetup<cmds::AttachShader, 0>(true); cmds::AttachShader cmd; @@ -20,11 +22,9 @@ TEST_F(GLES2DecoderTest1, AttachShaderValidArgs) { EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -// TODO(gman): BindAttribLocation - // TODO(gman): BindAttribLocationBucket -TEST_F(GLES2DecoderTest1, BindBufferValidArgs) { +TEST_P(GLES2DecoderTest1, BindBufferValidArgs) { EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, kServiceBufferId)); SpecializedSetup<cmds::BindBuffer, 0>(true); cmds::BindBuffer cmd; @@ -33,10 +33,10 @@ TEST_F(GLES2DecoderTest1, BindBufferValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindBufferValidArgsNewId) { +TEST_P(GLES2DecoderTest1, BindBufferValidArgsNewId) { EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, kNewServiceId)); EXPECT_CALL(*gl_, GenBuffersARB(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); SpecializedSetup<cmds::BindBuffer, 0>(true); cmds::BindBuffer cmd; cmd.Init(GL_ARRAY_BUFFER, kNewClientId); @@ -45,7 +45,7 @@ TEST_F(GLES2DecoderTest1, BindBufferValidArgsNewId) { EXPECT_TRUE(GetBuffer(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, BindBufferInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, BindBufferInvalidArgs0_0) { EXPECT_CALL(*gl_, BindBuffer(_, _)).Times(0); SpecializedSetup<cmds::BindBuffer, 0>(false); cmds::BindBuffer cmd; @@ -54,7 +54,7 @@ TEST_F(GLES2DecoderTest1, BindBufferInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindFramebufferValidArgs) { +TEST_P(GLES2DecoderTest1, BindFramebufferValidArgs) { EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER, kServiceFramebufferId)); SpecializedSetup<cmds::BindFramebuffer, 0>(true); cmds::BindFramebuffer cmd; @@ -63,10 +63,10 @@ TEST_F(GLES2DecoderTest1, BindFramebufferValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindFramebufferValidArgsNewId) { +TEST_P(GLES2DecoderTest1, BindFramebufferValidArgsNewId) { EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER, kNewServiceId)); EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); SpecializedSetup<cmds::BindFramebuffer, 0>(true); cmds::BindFramebuffer cmd; cmd.Init(GL_FRAMEBUFFER, kNewClientId); @@ -75,7 +75,7 @@ TEST_F(GLES2DecoderTest1, BindFramebufferValidArgsNewId) { EXPECT_TRUE(GetFramebuffer(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, BindFramebufferInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, BindFramebufferInvalidArgs0_0) { EXPECT_CALL(*gl_, BindFramebufferEXT(_, _)).Times(0); SpecializedSetup<cmds::BindFramebuffer, 0>(false); cmds::BindFramebuffer cmd; @@ -84,7 +84,7 @@ TEST_F(GLES2DecoderTest1, BindFramebufferInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindFramebufferInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, BindFramebufferInvalidArgs0_1) { EXPECT_CALL(*gl_, BindFramebufferEXT(_, _)).Times(0); SpecializedSetup<cmds::BindFramebuffer, 0>(false); cmds::BindFramebuffer cmd; @@ -93,9 +93,9 @@ TEST_F(GLES2DecoderTest1, BindFramebufferInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindRenderbufferValidArgs) { - EXPECT_CALL( - *gl_, BindRenderbufferEXT(GL_RENDERBUFFER, kServiceRenderbufferId)); +TEST_P(GLES2DecoderTest1, BindRenderbufferValidArgs) { + EXPECT_CALL(*gl_, + BindRenderbufferEXT(GL_RENDERBUFFER, kServiceRenderbufferId)); SpecializedSetup<cmds::BindRenderbuffer, 0>(true); cmds::BindRenderbuffer cmd; cmd.Init(GL_RENDERBUFFER, client_renderbuffer_id_); @@ -103,10 +103,10 @@ TEST_F(GLES2DecoderTest1, BindRenderbufferValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindRenderbufferValidArgsNewId) { +TEST_P(GLES2DecoderTest1, BindRenderbufferValidArgsNewId) { EXPECT_CALL(*gl_, BindRenderbufferEXT(GL_RENDERBUFFER, kNewServiceId)); EXPECT_CALL(*gl_, GenRenderbuffersEXT(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); SpecializedSetup<cmds::BindRenderbuffer, 0>(true); cmds::BindRenderbuffer cmd; cmd.Init(GL_RENDERBUFFER, kNewClientId); @@ -115,7 +115,7 @@ TEST_F(GLES2DecoderTest1, BindRenderbufferValidArgsNewId) { EXPECT_TRUE(GetRenderbuffer(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, BindRenderbufferInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, BindRenderbufferInvalidArgs0_0) { EXPECT_CALL(*gl_, BindRenderbufferEXT(_, _)).Times(0); SpecializedSetup<cmds::BindRenderbuffer, 0>(false); cmds::BindRenderbuffer cmd; @@ -124,7 +124,7 @@ TEST_F(GLES2DecoderTest1, BindRenderbufferInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindTextureValidArgs) { +TEST_P(GLES2DecoderTest1, BindTextureValidArgs) { EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)); SpecializedSetup<cmds::BindTexture, 0>(true); cmds::BindTexture cmd; @@ -133,10 +133,10 @@ TEST_F(GLES2DecoderTest1, BindTextureValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindTextureValidArgsNewId) { +TEST_P(GLES2DecoderTest1, BindTextureValidArgsNewId) { EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kNewServiceId)); EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); SpecializedSetup<cmds::BindTexture, 0>(true); cmds::BindTexture cmd; cmd.Init(GL_TEXTURE_2D, kNewClientId); @@ -145,7 +145,7 @@ TEST_F(GLES2DecoderTest1, BindTextureValidArgsNewId) { EXPECT_TRUE(GetTexture(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, BindTextureInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, BindTextureInvalidArgs0_0) { EXPECT_CALL(*gl_, BindTexture(_, _)).Times(0); SpecializedSetup<cmds::BindTexture, 0>(false); cmds::BindTexture cmd; @@ -154,7 +154,7 @@ TEST_F(GLES2DecoderTest1, BindTextureInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BindTextureInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, BindTextureInvalidArgs0_1) { EXPECT_CALL(*gl_, BindTexture(_, _)).Times(0); SpecializedSetup<cmds::BindTexture, 0>(false); cmds::BindTexture cmd; @@ -163,7 +163,7 @@ TEST_F(GLES2DecoderTest1, BindTextureInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendColorValidArgs) { +TEST_P(GLES2DecoderTest1, BlendColorValidArgs) { EXPECT_CALL(*gl_, BlendColor(1, 2, 3, 4)); SpecializedSetup<cmds::BlendColor, 0>(true); cmds::BlendColor cmd; @@ -172,7 +172,7 @@ TEST_F(GLES2DecoderTest1, BlendColorValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationValidArgs) { +TEST_P(GLES2DecoderTest1, BlendEquationValidArgs) { EXPECT_CALL(*gl_, BlendEquation(GL_FUNC_SUBTRACT)); SpecializedSetup<cmds::BlendEquation, 0>(true); cmds::BlendEquation cmd; @@ -181,7 +181,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, BlendEquationInvalidArgs0_0) { EXPECT_CALL(*gl_, BlendEquation(_)).Times(0); SpecializedSetup<cmds::BlendEquation, 0>(false); cmds::BlendEquation cmd; @@ -190,7 +190,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, BlendEquationInvalidArgs0_1) { EXPECT_CALL(*gl_, BlendEquation(_)).Times(0); SpecializedSetup<cmds::BlendEquation, 0>(false); cmds::BlendEquation cmd; @@ -199,7 +199,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationSeparateValidArgs) { +TEST_P(GLES2DecoderTest1, BlendEquationSeparateValidArgs) { EXPECT_CALL(*gl_, BlendEquationSeparate(GL_FUNC_SUBTRACT, GL_FUNC_ADD)); SpecializedSetup<cmds::BlendEquationSeparate, 0>(true); cmds::BlendEquationSeparate cmd; @@ -208,7 +208,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationSeparateValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs0_0) { EXPECT_CALL(*gl_, BlendEquationSeparate(_, _)).Times(0); SpecializedSetup<cmds::BlendEquationSeparate, 0>(false); cmds::BlendEquationSeparate cmd; @@ -217,7 +217,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs0_1) { EXPECT_CALL(*gl_, BlendEquationSeparate(_, _)).Times(0); SpecializedSetup<cmds::BlendEquationSeparate, 0>(false); cmds::BlendEquationSeparate cmd; @@ -226,7 +226,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs1_0) { +TEST_P(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs1_0) { EXPECT_CALL(*gl_, BlendEquationSeparate(_, _)).Times(0); SpecializedSetup<cmds::BlendEquationSeparate, 0>(false); cmds::BlendEquationSeparate cmd; @@ -235,7 +235,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs1_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs1_1) { +TEST_P(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs1_1) { EXPECT_CALL(*gl_, BlendEquationSeparate(_, _)).Times(0); SpecializedSetup<cmds::BlendEquationSeparate, 0>(false); cmds::BlendEquationSeparate cmd; @@ -244,7 +244,7 @@ TEST_F(GLES2DecoderTest1, BlendEquationSeparateInvalidArgs1_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendFuncValidArgs) { +TEST_P(GLES2DecoderTest1, BlendFuncValidArgs) { EXPECT_CALL(*gl_, BlendFunc(GL_ZERO, GL_ZERO)); SpecializedSetup<cmds::BlendFunc, 0>(true); cmds::BlendFunc cmd; @@ -253,7 +253,7 @@ TEST_F(GLES2DecoderTest1, BlendFuncValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, BlendFuncSeparateValidArgs) { +TEST_P(GLES2DecoderTest1, BlendFuncSeparateValidArgs) { EXPECT_CALL(*gl_, BlendFuncSeparate(GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO)); SpecializedSetup<cmds::BlendFuncSeparate, 0>(true); cmds::BlendFuncSeparate cmd; @@ -265,8 +265,7 @@ TEST_F(GLES2DecoderTest1, BlendFuncSeparateValidArgs) { // TODO(gman): BufferSubData - -TEST_F(GLES2DecoderTest1, CheckFramebufferStatusValidArgs) { +TEST_P(GLES2DecoderTest1, CheckFramebufferStatusValidArgs) { EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)); SpecializedSetup<cmds::CheckFramebufferStatus, 0>(true); cmds::CheckFramebufferStatus cmd; @@ -275,7 +274,7 @@ TEST_F(GLES2DecoderTest1, CheckFramebufferStatusValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgs0_0) { EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)).Times(0); SpecializedSetup<cmds::CheckFramebufferStatus, 0>(false); cmds::CheckFramebufferStatus cmd; @@ -284,7 +283,7 @@ TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgs0_1) { EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)).Times(0); SpecializedSetup<cmds::CheckFramebufferStatus, 0>(false); cmds::CheckFramebufferStatus cmd; @@ -293,7 +292,7 @@ TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgsBadSharedMemoryId) { +TEST_P(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgsBadSharedMemoryId) { EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)).Times(0); SpecializedSetup<cmds::CheckFramebufferStatus, 0>(false); cmds::CheckFramebufferStatus cmd; @@ -303,7 +302,7 @@ TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgsBadSharedMemoryId) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest1, ClearValidArgs) { +TEST_P(GLES2DecoderTest1, ClearValidArgs) { EXPECT_CALL(*gl_, Clear(1)); SpecializedSetup<cmds::Clear, 0>(true); cmds::Clear cmd; @@ -312,7 +311,7 @@ TEST_F(GLES2DecoderTest1, ClearValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, ClearColorValidArgs) { +TEST_P(GLES2DecoderTest1, ClearColorValidArgs) { EXPECT_CALL(*gl_, ClearColor(1, 2, 3, 4)); SpecializedSetup<cmds::ClearColor, 0>(true); cmds::ClearColor cmd; @@ -321,7 +320,7 @@ TEST_F(GLES2DecoderTest1, ClearColorValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, ClearDepthfValidArgs) { +TEST_P(GLES2DecoderTest1, ClearDepthfValidArgs) { EXPECT_CALL(*gl_, ClearDepth(0.5f)); SpecializedSetup<cmds::ClearDepthf, 0>(true); cmds::ClearDepthf cmd; @@ -330,7 +329,7 @@ TEST_F(GLES2DecoderTest1, ClearDepthfValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, ClearStencilValidArgs) { +TEST_P(GLES2DecoderTest1, ClearStencilValidArgs) { EXPECT_CALL(*gl_, ClearStencil(1)); SpecializedSetup<cmds::ClearStencil, 0>(true); cmds::ClearStencil cmd; @@ -339,7 +338,7 @@ TEST_F(GLES2DecoderTest1, ClearStencilValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, ColorMaskValidArgs) { +TEST_P(GLES2DecoderTest1, ColorMaskValidArgs) { SpecializedSetup<cmds::ColorMask, 0>(true); cmds::ColorMask cmd; cmd.Init(true, true, true, true); @@ -347,15 +346,15 @@ TEST_F(GLES2DecoderTest1, ColorMaskValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } // TODO(gman): CompileShader +// TODO(gman): CompressedTexImage2DBucket // TODO(gman): CompressedTexImage2D -// TODO(gman): CompressedTexImage2DBucket +// TODO(gman): CompressedTexSubImage2DBucket // TODO(gman): CompressedTexSubImage2D -// TODO(gman): CompressedTexSubImage2DBucket // TODO(gman): CopyTexImage2D -TEST_F(GLES2DecoderTest1, CopyTexSubImage2DValidArgs) { +TEST_P(GLES2DecoderTest1, CopyTexSubImage2DValidArgs) { EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 2, 3, 4, 5, 6, 7, 8)); SpecializedSetup<cmds::CopyTexSubImage2D, 0>(true); cmds::CopyTexSubImage2D cmd; @@ -364,7 +363,7 @@ TEST_F(GLES2DecoderTest1, CopyTexSubImage2DValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs0_0) { EXPECT_CALL(*gl_, CopyTexSubImage2D(_, _, _, _, _, _, _, _)).Times(0); SpecializedSetup<cmds::CopyTexSubImage2D, 0>(false); cmds::CopyTexSubImage2D cmd; @@ -373,7 +372,7 @@ TEST_F(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs6_0) { +TEST_P(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs6_0) { EXPECT_CALL(*gl_, CopyTexSubImage2D(_, _, _, _, _, _, _, _)).Times(0); SpecializedSetup<cmds::CopyTexSubImage2D, 0>(false); cmds::CopyTexSubImage2D cmd; @@ -382,7 +381,7 @@ TEST_F(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs6_0) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_F(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs7_0) { +TEST_P(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs7_0) { EXPECT_CALL(*gl_, CopyTexSubImage2D(_, _, _, _, _, _, _, _)).Times(0); SpecializedSetup<cmds::CopyTexSubImage2D, 0>(false); cmds::CopyTexSubImage2D cmd; @@ -391,9 +390,8 @@ TEST_F(GLES2DecoderTest1, CopyTexSubImage2DInvalidArgs7_0) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_F(GLES2DecoderTest1, CreateProgramValidArgs) { - EXPECT_CALL(*gl_, CreateProgram()) - .WillOnce(Return(kNewServiceId)); +TEST_P(GLES2DecoderTest1, CreateProgramValidArgs) { + EXPECT_CALL(*gl_, CreateProgram()).WillOnce(Return(kNewServiceId)); SpecializedSetup<cmds::CreateProgram, 0>(true); cmds::CreateProgram cmd; cmd.Init(kNewClientId); @@ -402,7 +400,7 @@ TEST_F(GLES2DecoderTest1, CreateProgramValidArgs) { EXPECT_TRUE(GetProgram(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, CreateShaderValidArgs) { +TEST_P(GLES2DecoderTest1, CreateShaderValidArgs) { EXPECT_CALL(*gl_, CreateShader(GL_VERTEX_SHADER)) .WillOnce(Return(kNewServiceId)); SpecializedSetup<cmds::CreateShader, 0>(true); @@ -413,7 +411,7 @@ TEST_F(GLES2DecoderTest1, CreateShaderValidArgs) { EXPECT_TRUE(GetShader(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, CreateShaderInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, CreateShaderInvalidArgs0_0) { EXPECT_CALL(*gl_, CreateShader(_)).Times(0); SpecializedSetup<cmds::CreateShader, 0>(false); cmds::CreateShader cmd; @@ -422,7 +420,7 @@ TEST_F(GLES2DecoderTest1, CreateShaderInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, CullFaceValidArgs) { +TEST_P(GLES2DecoderTest1, CullFaceValidArgs) { EXPECT_CALL(*gl_, CullFace(GL_FRONT)); SpecializedSetup<cmds::CullFace, 0>(true); cmds::CullFace cmd; @@ -431,34 +429,8 @@ TEST_F(GLES2DecoderTest1, CullFaceValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DeleteBuffersValidArgs) { - EXPECT_CALL( - *gl_, - DeleteBuffersARB(1, Pointee(kServiceBufferId))) - .Times(1); - GetSharedMemoryAs<GLuint*>()[0] = client_buffer_id_; - SpecializedSetup<cmds::DeleteBuffers, 0>(true); - cmds::DeleteBuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetBuffer(client_buffer_id_) == NULL); -} - -TEST_F(GLES2DecoderTest1, DeleteBuffersInvalidArgs) { - GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId; - SpecializedSetup<cmds::DeleteBuffers, 0>(false); - cmds::DeleteBuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest1, DeleteBuffersImmediateValidArgs) { - EXPECT_CALL( - *gl_, - DeleteBuffersARB(1, Pointee(kServiceBufferId))) - .Times(1); +TEST_P(GLES2DecoderTest1, DeleteBuffersImmediateValidArgs) { + EXPECT_CALL(*gl_, DeleteBuffersARB(1, Pointee(kServiceBufferId))).Times(1); cmds::DeleteBuffersImmediate& cmd = *GetImmediateAs<cmds::DeleteBuffersImmediate>(); SpecializedSetup<cmds::DeleteBuffersImmediate, 0>(true); @@ -466,47 +438,20 @@ TEST_F(GLES2DecoderTest1, DeleteBuffersImmediateValidArgs) { EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(client_buffer_id_))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetBuffer(client_buffer_id_) == NULL); + EXPECT_TRUE(GetBuffer(client_buffer_id_) == NULL); } -TEST_F(GLES2DecoderTest1, DeleteBuffersImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, DeleteBuffersImmediateInvalidArgs) { cmds::DeleteBuffersImmediate& cmd = *GetImmediateAs<cmds::DeleteBuffersImmediate>(); SpecializedSetup<cmds::DeleteBuffersImmediate, 0>(false); GLuint temp = kInvalidClientId; cmd.Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); -} - -TEST_F(GLES2DecoderTest1, DeleteFramebuffersValidArgs) { - EXPECT_CALL( - *gl_, - DeleteFramebuffersEXT(1, Pointee(kServiceFramebufferId))) - .Times(1); - GetSharedMemoryAs<GLuint*>()[0] = client_framebuffer_id_; - SpecializedSetup<cmds::DeleteFramebuffers, 0>(true); - cmds::DeleteFramebuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetFramebuffer(client_framebuffer_id_) == NULL); -} - -TEST_F(GLES2DecoderTest1, DeleteFramebuffersInvalidArgs) { - GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId; - SpecializedSetup<cmds::DeleteFramebuffers, 0>(false); - cmds::DeleteFramebuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } -TEST_F(GLES2DecoderTest1, DeleteFramebuffersImmediateValidArgs) { - EXPECT_CALL( - *gl_, - DeleteFramebuffersEXT(1, Pointee(kServiceFramebufferId))) +TEST_P(GLES2DecoderTest1, DeleteFramebuffersImmediateValidArgs) { + EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, Pointee(kServiceFramebufferId))) .Times(1); cmds::DeleteFramebuffersImmediate& cmd = *GetImmediateAs<cmds::DeleteFramebuffersImmediate>(); @@ -515,21 +460,19 @@ TEST_F(GLES2DecoderTest1, DeleteFramebuffersImmediateValidArgs) { EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(client_framebuffer_id_))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetFramebuffer(client_framebuffer_id_) == NULL); + EXPECT_TRUE(GetFramebuffer(client_framebuffer_id_) == NULL); } -TEST_F(GLES2DecoderTest1, DeleteFramebuffersImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, DeleteFramebuffersImmediateInvalidArgs) { cmds::DeleteFramebuffersImmediate& cmd = *GetImmediateAs<cmds::DeleteFramebuffersImmediate>(); SpecializedSetup<cmds::DeleteFramebuffersImmediate, 0>(false); GLuint temp = kInvalidClientId; cmd.Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } -TEST_F(GLES2DecoderTest1, DeleteProgramValidArgs) { +TEST_P(GLES2DecoderTest1, DeleteProgramValidArgs) { EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)); SpecializedSetup<cmds::DeleteProgram, 0>(true); cmds::DeleteProgram cmd; @@ -538,33 +481,8 @@ TEST_F(GLES2DecoderTest1, DeleteProgramValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DeleteRenderbuffersValidArgs) { - EXPECT_CALL( - *gl_, - DeleteRenderbuffersEXT(1, Pointee(kServiceRenderbufferId))) - .Times(1); - GetSharedMemoryAs<GLuint*>()[0] = client_renderbuffer_id_; - SpecializedSetup<cmds::DeleteRenderbuffers, 0>(true); - cmds::DeleteRenderbuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetRenderbuffer(client_renderbuffer_id_) == NULL); -} - -TEST_F(GLES2DecoderTest1, DeleteRenderbuffersInvalidArgs) { - GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId; - SpecializedSetup<cmds::DeleteRenderbuffers, 0>(false); - cmds::DeleteRenderbuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest1, DeleteRenderbuffersImmediateValidArgs) { - EXPECT_CALL( - *gl_, - DeleteRenderbuffersEXT(1, Pointee(kServiceRenderbufferId))) +TEST_P(GLES2DecoderTest1, DeleteRenderbuffersImmediateValidArgs) { + EXPECT_CALL(*gl_, DeleteRenderbuffersEXT(1, Pointee(kServiceRenderbufferId))) .Times(1); cmds::DeleteRenderbuffersImmediate& cmd = *GetImmediateAs<cmds::DeleteRenderbuffersImmediate>(); @@ -573,21 +491,19 @@ TEST_F(GLES2DecoderTest1, DeleteRenderbuffersImmediateValidArgs) { EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(client_renderbuffer_id_))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetRenderbuffer(client_renderbuffer_id_) == NULL); + EXPECT_TRUE(GetRenderbuffer(client_renderbuffer_id_) == NULL); } -TEST_F(GLES2DecoderTest1, DeleteRenderbuffersImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, DeleteRenderbuffersImmediateInvalidArgs) { cmds::DeleteRenderbuffersImmediate& cmd = *GetImmediateAs<cmds::DeleteRenderbuffersImmediate>(); SpecializedSetup<cmds::DeleteRenderbuffersImmediate, 0>(false); GLuint temp = kInvalidClientId; cmd.Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } -TEST_F(GLES2DecoderTest1, DeleteShaderValidArgs) { +TEST_P(GLES2DecoderTest1, DeleteShaderValidArgs) { EXPECT_CALL(*gl_, DeleteShader(kServiceShaderId)); SpecializedSetup<cmds::DeleteShader, 0>(true); cmds::DeleteShader cmd; @@ -596,34 +512,8 @@ TEST_F(GLES2DecoderTest1, DeleteShaderValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DeleteTexturesValidArgs) { - EXPECT_CALL( - *gl_, - DeleteTextures(1, Pointee(kServiceTextureId))) - .Times(1); - GetSharedMemoryAs<GLuint*>()[0] = client_texture_id_; - SpecializedSetup<cmds::DeleteTextures, 0>(true); - cmds::DeleteTextures cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetTexture(client_texture_id_) == NULL); -} - -TEST_F(GLES2DecoderTest1, DeleteTexturesInvalidArgs) { - GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId; - SpecializedSetup<cmds::DeleteTextures, 0>(false); - cmds::DeleteTextures cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest1, DeleteTexturesImmediateValidArgs) { - EXPECT_CALL( - *gl_, - DeleteTextures(1, Pointee(kServiceTextureId))) - .Times(1); +TEST_P(GLES2DecoderTest1, DeleteTexturesImmediateValidArgs) { + EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(kServiceTextureId))).Times(1); cmds::DeleteTexturesImmediate& cmd = *GetImmediateAs<cmds::DeleteTexturesImmediate>(); SpecializedSetup<cmds::DeleteTexturesImmediate, 0>(true); @@ -631,21 +521,19 @@ TEST_F(GLES2DecoderTest1, DeleteTexturesImmediateValidArgs) { EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(client_texture_id_))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetTexture(client_texture_id_) == NULL); + EXPECT_TRUE(GetTexture(client_texture_id_) == NULL); } -TEST_F(GLES2DecoderTest1, DeleteTexturesImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, DeleteTexturesImmediateInvalidArgs) { cmds::DeleteTexturesImmediate& cmd = *GetImmediateAs<cmds::DeleteTexturesImmediate>(); SpecializedSetup<cmds::DeleteTexturesImmediate, 0>(false); GLuint temp = kInvalidClientId; cmd.Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } -TEST_F(GLES2DecoderTest1, DepthFuncValidArgs) { +TEST_P(GLES2DecoderTest1, DepthFuncValidArgs) { EXPECT_CALL(*gl_, DepthFunc(GL_NEVER)); SpecializedSetup<cmds::DepthFunc, 0>(true); cmds::DepthFunc cmd; @@ -654,7 +542,7 @@ TEST_F(GLES2DecoderTest1, DepthFuncValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DepthMaskValidArgs) { +TEST_P(GLES2DecoderTest1, DepthMaskValidArgs) { SpecializedSetup<cmds::DepthMask, 0>(true); cmds::DepthMask cmd; cmd.Init(true); @@ -662,7 +550,7 @@ TEST_F(GLES2DecoderTest1, DepthMaskValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DepthRangefValidArgs) { +TEST_P(GLES2DecoderTest1, DepthRangefValidArgs) { EXPECT_CALL(*gl_, DepthRange(1, 2)); SpecializedSetup<cmds::DepthRangef, 0>(true); cmds::DepthRangef cmd; @@ -671,7 +559,7 @@ TEST_F(GLES2DecoderTest1, DepthRangefValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DetachShaderValidArgs) { +TEST_P(GLES2DecoderTest1, DetachShaderValidArgs) { EXPECT_CALL(*gl_, DetachShader(kServiceProgramId, kServiceShaderId)); SpecializedSetup<cmds::DetachShader, 0>(true); cmds::DetachShader cmd; @@ -680,8 +568,8 @@ TEST_F(GLES2DecoderTest1, DetachShaderValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DisableValidArgs) { - EXPECT_CALL(*gl_, Disable(GL_BLEND)); +TEST_P(GLES2DecoderTest1, DisableValidArgs) { + SetupExpectationsForEnableDisable(GL_BLEND, false); SpecializedSetup<cmds::Disable, 0>(true); cmds::Disable cmd; cmd.Init(GL_BLEND); @@ -689,7 +577,7 @@ TEST_F(GLES2DecoderTest1, DisableValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, DisableInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, DisableInvalidArgs0_0) { EXPECT_CALL(*gl_, Disable(_)).Times(0); SpecializedSetup<cmds::Disable, 0>(false); cmds::Disable cmd; @@ -698,7 +586,7 @@ TEST_F(GLES2DecoderTest1, DisableInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, DisableInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, DisableInvalidArgs0_1) { EXPECT_CALL(*gl_, Disable(_)).Times(0); SpecializedSetup<cmds::Disable, 0>(false); cmds::Disable cmd; @@ -707,7 +595,7 @@ TEST_F(GLES2DecoderTest1, DisableInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, DisableVertexAttribArrayValidArgs) { +TEST_P(GLES2DecoderTest1, DisableVertexAttribArrayValidArgs) { EXPECT_CALL(*gl_, DisableVertexAttribArray(1)); SpecializedSetup<cmds::DisableVertexAttribArray, 0>(true); cmds::DisableVertexAttribArray cmd; @@ -719,9 +607,8 @@ TEST_F(GLES2DecoderTest1, DisableVertexAttribArrayValidArgs) { // TODO(gman): DrawElements - -TEST_F(GLES2DecoderTest1, EnableValidArgs) { - EXPECT_CALL(*gl_, Enable(GL_BLEND)); +TEST_P(GLES2DecoderTest1, EnableValidArgs) { + SetupExpectationsForEnableDisable(GL_BLEND, true); SpecializedSetup<cmds::Enable, 0>(true); cmds::Enable cmd; cmd.Init(GL_BLEND); @@ -729,7 +616,7 @@ TEST_F(GLES2DecoderTest1, EnableValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, EnableInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, EnableInvalidArgs0_0) { EXPECT_CALL(*gl_, Enable(_)).Times(0); SpecializedSetup<cmds::Enable, 0>(false); cmds::Enable cmd; @@ -738,7 +625,7 @@ TEST_F(GLES2DecoderTest1, EnableInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, EnableInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, EnableInvalidArgs0_1) { EXPECT_CALL(*gl_, Enable(_)).Times(0); SpecializedSetup<cmds::Enable, 0>(false); cmds::Enable cmd; @@ -747,7 +634,7 @@ TEST_F(GLES2DecoderTest1, EnableInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, EnableVertexAttribArrayValidArgs) { +TEST_P(GLES2DecoderTest1, EnableVertexAttribArrayValidArgs) { EXPECT_CALL(*gl_, EnableVertexAttribArray(1)); SpecializedSetup<cmds::EnableVertexAttribArray, 0>(true); cmds::EnableVertexAttribArray cmd; @@ -756,7 +643,7 @@ TEST_F(GLES2DecoderTest1, EnableVertexAttribArrayValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, FinishValidArgs) { +TEST_P(GLES2DecoderTest1, FinishValidArgs) { EXPECT_CALL(*gl_, Finish()); SpecializedSetup<cmds::Finish, 0>(true); cmds::Finish cmd; @@ -765,7 +652,7 @@ TEST_F(GLES2DecoderTest1, FinishValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, FlushValidArgs) { +TEST_P(GLES2DecoderTest1, FlushValidArgs) { EXPECT_CALL(*gl_, Flush()); SpecializedSetup<cmds::Flush, 0>(true); cmds::Flush cmd; @@ -774,112 +661,110 @@ TEST_F(GLES2DecoderTest1, FlushValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferRenderbufferValidArgs) { - EXPECT_CALL( - *gl_, FramebufferRenderbufferEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - kServiceRenderbufferId)); +TEST_P(GLES2DecoderTest1, FramebufferRenderbufferValidArgs) { + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + kServiceRenderbufferId)); SpecializedSetup<cmds::FramebufferRenderbuffer, 0>(true); cmds::FramebufferRenderbuffer cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs0_0) { EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)).Times(0); SpecializedSetup<cmds::FramebufferRenderbuffer, 0>(false); cmds::FramebufferRenderbuffer cmd; - cmd.Init( - GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); + cmd.Init(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs0_1) { EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)).Times(0); SpecializedSetup<cmds::FramebufferRenderbuffer, 0>(false); cmds::FramebufferRenderbuffer cmd; - cmd.Init( - GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); + cmd.Init(GL_READ_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs2_0) { EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)).Times(0); SpecializedSetup<cmds::FramebufferRenderbuffer, 0>(false); cmds::FramebufferRenderbuffer cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER, - client_renderbuffer_id_); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER, + client_renderbuffer_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferTexture2DValidArgs) { - EXPECT_CALL( - *gl_, FramebufferTexture2DEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - kServiceTextureId, 0)); +TEST_P(GLES2DecoderTest1, FramebufferTexture2DValidArgs) { + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kServiceTextureId, + 0)); SpecializedSetup<cmds::FramebufferTexture2D, 0>(true); cmds::FramebufferTexture2D cmd; cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_, - 0); + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs0_0) { EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); SpecializedSetup<cmds::FramebufferTexture2D, 0>(false); cmds::FramebufferTexture2D cmd; - cmd.Init( - GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_, 0); + cmd.Init(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs0_1) { EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); SpecializedSetup<cmds::FramebufferTexture2D, 0>(false); cmds::FramebufferTexture2D cmd; - cmd.Init( - GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_, 0); + cmd.Init(GL_READ_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs2_0) { EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); SpecializedSetup<cmds::FramebufferTexture2D, 0>(false); cmds::FramebufferTexture2D cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_PROXY_TEXTURE_CUBE_MAP, - client_texture_id_, 0); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_PROXY_TEXTURE_CUBE_MAP, + client_texture_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs4_0) { - EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); - SpecializedSetup<cmds::FramebufferTexture2D, 0>(false); - cmds::FramebufferTexture2D cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_, - 1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest1, FrontFaceValidArgs) { +TEST_P(GLES2DecoderTest1, FrontFaceValidArgs) { EXPECT_CALL(*gl_, FrontFace(GL_CW)); SpecializedSetup<cmds::FrontFace, 0>(true); cmds::FrontFace cmd; @@ -888,41 +773,19 @@ TEST_F(GLES2DecoderTest1, FrontFaceValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GenBuffersValidArgs) { - EXPECT_CALL(*gl_, GenBuffersARB(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - GetSharedMemoryAs<GLuint*>()[0] = kNewClientId; - SpecializedSetup<cmds::GenBuffers, 0>(true); - cmds::GenBuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetBuffer(kNewClientId) != NULL); -} - -TEST_F(GLES2DecoderTest1, GenBuffersInvalidArgs) { - EXPECT_CALL(*gl_, GenBuffersARB(_, _)).Times(0); - GetSharedMemoryAs<GLuint*>()[0] = client_buffer_id_; - SpecializedSetup<cmds::GenBuffers, 0>(false); - cmds::GenBuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest1, GenBuffersImmediateValidArgs) { +TEST_P(GLES2DecoderTest1, GenBuffersImmediateValidArgs) { EXPECT_CALL(*gl_, GenBuffersARB(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); cmds::GenBuffersImmediate* cmd = GetImmediateAs<cmds::GenBuffersImmediate>(); GLuint temp = kNewClientId; SpecializedSetup<cmds::GenBuffersImmediate, 0>(true); cmd->Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_TRUE(GetBuffer(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, GenBuffersImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, GenBuffersImmediateInvalidArgs) { EXPECT_CALL(*gl_, GenBuffersARB(_, _)).Times(0); cmds::GenBuffersImmediate* cmd = GetImmediateAs<cmds::GenBuffersImmediate>(); SpecializedSetup<cmds::GenBuffersImmediate, 0>(false); @@ -931,7 +794,7 @@ TEST_F(GLES2DecoderTest1, GenBuffersImmediateInvalidArgs) { ExecuteImmediateCmd(*cmd, sizeof(&client_buffer_id_))); } -TEST_F(GLES2DecoderTest1, GenerateMipmapValidArgs) { +TEST_P(GLES2DecoderTest1, GenerateMipmapValidArgs) { EXPECT_CALL(*gl_, GenerateMipmapEXT(GL_TEXTURE_2D)); SpecializedSetup<cmds::GenerateMipmap, 0>(true); cmds::GenerateMipmap cmd; @@ -940,7 +803,7 @@ TEST_F(GLES2DecoderTest1, GenerateMipmapValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GenerateMipmapInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GenerateMipmapInvalidArgs0_0) { EXPECT_CALL(*gl_, GenerateMipmapEXT(_)).Times(0); SpecializedSetup<cmds::GenerateMipmap, 0>(false); cmds::GenerateMipmap cmd; @@ -949,7 +812,7 @@ TEST_F(GLES2DecoderTest1, GenerateMipmapInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GenerateMipmapInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, GenerateMipmapInvalidArgs0_1) { EXPECT_CALL(*gl_, GenerateMipmapEXT(_)).Times(0); SpecializedSetup<cmds::GenerateMipmap, 0>(false); cmds::GenerateMipmap cmd; @@ -958,28 +821,7 @@ TEST_F(GLES2DecoderTest1, GenerateMipmapInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GenFramebuffersValidArgs) { - EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - GetSharedMemoryAs<GLuint*>()[0] = kNewClientId; - SpecializedSetup<cmds::GenFramebuffers, 0>(true); - cmds::GenFramebuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetFramebuffer(kNewClientId) != NULL); -} - -TEST_F(GLES2DecoderTest1, GenFramebuffersInvalidArgs) { - EXPECT_CALL(*gl_, GenFramebuffersEXT(_, _)).Times(0); - GetSharedMemoryAs<GLuint*>()[0] = client_framebuffer_id_; - SpecializedSetup<cmds::GenFramebuffers, 0>(false); - cmds::GenFramebuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest1, GenFramebuffersImmediateValidArgs) { +TEST_P(GLES2DecoderTest1, GenFramebuffersImmediateValidArgs) { EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); cmds::GenFramebuffersImmediate* cmd = @@ -987,13 +829,12 @@ TEST_F(GLES2DecoderTest1, GenFramebuffersImmediateValidArgs) { GLuint temp = kNewClientId; SpecializedSetup<cmds::GenFramebuffersImmediate, 0>(true); cmd->Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_TRUE(GetFramebuffer(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, GenFramebuffersImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, GenFramebuffersImmediateInvalidArgs) { EXPECT_CALL(*gl_, GenFramebuffersEXT(_, _)).Times(0); cmds::GenFramebuffersImmediate* cmd = GetImmediateAs<cmds::GenFramebuffersImmediate>(); @@ -1003,28 +844,7 @@ TEST_F(GLES2DecoderTest1, GenFramebuffersImmediateInvalidArgs) { ExecuteImmediateCmd(*cmd, sizeof(&client_framebuffer_id_))); } -TEST_F(GLES2DecoderTest1, GenRenderbuffersValidArgs) { - EXPECT_CALL(*gl_, GenRenderbuffersEXT(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - GetSharedMemoryAs<GLuint*>()[0] = kNewClientId; - SpecializedSetup<cmds::GenRenderbuffers, 0>(true); - cmds::GenRenderbuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetRenderbuffer(kNewClientId) != NULL); -} - -TEST_F(GLES2DecoderTest1, GenRenderbuffersInvalidArgs) { - EXPECT_CALL(*gl_, GenRenderbuffersEXT(_, _)).Times(0); - GetSharedMemoryAs<GLuint*>()[0] = client_renderbuffer_id_; - SpecializedSetup<cmds::GenRenderbuffers, 0>(false); - cmds::GenRenderbuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest1, GenRenderbuffersImmediateValidArgs) { +TEST_P(GLES2DecoderTest1, GenRenderbuffersImmediateValidArgs) { EXPECT_CALL(*gl_, GenRenderbuffersEXT(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); cmds::GenRenderbuffersImmediate* cmd = @@ -1032,13 +852,12 @@ TEST_F(GLES2DecoderTest1, GenRenderbuffersImmediateValidArgs) { GLuint temp = kNewClientId; SpecializedSetup<cmds::GenRenderbuffersImmediate, 0>(true); cmd->Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_TRUE(GetRenderbuffer(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, GenRenderbuffersImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, GenRenderbuffersImmediateInvalidArgs) { EXPECT_CALL(*gl_, GenRenderbuffersEXT(_, _)).Times(0); cmds::GenRenderbuffersImmediate* cmd = GetImmediateAs<cmds::GenRenderbuffersImmediate>(); @@ -1048,28 +867,7 @@ TEST_F(GLES2DecoderTest1, GenRenderbuffersImmediateInvalidArgs) { ExecuteImmediateCmd(*cmd, sizeof(&client_renderbuffer_id_))); } -TEST_F(GLES2DecoderTest1, GenTexturesValidArgs) { - EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - GetSharedMemoryAs<GLuint*>()[0] = kNewClientId; - SpecializedSetup<cmds::GenTextures, 0>(true); - cmds::GenTextures cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetTexture(kNewClientId) != NULL); -} - -TEST_F(GLES2DecoderTest1, GenTexturesInvalidArgs) { - EXPECT_CALL(*gl_, GenTextures(_, _)).Times(0); - GetSharedMemoryAs<GLuint*>()[0] = client_texture_id_; - SpecializedSetup<cmds::GenTextures, 0>(false); - cmds::GenTextures cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest1, GenTexturesImmediateValidArgs) { +TEST_P(GLES2DecoderTest1, GenTexturesImmediateValidArgs) { EXPECT_CALL(*gl_, GenTextures(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); cmds::GenTexturesImmediate* cmd = @@ -1077,13 +875,12 @@ TEST_F(GLES2DecoderTest1, GenTexturesImmediateValidArgs) { GLuint temp = kNewClientId; SpecializedSetup<cmds::GenTexturesImmediate, 0>(true); cmd->Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_TRUE(GetTexture(kNewClientId) != NULL); } -TEST_F(GLES2DecoderTest1, GenTexturesImmediateInvalidArgs) { +TEST_P(GLES2DecoderTest1, GenTexturesImmediateInvalidArgs) { EXPECT_CALL(*gl_, GenTextures(_, _)).Times(0); cmds::GenTexturesImmediate* cmd = GetImmediateAs<cmds::GenTexturesImmediate>(); @@ -1100,10 +897,7 @@ TEST_F(GLES2DecoderTest1, GenTexturesImmediateInvalidArgs) { // TODO(gman): GetAttribLocation -// TODO(gman): GetAttribLocationBucket - - -TEST_F(GLES2DecoderTest1, GetBooleanvValidArgs) { +TEST_P(GLES2DecoderTest1, GetBooleanvValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1116,13 +910,12 @@ TEST_F(GLES2DecoderTest1, GetBooleanvValidArgs) { cmds::GetBooleanv cmd; cmd.Init(GL_ACTIVE_TEXTURE, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_ACTIVE_TEXTURE), + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ACTIVE_TEXTURE), result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetBooleanvInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GetBooleanvInvalidArgs0_0) { EXPECT_CALL(*gl_, GetBooleanv(_, _)).Times(0); SpecializedSetup<cmds::GetBooleanv, 0>(false); cmds::GetBooleanv::Result* result = @@ -1135,7 +928,7 @@ TEST_F(GLES2DecoderTest1, GetBooleanvInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetBooleanvInvalidArgs1_0) { +TEST_P(GLES2DecoderTest1, GetBooleanvInvalidArgs1_0) { EXPECT_CALL(*gl_, GetBooleanv(_, _)).Times(0); SpecializedSetup<cmds::GetBooleanv, 0>(false); cmds::GetBooleanv::Result* result = @@ -1147,7 +940,7 @@ TEST_F(GLES2DecoderTest1, GetBooleanvInvalidArgs1_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetBooleanvInvalidArgs1_1) { +TEST_P(GLES2DecoderTest1, GetBooleanvInvalidArgs1_1) { EXPECT_CALL(*gl_, GetBooleanv(_, _)).Times(0); SpecializedSetup<cmds::GetBooleanv, 0>(false); cmds::GetBooleanv::Result* result = @@ -1159,53 +952,55 @@ TEST_F(GLES2DecoderTest1, GetBooleanvInvalidArgs1_1) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetBufferParameterivValidArgs) { +TEST_P(GLES2DecoderTest1, GetBufferParameterivValidArgs) { SpecializedSetup<cmds::GetBufferParameteriv, 0>(true); typedef cmds::GetBufferParameteriv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); result->size = 0; cmds::GetBufferParameteriv cmd; - cmd.Init( - GL_ARRAY_BUFFER, GL_BUFFER_SIZE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_ARRAY_BUFFER, + GL_BUFFER_SIZE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_BUFFER_SIZE), + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_BUFFER_SIZE), result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetBufferParameterivInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GetBufferParameterivInvalidArgs0_0) { EXPECT_CALL(*gl_, GetBufferParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetBufferParameteriv, 0>(false); cmds::GetBufferParameteriv::Result* result = static_cast<cmds::GetBufferParameteriv::Result*>(shared_memory_address_); result->size = 0; cmds::GetBufferParameteriv cmd; - cmd.Init( - GL_RENDERBUFFER, GL_BUFFER_SIZE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_RENDERBUFFER, + GL_BUFFER_SIZE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetBufferParameterivInvalidArgs1_0) { +TEST_P(GLES2DecoderTest1, GetBufferParameterivInvalidArgs1_0) { EXPECT_CALL(*gl_, GetBufferParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetBufferParameteriv, 0>(false); cmds::GetBufferParameteriv::Result* result = static_cast<cmds::GetBufferParameteriv::Result*>(shared_memory_address_); result->size = 0; cmds::GetBufferParameteriv cmd; - cmd.Init( - GL_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_ARRAY_BUFFER, + GL_PIXEL_PACK_BUFFER, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetBufferParameterivInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetBufferParameterivInvalidArgs2_0) { EXPECT_CALL(*gl_, GetBufferParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetBufferParameteriv, 0>(false); cmds::GetBufferParameteriv::Result* result = @@ -1217,21 +1012,22 @@ TEST_F(GLES2DecoderTest1, GetBufferParameterivInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetBufferParameterivInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetBufferParameterivInvalidArgs2_1) { EXPECT_CALL(*gl_, GetBufferParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetBufferParameteriv, 0>(false); cmds::GetBufferParameteriv::Result* result = static_cast<cmds::GetBufferParameteriv::Result*>(shared_memory_address_); result->size = 0; cmds::GetBufferParameteriv cmd; - cmd.Init( - GL_ARRAY_BUFFER, GL_BUFFER_SIZE, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(GL_ARRAY_BUFFER, + GL_BUFFER_SIZE, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetErrorValidArgs) { +TEST_P(GLES2DecoderTest1, GetErrorValidArgs) { EXPECT_CALL(*gl_, GetError()); SpecializedSetup<cmds::GetError, 0>(true); cmds::GetError cmd; @@ -1240,7 +1036,7 @@ TEST_F(GLES2DecoderTest1, GetErrorValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetErrorInvalidArgsBadSharedMemoryId) { +TEST_P(GLES2DecoderTest1, GetErrorInvalidArgsBadSharedMemoryId) { EXPECT_CALL(*gl_, GetError()).Times(0); SpecializedSetup<cmds::GetError, 0>(false); cmds::GetError cmd; @@ -1250,7 +1046,7 @@ TEST_F(GLES2DecoderTest1, GetErrorInvalidArgsBadSharedMemoryId) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest1, GetFloatvValidArgs) { +TEST_P(GLES2DecoderTest1, GetFloatvValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1263,13 +1059,12 @@ TEST_F(GLES2DecoderTest1, GetFloatvValidArgs) { cmds::GetFloatv cmd; cmd.Init(GL_ACTIVE_TEXTURE, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_ACTIVE_TEXTURE), + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ACTIVE_TEXTURE), result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetFloatvInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GetFloatvInvalidArgs0_0) { EXPECT_CALL(*gl_, GetFloatv(_, _)).Times(0); SpecializedSetup<cmds::GetFloatv, 0>(false); cmds::GetFloatv::Result* result = @@ -1282,7 +1077,7 @@ TEST_F(GLES2DecoderTest1, GetFloatvInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetFloatvInvalidArgs1_0) { +TEST_P(GLES2DecoderTest1, GetFloatvInvalidArgs1_0) { EXPECT_CALL(*gl_, GetFloatv(_, _)).Times(0); SpecializedSetup<cmds::GetFloatv, 0>(false); cmds::GetFloatv::Result* result = @@ -1294,7 +1089,7 @@ TEST_F(GLES2DecoderTest1, GetFloatvInvalidArgs1_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetFloatvInvalidArgs1_1) { +TEST_P(GLES2DecoderTest1, GetFloatvInvalidArgs1_1) { EXPECT_CALL(*gl_, GetFloatv(_, _)).Times(0); SpecializedSetup<cmds::GetFloatv, 0>(false); cmds::GetFloatv::Result* result = @@ -1306,7 +1101,7 @@ TEST_F(GLES2DecoderTest1, GetFloatvInvalidArgs1_1) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivValidArgs) { +TEST_P(GLES2DecoderTest1, GetFramebufferAttachmentParameterivValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1314,16 +1109,19 @@ TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivValidArgs) { SpecializedSetup<cmds::GetFramebufferAttachmentParameteriv, 0>(true); typedef cmds::GetFramebufferAttachmentParameteriv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL( - *gl_, GetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, result->GetData())); + EXPECT_CALL(*gl_, + GetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + result->GetData())); result->size = 0; cmds::GetFramebufferAttachmentParameteriv cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE), @@ -1331,76 +1129,81 @@ TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs0_0) { - EXPECT_CALL( - *gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)).Times(0); +TEST_P(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs0_0) { + EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)) + .Times(0); SpecializedSetup<cmds::GetFramebufferAttachmentParameteriv, 0>(false); cmds::GetFramebufferAttachmentParameteriv::Result* result = static_cast<cmds::GetFramebufferAttachmentParameteriv::Result*>( shared_memory_address_); result->size = 0; cmds::GetFramebufferAttachmentParameteriv cmd; - cmd.Init( - GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs0_1) { - EXPECT_CALL( - *gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)).Times(0); +TEST_P(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs0_1) { + EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)) + .Times(0); SpecializedSetup<cmds::GetFramebufferAttachmentParameteriv, 0>(false); cmds::GetFramebufferAttachmentParameteriv::Result* result = static_cast<cmds::GetFramebufferAttachmentParameteriv::Result*>( shared_memory_address_); result->size = 0; cmds::GetFramebufferAttachmentParameteriv cmd; - cmd.Init( - GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_READ_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs3_0) { - EXPECT_CALL( - *gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)).Times(0); +TEST_P(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs3_0) { + EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)) + .Times(0); SpecializedSetup<cmds::GetFramebufferAttachmentParameteriv, 0>(false); cmds::GetFramebufferAttachmentParameteriv::Result* result = static_cast<cmds::GetFramebufferAttachmentParameteriv::Result*>( shared_memory_address_); result->size = 0; cmds::GetFramebufferAttachmentParameteriv cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, kInvalidSharedMemoryId, 0); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + kInvalidSharedMemoryId, + 0); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs3_1) { - EXPECT_CALL( - *gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)).Times(0); +TEST_P(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs3_1) { + EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)) + .Times(0); SpecializedSetup<cmds::GetFramebufferAttachmentParameteriv, 0>(false); cmds::GetFramebufferAttachmentParameteriv::Result* result = static_cast<cmds::GetFramebufferAttachmentParameteriv::Result*>( shared_memory_address_); result->size = 0; cmds::GetFramebufferAttachmentParameteriv cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetIntegervValidArgs) { +TEST_P(GLES2DecoderTest1, GetIntegervValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1413,13 +1216,12 @@ TEST_F(GLES2DecoderTest1, GetIntegervValidArgs) { cmds::GetIntegerv cmd; cmd.Init(GL_ACTIVE_TEXTURE, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_ACTIVE_TEXTURE), + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ACTIVE_TEXTURE), result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetIntegervInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GetIntegervInvalidArgs0_0) { EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0); SpecializedSetup<cmds::GetIntegerv, 0>(false); cmds::GetIntegerv::Result* result = @@ -1432,7 +1234,7 @@ TEST_F(GLES2DecoderTest1, GetIntegervInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetIntegervInvalidArgs1_0) { +TEST_P(GLES2DecoderTest1, GetIntegervInvalidArgs1_0) { EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0); SpecializedSetup<cmds::GetIntegerv, 0>(false); cmds::GetIntegerv::Result* result = @@ -1444,7 +1246,7 @@ TEST_F(GLES2DecoderTest1, GetIntegervInvalidArgs1_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetIntegervInvalidArgs1_1) { +TEST_P(GLES2DecoderTest1, GetIntegervInvalidArgs1_1) { EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0); SpecializedSetup<cmds::GetIntegerv, 0>(false); cmds::GetIntegerv::Result* result = @@ -1456,23 +1258,23 @@ TEST_F(GLES2DecoderTest1, GetIntegervInvalidArgs1_1) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetProgramivValidArgs) { +TEST_P(GLES2DecoderTest1, GetProgramivValidArgs) { SpecializedSetup<cmds::GetProgramiv, 0>(true); typedef cmds::GetProgramiv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); result->size = 0; cmds::GetProgramiv cmd; - cmd.Init( - client_program_id_, GL_DELETE_STATUS, shared_memory_id_, - shared_memory_offset_); + cmd.Init(client_program_id_, + GL_DELETE_STATUS, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_DELETE_STATUS), + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DELETE_STATUS), result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetProgramivInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetProgramivInvalidArgs2_0) { EXPECT_CALL(*gl_, GetProgramiv(_, _, _)).Times(0); SpecializedSetup<cmds::GetProgramiv, 0>(false); cmds::GetProgramiv::Result* result = @@ -1484,23 +1286,24 @@ TEST_F(GLES2DecoderTest1, GetProgramivInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetProgramivInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetProgramivInvalidArgs2_1) { EXPECT_CALL(*gl_, GetProgramiv(_, _, _)).Times(0); SpecializedSetup<cmds::GetProgramiv, 0>(false); cmds::GetProgramiv::Result* result = static_cast<cmds::GetProgramiv::Result*>(shared_memory_address_); result->size = 0; cmds::GetProgramiv cmd; - cmd.Init( - client_program_id_, GL_DELETE_STATUS, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(client_program_id_, + GL_DELETE_STATUS, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetProgramInfoLogValidArgs) { +TEST_P(GLES2DecoderTest1, GetProgramInfoLogValidArgs) { const char* kInfo = "hello"; - const uint32 kBucketId = 123; + const uint32_t kBucketId = 123; SpecializedSetup<cmds::GetProgramInfoLog, 0>(true); cmds::GetProgramInfoLog cmd; @@ -1509,20 +1312,20 @@ TEST_F(GLES2DecoderTest1, GetProgramInfoLogValidArgs) { CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); ASSERT_TRUE(bucket != NULL); EXPECT_EQ(strlen(kInfo) + 1, bucket->size()); - EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kInfo, - bucket->size())); + EXPECT_EQ(0, + memcmp(bucket->GetData(0, bucket->size()), kInfo, bucket->size())); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetProgramInfoLogInvalidArgs) { - const uint32 kBucketId = 123; +TEST_P(GLES2DecoderTest1, GetProgramInfoLogInvalidArgs) { + const uint32_t kBucketId = 123; cmds::GetProgramInfoLog cmd; cmd.Init(kInvalidClientId, kBucketId); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivValidArgs) { +TEST_P(GLES2DecoderTest1, GetRenderbufferParameterivValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1531,13 +1334,15 @@ TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivValidArgs) { typedef cmds::GetRenderbufferParameteriv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); EXPECT_CALL( - *gl_, GetRenderbufferParameterivEXT( + *gl_, + GetRenderbufferParameterivEXT( GL_RENDERBUFFER, GL_RENDERBUFFER_RED_SIZE, result->GetData())); result->size = 0; cmds::GetRenderbufferParameteriv cmd; - cmd.Init( - GL_RENDERBUFFER, GL_RENDERBUFFER_RED_SIZE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_RENDERBUFFER, + GL_RENDERBUFFER_RED_SIZE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( GL_RENDERBUFFER_RED_SIZE), @@ -1545,7 +1350,7 @@ TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs0_0) { EXPECT_CALL(*gl_, GetRenderbufferParameterivEXT(_, _, _)).Times(0); SpecializedSetup<cmds::GetRenderbufferParameteriv, 0>(false); cmds::GetRenderbufferParameteriv::Result* result = @@ -1553,15 +1358,16 @@ TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs0_0) { shared_memory_address_); result->size = 0; cmds::GetRenderbufferParameteriv cmd; - cmd.Init( - GL_FRAMEBUFFER, GL_RENDERBUFFER_RED_SIZE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_FRAMEBUFFER, + GL_RENDERBUFFER_RED_SIZE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs2_0) { EXPECT_CALL(*gl_, GetRenderbufferParameterivEXT(_, _, _)).Times(0); SpecializedSetup<cmds::GetRenderbufferParameteriv, 0>(false); cmds::GetRenderbufferParameteriv::Result* result = @@ -1575,7 +1381,7 @@ TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs2_1) { EXPECT_CALL(*gl_, GetRenderbufferParameterivEXT(_, _, _)).Times(0); SpecializedSetup<cmds::GetRenderbufferParameteriv, 0>(false); cmds::GetRenderbufferParameteriv::Result* result = @@ -1583,14 +1389,15 @@ TEST_F(GLES2DecoderTest1, GetRenderbufferParameterivInvalidArgs2_1) { shared_memory_address_); result->size = 0; cmds::GetRenderbufferParameteriv cmd; - cmd.Init( - GL_RENDERBUFFER, GL_RENDERBUFFER_RED_SIZE, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(GL_RENDERBUFFER, + GL_RENDERBUFFER_RED_SIZE, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetShaderivValidArgs) { +TEST_P(GLES2DecoderTest1, GetShaderivValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1598,21 +1405,21 @@ TEST_F(GLES2DecoderTest1, GetShaderivValidArgs) { SpecializedSetup<cmds::GetShaderiv, 0>(true); typedef cmds::GetShaderiv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL( - *gl_, GetShaderiv(kServiceShaderId, GL_SHADER_TYPE, result->GetData())); + EXPECT_CALL(*gl_, + GetShaderiv(kServiceShaderId, GL_SHADER_TYPE, result->GetData())); result->size = 0; cmds::GetShaderiv cmd; - cmd.Init( - client_shader_id_, GL_SHADER_TYPE, shared_memory_id_, - shared_memory_offset_); + cmd.Init(client_shader_id_, + GL_SHADER_TYPE, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_SHADER_TYPE), + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_SHADER_TYPE), result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetShaderivInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetShaderivInvalidArgs2_0) { EXPECT_CALL(*gl_, GetShaderiv(_, _, _)).Times(0); SpecializedSetup<cmds::GetShaderiv, 0>(false); cmds::GetShaderiv::Result* result = @@ -1624,16 +1431,17 @@ TEST_F(GLES2DecoderTest1, GetShaderivInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetShaderivInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetShaderivInvalidArgs2_1) { EXPECT_CALL(*gl_, GetShaderiv(_, _, _)).Times(0); SpecializedSetup<cmds::GetShaderiv, 0>(false); cmds::GetShaderiv::Result* result = static_cast<cmds::GetShaderiv::Result*>(shared_memory_address_); result->size = 0; cmds::GetShaderiv cmd; - cmd.Init( - client_shader_id_, GL_SHADER_TYPE, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(client_shader_id_, + GL_SHADER_TYPE, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } @@ -1643,8 +1451,7 @@ TEST_F(GLES2DecoderTest1, GetShaderivInvalidArgs2_1) { // TODO(gman): GetShaderSource // TODO(gman): GetString - -TEST_F(GLES2DecoderTest1, GetTexParameterfvValidArgs) { +TEST_P(GLES2DecoderTest1, GetTexParameterfvValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1652,52 +1459,55 @@ TEST_F(GLES2DecoderTest1, GetTexParameterfvValidArgs) { SpecializedSetup<cmds::GetTexParameterfv, 0>(true); typedef cmds::GetTexParameterfv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL( - *gl_, GetTexParameterfv( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, result->GetData())); + EXPECT_CALL(*gl_, + GetTexParameterfv( + GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, result->GetData())); result->size = 0; cmds::GetTexParameterfv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_TEXTURE_MAG_FILTER), - result->GetNumResults()); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER), + result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetTexParameterfvInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs0_0) { EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameterfv, 0>(false); cmds::GetTexParameterfv::Result* result = static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_); result->size = 0; cmds::GetTexParameterfv cmd; - cmd.Init( - GL_PROXY_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_PROXY_TEXTURE_CUBE_MAP, + GL_TEXTURE_MAG_FILTER, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetTexParameterfvInvalidArgs1_0) { +TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs1_0) { EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameterfv, 0>(false); cmds::GetTexParameterfv::Result* result = static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_); result->size = 0; cmds::GetTexParameterfv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_TEXTURE_2D, + GL_GENERATE_MIPMAP, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetTexParameterfvInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs2_0) { EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameterfv, 0>(false); cmds::GetTexParameterfv::Result* result = @@ -1709,21 +1519,22 @@ TEST_F(GLES2DecoderTest1, GetTexParameterfvInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetTexParameterfvInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs2_1) { EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameterfv, 0>(false); cmds::GetTexParameterfv::Result* result = static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_); result->size = 0; cmds::GetTexParameterfv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetTexParameterivValidArgs) { +TEST_P(GLES2DecoderTest1, GetTexParameterivValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) @@ -1731,52 +1542,55 @@ TEST_F(GLES2DecoderTest1, GetTexParameterivValidArgs) { SpecializedSetup<cmds::GetTexParameteriv, 0>(true); typedef cmds::GetTexParameteriv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL( - *gl_, GetTexParameteriv( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, result->GetData())); + EXPECT_CALL(*gl_, + GetTexParameteriv( + GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, result->GetData())); result->size = 0; cmds::GetTexParameteriv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_TEXTURE_MAG_FILTER), - result->GetNumResults()); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER), + result->GetNumResults()); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs0_0) { EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameteriv, 0>(false); cmds::GetTexParameteriv::Result* result = static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_); result->size = 0; cmds::GetTexParameteriv cmd; - cmd.Init( - GL_PROXY_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_PROXY_TEXTURE_CUBE_MAP, + GL_TEXTURE_MAG_FILTER, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs1_0) { +TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs1_0) { EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameteriv, 0>(false); cmds::GetTexParameteriv::Result* result = static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_); result->size = 0; cmds::GetTexParameteriv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_, - shared_memory_offset_); + cmd.Init(GL_TEXTURE_2D, + GL_GENERATE_MIPMAP, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_0) { EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameteriv, 0>(false); cmds::GetTexParameteriv::Result* result = @@ -1788,16 +1602,17 @@ TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_1) { EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0); SpecializedSetup<cmds::GetTexParameteriv, 0>(false); cmds::GetTexParameteriv::Result* result = static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_); result->size = 0; cmds::GetTexParameteriv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } @@ -1807,18 +1622,16 @@ TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_1) { // TODO(gman): GetUniformLocation -// TODO(gman): GetUniformLocationBucket - - -TEST_F(GLES2DecoderTest1, GetVertexAttribfvValidArgs) { +TEST_P(GLES2DecoderTest1, GetVertexAttribfvValidArgs) { SpecializedSetup<cmds::GetVertexAttribfv, 0>(true); typedef cmds::GetVertexAttribfv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); result->size = 0; cmds::GetVertexAttribfv cmd; - cmd.Init( - 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, - shared_memory_offset_); + cmd.Init(1, + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( GL_VERTEX_ATTRIB_ARRAY_NORMALIZED), @@ -1826,7 +1639,7 @@ TEST_F(GLES2DecoderTest1, GetVertexAttribfvValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetVertexAttribfvInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetVertexAttribfvInvalidArgs2_0) { EXPECT_CALL(*gl_, GetVertexAttribfv(_, _, _)).Times(0); SpecializedSetup<cmds::GetVertexAttribfv, 0>(false); cmds::GetVertexAttribfv::Result* result = @@ -1838,29 +1651,31 @@ TEST_F(GLES2DecoderTest1, GetVertexAttribfvInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetVertexAttribfvInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetVertexAttribfvInvalidArgs2_1) { EXPECT_CALL(*gl_, GetVertexAttribfv(_, _, _)).Times(0); SpecializedSetup<cmds::GetVertexAttribfv, 0>(false); cmds::GetVertexAttribfv::Result* result = static_cast<cmds::GetVertexAttribfv::Result*>(shared_memory_address_); result->size = 0; cmds::GetVertexAttribfv cmd; - cmd.Init( - 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(1, + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetVertexAttribivValidArgs) { +TEST_P(GLES2DecoderTest1, GetVertexAttribivValidArgs) { SpecializedSetup<cmds::GetVertexAttribiv, 0>(true); typedef cmds::GetVertexAttribiv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); result->size = 0; cmds::GetVertexAttribiv cmd; - cmd.Init( - 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, - shared_memory_offset_); + cmd.Init(1, + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, + shared_memory_id_, + shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( GL_VERTEX_ATTRIB_ARRAY_NORMALIZED), @@ -1868,7 +1683,7 @@ TEST_F(GLES2DecoderTest1, GetVertexAttribivValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, GetVertexAttribivInvalidArgs2_0) { +TEST_P(GLES2DecoderTest1, GetVertexAttribivInvalidArgs2_0) { EXPECT_CALL(*gl_, GetVertexAttribiv(_, _, _)).Times(0); SpecializedSetup<cmds::GetVertexAttribiv, 0>(false); cmds::GetVertexAttribiv::Result* result = @@ -1880,23 +1695,23 @@ TEST_F(GLES2DecoderTest1, GetVertexAttribivInvalidArgs2_0) { EXPECT_EQ(0u, result->size); } -TEST_F(GLES2DecoderTest1, GetVertexAttribivInvalidArgs2_1) { +TEST_P(GLES2DecoderTest1, GetVertexAttribivInvalidArgs2_1) { EXPECT_CALL(*gl_, GetVertexAttribiv(_, _, _)).Times(0); SpecializedSetup<cmds::GetVertexAttribiv, 0>(false); cmds::GetVertexAttribiv::Result* result = static_cast<cmds::GetVertexAttribiv::Result*>(shared_memory_address_); result->size = 0; cmds::GetVertexAttribiv cmd; - cmd.Init( - 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, - kInvalidSharedMemoryOffset); + cmd.Init(1, + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, + shared_memory_id_, + kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } // TODO(gman): GetVertexAttribPointerv - -TEST_F(GLES2DecoderTest1, HintValidArgs) { +TEST_P(GLES2DecoderTest1, HintValidArgs) { EXPECT_CALL(*gl_, Hint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST)); SpecializedSetup<cmds::Hint, 0>(true); cmds::Hint cmd; @@ -1905,7 +1720,7 @@ TEST_F(GLES2DecoderTest1, HintValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, HintInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, HintInvalidArgs0_0) { EXPECT_CALL(*gl_, Hint(_, _)).Times(0); SpecializedSetup<cmds::Hint, 0>(false); cmds::Hint cmd; @@ -1914,7 +1729,7 @@ TEST_F(GLES2DecoderTest1, HintInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, IsBufferValidArgs) { +TEST_P(GLES2DecoderTest1, IsBufferValidArgs) { SpecializedSetup<cmds::IsBuffer, 0>(true); cmds::IsBuffer cmd; cmd.Init(client_buffer_id_, shared_memory_id_, shared_memory_offset_); @@ -1922,7 +1737,7 @@ TEST_F(GLES2DecoderTest1, IsBufferValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, IsBufferInvalidArgsBadSharedMemoryId) { +TEST_P(GLES2DecoderTest1, IsBufferInvalidArgsBadSharedMemoryId) { SpecializedSetup<cmds::IsBuffer, 0>(false); cmds::IsBuffer cmd; cmd.Init(client_buffer_id_, kInvalidSharedMemoryId, shared_memory_offset_); @@ -1931,7 +1746,7 @@ TEST_F(GLES2DecoderTest1, IsBufferInvalidArgsBadSharedMemoryId) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest1, IsEnabledValidArgs) { +TEST_P(GLES2DecoderTest1, IsEnabledValidArgs) { SpecializedSetup<cmds::IsEnabled, 0>(true); cmds::IsEnabled cmd; cmd.Init(GL_BLEND, shared_memory_id_, shared_memory_offset_); @@ -1939,7 +1754,7 @@ TEST_F(GLES2DecoderTest1, IsEnabledValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, IsEnabledInvalidArgs0_0) { +TEST_P(GLES2DecoderTest1, IsEnabledInvalidArgs0_0) { EXPECT_CALL(*gl_, IsEnabled(_)).Times(0); SpecializedSetup<cmds::IsEnabled, 0>(false); cmds::IsEnabled cmd; @@ -1948,7 +1763,7 @@ TEST_F(GLES2DecoderTest1, IsEnabledInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, IsEnabledInvalidArgs0_1) { +TEST_P(GLES2DecoderTest1, IsEnabledInvalidArgs0_1) { EXPECT_CALL(*gl_, IsEnabled(_)).Times(0); SpecializedSetup<cmds::IsEnabled, 0>(false); cmds::IsEnabled cmd; @@ -1957,7 +1772,7 @@ TEST_F(GLES2DecoderTest1, IsEnabledInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest1, IsEnabledInvalidArgsBadSharedMemoryId) { +TEST_P(GLES2DecoderTest1, IsEnabledInvalidArgsBadSharedMemoryId) { SpecializedSetup<cmds::IsEnabled, 0>(false); cmds::IsEnabled cmd; cmd.Init(GL_BLEND, kInvalidSharedMemoryId, shared_memory_offset_); @@ -1966,7 +1781,7 @@ TEST_F(GLES2DecoderTest1, IsEnabledInvalidArgsBadSharedMemoryId) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest1, IsFramebufferValidArgs) { +TEST_P(GLES2DecoderTest1, IsFramebufferValidArgs) { SpecializedSetup<cmds::IsFramebuffer, 0>(true); cmds::IsFramebuffer cmd; cmd.Init(client_framebuffer_id_, shared_memory_id_, shared_memory_offset_); @@ -1974,7 +1789,7 @@ TEST_F(GLES2DecoderTest1, IsFramebufferValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, IsFramebufferInvalidArgsBadSharedMemoryId) { +TEST_P(GLES2DecoderTest1, IsFramebufferInvalidArgsBadSharedMemoryId) { SpecializedSetup<cmds::IsFramebuffer, 0>(false); cmds::IsFramebuffer cmd; cmd.Init( @@ -1985,7 +1800,7 @@ TEST_F(GLES2DecoderTest1, IsFramebufferInvalidArgsBadSharedMemoryId) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } -TEST_F(GLES2DecoderTest1, IsProgramValidArgs) { +TEST_P(GLES2DecoderTest1, IsProgramValidArgs) { SpecializedSetup<cmds::IsProgram, 0>(true); cmds::IsProgram cmd; cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_); @@ -1993,7 +1808,7 @@ TEST_F(GLES2DecoderTest1, IsProgramValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest1, IsProgramInvalidArgsBadSharedMemoryId) { +TEST_P(GLES2DecoderTest1, IsProgramInvalidArgsBadSharedMemoryId) { SpecializedSetup<cmds::IsProgram, 0>(false); cmds::IsProgram cmd; cmd.Init(client_program_id_, kInvalidSharedMemoryId, shared_memory_offset_); @@ -2001,5 +1816,140 @@ TEST_F(GLES2DecoderTest1, IsProgramInvalidArgsBadSharedMemoryId) { cmd.Init(client_program_id_, shared_memory_id_, kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } -#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_ +TEST_P(GLES2DecoderTest1, IsRenderbufferValidArgs) { + SpecializedSetup<cmds::IsRenderbuffer, 0>(true); + cmds::IsRenderbuffer cmd; + cmd.Init(client_renderbuffer_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, IsRenderbufferInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsRenderbuffer, 0>(false); + cmds::IsRenderbuffer cmd; + cmd.Init( + client_renderbuffer_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init( + client_renderbuffer_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest1, IsShaderValidArgs) { + SpecializedSetup<cmds::IsShader, 0>(true); + cmds::IsShader cmd; + cmd.Init(client_shader_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, IsShaderInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsShader, 0>(false); + cmds::IsShader cmd; + cmd.Init(client_shader_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_shader_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest1, IsTextureValidArgs) { + SpecializedSetup<cmds::IsTexture, 0>(true); + cmds::IsTexture cmd; + cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, IsTextureInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsTexture, 0>(false); + cmds::IsTexture cmd; + cmd.Init(client_texture_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_texture_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest1, LineWidthValidArgs) { + EXPECT_CALL(*gl_, LineWidth(0.5f)); + SpecializedSetup<cmds::LineWidth, 0>(true); + cmds::LineWidth cmd; + cmd.Init(0.5f); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, LineWidthInvalidValue0_0) { + SpecializedSetup<cmds::LineWidth, 0>(false); + cmds::LineWidth cmd; + cmd.Init(0.0f); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, LinkProgramValidArgs) { + EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)); + SpecializedSetup<cmds::LinkProgram, 0>(true); + cmds::LinkProgram cmd; + cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} +// TODO(gman): PixelStorei + +TEST_P(GLES2DecoderTest1, PolygonOffsetValidArgs) { + EXPECT_CALL(*gl_, PolygonOffset(1, 2)); + SpecializedSetup<cmds::PolygonOffset, 0>(true); + cmds::PolygonOffset cmd; + cmd.Init(1, 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} +// TODO(gman): ReadPixels + +// TODO(gman): ReleaseShaderCompiler + +TEST_P(GLES2DecoderTest1, RenderbufferStorageValidArgs) { + SpecializedSetup<cmds::RenderbufferStorage, 0>(true); + cmds::RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 3, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, RenderbufferStorageInvalidArgs0_0) { + EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0); + SpecializedSetup<cmds::RenderbufferStorage, 0>(false); + cmds::RenderbufferStorage cmd; + cmd.Init(GL_FRAMEBUFFER, GL_RGBA4, 3, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, RenderbufferStorageInvalidArgs2_0) { + EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0); + SpecializedSetup<cmds::RenderbufferStorage, 0>(false); + cmds::RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, -1, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, RenderbufferStorageInvalidArgs3_0) { + EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0); + SpecializedSetup<cmds::RenderbufferStorage, 0>(false); + cmds::RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 3, -1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest1, SampleCoverageValidArgs) { + EXPECT_CALL(*gl_, SampleCoverage(1, true)); + SpecializedSetup<cmds::SampleCoverage, 0>(true); + cmds::SampleCoverage cmd; + cmd.Init(1, true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc index 8c9c6ecd839..221aa332a48 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc @@ -15,6 +15,7 @@ using ::gfx::MockGLInterface; using ::testing::_; +using ::testing::AnyNumber; using ::testing::DoAll; using ::testing::InSequence; using ::testing::MatcherCast; @@ -30,43 +31,236 @@ namespace gles2 { class GLES2DecoderTest2 : public GLES2DecoderTestBase { public: GLES2DecoderTest2() { } -}; -template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::GenQueriesEXT, 0>( - bool valid) { - if (!valid) { - // Make the client_query_id_ so that trying to make it again - // will fail. - GetSharedMemoryAs<GLuint*>()[0] = client_query_id_; - cmds::GenQueriesEXT cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + void TestAcceptedUniform(GLenum uniform_type, uint32 accepts_apis) { + SetupShaderForUniform(uniform_type); + bool valid_uniform = false; + + EXPECT_CALL(*gl_, Uniform1i(1, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform1iv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform2iv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform3iv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform4iv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform1f(1, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform1fv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform2fv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform3fv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, Uniform4fv(1, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, UniformMatrix2fv(1, _, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, UniformMatrix3fv(1, _, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl_, UniformMatrix4fv(1, _, _, _)).Times(AnyNumber()); + + { + valid_uniform = accepts_apis & Program::kUniform1i; + cmds::Uniform1i cmd; + cmd.Init(1, 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform1i; + cmds::Uniform1ivImmediate& cmd = + *GetImmediateAs<cmds::Uniform1ivImmediate>(); + GLint data[2][1] = {{0}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform2i; + cmds::Uniform2i cmd; + cmd.Init(1, 2, 3); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform2i; + cmds::Uniform2ivImmediate& cmd = + *GetImmediateAs<cmds::Uniform2ivImmediate>(); + GLint data[2][2] = {{0}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform3i; + cmds::Uniform3i cmd; + cmd.Init(1, 2, 3, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform3i; + cmds::Uniform3ivImmediate& cmd = + *GetImmediateAs<cmds::Uniform3ivImmediate>(); + GLint data[2][3] = {{0}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform4i; + cmds::Uniform4i cmd; + cmd.Init(1, 2, 3, 4, 5); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform4i; + cmds::Uniform4ivImmediate& cmd = + *GetImmediateAs<cmds::Uniform4ivImmediate>(); + GLint data[2][4] = {{0}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + //////////////////// + + { + valid_uniform = accepts_apis & Program::kUniform1f; + cmds::Uniform1f cmd; + cmd.Init(1, 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform1f; + cmds::Uniform1fvImmediate& cmd = + *GetImmediateAs<cmds::Uniform1fvImmediate>(); + GLfloat data[2][1] = {{0.0f}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform2f; + cmds::Uniform2f cmd; + cmd.Init(1, 2, 3); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform2f; + cmds::Uniform2fvImmediate& cmd = + *GetImmediateAs<cmds::Uniform2fvImmediate>(); + GLfloat data[2][2] = {{0.0f}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform3f; + cmds::Uniform3f cmd; + cmd.Init(1, 2, 3, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform3f; + cmds::Uniform3fvImmediate& cmd = + *GetImmediateAs<cmds::Uniform3fvImmediate>(); + GLfloat data[2][3] = {{0.0f}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform4f; + cmds::Uniform4f cmd; + cmd.Init(1, 2, 3, 4, 5); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniform4f; + cmds::Uniform4fvImmediate& cmd = + *GetImmediateAs<cmds::Uniform4fvImmediate>(); + GLfloat data[2][4] = {{0.0f}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniformMatrix2f; + cmds::UniformMatrix2fvImmediate& cmd = + *GetImmediateAs<cmds::UniformMatrix2fvImmediate>(); + GLfloat data[2][2 * 2] = {{0.0f}}; + + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniformMatrix3f; + cmds::UniformMatrix3fvImmediate& cmd = + *GetImmediateAs<cmds::UniformMatrix3fvImmediate>(); + GLfloat data[2][3 * 3] = {{0.0f}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } + + { + valid_uniform = accepts_apis & Program::kUniformMatrix4f; + cmds::UniformMatrix4fvImmediate& cmd = + *GetImmediateAs<cmds::UniformMatrix4fvImmediate>(); + GLfloat data[2][4 * 4] = {{0.0f}}; + cmd.Init(1, 2, &data[0][0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(data))); + EXPECT_EQ(valid_uniform ? GL_NO_ERROR : GL_INVALID_OPERATION, + GetGLError()); + } } }; +INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderTest2, ::testing::Bool()); + template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::GenQueriesEXTImmediate, 0>( bool valid) { if (!valid) { // Make the client_query_id_ so that trying to make it again // will fail. - GetSharedMemoryAs<GLuint*>()[0] = client_query_id_; - cmds::GenQueriesEXT cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } -}; - -template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::DeleteQueriesEXT, 0>( - bool valid) { - if (valid) { - // Make the client_query_id_ so that trying to delete it will succeed. - GetSharedMemoryAs<GLuint*>()[0] = client_query_id_; - cmds::GenQueriesEXT cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + cmds::GenQueriesEXTImmediate& cmd = + *GetImmediateAs<cmds::GenQueriesEXTImmediate>(); + cmd.Init(1, &client_query_id_); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(client_query_id_))); } }; @@ -75,10 +269,11 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::DeleteQueriesEXTImmediate, 0>( bool valid) { if (valid) { // Make the client_query_id_ so that trying to delete it will succeed. - GetSharedMemoryAs<GLuint*>()[0] = client_query_id_; - cmds::GenQueriesEXT cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + cmds::GenQueriesEXTImmediate& cmd = + *GetImmediateAs<cmds::GenQueriesEXTImmediate>(); + cmd.Init(1, &client_query_id_); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(client_query_id_))); } }; @@ -134,6 +329,21 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::LinkProgram, 0>( }; template <> +void GLES2DecoderTestBase::SpecializedSetup<cmds::UseProgram, 0>( + bool /* valid */) { + // Needs the same setup as LinkProgram. + SpecializedSetup<cmds::LinkProgram, 0>(false); + + EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)) + .Times(1) + .RetiresOnSaturation(); + + cmds::LinkProgram link_cmd; + link_cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd)); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::ValidateProgram, 0>( bool /* valid */) { // Needs the same setup as LinkProgram. @@ -160,24 +370,12 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform1f, 0>( }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform1fv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_FLOAT); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform1fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT); }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform1iv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_INT); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform1ivImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_INT); @@ -196,18 +394,6 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform2i, 0>( }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform2fv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_FLOAT_VEC2); -}; - -template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform2iv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_INT_VEC2); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform2fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_VEC2); @@ -232,18 +418,6 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform3i, 0>( }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform3fv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_FLOAT_VEC3); -}; - -template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform3iv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_INT_VEC3); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform3fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_VEC3); @@ -268,18 +442,6 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform4i, 0>( }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform4fv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_FLOAT_VEC4); -}; - -template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform4iv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_INT_VEC4); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform4fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_VEC4); @@ -292,61 +454,24 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform4ivImmediate, 0>( }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::UniformMatrix2fv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_FLOAT_MAT2); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::UniformMatrix2fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_MAT2); }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::UniformMatrix3fv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_FLOAT_MAT3); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::UniformMatrix3fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_MAT3); }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::UniformMatrix4fv, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_FLOAT_MAT4); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::UniformMatrix4fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_MAT4); }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::RenderbufferStorage, 0>( - bool valid) { - DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, - kServiceRenderbufferId); - if (valid) { - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, - RenderbufferStorageEXT(GL_RENDERBUFFER, _, 3, 4)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - } -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::TexParameterf, 0>( bool /* valid */) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); @@ -359,24 +484,12 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::TexParameteri, 0>( }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::TexParameterfv, 0>( - bool /* valid */) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::TexParameterfvImmediate, 0>( bool /* valid */) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::TexParameteriv, 0>( - bool /* valid */) { - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::TexParameterivImmediate, 0>( bool /* valid */) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); @@ -384,6 +497,66 @@ void GLES2DecoderTestBase::SpecializedSetup<cmds::TexParameterivImmediate, 0>( #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h" +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_INT) { + TestAcceptedUniform(GL_INT, Program::kUniform1i); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_INT_VEC2) { + TestAcceptedUniform(GL_INT_VEC2, Program::kUniform2i); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_INT_VEC3) { + TestAcceptedUniform(GL_INT_VEC3, Program::kUniform3i); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_INT_VEC4) { + TestAcceptedUniform(GL_INT_VEC4, Program::kUniform4i); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_BOOL) { + TestAcceptedUniform(GL_BOOL, Program::kUniform1i | Program::kUniform1f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_BOOL_VEC2) { + TestAcceptedUniform(GL_BOOL_VEC2, Program::kUniform2i | Program::kUniform2f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_BOOL_VEC3) { + TestAcceptedUniform(GL_BOOL_VEC3, Program::kUniform3i | Program::kUniform3f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_BOOL_VEC4) { + TestAcceptedUniform(GL_BOOL_VEC4, Program::kUniform4i | Program::kUniform4f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniformTypeFLOAT) { + TestAcceptedUniform(GL_FLOAT, Program::kUniform1f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_FLOAT_VEC2) { + TestAcceptedUniform(GL_FLOAT_VEC2, Program::kUniform2f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_FLOAT_VEC3) { + TestAcceptedUniform(GL_FLOAT_VEC3, Program::kUniform3f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_FLOAT_VEC4) { + TestAcceptedUniform(GL_FLOAT_VEC4, Program::kUniform4f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_FLOAT_MAT2) { + TestAcceptedUniform(GL_FLOAT_MAT2, Program::kUniformMatrix2f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_FLOAT_MAT3) { + TestAcceptedUniform(GL_FLOAT_MAT3, Program::kUniformMatrix3f); +} + +TEST_P(GLES2DecoderTest2, AcceptsUniform_GL_FLOAT_MAT4) { + TestAcceptedUniform(GL_FLOAT_MAT4, Program::kUniformMatrix4f); +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index db72cac7225..dd2cd0edafb 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -1,154 +1,18 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! // It is included by gles2_cmd_decoder_unittest_2.cc #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ - -TEST_F(GLES2DecoderTest2, IsRenderbufferValidArgs) { - SpecializedSetup<cmds::IsRenderbuffer, 0>(true); - cmds::IsRenderbuffer cmd; - cmd.Init(client_renderbuffer_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, IsRenderbufferInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsRenderbuffer, 0>(false); - cmds::IsRenderbuffer cmd; - cmd.Init( - client_renderbuffer_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init( - client_renderbuffer_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, IsShaderValidArgs) { - SpecializedSetup<cmds::IsShader, 0>(true); - cmds::IsShader cmd; - cmd.Init(client_shader_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, IsShaderInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsShader, 0>(false); - cmds::IsShader cmd; - cmd.Init(client_shader_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_shader_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, IsTextureValidArgs) { - SpecializedSetup<cmds::IsTexture, 0>(true); - cmds::IsTexture cmd; - cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, IsTextureInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsTexture, 0>(false); - cmds::IsTexture cmd; - cmd.Init(client_texture_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_texture_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, LineWidthValidArgs) { - EXPECT_CALL(*gl_, LineWidth(0.5f)); - SpecializedSetup<cmds::LineWidth, 0>(true); - cmds::LineWidth cmd; - cmd.Init(0.5f); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, LineWidthInvalidValue0_0) { - SpecializedSetup<cmds::LineWidth, 0>(false); - cmds::LineWidth cmd; - cmd.Init(0.0f); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, LinkProgramValidArgs) { - EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)); - SpecializedSetup<cmds::LinkProgram, 0>(true); - cmds::LinkProgram cmd; - cmd.Init(client_program_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} -// TODO(gman): PixelStorei - - -TEST_F(GLES2DecoderTest2, PolygonOffsetValidArgs) { - EXPECT_CALL(*gl_, PolygonOffset(1, 2)); - SpecializedSetup<cmds::PolygonOffset, 0>(true); - cmds::PolygonOffset cmd; - cmd.Init(1, 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} -// TODO(gman): ReadPixels - -// TODO(gman): ReleaseShaderCompiler - -TEST_F(GLES2DecoderTest2, RenderbufferStorageValidArgs) { - SpecializedSetup<cmds::RenderbufferStorage, 0>(true); - cmds::RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 3, 4); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, RenderbufferStorageInvalidArgs0_0) { - EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0); - SpecializedSetup<cmds::RenderbufferStorage, 0>(false); - cmds::RenderbufferStorage cmd; - cmd.Init(GL_FRAMEBUFFER, GL_RGBA4, 3, 4); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, RenderbufferStorageInvalidArgs2_0) { - EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0); - SpecializedSetup<cmds::RenderbufferStorage, 0>(false); - cmds::RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, -1, 4); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, RenderbufferStorageInvalidArgs3_0) { - EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0); - SpecializedSetup<cmds::RenderbufferStorage, 0>(false); - cmds::RenderbufferStorage cmd; - cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 3, -1); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, SampleCoverageValidArgs) { - EXPECT_CALL(*gl_, SampleCoverage(1, true)); - SpecializedSetup<cmds::SampleCoverage, 0>(true); - cmds::SampleCoverage cmd; - cmd.Init(1, true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, ScissorValidArgs) { +TEST_P(GLES2DecoderTest2, ScissorValidArgs) { EXPECT_CALL(*gl_, Scissor(1, 2, 3, 4)); SpecializedSetup<cmds::Scissor, 0>(true); cmds::Scissor cmd; @@ -157,7 +21,7 @@ TEST_F(GLES2DecoderTest2, ScissorValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, ScissorInvalidArgs2_0) { +TEST_P(GLES2DecoderTest2, ScissorInvalidArgs2_0) { EXPECT_CALL(*gl_, Scissor(_, _, _, _)).Times(0); SpecializedSetup<cmds::Scissor, 0>(false); cmds::Scissor cmd; @@ -166,7 +30,7 @@ TEST_F(GLES2DecoderTest2, ScissorInvalidArgs2_0) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_F(GLES2DecoderTest2, ScissorInvalidArgs3_0) { +TEST_P(GLES2DecoderTest2, ScissorInvalidArgs3_0) { EXPECT_CALL(*gl_, Scissor(_, _, _, _)).Times(0); SpecializedSetup<cmds::Scissor, 0>(false); cmds::Scissor cmd; @@ -176,11 +40,9 @@ TEST_F(GLES2DecoderTest2, ScissorInvalidArgs3_0) { } // TODO(gman): ShaderBinary -// TODO(gman): ShaderSource - // TODO(gman): ShaderSourceBucket -TEST_F(GLES2DecoderTest2, StencilFuncValidArgs) { +TEST_P(GLES2DecoderTest2, StencilFuncValidArgs) { EXPECT_CALL(*gl_, StencilFunc(GL_NEVER, 2, 3)); SpecializedSetup<cmds::StencilFunc, 0>(true); cmds::StencilFunc cmd; @@ -189,7 +51,7 @@ TEST_F(GLES2DecoderTest2, StencilFuncValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, StencilFuncSeparateValidArgs) { +TEST_P(GLES2DecoderTest2, StencilFuncSeparateValidArgs) { EXPECT_CALL(*gl_, StencilFuncSeparate(GL_FRONT, GL_NEVER, 3, 4)); SpecializedSetup<cmds::StencilFuncSeparate, 0>(true); cmds::StencilFuncSeparate cmd; @@ -198,7 +60,7 @@ TEST_F(GLES2DecoderTest2, StencilFuncSeparateValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, StencilMaskValidArgs) { +TEST_P(GLES2DecoderTest2, StencilMaskValidArgs) { SpecializedSetup<cmds::StencilMask, 0>(true); cmds::StencilMask cmd; cmd.Init(1); @@ -206,7 +68,7 @@ TEST_F(GLES2DecoderTest2, StencilMaskValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, StencilMaskSeparateValidArgs) { +TEST_P(GLES2DecoderTest2, StencilMaskSeparateValidArgs) { SpecializedSetup<cmds::StencilMaskSeparate, 0>(true); cmds::StencilMaskSeparate cmd; cmd.Init(GL_FRONT, 2); @@ -214,7 +76,7 @@ TEST_F(GLES2DecoderTest2, StencilMaskSeparateValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, StencilOpValidArgs) { +TEST_P(GLES2DecoderTest2, StencilOpValidArgs) { EXPECT_CALL(*gl_, StencilOp(GL_KEEP, GL_INCR, GL_KEEP)); SpecializedSetup<cmds::StencilOp, 0>(true); cmds::StencilOp cmd; @@ -223,7 +85,7 @@ TEST_F(GLES2DecoderTest2, StencilOpValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, StencilOpSeparateValidArgs) { +TEST_P(GLES2DecoderTest2, StencilOpSeparateValidArgs) { EXPECT_CALL(*gl_, StencilOpSeparate(GL_FRONT, GL_INCR, GL_KEEP, GL_KEEP)); SpecializedSetup<cmds::StencilOpSeparate, 0>(true); cmds::StencilOpSeparate cmd; @@ -233,10 +95,9 @@ TEST_F(GLES2DecoderTest2, StencilOpSeparateValidArgs) { } // TODO(gman): TexImage2D - -TEST_F(GLES2DecoderTest2, TexParameterfValidArgs) { - EXPECT_CALL( - *gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); +TEST_P(GLES2DecoderTest2, TexParameterfValidArgs) { + EXPECT_CALL(*gl_, + TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); SpecializedSetup<cmds::TexParameterf, 0>(true); cmds::TexParameterf cmd; cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -244,8 +105,8 @@ TEST_F(GLES2DecoderTest2, TexParameterfValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterfInvalidArgs0_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); +TEST_P(GLES2DecoderTest2, TexParameterfInvalidArgs0_0) { + EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterf, 0>(false); cmds::TexParameterf cmd; cmd.Init(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -253,8 +114,8 @@ TEST_F(GLES2DecoderTest2, TexParameterfInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterfInvalidArgs0_1) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); +TEST_P(GLES2DecoderTest2, TexParameterfInvalidArgs0_1) { + EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterf, 0>(false); cmds::TexParameterf cmd; cmd.Init(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -262,8 +123,8 @@ TEST_F(GLES2DecoderTest2, TexParameterfInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterfInvalidArgs1_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); +TEST_P(GLES2DecoderTest2, TexParameterfInvalidArgs1_0) { + EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterf, 0>(false); cmds::TexParameterf cmd; cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_NEAREST); @@ -271,131 +132,65 @@ TEST_F(GLES2DecoderTest2, TexParameterfInvalidArgs1_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterfvValidArgs) { - SpecializedSetup<cmds::TexParameterfv, 0>(true); - cmds::TexParameterfv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = GL_NEAREST; - EXPECT_CALL( - *gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - *reinterpret_cast<const GLfloat*>(shared_memory_address_))); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterfvInvalidArgs0_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameterfv, 0>(false); - cmds::TexParameterfv cmd; - cmd.Init( - GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterfvInvalidArgs0_1) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameterfv, 0>(false); - cmds::TexParameterfv cmd; - cmd.Init( - GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterfvInvalidArgs1_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameterfv, 0>(false); - cmds::TexParameterfv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterfvInvalidArgs2_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameterfv, 0>(false); - cmds::TexParameterfv cmd; - cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, kInvalidSharedMemoryId, 0); - GetSharedMemoryAs<GLfloat*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, TexParameterfvInvalidArgs2_1) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameterfv, 0>(false); - cmds::TexParameterfv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - kInvalidSharedMemoryOffset); - GetSharedMemoryAs<GLfloat*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, TexParameterfvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, TexParameterfvImmediateValidArgs) { cmds::TexParameterfvImmediate& cmd = *GetImmediateAs<cmds::TexParameterfvImmediate>(); SpecializedSetup<cmds::TexParameterfvImmediate, 0>(true); - GLfloat temp[1] = { GL_NEAREST, }; + GLfloat temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &temp[0]); EXPECT_CALL( *gl_, - TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, *reinterpret_cast< - GLfloat*>(ImmediateDataAddress(&cmd)))); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + TexParameterf(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + *reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterfvImmediateInvalidArgs0_0) { +TEST_P(GLES2DecoderTest2, TexParameterfvImmediateInvalidArgs0_0) { cmds::TexParameterfvImmediate& cmd = *GetImmediateAs<cmds::TexParameterfvImmediate>(); - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); + EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterfvImmediate, 0>(false); - GLfloat temp[1] = { GL_NEAREST, }; + GLfloat temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterfvImmediateInvalidArgs0_1) { +TEST_P(GLES2DecoderTest2, TexParameterfvImmediateInvalidArgs0_1) { cmds::TexParameterfvImmediate& cmd = *GetImmediateAs<cmds::TexParameterfvImmediate>(); - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); + EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterfvImmediate, 0>(false); - GLfloat temp[1] = { GL_NEAREST, }; + GLfloat temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterfvImmediateInvalidArgs1_0) { +TEST_P(GLES2DecoderTest2, TexParameterfvImmediateInvalidArgs1_0) { cmds::TexParameterfvImmediate& cmd = *GetImmediateAs<cmds::TexParameterfvImmediate>(); - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); + EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterfvImmediate, 0>(false); - GLfloat temp[1] = { GL_NEAREST, }; + GLfloat temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameteriValidArgs) { - EXPECT_CALL( - *gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); +TEST_P(GLES2DecoderTest2, TexParameteriValidArgs) { + EXPECT_CALL(*gl_, + TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); SpecializedSetup<cmds::TexParameteri, 0>(true); cmds::TexParameteri cmd; cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -403,7 +198,7 @@ TEST_F(GLES2DecoderTest2, TexParameteriValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameteriInvalidArgs0_0) { +TEST_P(GLES2DecoderTest2, TexParameteriInvalidArgs0_0) { EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameteri, 0>(false); cmds::TexParameteri cmd; @@ -412,7 +207,7 @@ TEST_F(GLES2DecoderTest2, TexParameteriInvalidArgs0_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameteriInvalidArgs0_1) { +TEST_P(GLES2DecoderTest2, TexParameteriInvalidArgs0_1) { EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameteri, 0>(false); cmds::TexParameteri cmd; @@ -421,7 +216,7 @@ TEST_F(GLES2DecoderTest2, TexParameteriInvalidArgs0_1) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameteriInvalidArgs1_0) { +TEST_P(GLES2DecoderTest2, TexParameteriInvalidArgs1_0) { EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameteri, 0>(false); cmds::TexParameteri cmd; @@ -430,131 +225,64 @@ TEST_F(GLES2DecoderTest2, TexParameteriInvalidArgs1_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterivValidArgs) { - SpecializedSetup<cmds::TexParameteriv, 0>(true); - cmds::TexParameteriv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLint*>()[0] = GL_NEAREST; - EXPECT_CALL( - *gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, *reinterpret_cast<const GLint*>( - shared_memory_address_))); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterivInvalidArgs0_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameteriv, 0>(false); - cmds::TexParameteriv cmd; - cmd.Init( - GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLint*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterivInvalidArgs0_1) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameteriv, 0>(false); - cmds::TexParameteriv cmd; - cmd.Init( - GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLint*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterivInvalidArgs1_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameteriv, 0>(false); - cmds::TexParameteriv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_, - shared_memory_offset_); - GetSharedMemoryAs<GLint*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, TexParameterivInvalidArgs2_0) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameteriv, 0>(false); - cmds::TexParameteriv cmd; - cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, kInvalidSharedMemoryId, 0); - GetSharedMemoryAs<GLint*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, TexParameterivInvalidArgs2_1) { - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); - SpecializedSetup<cmds::TexParameteriv, 0>(false); - cmds::TexParameteriv cmd; - cmd.Init( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_, - kInvalidSharedMemoryOffset); - GetSharedMemoryAs<GLint*>()[0] = GL_NEAREST; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, TexParameterivImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, TexParameterivImmediateValidArgs) { cmds::TexParameterivImmediate& cmd = *GetImmediateAs<cmds::TexParameterivImmediate>(); SpecializedSetup<cmds::TexParameterivImmediate, 0>(true); - GLint temp[1] = { GL_NEAREST, }; + GLint temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &temp[0]); EXPECT_CALL( *gl_, - TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, *reinterpret_cast< - GLint*>(ImmediateDataAddress(&cmd)))); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + *reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterivImmediateInvalidArgs0_0) { +TEST_P(GLES2DecoderTest2, TexParameterivImmediateInvalidArgs0_0) { cmds::TexParameterivImmediate& cmd = *GetImmediateAs<cmds::TexParameterivImmediate>(); EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterivImmediate, 0>(false); - GLint temp[1] = { GL_NEAREST, }; + GLint temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterivImmediateInvalidArgs0_1) { +TEST_P(GLES2DecoderTest2, TexParameterivImmediateInvalidArgs0_1) { cmds::TexParameterivImmediate& cmd = *GetImmediateAs<cmds::TexParameterivImmediate>(); EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterivImmediate, 0>(false); - GLint temp[1] = { GL_NEAREST, }; + GLint temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_F(GLES2DecoderTest2, TexParameterivImmediateInvalidArgs1_0) { +TEST_P(GLES2DecoderTest2, TexParameterivImmediateInvalidArgs1_0) { cmds::TexParameterivImmediate& cmd = *GetImmediateAs<cmds::TexParameterivImmediate>(); EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); SpecializedSetup<cmds::TexParameterivImmediate, 0>(false); - GLint temp[1] = { GL_NEAREST, }; + GLint temp[1] = { + GL_NEAREST, + }; cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } // TODO(gman): TexSubImage2D - -TEST_F(GLES2DecoderTest2, Uniform1fValidArgs) { +TEST_P(GLES2DecoderTest2, Uniform1fValidArgs) { EXPECT_CALL(*gl_, Uniform1fv(1, 1, _)); SpecializedSetup<cmds::Uniform1f, 0>(true); cmds::Uniform1f cmd; @@ -563,74 +291,23 @@ TEST_F(GLES2DecoderTest2, Uniform1fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform1fvValidArgs) { - EXPECT_CALL( - *gl_, Uniform1fv( - 1, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform1fv, 0>(true); - cmds::Uniform1fv cmd; - cmd.Init(1, 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform1fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, Uniform1fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform1fv, 0>(false); - cmds::Uniform1fv cmd; - cmd.Init(1, -1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform1fvInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform1fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform1fv, 0>(false); - cmds::Uniform1fv cmd; - cmd.Init(1, 2, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform1fvInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform1fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform1fv, 0>(false); - cmds::Uniform1fv cmd; - cmd.Init(1, 2, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform1fvValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, Uniform1fv( - 3, 3, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform1fv, 0>(true); - cmds::Uniform1fv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform1fvImmediateValidArgs) { - cmds::Uniform1fvImmediate& cmd = - *GetImmediateAs<cmds::Uniform1fvImmediate>(); +TEST_P(GLES2DecoderTest2, Uniform1fvImmediateValidArgs) { + cmds::Uniform1fvImmediate& cmd = *GetImmediateAs<cmds::Uniform1fvImmediate>(); EXPECT_CALL( *gl_, - Uniform1fv(1, 2, - reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + Uniform1fv(1, 2, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::Uniform1fvImmediate, 0>(true); - GLfloat temp[1 * 2] = { 0, }; + GLfloat temp[1 * 2] = { + 0, + }; cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } // TODO(gman): Uniform1i -// TODO(gman): Uniform1iv // TODO(gman): Uniform1ivImmediate -TEST_F(GLES2DecoderTest2, Uniform2fValidArgs) { +TEST_P(GLES2DecoderTest2, Uniform2fValidArgs) { EXPECT_CALL(*gl_, Uniform2fv(1, 1, _)); SpecializedSetup<cmds::Uniform2f, 0>(true); cmds::Uniform2f cmd; @@ -639,71 +316,21 @@ TEST_F(GLES2DecoderTest2, Uniform2fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform2fvValidArgs) { - EXPECT_CALL( - *gl_, Uniform2fv( - 1, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform2fv, 0>(true); - cmds::Uniform2fv cmd; - cmd.Init(1, 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform2fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, Uniform2fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform2fv, 0>(false); - cmds::Uniform2fv cmd; - cmd.Init(1, -1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform2fvInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform2fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform2fv, 0>(false); - cmds::Uniform2fv cmd; - cmd.Init(1, 2, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform2fvInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform2fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform2fv, 0>(false); - cmds::Uniform2fv cmd; - cmd.Init(1, 2, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform2fvValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, Uniform2fv( - 3, 3, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform2fv, 0>(true); - cmds::Uniform2fv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform2fvImmediateValidArgs) { - cmds::Uniform2fvImmediate& cmd = - *GetImmediateAs<cmds::Uniform2fvImmediate>(); +TEST_P(GLES2DecoderTest2, Uniform2fvImmediateValidArgs) { + cmds::Uniform2fvImmediate& cmd = *GetImmediateAs<cmds::Uniform2fvImmediate>(); EXPECT_CALL( *gl_, - Uniform2fv(1, 2, - reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + Uniform2fv(1, 2, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::Uniform2fvImmediate, 0>(true); - GLfloat temp[2 * 2] = { 0, }; + GLfloat temp[2 * 2] = { + 0, + }; cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform2iValidArgs) { +TEST_P(GLES2DecoderTest2, Uniform2iValidArgs) { EXPECT_CALL(*gl_, Uniform2iv(1, 1, _)); SpecializedSetup<cmds::Uniform2i, 0>(true); cmds::Uniform2i cmd; @@ -712,71 +339,21 @@ TEST_F(GLES2DecoderTest2, Uniform2iValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform2ivValidArgs) { - EXPECT_CALL( - *gl_, Uniform2iv( - 1, 2, reinterpret_cast<const GLint*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform2iv, 0>(true); - cmds::Uniform2iv cmd; - cmd.Init(1, 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform2ivInvalidArgs1_0) { - EXPECT_CALL(*gl_, Uniform2iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform2iv, 0>(false); - cmds::Uniform2iv cmd; - cmd.Init(1, -1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform2ivInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform2iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform2iv, 0>(false); - cmds::Uniform2iv cmd; - cmd.Init(1, 2, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform2ivInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform2iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform2iv, 0>(false); - cmds::Uniform2iv cmd; - cmd.Init(1, 2, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform2ivValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, Uniform2iv( - 3, 3, reinterpret_cast<const GLint*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform2iv, 0>(true); - cmds::Uniform2iv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform2ivImmediateValidArgs) { - cmds::Uniform2ivImmediate& cmd = - *GetImmediateAs<cmds::Uniform2ivImmediate>(); +TEST_P(GLES2DecoderTest2, Uniform2ivImmediateValidArgs) { + cmds::Uniform2ivImmediate& cmd = *GetImmediateAs<cmds::Uniform2ivImmediate>(); EXPECT_CALL( *gl_, - Uniform2iv(1, 2, - reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); + Uniform2iv(1, 2, reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::Uniform2ivImmediate, 0>(true); - GLint temp[2 * 2] = { 0, }; + GLint temp[2 * 2] = { + 0, + }; cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform3fValidArgs) { +TEST_P(GLES2DecoderTest2, Uniform3fValidArgs) { EXPECT_CALL(*gl_, Uniform3fv(1, 1, _)); SpecializedSetup<cmds::Uniform3f, 0>(true); cmds::Uniform3f cmd; @@ -785,71 +362,21 @@ TEST_F(GLES2DecoderTest2, Uniform3fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform3fvValidArgs) { - EXPECT_CALL( - *gl_, Uniform3fv( - 1, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform3fv, 0>(true); - cmds::Uniform3fv cmd; - cmd.Init(1, 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform3fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, Uniform3fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform3fv, 0>(false); - cmds::Uniform3fv cmd; - cmd.Init(1, -1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform3fvInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform3fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform3fv, 0>(false); - cmds::Uniform3fv cmd; - cmd.Init(1, 2, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform3fvInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform3fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform3fv, 0>(false); - cmds::Uniform3fv cmd; - cmd.Init(1, 2, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform3fvValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, Uniform3fv( - 3, 3, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform3fv, 0>(true); - cmds::Uniform3fv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform3fvImmediateValidArgs) { - cmds::Uniform3fvImmediate& cmd = - *GetImmediateAs<cmds::Uniform3fvImmediate>(); +TEST_P(GLES2DecoderTest2, Uniform3fvImmediateValidArgs) { + cmds::Uniform3fvImmediate& cmd = *GetImmediateAs<cmds::Uniform3fvImmediate>(); EXPECT_CALL( *gl_, - Uniform3fv(1, 2, - reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + Uniform3fv(1, 2, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::Uniform3fvImmediate, 0>(true); - GLfloat temp[3 * 2] = { 0, }; + GLfloat temp[3 * 2] = { + 0, + }; cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform3iValidArgs) { +TEST_P(GLES2DecoderTest2, Uniform3iValidArgs) { EXPECT_CALL(*gl_, Uniform3iv(1, 1, _)); SpecializedSetup<cmds::Uniform3i, 0>(true); cmds::Uniform3i cmd; @@ -858,71 +385,21 @@ TEST_F(GLES2DecoderTest2, Uniform3iValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform3ivValidArgs) { - EXPECT_CALL( - *gl_, Uniform3iv( - 1, 2, reinterpret_cast<const GLint*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform3iv, 0>(true); - cmds::Uniform3iv cmd; - cmd.Init(1, 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform3ivInvalidArgs1_0) { - EXPECT_CALL(*gl_, Uniform3iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform3iv, 0>(false); - cmds::Uniform3iv cmd; - cmd.Init(1, -1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform3ivInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform3iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform3iv, 0>(false); - cmds::Uniform3iv cmd; - cmd.Init(1, 2, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform3ivInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform3iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform3iv, 0>(false); - cmds::Uniform3iv cmd; - cmd.Init(1, 2, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform3ivValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, Uniform3iv( - 3, 3, reinterpret_cast<const GLint*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform3iv, 0>(true); - cmds::Uniform3iv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform3ivImmediateValidArgs) { - cmds::Uniform3ivImmediate& cmd = - *GetImmediateAs<cmds::Uniform3ivImmediate>(); +TEST_P(GLES2DecoderTest2, Uniform3ivImmediateValidArgs) { + cmds::Uniform3ivImmediate& cmd = *GetImmediateAs<cmds::Uniform3ivImmediate>(); EXPECT_CALL( *gl_, - Uniform3iv(1, 2, - reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); + Uniform3iv(1, 2, reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::Uniform3ivImmediate, 0>(true); - GLint temp[3 * 2] = { 0, }; + GLint temp[3 * 2] = { + 0, + }; cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform4fValidArgs) { +TEST_P(GLES2DecoderTest2, Uniform4fValidArgs) { EXPECT_CALL(*gl_, Uniform4fv(1, 1, _)); SpecializedSetup<cmds::Uniform4f, 0>(true); cmds::Uniform4f cmd; @@ -931,71 +408,21 @@ TEST_F(GLES2DecoderTest2, Uniform4fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform4fvValidArgs) { - EXPECT_CALL( - *gl_, Uniform4fv( - 1, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform4fv, 0>(true); - cmds::Uniform4fv cmd; - cmd.Init(1, 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform4fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, Uniform4fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform4fv, 0>(false); - cmds::Uniform4fv cmd; - cmd.Init(1, -1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform4fvInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform4fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform4fv, 0>(false); - cmds::Uniform4fv cmd; - cmd.Init(1, 2, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform4fvInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform4fv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform4fv, 0>(false); - cmds::Uniform4fv cmd; - cmd.Init(1, 2, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform4fvValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, Uniform4fv( - 3, 3, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform4fv, 0>(true); - cmds::Uniform4fv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform4fvImmediateValidArgs) { - cmds::Uniform4fvImmediate& cmd = - *GetImmediateAs<cmds::Uniform4fvImmediate>(); +TEST_P(GLES2DecoderTest2, Uniform4fvImmediateValidArgs) { + cmds::Uniform4fvImmediate& cmd = *GetImmediateAs<cmds::Uniform4fvImmediate>(); EXPECT_CALL( *gl_, - Uniform4fv(1, 2, - reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + Uniform4fv(1, 2, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::Uniform4fvImmediate, 0>(true); - GLfloat temp[4 * 2] = { 0, }; + GLfloat temp[4 * 2] = { + 0, + }; cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform4iValidArgs) { +TEST_P(GLES2DecoderTest2, Uniform4iValidArgs) { EXPECT_CALL(*gl_, Uniform4iv(1, 1, _)); SpecializedSetup<cmds::Uniform4i, 0>(true); cmds::Uniform4i cmd; @@ -1004,333 +431,87 @@ TEST_F(GLES2DecoderTest2, Uniform4iValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, Uniform4ivValidArgs) { - EXPECT_CALL( - *gl_, Uniform4iv( - 1, 2, reinterpret_cast<const GLint*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform4iv, 0>(true); - cmds::Uniform4iv cmd; - cmd.Init(1, 2, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform4ivInvalidArgs1_0) { - EXPECT_CALL(*gl_, Uniform4iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform4iv, 0>(false); - cmds::Uniform4iv cmd; - cmd.Init(1, -1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform4ivInvalidArgs2_0) { - EXPECT_CALL(*gl_, Uniform4iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform4iv, 0>(false); - cmds::Uniform4iv cmd; - cmd.Init(1, 2, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform4ivInvalidArgs2_1) { - EXPECT_CALL(*gl_, Uniform4iv(_, _, _)).Times(0); - SpecializedSetup<cmds::Uniform4iv, 0>(false); - cmds::Uniform4iv cmd; - cmd.Init(1, 2, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, Uniform4ivValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, Uniform4iv( - 3, 3, reinterpret_cast<const GLint*>(shared_memory_address_))); - SpecializedSetup<cmds::Uniform4iv, 0>(true); - cmds::Uniform4iv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, Uniform4ivImmediateValidArgs) { - cmds::Uniform4ivImmediate& cmd = - *GetImmediateAs<cmds::Uniform4ivImmediate>(); +TEST_P(GLES2DecoderTest2, Uniform4ivImmediateValidArgs) { + cmds::Uniform4ivImmediate& cmd = *GetImmediateAs<cmds::Uniform4ivImmediate>(); EXPECT_CALL( *gl_, - Uniform4iv(1, 2, - reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); + Uniform4iv(1, 2, reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::Uniform4ivImmediate, 0>(true); - GLint temp[4 * 2] = { 0, }; + GLint temp[4 * 2] = { + 0, + }; cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, UniformMatrix2fvValidArgs) { - EXPECT_CALL( - *gl_, UniformMatrix2fv( - 1, 2, false, reinterpret_cast<const GLfloat*>( - shared_memory_address_))); - SpecializedSetup<cmds::UniformMatrix2fv, 0>(true); - cmds::UniformMatrix2fv cmd; - cmd.Init(1, 2, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix2fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, UniformMatrix2fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix2fv, 0>(false); - cmds::UniformMatrix2fv cmd; - cmd.Init(1, -1, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix2fvInvalidArgs2_0) { - EXPECT_CALL(*gl_, UniformMatrix2fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix2fv, 0>(false); - cmds::UniformMatrix2fv cmd; - cmd.Init(1, 2, true, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix2fvInvalidArgs3_0) { - EXPECT_CALL(*gl_, UniformMatrix2fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix2fv, 0>(false); - cmds::UniformMatrix2fv cmd; - cmd.Init(1, 2, false, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix2fvInvalidArgs3_1) { - EXPECT_CALL(*gl_, UniformMatrix2fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix2fv, 0>(false); - cmds::UniformMatrix2fv cmd; - cmd.Init(1, 2, false, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix2fvValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, UniformMatrix2fv( - 3, 3, false, reinterpret_cast<const GLfloat*>( - shared_memory_address_))); - SpecializedSetup<cmds::UniformMatrix2fv, 0>(true); - cmds::UniformMatrix2fv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix2fvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, UniformMatrix2fvImmediateValidArgs) { cmds::UniformMatrix2fvImmediate& cmd = *GetImmediateAs<cmds::UniformMatrix2fvImmediate>(); EXPECT_CALL( *gl_, - UniformMatrix2fv(1, 2, false, - reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + UniformMatrix2fv( + 1, 2, false, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::UniformMatrix2fvImmediate, 0>(true); - GLfloat temp[4 * 2] = { 0, }; - cmd.Init(1, 2, false, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix2fvImmediateInvalidArgs2_0) { - cmds::UniformMatrix2fvImmediate& cmd = - *GetImmediateAs<cmds::UniformMatrix2fvImmediate>(); - EXPECT_CALL(*gl_, UniformMatrix2fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix2fvImmediate, 0>(false); - GLfloat temp[4 * 2] = { 0, }; - cmd.Init(1, 2, true, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix3fvValidArgs) { - EXPECT_CALL( - *gl_, UniformMatrix3fv( - 1, 2, false, reinterpret_cast<const GLfloat*>( - shared_memory_address_))); - SpecializedSetup<cmds::UniformMatrix3fv, 0>(true); - cmds::UniformMatrix3fv cmd; - cmd.Init(1, 2, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix3fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, UniformMatrix3fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix3fv, 0>(false); - cmds::UniformMatrix3fv cmd; - cmd.Init(1, -1, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix3fvInvalidArgs2_0) { - EXPECT_CALL(*gl_, UniformMatrix3fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix3fv, 0>(false); - cmds::UniformMatrix3fv cmd; - cmd.Init(1, 2, true, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix3fvInvalidArgs3_0) { - EXPECT_CALL(*gl_, UniformMatrix3fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix3fv, 0>(false); - cmds::UniformMatrix3fv cmd; - cmd.Init(1, 2, false, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix3fvInvalidArgs3_1) { - EXPECT_CALL(*gl_, UniformMatrix3fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix3fv, 0>(false); - cmds::UniformMatrix3fv cmd; - cmd.Init(1, 2, false, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix3fvValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, UniformMatrix3fv( - 3, 3, false, reinterpret_cast<const GLfloat*>( - shared_memory_address_))); - SpecializedSetup<cmds::UniformMatrix3fv, 0>(true); - cmds::UniformMatrix3fv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + GLfloat temp[4 * 2] = { + 0, + }; + cmd.Init(1, 2, &temp[0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, UniformMatrix3fvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, UniformMatrix3fvImmediateValidArgs) { cmds::UniformMatrix3fvImmediate& cmd = *GetImmediateAs<cmds::UniformMatrix3fvImmediate>(); EXPECT_CALL( *gl_, - UniformMatrix3fv(1, 2, false, - reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + UniformMatrix3fv( + 1, 2, false, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::UniformMatrix3fvImmediate, 0>(true); - GLfloat temp[9 * 2] = { 0, }; - cmd.Init(1, 2, false, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix3fvImmediateInvalidArgs2_0) { - cmds::UniformMatrix3fvImmediate& cmd = - *GetImmediateAs<cmds::UniformMatrix3fvImmediate>(); - EXPECT_CALL(*gl_, UniformMatrix3fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix3fvImmediate, 0>(false); - GLfloat temp[9 * 2] = { 0, }; - cmd.Init(1, 2, true, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix4fvValidArgs) { - EXPECT_CALL( - *gl_, UniformMatrix4fv( - 1, 2, false, reinterpret_cast<const GLfloat*>( - shared_memory_address_))); - SpecializedSetup<cmds::UniformMatrix4fv, 0>(true); - cmds::UniformMatrix4fv cmd; - cmd.Init(1, 2, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix4fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, UniformMatrix4fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix4fv, 0>(false); - cmds::UniformMatrix4fv cmd; - cmd.Init(1, -1, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix4fvInvalidArgs2_0) { - EXPECT_CALL(*gl_, UniformMatrix4fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix4fv, 0>(false); - cmds::UniformMatrix4fv cmd; - cmd.Init(1, 2, true, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix4fvInvalidArgs3_0) { - EXPECT_CALL(*gl_, UniformMatrix4fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix4fv, 0>(false); - cmds::UniformMatrix4fv cmd; - cmd.Init(1, 2, false, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix4fvInvalidArgs3_1) { - EXPECT_CALL(*gl_, UniformMatrix4fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix4fv, 0>(false); - cmds::UniformMatrix4fv cmd; - cmd.Init(1, 2, false, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, UniformMatrix4fvValidArgsCountTooLarge) { - EXPECT_CALL( - *gl_, UniformMatrix4fv( - 3, 3, false, reinterpret_cast<const GLfloat*>( - shared_memory_address_))); - SpecializedSetup<cmds::UniformMatrix4fv, 0>(true); - cmds::UniformMatrix4fv cmd; - cmd.Init( - ProgramManager::MakeFakeLocation( - 1, 1), 5, false, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + GLfloat temp[9 * 2] = { + 0, + }; + cmd.Init(1, 2, &temp[0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, UniformMatrix4fvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, UniformMatrix4fvImmediateValidArgs) { cmds::UniformMatrix4fvImmediate& cmd = *GetImmediateAs<cmds::UniformMatrix4fvImmediate>(); EXPECT_CALL( *gl_, - UniformMatrix4fv(1, 2, false, - reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + UniformMatrix4fv( + 1, 2, false, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); SpecializedSetup<cmds::UniformMatrix4fvImmediate, 0>(true); - GLfloat temp[16 * 2] = { 0, }; - cmd.Init(1, 2, false, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + GLfloat temp[16 * 2] = { + 0, + }; + cmd.Init(1, 2, &temp[0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, UniformMatrix4fvImmediateInvalidArgs2_0) { - cmds::UniformMatrix4fvImmediate& cmd = - *GetImmediateAs<cmds::UniformMatrix4fvImmediate>(); - EXPECT_CALL(*gl_, UniformMatrix4fv(_, _, _, _)).Times(0); - SpecializedSetup<cmds::UniformMatrix4fvImmediate, 0>(false); - GLfloat temp[16 * 2] = { 0, }; - cmd.Init(1, 2, true, &temp[0]); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); +TEST_P(GLES2DecoderTest2, UseProgramValidArgs) { + EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)); + SpecializedSetup<cmds::UseProgram, 0>(true); + cmds::UseProgram cmd; + cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, UseProgramInvalidArgs0_0) { + EXPECT_CALL(*gl_, UseProgram(_)).Times(0); + SpecializedSetup<cmds::UseProgram, 0>(false); + cmds::UseProgram cmd; + cmd.Init(kInvalidClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -// TODO(gman): UseProgram -TEST_F(GLES2DecoderTest2, ValidateProgramValidArgs) { +TEST_P(GLES2DecoderTest2, ValidateProgramValidArgs) { EXPECT_CALL(*gl_, ValidateProgram(kServiceProgramId)); SpecializedSetup<cmds::ValidateProgram, 0>(true); cmds::ValidateProgram cmd; @@ -1339,7 +520,7 @@ TEST_F(GLES2DecoderTest2, ValidateProgramValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib1fValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib1fValidArgs) { EXPECT_CALL(*gl_, VertexAttrib1f(1, 2)); SpecializedSetup<cmds::VertexAttrib1f, 0>(true); cmds::VertexAttrib1f cmd; @@ -1348,52 +529,22 @@ TEST_F(GLES2DecoderTest2, VertexAttrib1fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib1fvValidArgs) { - SpecializedSetup<cmds::VertexAttrib1fv, 0>(true); - cmds::VertexAttrib1fv cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_CALL( - *gl_, VertexAttrib1fv( - 1, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib1fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, VertexAttrib1fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib1fv, 0>(false); - cmds::VertexAttrib1fv cmd; - cmd.Init(1, kInvalidSharedMemoryId, 0); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib1fvInvalidArgs1_1) { - EXPECT_CALL(*gl_, VertexAttrib1fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib1fv, 0>(false); - cmds::VertexAttrib1fv cmd; - cmd.Init(1, shared_memory_id_, kInvalidSharedMemoryOffset); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib1fvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib1fvImmediateValidArgs) { cmds::VertexAttrib1fvImmediate& cmd = *GetImmediateAs<cmds::VertexAttrib1fvImmediate>(); SpecializedSetup<cmds::VertexAttrib1fvImmediate, 0>(true); - GLfloat temp[1] = { 0, }; + GLfloat temp[1] = { + 0, + }; cmd.Init(1, &temp[0]); - EXPECT_CALL( - *gl_, - VertexAttrib1fv(1, reinterpret_cast< - GLfloat*>(ImmediateDataAddress(&cmd)))); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_CALL(*gl_, + VertexAttrib1fv( + 1, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib2fValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib2fValidArgs) { EXPECT_CALL(*gl_, VertexAttrib2f(1, 2, 3)); SpecializedSetup<cmds::VertexAttrib2f, 0>(true); cmds::VertexAttrib2f cmd; @@ -1402,52 +553,22 @@ TEST_F(GLES2DecoderTest2, VertexAttrib2fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib2fvValidArgs) { - SpecializedSetup<cmds::VertexAttrib2fv, 0>(true); - cmds::VertexAttrib2fv cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_CALL( - *gl_, VertexAttrib2fv( - 1, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib2fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, VertexAttrib2fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib2fv, 0>(false); - cmds::VertexAttrib2fv cmd; - cmd.Init(1, kInvalidSharedMemoryId, 0); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib2fvInvalidArgs1_1) { - EXPECT_CALL(*gl_, VertexAttrib2fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib2fv, 0>(false); - cmds::VertexAttrib2fv cmd; - cmd.Init(1, shared_memory_id_, kInvalidSharedMemoryOffset); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib2fvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib2fvImmediateValidArgs) { cmds::VertexAttrib2fvImmediate& cmd = *GetImmediateAs<cmds::VertexAttrib2fvImmediate>(); SpecializedSetup<cmds::VertexAttrib2fvImmediate, 0>(true); - GLfloat temp[2] = { 0, }; + GLfloat temp[2] = { + 0, + }; cmd.Init(1, &temp[0]); - EXPECT_CALL( - *gl_, - VertexAttrib2fv(1, reinterpret_cast< - GLfloat*>(ImmediateDataAddress(&cmd)))); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_CALL(*gl_, + VertexAttrib2fv( + 1, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib3fValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib3fValidArgs) { EXPECT_CALL(*gl_, VertexAttrib3f(1, 2, 3, 4)); SpecializedSetup<cmds::VertexAttrib3f, 0>(true); cmds::VertexAttrib3f cmd; @@ -1456,52 +577,22 @@ TEST_F(GLES2DecoderTest2, VertexAttrib3fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib3fvValidArgs) { - SpecializedSetup<cmds::VertexAttrib3fv, 0>(true); - cmds::VertexAttrib3fv cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_CALL( - *gl_, VertexAttrib3fv( - 1, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib3fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, VertexAttrib3fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib3fv, 0>(false); - cmds::VertexAttrib3fv cmd; - cmd.Init(1, kInvalidSharedMemoryId, 0); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib3fvInvalidArgs1_1) { - EXPECT_CALL(*gl_, VertexAttrib3fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib3fv, 0>(false); - cmds::VertexAttrib3fv cmd; - cmd.Init(1, shared_memory_id_, kInvalidSharedMemoryOffset); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib3fvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib3fvImmediateValidArgs) { cmds::VertexAttrib3fvImmediate& cmd = *GetImmediateAs<cmds::VertexAttrib3fvImmediate>(); SpecializedSetup<cmds::VertexAttrib3fvImmediate, 0>(true); - GLfloat temp[3] = { 0, }; + GLfloat temp[3] = { + 0, + }; cmd.Init(1, &temp[0]); - EXPECT_CALL( - *gl_, - VertexAttrib3fv(1, reinterpret_cast< - GLfloat*>(ImmediateDataAddress(&cmd)))); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_CALL(*gl_, + VertexAttrib3fv( + 1, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib4fValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib4fValidArgs) { EXPECT_CALL(*gl_, VertexAttrib4f(1, 2, 3, 4, 5)); SpecializedSetup<cmds::VertexAttrib4f, 0>(true); cmds::VertexAttrib4f cmd; @@ -1510,54 +601,23 @@ TEST_F(GLES2DecoderTest2, VertexAttrib4fValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, VertexAttrib4fvValidArgs) { - SpecializedSetup<cmds::VertexAttrib4fv, 0>(true); - cmds::VertexAttrib4fv cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_CALL( - *gl_, VertexAttrib4fv( - 1, reinterpret_cast<const GLfloat*>(shared_memory_address_))); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib4fvInvalidArgs1_0) { - EXPECT_CALL(*gl_, VertexAttrib4fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib4fv, 0>(false); - cmds::VertexAttrib4fv cmd; - cmd.Init(1, kInvalidSharedMemoryId, 0); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib4fvInvalidArgs1_1) { - EXPECT_CALL(*gl_, VertexAttrib4fv(_, _)).Times(0); - SpecializedSetup<cmds::VertexAttrib4fv, 0>(false); - cmds::VertexAttrib4fv cmd; - cmd.Init(1, shared_memory_id_, kInvalidSharedMemoryOffset); - GetSharedMemoryAs<GLfloat*>()[0] = 0; - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_F(GLES2DecoderTest2, VertexAttrib4fvImmediateValidArgs) { +TEST_P(GLES2DecoderTest2, VertexAttrib4fvImmediateValidArgs) { cmds::VertexAttrib4fvImmediate& cmd = *GetImmediateAs<cmds::VertexAttrib4fvImmediate>(); SpecializedSetup<cmds::VertexAttrib4fvImmediate, 0>(true); - GLfloat temp[4] = { 0, }; + GLfloat temp[4] = { + 0, + }; cmd.Init(1, &temp[0]); - EXPECT_CALL( - *gl_, - VertexAttrib4fv(1, reinterpret_cast< - GLfloat*>(ImmediateDataAddress(&cmd)))); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_CALL(*gl_, + VertexAttrib4fv( + 1, reinterpret_cast<GLfloat*>(ImmediateDataAddress(&cmd)))); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } // TODO(gman): VertexAttribPointer - -TEST_F(GLES2DecoderTest2, ViewportValidArgs) { +TEST_P(GLES2DecoderTest2, ViewportValidArgs) { EXPECT_CALL(*gl_, Viewport(1, 2, 3, 4)); SpecializedSetup<cmds::Viewport, 0>(true); cmds::Viewport cmd; @@ -1566,7 +626,7 @@ TEST_F(GLES2DecoderTest2, ViewportValidArgs) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_F(GLES2DecoderTest2, ViewportInvalidArgs2_0) { +TEST_P(GLES2DecoderTest2, ViewportInvalidArgs2_0) { EXPECT_CALL(*gl_, Viewport(_, _, _, _)).Times(0); SpecializedSetup<cmds::Viewport, 0>(false); cmds::Viewport cmd; @@ -1575,7 +635,7 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs2_0) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } -TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) { +TEST_P(GLES2DecoderTest2, ViewportInvalidArgs3_0) { EXPECT_CALL(*gl_, Viewport(_, _, _, _)).Times(0); SpecializedSetup<cmds::Viewport, 0>(false); cmds::Viewport cmd; @@ -1588,9 +648,7 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) { // TODO(gman): RenderbufferStorageMultisampleEXT // TODO(gman): FramebufferTexture2DMultisampleEXT // TODO(gman): TexStorage2DEXT -// TODO(gman): GenQueriesEXT // TODO(gman): GenQueriesEXTImmediate -// TODO(gman): DeleteQueriesEXT // TODO(gman): DeleteQueriesEXTImmediate // TODO(gman): BeginQueryEXT @@ -1600,17 +658,14 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) { // TODO(gman): PushGroupMarkerEXT - -TEST_F(GLES2DecoderTest2, PopGroupMarkerEXTValidArgs) { +TEST_P(GLES2DecoderTest2, PopGroupMarkerEXTValidArgs) { SpecializedSetup<cmds::PopGroupMarkerEXT, 0>(true); cmds::PopGroupMarkerEXT cmd; cmd.Init(); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -// TODO(gman): GenVertexArraysOES // TODO(gman): GenVertexArraysOESImmediate -// TODO(gman): DeleteVertexArraysOES // TODO(gman): DeleteVertexArraysOESImmediate // TODO(gman): IsVertexArrayOES // TODO(gman): BindVertexArrayOES @@ -1618,5 +673,52 @@ TEST_F(GLES2DecoderTest2, PopGroupMarkerEXTValidArgs) { // TODO(gman): GetMaxValueInBufferCHROMIUM // TODO(gman): GenSharedIdsCHROMIUM -#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ +// TODO(gman): DeleteSharedIdsCHROMIUM + +// TODO(gman): RegisterSharedIdsCHROMIUM + +// TODO(gman): EnableFeatureCHROMIUM + +// TODO(gman): ResizeCHROMIUM +// TODO(gman): GetRequestableExtensionsCHROMIUM +// TODO(gman): RequestExtensionCHROMIUM + +// TODO(gman): GetMultipleIntegervCHROMIUM + +// TODO(gman): GetProgramInfoCHROMIUM + +// TODO(gman): GetTranslatedShaderSourceANGLE +// TODO(gman): PostSubBufferCHROMIUM +// TODO(gman): TexImageIOSurface2DCHROMIUM +// TODO(gman): CopyTextureCHROMIUM +// TODO(gman): DrawArraysInstancedANGLE +// TODO(gman): DrawElementsInstancedANGLE +// TODO(gman): VertexAttribDivisorANGLE +// TODO(gman): GenMailboxCHROMIUM + +// TODO(gman): ProduceTextureCHROMIUMImmediate +// TODO(gman): ProduceTextureDirectCHROMIUMImmediate +// TODO(gman): ConsumeTextureCHROMIUMImmediate +// TODO(gman): CreateAndConsumeTextureCHROMIUMImmediate +// TODO(gman): BindUniformLocationCHROMIUMBucket +// TODO(gman): BindTexImage2DCHROMIUM +// TODO(gman): ReleaseTexImage2DCHROMIUM +// TODO(gman): TraceBeginCHROMIUM + +// TODO(gman): TraceEndCHROMIUM +// TODO(gman): AsyncTexSubImage2DCHROMIUM + +// TODO(gman): AsyncTexImage2DCHROMIUM + +// TODO(gman): WaitAsyncTexImage2DCHROMIUM + +// TODO(gman): WaitAllAsyncTexImage2DCHROMIUM + +// TODO(gman): DiscardFramebufferEXTImmediate +// TODO(gman): LoseContextCHROMIUM +// TODO(gman): InsertSyncPointCHROMIUM + +// TODO(gman): WaitSyncPointCHROMIUM + +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc index b41eed2953a..3fadaf07634 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc @@ -34,7 +34,9 @@ class GLES2DecoderTest3 : public GLES2DecoderTestBase { GLES2DecoderTest3() { } }; -TEST_F(GLES2DecoderTest3, TraceBeginCHROMIUM) { +INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderTest3, ::testing::Bool()); + +TEST_P(GLES2DecoderTest3, TraceBeginCHROMIUM) { const uint32 kBucketId = 123; const char kName[] = "test_command"; SetBucketAsCString(kBucketId, kName); @@ -44,7 +46,7 @@ TEST_F(GLES2DecoderTest3, TraceBeginCHROMIUM) { EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd)); } -TEST_F(GLES2DecoderTest3, TraceEndCHROMIUM) { +TEST_P(GLES2DecoderTest3, TraceEndCHROMIUM) { // Test end fails if no begin. TraceEndCHROMIUM end_cmd; end_cmd.Init(); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index ab338e46eff..adbde496acd 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -1,70 +1,19 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! // It is included by gles2_cmd_decoder_unittest_3.cc #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ -// TODO(gman): DeleteSharedIdsCHROMIUM - -// TODO(gman): RegisterSharedIdsCHROMIUM - -// TODO(gman): EnableFeatureCHROMIUM - -// TODO(gman): ResizeCHROMIUM -// TODO(gman): GetRequestableExtensionsCHROMIUM - -// TODO(gman): RequestExtensionCHROMIUM - -// TODO(gman): GetMultipleIntegervCHROMIUM - -// TODO(gman): GetProgramInfoCHROMIUM - -// TODO(gman): CreateStreamTextureCHROMIUM - -// TODO(gman): DestroyStreamTextureCHROMIUM - -// TODO(gman): GetTranslatedShaderSourceANGLE -// TODO(gman): PostSubBufferCHROMIUM -// TODO(gman): TexImageIOSurface2DCHROMIUM -// TODO(gman): CopyTextureCHROMIUM -// TODO(gman): DrawArraysInstancedANGLE -// TODO(gman): DrawElementsInstancedANGLE -// TODO(gman): VertexAttribDivisorANGLE -// TODO(gman): GenMailboxCHROMIUM - -// TODO(gman): ProduceTextureCHROMIUM -// TODO(gman): ProduceTextureCHROMIUMImmediate -// TODO(gman): ConsumeTextureCHROMIUM -// TODO(gman): ConsumeTextureCHROMIUMImmediate -// TODO(gman): BindUniformLocationCHROMIUM - -// TODO(gman): BindUniformLocationCHROMIUMBucket -// TODO(gman): BindTexImage2DCHROMIUM -// TODO(gman): ReleaseTexImage2DCHROMIUM -// TODO(gman): TraceBeginCHROMIUM - -// TODO(gman): TraceEndCHROMIUM -// TODO(gman): AsyncTexSubImage2DCHROMIUM - -// TODO(gman): AsyncTexImage2DCHROMIUM - -// TODO(gman): WaitAsyncTexImage2DCHROMIUM - -// TODO(gman): DiscardFramebufferEXT -// TODO(gman): DiscardFramebufferEXTImmediate -// TODO(gman): LoseContextCHROMIUM - -// TODO(gman): InsertSyncPointCHROMIUM - -// TODO(gman): WaitSyncPointCHROMIUM - -// TODO(gman): DrawBuffersEXT // TODO(gman): DrawBuffersEXTImmediate -#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ +// TODO(gman): DiscardBackbufferCHROMIUM +// TODO(gman): ScheduleOverlayPlaneCHROMIUM +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc new file mode 100644 index 00000000000..d32870d9a1a --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc @@ -0,0 +1,388 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +TEST_P(GLES2DecoderManualInitTest, AsyncPixelTransfers) { + InitState init; + init.extensions = "GL_CHROMIUM_async_pixel_transfers"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + // Set up the texture. + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + TextureRef* texture_ref = GetTexture(client_texture_id_); + Texture* texture = texture_ref->texture(); + + // Set a mock Async delegate + StrictMock<gpu::MockAsyncPixelTransferManager>* manager = + new StrictMock<gpu::MockAsyncPixelTransferManager>; + manager->Initialize(group().texture_manager()); + decoder_->SetAsyncPixelTransferManagerForTest(manager); + StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate = NULL; + + // Tex(Sub)Image2D upload commands. + AsyncTexImage2DCHROMIUM teximage_cmd; + teximage_cmd.Init(GL_TEXTURE_2D, + 0, + GL_RGBA, + 8, + 8, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + 0, + 0, + 0); + AsyncTexSubImage2DCHROMIUM texsubimage_cmd; + texsubimage_cmd.Init(GL_TEXTURE_2D, + 0, + 0, + 0, + 8, + 8, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + 0, + 0, + 0); + WaitAsyncTexImage2DCHROMIUM wait_cmd; + wait_cmd.Init(GL_TEXTURE_2D); + WaitAllAsyncTexImage2DCHROMIUM wait_all_cmd; + wait_all_cmd.Init(); + + // No transfer state exists initially. + EXPECT_FALSE( + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + + base::Closure bind_callback; + + // AsyncTexImage2D + { + // Create transfer state since it doesn't exist. + EXPECT_EQ(texture_ref->num_observers(), 0); + EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) + .WillOnce(Return( + delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) + .RetiresOnSaturation(); + EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)) + .WillOnce(SaveArg<2>(&bind_callback)) + .RetiresOnSaturation(); + // Command succeeds. + EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ( + delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + EXPECT_TRUE(texture->IsImmutable()); + // The texture is safe but the level has not been defined yet. + EXPECT_TRUE(texture->SafeToRenderFrom()); + GLsizei width, height; + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(texture_ref->num_observers(), 1); + } + { + // Async redefinitions are not allowed! + // Command fails. + EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ( + delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + EXPECT_TRUE(texture->IsImmutable()); + EXPECT_TRUE(texture->SafeToRenderFrom()); + } + + // Binding/defining of the async transfer + { + // TODO(epenner): We should check that the manager gets the + // BindCompletedAsyncTransfers() call, which is required to + // guarantee the delegate calls the bind callback. + + // Simulate the bind callback from the delegate. + bind_callback.Run(); + + // After the bind callback is run, the texture is safe, + // and has the right size etc. + EXPECT_TRUE(texture->SafeToRenderFrom()); + GLsizei width, height; + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(width, 8); + EXPECT_EQ(height, 8); + } + + // AsyncTexSubImage2D + EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); + decoder_->GetAsyncPixelTransferManager()->ClearPixelTransferDelegateForTest( + texture_ref); + EXPECT_EQ(texture_ref->num_observers(), 0); + texture->SetImmutable(false); + { + // Create transfer state since it doesn't exist. + EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) + .WillOnce(Return( + delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) + .RetiresOnSaturation(); + EXPECT_CALL(*delegate, AsyncTexSubImage2D(_, _)).RetiresOnSaturation(); + // Command succeeds. + EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ( + delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + EXPECT_TRUE(texture->IsImmutable()); + EXPECT_TRUE(texture->SafeToRenderFrom()); + } + { + // No transfer is in progress. + EXPECT_CALL(*delegate, TransferIsInProgress()) + .WillOnce(Return(false)) // texSubImage validation + .WillOnce(Return(false)) // async validation + .RetiresOnSaturation(); + EXPECT_CALL(*delegate, AsyncTexSubImage2D(_, _)).RetiresOnSaturation(); + // Command succeeds. + EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ( + delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + EXPECT_TRUE(texture->IsImmutable()); + EXPECT_TRUE(texture->SafeToRenderFrom()); + } + { + // A transfer is still in progress! + EXPECT_CALL(*delegate, TransferIsInProgress()) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + // No async call, command fails. + EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ( + delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + EXPECT_TRUE(texture->IsImmutable()); + EXPECT_TRUE(texture->SafeToRenderFrom()); + } + + // Delete delegate on DeleteTexture. + { + EXPECT_EQ(texture_ref->num_observers(), 1); + EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); + DoDeleteTexture(client_texture_id_, kServiceTextureId); + EXPECT_FALSE( + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + texture = NULL; + texture_ref = NULL; + delegate = NULL; + } + + // WaitAsyncTexImage2D + { + // Get a fresh texture since the existing texture cannot be respecified + // asynchronously and AsyncTexSubImage2D does not involve binding. + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgumentPointee<1>(kServiceTextureId)); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + texture_ref = GetTexture(client_texture_id_); + texture = texture_ref->texture(); + texture->SetImmutable(false); + // Create transfer state since it doesn't exist. + EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) + .WillOnce(Return( + delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) + .RetiresOnSaturation(); + EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)).RetiresOnSaturation(); + // Start async transfer. + EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ( + delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + + EXPECT_TRUE(texture->IsImmutable()); + // Wait for completion. + EXPECT_CALL(*delegate, WaitForTransferCompletion()); + EXPECT_CALL(*manager, BindCompletedAsyncTransfers()); + EXPECT_EQ(error::kNoError, ExecuteCmd(wait_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + // WaitAllAsyncTexImage2D + EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); + DoDeleteTexture(client_texture_id_, kServiceTextureId); + EXPECT_FALSE( + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + texture = NULL; + texture_ref = NULL; + delegate = NULL; + { + // Get a fresh texture since the existing texture cannot be respecified + // asynchronously and AsyncTexSubImage2D does not involve binding. + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgumentPointee<1>(kServiceTextureId)); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + texture_ref = GetTexture(client_texture_id_); + texture = texture_ref->texture(); + texture->SetImmutable(false); + // Create transfer state since it doesn't exist. + EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) + .WillOnce(Return( + delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) + .RetiresOnSaturation(); + EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)).RetiresOnSaturation(); + // Start async transfer. + EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ( + delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + + EXPECT_TRUE(texture->IsImmutable()); + // Wait for completion of all uploads. + EXPECT_CALL(*manager, WaitAllAsyncTexImage2D()).RetiresOnSaturation(); + EXPECT_CALL(*manager, BindCompletedAsyncTransfers()); + EXPECT_EQ(error::kNoError, ExecuteCmd(wait_all_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + // Remove PixelTransferManager before the decoder destroys. + EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); + decoder_->ResetAsyncPixelTransferManagerForTest(); + manager = NULL; +} + +TEST_P(GLES2DecoderManualInitTest, AsyncPixelTransferManager) { + InitState init; + init.extensions = "GL_CHROMIUM_async_pixel_transfers"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + // Set up the texture. + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + TextureRef* texture_ref = GetTexture(client_texture_id_); + + // Set a mock Async delegate. + StrictMock<gpu::MockAsyncPixelTransferManager>* manager = + new StrictMock<gpu::MockAsyncPixelTransferManager>; + manager->Initialize(group().texture_manager()); + decoder_->SetAsyncPixelTransferManagerForTest(manager); + StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate = NULL; + + AsyncTexImage2DCHROMIUM teximage_cmd; + teximage_cmd.Init(GL_TEXTURE_2D, + 0, + GL_RGBA, + 8, + 8, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + 0, + 0, + 0); + + // No transfer delegate exists initially. + EXPECT_FALSE( + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + + // Create delegate on AsyncTexImage2D. + { + EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) + .WillOnce(Return( + delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) + .RetiresOnSaturation(); + EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)).RetiresOnSaturation(); + + // Command succeeds. + EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + // Delegate is cached. + EXPECT_EQ(delegate, + decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( + texture_ref)); + + // Delete delegate on manager teardown. + { + EXPECT_EQ(texture_ref->num_observers(), 1); + EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); + decoder_->ResetAsyncPixelTransferManagerForTest(); + manager = NULL; + + // Texture ref still valid. + EXPECT_EQ(texture_ref, GetTexture(client_texture_id_)); + EXPECT_EQ(texture_ref->num_observers(), 0); + } +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc new file mode 100644 index 00000000000..3b000fca37c --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc @@ -0,0 +1,485 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +TEST_P(GLES2DecoderWithShaderTest, GetVertexAttribPointervSucceeds) { + const float dummy = 0; + const GLuint kOffsetToTestFor = sizeof(dummy) * 4; + const GLuint kIndexToTest = 1; + GetVertexAttribPointerv::Result* result = + static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_); + result->size = 0; + const GLuint* result_value = result->GetData(); + // Test that initial value is 0. + GetVertexAttribPointerv cmd; + cmd.Init(kIndexToTest, + GL_VERTEX_ATTRIB_ARRAY_POINTER, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(sizeof(*result_value), result->size); + EXPECT_EQ(0u, *result_value); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Set the value and see that we get it. + SetupVertexBuffer(); + DoVertexAttribPointer(kIndexToTest, 2, GL_FLOAT, 0, kOffsetToTestFor); + result->size = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(sizeof(*result_value), result->size); + EXPECT_EQ(kOffsetToTestFor, *result_value); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetVertexAttribPointervBadArgsFails) { + const GLuint kIndexToTest = 1; + GetVertexAttribPointerv::Result* result = + static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_); + result->size = 0; + const GLuint* result_value = result->GetData(); + // Test pname invalid fails. + GetVertexAttribPointerv cmd; + cmd.Init(kIndexToTest, + GL_VERTEX_ATTRIB_ARRAY_POINTER + 1, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0u, result->size); + EXPECT_EQ(kInitialResult, *result_value); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + // Test index out of range fails. + result->size = 0; + cmd.Init(kNumVertexAttribs, + GL_VERTEX_ATTRIB_ARRAY_POINTER, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0u, result->size); + EXPECT_EQ(kInitialResult, *result_value); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + // Test memory id bad fails. + cmd.Init(kIndexToTest, + GL_VERTEX_ATTRIB_ARRAY_POINTER, + kInvalidSharedMemoryId, + shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + + // Test memory offset bad fails. + cmd.Init(kIndexToTest, + GL_VERTEX_ATTRIB_ARRAY_POINTER, + shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, BindBufferToDifferentTargetFails) { + // Bind the buffer to GL_ARRAY_BUFFER + DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); + // Attempt to rebind to GL_ELEMENT_ARRAY_BUFFER + // NOTE: Real GLES2 does not have this restriction but WebGL and we do. + // This can be restriction can be removed at runtime. + EXPECT_CALL(*gl_, BindBuffer(_, _)).Times(0); + BindBuffer cmd; + cmd.Init(GL_ELEMENT_ARRAY_BUFFER, client_buffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, VertexAttribPointer) { + SetupVertexBuffer(); + static const GLenum types[] = { + GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, + GL_FLOAT, GL_FIXED, GL_INT, GL_UNSIGNED_INT, + }; + static const GLsizei sizes[] = { + 1, 1, 2, 2, 4, 4, 4, 4, + }; + static const GLuint indices[] = { + 0, 1, kNumVertexAttribs - 1, kNumVertexAttribs, + }; + static const GLsizei offset_mult[] = { + 0, 0, 1, 1, 2, 1000, + }; + static const GLsizei offset_offset[] = { + 0, 1, 0, 1, 0, 0, + }; + static const GLsizei stride_mult[] = { + -1, 0, 0, 1, 1, 2, 1000, + }; + static const GLsizei stride_offset[] = { + 0, 0, 1, 0, 1, 0, 0, + }; + for (size_t tt = 0; tt < arraysize(types); ++tt) { + GLenum type = types[tt]; + GLsizei num_bytes = sizes[tt]; + for (size_t ii = 0; ii < arraysize(indices); ++ii) { + GLuint index = indices[ii]; + for (GLint size = 0; size < 5; ++size) { + for (size_t oo = 0; oo < arraysize(offset_mult); ++oo) { + GLuint offset = num_bytes * offset_mult[oo] + offset_offset[oo]; + for (size_t ss = 0; ss < arraysize(stride_mult); ++ss) { + GLsizei stride = num_bytes * stride_mult[ss] + stride_offset[ss]; + for (int normalize = 0; normalize < 2; ++normalize) { + bool index_good = index < static_cast<GLuint>(kNumVertexAttribs); + bool size_good = (size > 0 && size < 5); + bool offset_good = (offset % num_bytes == 0); + bool stride_good = + (stride % num_bytes == 0) && stride >= 0 && stride <= 255; + bool type_good = (type != GL_INT && type != GL_UNSIGNED_INT && + type != GL_FIXED); + bool good = size_good && offset_good && stride_good && + type_good && index_good; + bool call = good && (type != GL_FIXED); + if (call) { + EXPECT_CALL(*gl_, + VertexAttribPointer(index, + size, + type, + normalize, + stride, + BufferOffset(offset))); + } + VertexAttribPointer cmd; + cmd.Init(index, size, type, normalize, stride, offset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + if (good) { + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } else if (size_good && offset_good && stride_good && type_good && + !index_good) { + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } else if (size_good && offset_good && stride_good && + !type_good && index_good) { + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + } else if (size_good && offset_good && !stride_good && + type_good && index_good) { + if (stride < 0 || stride > 255) { + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } else { + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + } + } else if (size_good && !offset_good && stride_good && + type_good && index_good) { + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + } else if (!size_good && offset_good && stride_good && + type_good && index_good) { + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } else { + EXPECT_NE(GL_NO_ERROR, GetGLError()); + } + } + } + } + } + } + } +} + +class GLES2DecoderVertexArraysOESTest : public GLES2DecoderWithShaderTest { + public: + GLES2DecoderVertexArraysOESTest() {} + + bool vertex_array_deleted_manually_; + + virtual void SetUp() { + InitState init; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + SetupDefaultProgram(); + + AddExpectationsForGenVertexArraysOES(); + GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_); + + vertex_array_deleted_manually_ = false; + } + + virtual void TearDown() { + // This should only be set if the test handled deletion of the vertex array + // itself. Necessary because vertex_array_objects are not sharable, and thus + // not managed in the ContextGroup, meaning they will be destroyed during + // test tear down + if (!vertex_array_deleted_manually_) { + AddExpectationsForDeleteVertexArraysOES(); + } + + GLES2DecoderWithShaderTest::TearDown(); + } + + void GenVertexArraysOESImmediateValidArgs() { + AddExpectationsForGenVertexArraysOES(); + GenVertexArraysOESImmediate* cmd = + GetImmediateAs<GenVertexArraysOESImmediate>(); + GLuint temp = kNewClientId; + cmd->Init(1, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL); + AddExpectationsForDeleteVertexArraysOES(); + } + + void GenVertexArraysOESImmediateInvalidArgs() { + EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0); + GenVertexArraysOESImmediate* cmd = + GetImmediateAs<GenVertexArraysOESImmediate>(); + cmd->Init(1, &client_vertexarray_id_); + EXPECT_EQ(error::kInvalidArguments, + ExecuteImmediateCmd(*cmd, sizeof(&client_vertexarray_id_))); + } + + void DeleteVertexArraysOESImmediateValidArgs() { + AddExpectationsForDeleteVertexArraysOES(); + DeleteVertexArraysOESImmediate& cmd = + *GetImmediateAs<DeleteVertexArraysOESImmediate>(); + cmd.Init(1, &client_vertexarray_id_); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(client_vertexarray_id_))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetVertexArrayInfo(client_vertexarray_id_) == NULL); + vertex_array_deleted_manually_ = true; + } + + void DeleteVertexArraysOESImmediateInvalidArgs() { + DeleteVertexArraysOESImmediate& cmd = + *GetImmediateAs<DeleteVertexArraysOESImmediate>(); + GLuint temp = kInvalidClientId; + cmd.Init(1, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + } + + void DeleteBoundVertexArraysOESImmediateValidArgs() { + BindVertexArrayOESValidArgs(); + + AddExpectationsForDeleteBoundVertexArraysOES(); + DeleteVertexArraysOESImmediate& cmd = + *GetImmediateAs<DeleteVertexArraysOESImmediate>(); + cmd.Init(1, &client_vertexarray_id_); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(client_vertexarray_id_))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetVertexArrayInfo(client_vertexarray_id_) == NULL); + vertex_array_deleted_manually_ = true; + } + + void IsVertexArrayOESValidArgs() { + IsVertexArrayOES cmd; + cmd.Init(client_vertexarray_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + void IsVertexArrayOESInvalidArgsBadSharedMemoryId() { + IsVertexArrayOES cmd; + cmd.Init( + client_vertexarray_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init( + client_vertexarray_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + } + + void BindVertexArrayOESValidArgs() { + AddExpectationsForBindVertexArrayOES(); + BindVertexArrayOES cmd; + cmd.Init(client_vertexarray_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + void BindVertexArrayOESValidArgsNewId() { + BindVertexArrayOES cmd; + cmd.Init(kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + } +}; + +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderVertexArraysOESTest, + ::testing::Bool()); + +class GLES2DecoderEmulatedVertexArraysOESTest + : public GLES2DecoderVertexArraysOESTest { + public: + GLES2DecoderEmulatedVertexArraysOESTest() {} + + virtual void SetUp() { + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + init.use_native_vao = false; + InitDecoder(init); + SetupDefaultProgram(); + + AddExpectationsForGenVertexArraysOES(); + GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_); + + vertex_array_deleted_manually_ = false; + } +}; + +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderEmulatedVertexArraysOESTest, + ::testing::Bool()); + +// Test vertex array objects with native support +TEST_P(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESImmediateValidArgs) { + GenVertexArraysOESImmediateValidArgs(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, + GenVertexArraysOESImmediateValidArgs) { + GenVertexArraysOESImmediateValidArgs(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, + GenVertexArraysOESImmediateInvalidArgs) { + GenVertexArraysOESImmediateInvalidArgs(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, + GenVertexArraysOESImmediateInvalidArgs) { + GenVertexArraysOESImmediateInvalidArgs(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, + DeleteVertexArraysOESImmediateValidArgs) { + DeleteVertexArraysOESImmediateValidArgs(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, + DeleteVertexArraysOESImmediateValidArgs) { + DeleteVertexArraysOESImmediateValidArgs(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, + DeleteVertexArraysOESImmediateInvalidArgs) { + DeleteVertexArraysOESImmediateInvalidArgs(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, + DeleteVertexArraysOESImmediateInvalidArgs) { + DeleteVertexArraysOESImmediateInvalidArgs(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, + DeleteBoundVertexArraysOESImmediateValidArgs) { + DeleteBoundVertexArraysOESImmediateValidArgs(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, + DeleteBoundVertexArraysOESImmediateValidArgs) { + DeleteBoundVertexArraysOESImmediateValidArgs(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, IsVertexArrayOESValidArgs) { + IsVertexArrayOESValidArgs(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, IsVertexArrayOESValidArgs) { + IsVertexArrayOESValidArgs(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, + IsVertexArrayOESInvalidArgsBadSharedMemoryId) { + IsVertexArrayOESInvalidArgsBadSharedMemoryId(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, + IsVertexArrayOESInvalidArgsBadSharedMemoryId) { + IsVertexArrayOESInvalidArgsBadSharedMemoryId(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgs) { + BindVertexArrayOESValidArgs(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, BindVertexArrayOESValidArgs) { + BindVertexArrayOESValidArgs(); +} + +TEST_P(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgsNewId) { + BindVertexArrayOESValidArgsNewId(); +} +TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, + BindVertexArrayOESValidArgsNewId) { + BindVertexArrayOESValidArgsNewId(); +} + +TEST_P(GLES2DecoderTest, BufferDataGLError) { + GLenum target = GL_ARRAY_BUFFER; + GLsizeiptr size = 4; + DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); + BufferManager* manager = group().buffer_manager(); + Buffer* buffer = manager->GetBuffer(client_buffer_id_); + ASSERT_TRUE(buffer != NULL); + EXPECT_EQ(0, buffer->size()); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BufferData(target, size, _, GL_STREAM_DRAW)) + .Times(1) + .RetiresOnSaturation(); + BufferData cmd; + cmd.Init(target, size, 0, 0, GL_STREAM_DRAW); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_EQ(0, buffer->size()); +} + +// TODO(gman): BufferData + +// TODO(gman): BufferDataImmediate + +// TODO(gman): BufferSubData + +// TODO(gman): BufferSubDataImmediate + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 9534b627adc..57c9c9dd6a6 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -14,7 +14,6 @@ #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/test_helper.h" @@ -22,11 +21,14 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface.h" using ::gfx::MockGLInterface; using ::testing::_; using ::testing::DoAll; using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::InvokeWithoutArgs; using ::testing::MatcherCast; using ::testing::Pointee; using ::testing::Return; @@ -35,6 +37,45 @@ using ::testing::SetArgPointee; using ::testing::SetArgumentPointee; using ::testing::StrEq; using ::testing::StrictMock; +using ::testing::WithArg; + +namespace { + +void NormalizeInitState(gpu::gles2::GLES2DecoderTestBase::InitState* init) { + CHECK(init); + const char* kVAOExtensions[] = { + "GL_OES_vertex_array_object", + "GL_ARB_vertex_array_object", + "GL_APPLE_vertex_array_object" + }; + bool contains_vao_extension = false; + for (size_t ii = 0; ii < arraysize(kVAOExtensions); ++ii) { + if (init->extensions.find(kVAOExtensions[ii]) != std::string::npos) { + contains_vao_extension = true; + break; + } + } + if (init->use_native_vao) { + if (contains_vao_extension) + return; + if (!init->extensions.empty()) + init->extensions += " "; + if (StartsWithASCII(init->gl_version, "opengl es", false)) { + init->extensions += kVAOExtensions[0]; + } else { +#if !defined(OS_MACOSX) + init->extensions += kVAOExtensions[1]; +#else + init->extensions += kVAOExtensions[2]; +#endif // OS_MACOSX + } + } else { + // Make sure we don't set up an invalid InitState. + CHECK(!contains_vao_extension); + } +} + +} // namespace Anonymous namespace gpu { namespace gles2 { @@ -53,22 +94,29 @@ GLES2DecoderTestBase::GLES2DecoderTestBase() client_vertex_shader_id_(121), client_fragment_shader_id_(122), client_query_id_(123), - client_vertexarray_id_(124) { + client_vertexarray_id_(124), + ignore_cached_state_for_test_(GetParam()), + cached_color_mask_red_(true), + cached_color_mask_green_(true), + cached_color_mask_blue_(true), + cached_color_mask_alpha_(true), + cached_depth_mask_(true), + cached_stencil_front_mask_(0xFFFFFFFFU), + cached_stencil_back_mask_(0xFFFFFFFFU) { memset(immediate_buffer_, 0xEE, sizeof(immediate_buffer_)); } GLES2DecoderTestBase::~GLES2DecoderTestBase() {} void GLES2DecoderTestBase::SetUp() { - InitDecoder( - "", // extensions - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); } void GLES2DecoderTestBase::AddExpectationsForVertexAttribManager() { @@ -79,65 +127,73 @@ void GLES2DecoderTestBase::AddExpectationsForVertexAttribManager() { } } -void GLES2DecoderTestBase::InitDecoder( - const char* extensions, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource) { - InitDecoderWithCommandLine(extensions, - has_alpha, - has_depth, - has_stencil, - request_alpha, - request_depth, - request_stencil, - bind_generates_resource, - NULL); +GLES2DecoderTestBase::InitState::InitState() + : has_alpha(false), + has_depth(false), + has_stencil(false), + request_alpha(false), + request_depth(false), + request_stencil(false), + bind_generates_resource(false), + lose_context_when_out_of_memory(false), + use_native_vao(true) { +} + +void GLES2DecoderTestBase::InitDecoder(const InitState& init) { + InitDecoderWithCommandLine(init, NULL); } void GLES2DecoderTestBase::InitDecoderWithCommandLine( - const char* extensions, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource, - const CommandLine* command_line) { + const InitState& init, + const base::CommandLine* command_line) { + InitState normalized_init = init; + NormalizeInitState(&normalized_init); Framebuffer::ClearFramebufferCompleteComboMap(); + + gfx::SetGLGetProcAddressProc(gfx::MockGLInterface::GetGLProcAddress); + gfx::GLSurface::InitializeOneOffWithMockBindingsForTests(); + gl_.reset(new StrictMock<MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + ::gfx::MockGLInterface::SetGLInterface(gl_.get()); + + SetupMockGLBehaviors(); // Only create stream texture manager if extension is requested. std::vector<std::string> list; - base::SplitString(std::string(extensions), ' ', &list); - if (std::find(list.begin(), list.end(), - "GL_CHROMIUM_stream_texture") != list.end()) - stream_texture_manager_.reset(new StrictMock<MockStreamTextureManager>); + base::SplitString(normalized_init.extensions, ' ', &list); scoped_refptr<FeatureInfo> feature_info; if (command_line) feature_info = new FeatureInfo(*command_line); - group_ = scoped_refptr<ContextGroup>(new ContextGroup( - NULL, - NULL, - memory_tracker_, - stream_texture_manager_.get(), - feature_info.get(), - bind_generates_resource)); - // These two workarounds are always turned on. - group_->feature_info( - )->workarounds_.set_texture_filter_before_generating_mipmap = true; - group_->feature_info()->workarounds_.clear_alpha_in_readpixels = true; + group_ = scoped_refptr<ContextGroup>( + new ContextGroup(NULL, + NULL, + memory_tracker_, + new ShaderTranslatorCache, + feature_info.get(), + normalized_init.bind_generates_resource)); + bool use_default_textures = normalized_init.bind_generates_resource; InSequence sequence; - TestHelper::SetupContextGroupInitExpectations(gl_.get(), - DisallowedFeatures(), extensions); + surface_ = new gfx::GLSurfaceStub; + surface_->SetSize(gfx::Size(kBackBufferWidth, kBackBufferHeight)); + + // Context needs to be created before initializing ContextGroup, which will + // in turn initialize FeatureInfo, which needs a context to determine + // extension support. + context_ = new gfx::GLContextStubWithExtensions; + context_->AddExtensionsString(normalized_init.extensions.c_str()); + context_->SetGLVersionString(normalized_init.gl_version.c_str()); + + context_->MakeCurrent(surface_.get()); + gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_); + + TestHelper::SetupContextGroupInitExpectations( + gl_.get(), + DisallowedFeatures(), + normalized_init.extensions.c_str(), + normalized_init.gl_version.c_str(), + normalized_init.bind_generates_resource); // We initialize the ContextGroup with a MockGLES2Decoder so that // we can use the ContextGroup to figure out how the real GLES2Decoder @@ -146,7 +202,15 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( EXPECT_TRUE( group_->Initialize(mock_decoder_.get(), DisallowedFeatures())); - AddExpectationsForVertexAttribManager(); + if (group_->feature_info()->feature_flags().native_vertex_array_object) { + EXPECT_CALL(*gl_, GenVertexArraysOES(1, _)) + .WillOnce(SetArgumentPointee<1>(kServiceVertexArrayId)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindVertexArrayOES(_)).Times(1).RetiresOnSaturation(); + } + + if (group_->feature_info()->workarounds().init_vertex_attributes) + AddExpectationsForVertexAttribManager(); AddExpectationsForBindVertexArrayOES(); @@ -183,25 +247,36 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( .Times(1) .RetiresOnSaturation(); if (group_->feature_info()->feature_flags().oes_egl_image_external) { - EXPECT_CALL(*gl_, BindTexture( - GL_TEXTURE_EXTERNAL_OES, - TestHelper::kServiceDefaultExternalTextureId)) + EXPECT_CALL(*gl_, + BindTexture(GL_TEXTURE_EXTERNAL_OES, + use_default_textures + ? TestHelper::kServiceDefaultExternalTextureId + : 0)) .Times(1) .RetiresOnSaturation(); } if (group_->feature_info()->feature_flags().arb_texture_rectangle) { - EXPECT_CALL(*gl_, BindTexture( - GL_TEXTURE_RECTANGLE_ARB, - TestHelper::kServiceDefaultRectangleTextureId)) + EXPECT_CALL( + *gl_, + BindTexture(GL_TEXTURE_RECTANGLE_ARB, + use_default_textures + ? TestHelper::kServiceDefaultRectangleTextureId + : 0)) .Times(1) .RetiresOnSaturation(); } - EXPECT_CALL(*gl_, BindTexture( - GL_TEXTURE_CUBE_MAP, TestHelper::kServiceDefaultTextureCubemapId)) + EXPECT_CALL(*gl_, + BindTexture(GL_TEXTURE_CUBE_MAP, + use_default_textures + ? TestHelper::kServiceDefaultTextureCubemapId + : 0)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture( - GL_TEXTURE_2D, TestHelper::kServiceDefaultTexture2dId)) + EXPECT_CALL( + *gl_, + BindTexture( + GL_TEXTURE_2D, + use_default_textures ? TestHelper::kServiceDefaultTexture2dId : 0)) .Times(1) .RetiresOnSaturation(); } @@ -213,14 +288,14 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) - .WillOnce(SetArgumentPointee<1>(has_alpha ? 8 : 0)) - .RetiresOnSaturation(); + .WillOnce(SetArgumentPointee<1>(normalized_init.has_alpha ? 8 : 0)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(has_depth ? 24 : 0)) - .RetiresOnSaturation(); + .WillOnce(SetArgumentPointee<1>(normalized_init.has_depth ? 24 : 0)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(has_stencil ? 8 : 0)) - .RetiresOnSaturation(); + .WillOnce(SetArgumentPointee<1>(normalized_init.has_stencil ? 8 : 0)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, Enable(GL_VERTEX_PROGRAM_POINT_SIZE)) .Times(1) @@ -269,28 +344,29 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( #endif engine_.reset(new StrictMock<MockCommandBufferEngine>()); - gpu::Buffer buffer = engine_->GetSharedMemoryBuffer(kSharedMemoryId); + scoped_refptr<gpu::Buffer> buffer = + engine_->GetSharedMemoryBuffer(kSharedMemoryId); shared_memory_offset_ = kSharedMemoryOffset; - shared_memory_address_ = reinterpret_cast<int8*>(buffer.ptr) + - shared_memory_offset_; + shared_memory_address_ = + reinterpret_cast<int8*>(buffer->memory()) + shared_memory_offset_; shared_memory_id_ = kSharedMemoryId; - shared_memory_base_ = buffer.ptr; + shared_memory_base_ = buffer->memory(); - surface_ = new gfx::GLSurfaceStub; - surface_->SetSize(gfx::Size(kBackBufferWidth, kBackBufferHeight)); - - context_ = new gfx::GLContextStub; - - context_->MakeCurrent(surface_.get()); + static const int32 kLoseContextWhenOutOfMemory = 0x10003; int32 attributes[] = { - EGL_ALPHA_SIZE, request_alpha ? 8 : 0, - EGL_DEPTH_SIZE, request_depth ? 24 : 0, - EGL_STENCIL_SIZE, request_stencil ? 8 : 0, - }; + EGL_ALPHA_SIZE, + normalized_init.request_alpha ? 8 : 0, + EGL_DEPTH_SIZE, + normalized_init.request_depth ? 24 : 0, + EGL_STENCIL_SIZE, + normalized_init.request_stencil ? 8 : 0, + kLoseContextWhenOutOfMemory, + normalized_init.lose_context_when_out_of_memory ? 1 : 0, }; std::vector<int32> attribs(attributes, attributes + arraysize(attributes)); decoder_.reset(GLES2Decoder::Create(group_.get())); + decoder_->SetIgnoreCachedStateForTest(ignore_cached_state_for_test_); decoder_->GetLogger()->set_log_synthesized_gl_errors(false); decoder_->Initialize(surface_, context_, @@ -300,6 +376,7 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( attribs); decoder_->MakeCurrent(); decoder_->set_engine(engine_.get()); + decoder_->BeginDecoding(); EXPECT_CALL(*gl_, GenBuffersARB(_, _)) .WillOnce(SetArgumentPointee<1>(kServiceBufferId)) @@ -328,20 +405,33 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -void GLES2DecoderTestBase::TearDown() { +void GLES2DecoderTestBase::ResetDecoder() { + if (!decoder_.get()) + return; // All Tests should have read all their GLErrors before getting here. EXPECT_EQ(GL_NO_ERROR, GetGLError()); EXPECT_CALL(*gl_, DeleteBuffersARB(1, _)) .Times(2) .RetiresOnSaturation(); + if (group_->feature_info()->feature_flags().native_vertex_array_object) { + EXPECT_CALL(*gl_, DeleteVertexArraysOES(1, Pointee(kServiceVertexArrayId))) + .Times(1) + .RetiresOnSaturation(); + } + decoder_->EndDecoding(); decoder_->Destroy(true); decoder_.reset(); group_->Destroy(mock_decoder_.get(), false); engine_.reset(); - ::gfx::GLInterface::SetGLInterface(NULL); + ::gfx::MockGLInterface::SetGLInterface(NULL); gl_.reset(); + gfx::ClearGLBindings(); +} + +void GLES2DecoderTestBase::TearDown() { + ResetDecoder(); } void GLES2DecoderTestBase::ExpectEnableDisable(GLenum cap, bool enable) { @@ -429,12 +519,13 @@ void GLES2DecoderTestBase::SetBucketAsCString( } } -void GLES2DecoderTestBase::SetupClearTextureExpections( +void GLES2DecoderTestBase::SetupClearTextureExpectations( GLuint service_id, GLuint old_service_id, GLenum bind_target, GLenum target, GLint level, + GLenum internal_format, GLenum format, GLenum type, GLsizei width, @@ -443,7 +534,7 @@ void GLES2DecoderTestBase::SetupClearTextureExpections( .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, TexImage2D( - target, level, format, width, height, 0, format, type, _)) + target, level, internal_format, width, height, 0, format, type, _)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, BindTexture(bind_target, old_service_id)) @@ -530,9 +621,7 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( EXPECT_CALL(*gl_, ClearColor(0.0f, 0.0f, 0.0f, 0.0f)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ColorMask(true, true, true, true)) - .Times(1) - .RetiresOnSaturation(); + SetupExpectationsForColorMask(true, true, true, true); } if ((clear_bits & GL_STENCIL_BUFFER_BIT) != 0) { EXPECT_CALL(*gl_, ClearStencil(0)) @@ -546,13 +635,9 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( EXPECT_CALL(*gl_, ClearDepth(1.0f)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthMask(1)) - .Times(1) - .RetiresOnSaturation(); + SetupExpectationsForDepthMask(true); } - EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST)) - .Times(1) - .RetiresOnSaturation(); + SetupExpectationsForEnableDisable(GL_SCISSOR_TEST, false); EXPECT_CALL(*gl_, Clear(clear_bits)) .Times(1) .RetiresOnSaturation(); @@ -616,102 +701,167 @@ void GLES2DecoderTestBase::DoDeleteBuffer( EXPECT_CALL(*gl_, DeleteBuffersARB(1, Pointee(service_id))) .Times(1) .RetiresOnSaturation(); - cmds::DeleteBuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - memcpy(shared_memory_address_, &client_id, sizeof(client_id)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); -} - -void GLES2DecoderTestBase::SetupExpectationsForApplyingDirtyState( - bool framebuffer_is_rgb, - bool framebuffer_has_depth, - bool framebuffer_has_stencil, - GLuint color_bits, - bool depth_mask, - bool depth_enabled, - GLuint front_stencil_mask, - GLuint back_stencil_mask, - bool stencil_enabled, - bool cull_face_enabled, - bool scissor_test_enabled, - bool blend_enabled) { - EXPECT_CALL(*gl_, ColorMask( - (color_bits & 0x1000) != 0, - (color_bits & 0x0100) != 0, - (color_bits & 0x0010) != 0, - (color_bits & 0x0001) && !framebuffer_is_rgb)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthMask(depth_mask)) - .Times(1) - .RetiresOnSaturation(); - if (framebuffer_has_depth && depth_enabled) { - EXPECT_CALL(*gl_, Enable(GL_DEPTH_TEST)) - .Times(1) - .RetiresOnSaturation(); - } else { - EXPECT_CALL(*gl_, Disable(GL_DEPTH_TEST)) + GenHelper<cmds::DeleteBuffersImmediate>(client_id); +} + +void GLES2DecoderTestBase::SetupExpectationsForColorMask(bool red, + bool green, + bool blue, + bool alpha) { + if (ignore_cached_state_for_test_ || cached_color_mask_red_ != red || + cached_color_mask_green_ != green || cached_color_mask_blue_ != blue || + cached_color_mask_alpha_ != alpha) { + cached_color_mask_red_ = red; + cached_color_mask_green_ = green; + cached_color_mask_blue_ = blue; + cached_color_mask_alpha_ = alpha; + EXPECT_CALL(*gl_, ColorMask(red, green, blue, alpha)) .Times(1) .RetiresOnSaturation(); } - EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, front_stencil_mask)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, back_stencil_mask)) - .Times(1) - .RetiresOnSaturation(); - if (framebuffer_has_stencil && stencil_enabled) { - EXPECT_CALL(*gl_, Enable(GL_STENCIL_TEST)) - .Times(1) - .RetiresOnSaturation(); - } else { - EXPECT_CALL(*gl_, Disable(GL_STENCIL_TEST)) - .Times(1) - .RetiresOnSaturation(); +} + +void GLES2DecoderTestBase::SetupExpectationsForDepthMask(bool mask) { + if (ignore_cached_state_for_test_ || cached_depth_mask_ != mask) { + cached_depth_mask_ = mask; + EXPECT_CALL(*gl_, DepthMask(mask)).Times(1).RetiresOnSaturation(); } - if (cull_face_enabled) { - EXPECT_CALL(*gl_, Enable(GL_CULL_FACE)) - .Times(1) - .RetiresOnSaturation(); - } else { - EXPECT_CALL(*gl_, Disable(GL_CULL_FACE)) +} + +void GLES2DecoderTestBase::SetupExpectationsForStencilMask(uint32 front_mask, + uint32 back_mask) { + if (ignore_cached_state_for_test_ || + cached_stencil_front_mask_ != front_mask) { + cached_stencil_front_mask_ = front_mask; + EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, front_mask)) .Times(1) .RetiresOnSaturation(); } - if (scissor_test_enabled) { - EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST)) - .Times(1) - .RetiresOnSaturation(); - } else { - EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST)) + + if (ignore_cached_state_for_test_ || + cached_stencil_back_mask_ != back_mask) { + cached_stencil_back_mask_ = back_mask; + EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, back_mask)) .Times(1) .RetiresOnSaturation(); } - if (blend_enabled) { - EXPECT_CALL(*gl_, Enable(GL_BLEND)) - .Times(1) - .RetiresOnSaturation(); +} + +void GLES2DecoderTestBase::SetupExpectationsForEnableDisable(GLenum cap, + bool enable) { + switch (cap) { + case GL_BLEND: + if (enable_flags_.cached_blend == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_blend = enable; + break; + case GL_CULL_FACE: + if (enable_flags_.cached_cull_face == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_cull_face = enable; + break; + case GL_DEPTH_TEST: + if (enable_flags_.cached_depth_test == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_depth_test = enable; + break; + case GL_DITHER: + if (enable_flags_.cached_dither == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_dither = enable; + break; + case GL_POLYGON_OFFSET_FILL: + if (enable_flags_.cached_polygon_offset_fill == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_polygon_offset_fill = enable; + break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: + if (enable_flags_.cached_sample_alpha_to_coverage == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_sample_alpha_to_coverage = enable; + break; + case GL_SAMPLE_COVERAGE: + if (enable_flags_.cached_sample_coverage == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_sample_coverage = enable; + break; + case GL_SCISSOR_TEST: + if (enable_flags_.cached_scissor_test == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_scissor_test = enable; + break; + case GL_STENCIL_TEST: + if (enable_flags_.cached_stencil_test == enable && + !ignore_cached_state_for_test_) + return; + enable_flags_.cached_stencil_test = enable; + break; + default: + NOTREACHED(); + return; + } + if (enable) { + EXPECT_CALL(*gl_, Enable(cap)).Times(1).RetiresOnSaturation(); } else { - EXPECT_CALL(*gl_, Disable(GL_BLEND)) - .Times(1) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, Disable(cap)).Times(1).RetiresOnSaturation(); } } +void GLES2DecoderTestBase::SetupExpectationsForApplyingDirtyState( + bool framebuffer_is_rgb, + bool framebuffer_has_depth, + bool framebuffer_has_stencil, + GLuint color_bits, + bool depth_mask, + bool depth_enabled, + GLuint front_stencil_mask, + GLuint back_stencil_mask, + bool stencil_enabled) { + bool color_mask_red = (color_bits & 0x1000) != 0; + bool color_mask_green = (color_bits & 0x0100) != 0; + bool color_mask_blue = (color_bits & 0x0010) != 0; + bool color_mask_alpha = (color_bits & 0x0001) && !framebuffer_is_rgb; + + SetupExpectationsForColorMask( + color_mask_red, color_mask_green, color_mask_blue, color_mask_alpha); + SetupExpectationsForDepthMask(depth_mask); + SetupExpectationsForStencilMask(front_stencil_mask, back_stencil_mask); + SetupExpectationsForEnableDisable(GL_DEPTH_TEST, + framebuffer_has_depth && depth_enabled); + SetupExpectationsForEnableDisable(GL_STENCIL_TEST, + framebuffer_has_stencil && stencil_enabled); +} + void GLES2DecoderTestBase::SetupExpectationsForApplyingDefaultDirtyState() { - SetupExpectationsForApplyingDirtyState( - false, // Framebuffer is RGB - false, // Framebuffer has depth - false, // Framebuffer has stencil - 0x1111, // color bits - true, // depth mask - false, // depth enabled - 0, // front stencil mask - 0, // back stencil mask - false, // stencil enabled - false, // cull_face_enabled - false, // scissor_test_enabled - false); // blend_enabled + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + true, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled +} + +GLES2DecoderTestBase::EnableFlags::EnableFlags() + : cached_blend(false), + cached_cull_face(false), + cached_depth_test(false), + cached_dither(true), + cached_polygon_offset_fill(false), + cached_sample_alpha_to_coverage(false), + cached_sample_coverage(false), + cached_scissor_test(false), + cached_stencil_test(false) { } void GLES2DecoderTestBase::DoBindFramebuffer( @@ -746,10 +896,7 @@ void GLES2DecoderTestBase::DoDeleteFramebuffer( EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, Pointee(service_id))) .Times(1) .RetiresOnSaturation(); - cmds::DeleteFramebuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - memcpy(shared_memory_address_, &client_id, sizeof(client_id)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + GenHelper<cmds::DeleteFramebuffersImmediate>(client_id); } void GLES2DecoderTestBase::DoBindRenderbuffer( @@ -772,10 +919,7 @@ void GLES2DecoderTestBase::DoDeleteRenderbuffer( EXPECT_CALL(*gl_, DeleteRenderbuffersEXT(1, Pointee(service_id))) .Times(1) .RetiresOnSaturation(); - cmds::DeleteRenderbuffers cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - memcpy(shared_memory_address_, &client_id, sizeof(client_id)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + GenHelper<cmds::DeleteRenderbuffersImmediate>(client_id); } void GLES2DecoderTestBase::DoBindTexture( @@ -797,10 +941,7 @@ void GLES2DecoderTestBase::DoDeleteTexture( EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(service_id))) .Times(1) .RetiresOnSaturation(); - cmds::DeleteTextures cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - memcpy(shared_memory_address_, &client_id, sizeof(client_id)); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + GenHelper<cmds::DeleteTexturesImmediate>(client_id); } void GLES2DecoderTestBase::DoTexImage2D( @@ -819,11 +960,33 @@ void GLES2DecoderTestBase::DoTexImage2D( .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); cmds::TexImage2D cmd; - cmd.Init(target, level, internal_format, width, height, border, format, + cmd.Init(target, level, internal_format, width, height, format, type, shared_memory_id, shared_memory_offset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } +void GLES2DecoderTestBase::DoTexImage2DConvertInternalFormat( + GLenum target, GLint level, GLenum requested_internal_format, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + uint32 shared_memory_id, uint32 shared_memory_offset, + GLenum expected_internal_format) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexImage2D(target, level, expected_internal_format, + width, height, border, format, type, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + cmds::TexImage2D cmd; + cmd.Init(target, level, requested_internal_format, width, height, + format, type, shared_memory_id, shared_memory_offset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + void GLES2DecoderTestBase::DoCompressedTexImage2D( GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLint border, @@ -842,7 +1005,7 @@ void GLES2DecoderTestBase::DoCompressedTexImage2D( bucket->SetSize(size); cmds::CompressedTexImage2DBucket cmd; cmd.Init( - target, level, format, width, height, border, + target, level, format, width, height, bucket_id); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } @@ -880,7 +1043,7 @@ void GLES2DecoderTestBase::DoFramebufferTexture2D( .WillOnce(Return(error)) .RetiresOnSaturation(); cmds::FramebufferTexture2D cmd; - cmd.Init(target, attachment, textarget, texture_client_id, level); + cmd.Init(target, attachment, textarget, texture_client_id); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } @@ -945,6 +1108,12 @@ void GLES2DecoderTestBase::AddExpectationsForDeleteVertexArraysOES(){ } } +void GLES2DecoderTestBase::AddExpectationsForDeleteBoundVertexArraysOES() { + // Expectations are the same as a delete, followed by binding VAO 0. + AddExpectationsForDeleteVertexArraysOES(); + AddExpectationsForBindVertexArrayOES(); +} + void GLES2DecoderTestBase::AddExpectationsForBindVertexArrayOES() { if (group_->feature_info()->feature_flags().native_vertex_array_object) { EXPECT_CALL(*gl_, BindVertexArrayOES(_)) @@ -1255,6 +1424,19 @@ void GLES2DecoderTestBase::SetupShader( EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd)); } +void GLES2DecoderTestBase::DoEnableDisable(GLenum cap, bool enable) { + SetupExpectationsForEnableDisable(cap, enable); + if (enable) { + cmds::Enable cmd; + cmd.Init(cap); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } else { + cmds::Disable cmd; + cmd.Init(cap); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } +} + void GLES2DecoderTestBase::DoEnableVertexAttribArray(GLint index) { EXPECT_CALL(*gl_, EnableVertexAttribArray(index)) .Times(1) @@ -1360,12 +1542,6 @@ void GLES2DecoderTestBase::AddExpectationsForSimulatedAttrib0WithError( EXPECT_CALL(*gl_, VertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, VertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL)) - .Times(1) - .RetiresOnSaturation(); EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, buffer_id)) .Times(1) .RetiresOnSaturation(); @@ -1378,18 +1554,35 @@ void GLES2DecoderTestBase::AddExpectationsForSimulatedAttrib0( num_vertices, buffer_id, GL_NO_ERROR); } +void GLES2DecoderTestBase::SetupMockGLBehaviors() { + ON_CALL(*gl_, BindVertexArrayOES(_)) + .WillByDefault(Invoke( + &gl_states_, + &GLES2DecoderTestBase::MockGLStates::OnBindVertexArrayOES)); + ON_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, _)) + .WillByDefault(WithArg<1>(Invoke( + &gl_states_, + &GLES2DecoderTestBase::MockGLStates::OnBindArrayBuffer))); + ON_CALL(*gl_, VertexAttribPointer(_, _, _, _, _, NULL)) + .WillByDefault(InvokeWithoutArgs( + &gl_states_, + &GLES2DecoderTestBase::MockGLStates::OnVertexAttribNullPointer)); +} + GLES2DecoderWithShaderTestBase::MockCommandBufferEngine:: MockCommandBufferEngine() { - data_.reset(new int8[kSharedBufferSize]); + + scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + shm->CreateAndMapAnonymous(kSharedBufferSize); + valid_buffer_ = MakeBufferFromSharedMemory(shm.Pass(), kSharedBufferSize); + ClearSharedMemory(); - valid_buffer_.ptr = data_.get(); - valid_buffer_.size = kSharedBufferSize; } GLES2DecoderWithShaderTestBase::MockCommandBufferEngine:: ~MockCommandBufferEngine() {} -gpu::Buffer +scoped_refptr<gpu::Buffer> GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::GetSharedMemoryBuffer( int32 shm_id) { return shm_id == kSharedMemoryId ? valid_buffer_ : invalid_buffer_; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 55436192c06..8456698344e 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -12,27 +12,29 @@ #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/shader_manager.h" -#include "gpu/command_buffer/service/stream_texture_manager_mock.h" #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gl/gl_context_stub.h" +#include "ui/gl/gl_context_stub_with_extensions.h" #include "ui/gl/gl_surface_stub.h" #include "ui/gl/gl_mock.h" +namespace base { class CommandLine; +} namespace gpu { namespace gles2 { class MemoryTracker; -class GLES2DecoderTestBase : public testing::Test { +class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { public: GLES2DecoderTestBase(); virtual ~GLES2DecoderTestBase(); @@ -140,11 +142,6 @@ class GLES2DecoderTestBase : public testing::Test { return group_->program_manager(); } - ::testing::StrictMock<MockStreamTextureManager>* - stream_texture_manager() const { - return stream_texture_manager_.get(); - } - void DoCreateProgram(GLuint client_id, GLuint service_id); void DoCreateShader(GLenum shader_type, GLuint client_id, GLuint service_id); @@ -154,26 +151,27 @@ class GLES2DecoderTestBase : public testing::Test { memory_tracker_ = memory_tracker; } - void InitDecoder( - const char* extensions, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource); - - void InitDecoderWithCommandLine( - const char* extensions, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource, - const CommandLine* command_line); + struct InitState { + InitState(); + + std::string extensions; + std::string gl_version; + bool has_alpha; + bool has_depth; + bool has_stencil; + bool request_alpha; + bool request_depth; + bool request_stencil; + bool bind_generates_resource; + bool lose_context_when_out_of_memory; + bool use_native_vao; // default is true. + }; + + void InitDecoder(const InitState& init); + void InitDecoderWithCommandLine(const InitState& init, + const base::CommandLine* command_line); + + void ResetDecoder(); const ContextGroup& group() const { return *group_.get(); @@ -248,6 +246,12 @@ class GLES2DecoderTestBase : public testing::Test { GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, uint32 shared_memory_id, uint32 shared_memory_offset); + void DoTexImage2DConvertInternalFormat( + GLenum target, GLint level, GLenum requested_internal_format, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + uint32 shared_memory_id, uint32 shared_memory_offset, + GLenum expected_internal_format); void DoRenderbufferStorage( GLenum target, GLenum internal_format, GLenum actual_format, GLsizei width, GLsizei height, GLenum error); @@ -266,6 +270,8 @@ class GLES2DecoderTestBase : public testing::Test { GLuint index, GLint size, GLenum type, GLsizei stride, GLuint offset); void DoVertexAttribDivisorANGLE(GLuint index, GLuint divisor); + void DoEnableDisable(GLenum cap, bool enable); + void DoEnableVertexAttribArray(GLint index); void DoBufferData(GLenum target, GLsizei size); @@ -282,12 +288,13 @@ class GLES2DecoderTestBase : public testing::Test { void DeleteIndexBuffer(); - void SetupClearTextureExpections( + void SetupClearTextureExpectations( GLuint service_id, GLuint old_service_id, GLenum bind_target, GLenum target, GLint level, + GLenum internal_format, GLenum format, GLenum type, GLsizei width, @@ -326,6 +333,15 @@ class GLES2DecoderTestBase : public testing::Test { GLclampf restore_depth, bool restore_scissor_test); + void SetupExpectationsForDepthMask(bool mask); + void SetupExpectationsForEnableDisable(GLenum cap, bool enable); + void SetupExpectationsForColorMask(bool red, + bool green, + bool blue, + bool alpha); + void SetupExpectationsForStencilMask(uint32 front_mask, + uint32 back_mask); + void SetupExpectationsForApplyingDirtyState( bool framebuffer_is_rgb, bool framebuffer_has_depth, @@ -335,10 +351,7 @@ class GLES2DecoderTestBase : public testing::Test { bool depth_enabled, GLuint front_stencil_mask, GLuint back_stencil_mask, - bool stencil_enabled, - bool cull_face_enabled, - bool scissor_test_enabled, - bool blend_enabled); + bool stencil_enabled); void SetupExpectationsForApplyingDefaultDirtyState(); @@ -350,6 +363,7 @@ class GLES2DecoderTestBase : public testing::Test { void AddExpectationsForGenVertexArraysOES(); void AddExpectationsForDeleteVertexArraysOES(); + void AddExpectationsForDeleteBoundVertexArraysOES(); void AddExpectationsForBindVertexArrayOES(); void AddExpectationsForRestoreAttribState(GLuint attrib); @@ -481,8 +495,8 @@ class GLES2DecoderTestBase : public testing::Test { // Use StrictMock to make 100% sure we know how GL will be called. scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<gfx::GLSurfaceStub> surface_; - scoped_refptr<gfx::GLContextStub> context_; - scoped_ptr<GLES2Decoder> mock_decoder_; + scoped_refptr<gfx::GLContextStubWithExtensions> context_; + scoped_ptr<MockGLES2Decoder> mock_decoder_; scoped_ptr<GLES2Decoder> decoder_; MemoryTracker* memory_tracker_; @@ -505,6 +519,30 @@ class GLES2DecoderTestBase : public testing::Test { int8 immediate_buffer_[256]; + const bool ignore_cached_state_for_test_; + bool cached_color_mask_red_; + bool cached_color_mask_green_; + bool cached_color_mask_blue_; + bool cached_color_mask_alpha_; + bool cached_depth_mask_; + uint32 cached_stencil_front_mask_; + uint32 cached_stencil_back_mask_; + + struct EnableFlags { + EnableFlags(); + bool cached_blend; + bool cached_cull_face; + bool cached_depth_test; + bool cached_dither; + bool cached_polygon_offset_fill; + bool cached_sample_alpha_to_coverage; + bool cached_sample_coverage; + bool cached_scissor_test; + bool cached_stencil_test; + }; + + EnableFlags enable_flags_; + private: class MockCommandBufferEngine : public CommandBufferEngine { public: @@ -512,10 +550,11 @@ class GLES2DecoderTestBase : public testing::Test { virtual ~MockCommandBufferEngine(); - virtual gpu::Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE; + virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id) + OVERRIDE; void ClearSharedMemory() { - memset(data_.get(), kInitialMemoryValue, kSharedBufferSize); + memset(valid_buffer_->memory(), kInitialMemoryValue, kSharedBufferSize); } virtual void set_token(int32 token) OVERRIDE; @@ -529,17 +568,51 @@ class GLES2DecoderTestBase : public testing::Test { virtual int32 GetGetOffset() OVERRIDE; private: - scoped_ptr<int8[]> data_; - gpu::Buffer valid_buffer_; - gpu::Buffer invalid_buffer_; + scoped_refptr<gpu::Buffer> valid_buffer_; + scoped_refptr<gpu::Buffer> invalid_buffer_; }; + // MockGLStates is used to track GL states and emulate driver + // behaviors on top of MockGLInterface. + class MockGLStates { + public: + MockGLStates() + : bound_array_buffer_object_(0), + bound_vertex_array_object_(0) { + } + + ~MockGLStates() { + } + + void OnBindArrayBuffer(GLuint id) { + bound_array_buffer_object_ = id; + } + + void OnBindVertexArrayOES(GLuint id) { + bound_vertex_array_object_ = id; + } + + void OnVertexAttribNullPointer() { + // When a vertex array object is bound, some drivers (AMD Linux, + // Qualcomm, etc.) have a bug where it incorrectly generates an + // GL_INVALID_OPERATION on glVertexAttribPointer() if pointer + // is NULL, no buffer is bound on GL_ARRAY_BUFFER. + // Make sure we don't trigger this bug. + if (bound_vertex_array_object_ != 0) + EXPECT_TRUE(bound_array_buffer_object_ != 0); + } + + private: + GLuint bound_array_buffer_object_; + GLuint bound_vertex_array_object_; + }; // class MockGLStates + void AddExpectationsForVertexAttribManager(); + void SetupMockGLBehaviors(); scoped_ptr< ::testing::StrictMock<MockCommandBufferEngine> > engine_; - scoped_ptr< ::testing::StrictMock<MockStreamTextureManager> > - stream_texture_manager_; scoped_refptr<ContextGroup> group_; + MockGLStates gl_states_; }; class GLES2DecoderWithShaderTestBase : public GLES2DecoderTestBase { @@ -554,6 +627,10 @@ class GLES2DecoderWithShaderTestBase : public GLES2DecoderTestBase { }; +// SpecializedSetup specializations that are needed in multiple unittest files. +template <> +void GLES2DecoderTestBase::SpecializedSetup<cmds::LinkProgram, 0>(bool valid); + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc new file mode 100644 index 00000000000..49ebfc3f27a --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc @@ -0,0 +1,428 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +class GLES2DecoderRestoreStateTest : public GLES2DecoderManualInitTest { + public: + GLES2DecoderRestoreStateTest() {} + + protected: + void AddExpectationsForActiveTexture(GLenum unit); + void AddExpectationsForBindTexture(GLenum target, GLuint id); + void InitializeContextState(ContextState* state, + uint32 non_default_unit, + uint32 active_unit); +}; + +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderRestoreStateTest, + ::testing::Bool()); + +void GLES2DecoderRestoreStateTest::AddExpectationsForActiveTexture( + GLenum unit) { + EXPECT_CALL(*gl_, ActiveTexture(unit)).Times(1).RetiresOnSaturation(); +} + +void GLES2DecoderRestoreStateTest::AddExpectationsForBindTexture(GLenum target, + GLuint id) { + EXPECT_CALL(*gl_, BindTexture(target, id)).Times(1).RetiresOnSaturation(); +} + +void GLES2DecoderRestoreStateTest::InitializeContextState( + ContextState* state, + uint32 non_default_unit, + uint32 active_unit) { + state->texture_units.resize(group().max_texture_units()); + for (uint32 tt = 0; tt < state->texture_units.size(); ++tt) { + TextureRef* ref_cube_map = + group().texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP); + state->texture_units[tt].bound_texture_cube_map = ref_cube_map; + TextureRef* ref_2d = + (tt == non_default_unit) + ? group().texture_manager()->GetTexture(client_texture_id_) + : group().texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D); + state->texture_units[tt].bound_texture_2d = ref_2d; + } + state->active_texture_unit = active_unit; +} + +TEST_P(GLES2DecoderRestoreStateTest, NullPreviousStateBGR) { + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + SetupTexture(); + + InSequence sequence; + // Expect to restore texture bindings for unit GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, + TestHelper::kServiceDefaultTextureCubemapId); + + // Expect to restore texture bindings for remaining units. + for (uint32 i = 1; i < group().max_texture_units(); ++i) { + AddExpectationsForActiveTexture(GL_TEXTURE0 + i); + AddExpectationsForBindTexture(GL_TEXTURE_2D, + TestHelper::kServiceDefaultTexture2dId); + AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, + TestHelper::kServiceDefaultTextureCubemapId); + } + + // Expect to restore the active texture unit to GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + + GetDecoder()->RestoreAllTextureUnitBindings(NULL); +} + +TEST_P(GLES2DecoderRestoreStateTest, NullPreviousState) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + SetupTexture(); + + InSequence sequence; + // Expect to restore texture bindings for unit GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, 0); + + // Expect to restore texture bindings for remaining units. + for (uint32 i = 1; i < group().max_texture_units(); ++i) { + AddExpectationsForActiveTexture(GL_TEXTURE0 + i); + AddExpectationsForBindTexture(GL_TEXTURE_2D, 0); + AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, 0); + } + + // Expect to restore the active texture unit to GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + + GetDecoder()->RestoreAllTextureUnitBindings(NULL); +} + +TEST_P(GLES2DecoderRestoreStateTest, WithPreviousStateBGR) { + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + SetupTexture(); + + // Construct a previous ContextState with all texture bindings + // set to default textures. + ContextState prev_state(NULL, NULL, NULL); + InitializeContextState(&prev_state, std::numeric_limits<uint32>::max(), 0); + + InSequence sequence; + // Expect to restore only GL_TEXTURE_2D binding for GL_TEXTURE0 unit, + // since the rest of the bindings haven't changed between the current + // state and the |prev_state|. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + + // Expect to restore active texture unit to GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + + GetDecoder()->RestoreAllTextureUnitBindings(&prev_state); +} + +TEST_P(GLES2DecoderRestoreStateTest, WithPreviousState) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + SetupTexture(); + + // Construct a previous ContextState with all texture bindings + // set to default textures. + ContextState prev_state(NULL, NULL, NULL); + InitializeContextState(&prev_state, std::numeric_limits<uint32>::max(), 0); + + InSequence sequence; + // Expect to restore only GL_TEXTURE_2D binding for GL_TEXTURE0 unit, + // since the rest of the bindings haven't changed between the current + // state and the |prev_state|. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + + // Expect to restore active texture unit to GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + + GetDecoder()->RestoreAllTextureUnitBindings(&prev_state); +} + +TEST_P(GLES2DecoderRestoreStateTest, ActiveUnit1) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + // Bind a non-default texture to GL_TEXTURE1 unit. + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE1)); + ActiveTexture cmd; + cmd.Init(GL_TEXTURE1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + SetupTexture(); + + // Construct a previous ContextState with all texture bindings + // set to default textures. + ContextState prev_state(NULL, NULL, NULL); + InitializeContextState(&prev_state, std::numeric_limits<uint32>::max(), 0); + + InSequence sequence; + // Expect to restore only GL_TEXTURE_2D binding for GL_TEXTURE1 unit, + // since the rest of the bindings haven't changed between the current + // state and the |prev_state|. + AddExpectationsForActiveTexture(GL_TEXTURE1); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + + // Expect to restore active texture unit to GL_TEXTURE1. + AddExpectationsForActiveTexture(GL_TEXTURE1); + + GetDecoder()->RestoreAllTextureUnitBindings(&prev_state); +} + +TEST_P(GLES2DecoderRestoreStateTest, NonDefaultUnit0BGR) { + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + // Bind a non-default texture to GL_TEXTURE1 unit. + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE1)); + SpecializedSetup<ActiveTexture, 0>(true); + ActiveTexture cmd; + cmd.Init(GL_TEXTURE1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + SetupTexture(); + + // Construct a previous ContextState with GL_TEXTURE_2D target in + // GL_TEXTURE0 unit bound to a non-default texture and the rest + // set to default textures. + ContextState prev_state(NULL, NULL, NULL); + InitializeContextState(&prev_state, 0, kServiceTextureId); + + InSequence sequence; + // Expect to restore GL_TEXTURE_2D binding for GL_TEXTURE0 unit to + // a default texture. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, + TestHelper::kServiceDefaultTexture2dId); + + // Expect to restore GL_TEXTURE_2D binding for GL_TEXTURE1 unit to + // non-default. + AddExpectationsForActiveTexture(GL_TEXTURE1); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + + // Expect to restore active texture unit to GL_TEXTURE1. + AddExpectationsForActiveTexture(GL_TEXTURE1); + + GetDecoder()->RestoreAllTextureUnitBindings(&prev_state); +} + +TEST_P(GLES2DecoderRestoreStateTest, NonDefaultUnit1BGR) { + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + // Bind a non-default texture to GL_TEXTURE0 unit. + SetupTexture(); + + // Construct a previous ContextState with GL_TEXTURE_2D target in + // GL_TEXTURE1 unit bound to a non-default texture and the rest + // set to default textures. + ContextState prev_state(NULL, NULL, NULL); + InitializeContextState(&prev_state, 1, kServiceTextureId); + + InSequence sequence; + // Expect to restore GL_TEXTURE_2D binding to the non-default texture + // for GL_TEXTURE0 unit. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + + // Expect to restore GL_TEXTURE_2D binding to the default texture + // for GL_TEXTURE1 unit. + AddExpectationsForActiveTexture(GL_TEXTURE1); + AddExpectationsForBindTexture(GL_TEXTURE_2D, + TestHelper::kServiceDefaultTexture2dId); + + // Expect to restore active texture unit to GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + + GetDecoder()->RestoreAllTextureUnitBindings(&prev_state); +} + +TEST_P(GLES2DecoderRestoreStateTest, DefaultUnit0) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + // Bind a non-default texture to GL_TEXTURE1 unit. + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE1)); + SpecializedSetup<ActiveTexture, 0>(true); + ActiveTexture cmd; + cmd.Init(GL_TEXTURE1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + SetupTexture(); + + // Construct a previous ContextState with GL_TEXTURE_2D target in + // GL_TEXTURE0 unit bound to a non-default texture and the rest + // set to default textures. + ContextState prev_state(NULL, NULL, NULL); + InitializeContextState(&prev_state, 0, kServiceTextureId); + + InSequence sequence; + // Expect to restore GL_TEXTURE_2D binding for GL_TEXTURE0 unit to + // the 0 texture. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, 0); + + // Expect to restore GL_TEXTURE_2D binding for GL_TEXTURE1 unit to + // non-default. + AddExpectationsForActiveTexture(GL_TEXTURE1); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + + // Expect to restore active texture unit to GL_TEXTURE1. + AddExpectationsForActiveTexture(GL_TEXTURE1); + + GetDecoder()->RestoreAllTextureUnitBindings(&prev_state); +} + +TEST_P(GLES2DecoderRestoreStateTest, DefaultUnit1) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + // Bind a non-default texture to GL_TEXTURE0 unit. + SetupTexture(); + + // Construct a previous ContextState with GL_TEXTURE_2D target in + // GL_TEXTURE1 unit bound to a non-default texture and the rest + // set to default textures. + ContextState prev_state(NULL, NULL, NULL); + InitializeContextState(&prev_state, 1, kServiceTextureId); + + InSequence sequence; + // Expect to restore GL_TEXTURE_2D binding to the non-default texture + // for GL_TEXTURE0 unit. + AddExpectationsForActiveTexture(GL_TEXTURE0); + AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); + + // Expect to restore GL_TEXTURE_2D binding to the 0 texture + // for GL_TEXTURE1 unit. + AddExpectationsForActiveTexture(GL_TEXTURE1); + AddExpectationsForBindTexture(GL_TEXTURE_2D, 0); + + // Expect to restore active texture unit to GL_TEXTURE0. + AddExpectationsForActiveTexture(GL_TEXTURE0); + + GetDecoder()->RestoreAllTextureUnitBindings(&prev_state); +} + +TEST_P(GLES2DecoderManualInitTest, ContextStateCapabilityCaching) { + struct TestInfo { + GLenum gl_enum; + bool default_state; + bool expect_set; + }; + + // TODO(vmiura): Should autogen this to match build_gles2_cmd_buffer.py. + TestInfo test[] = {{GL_BLEND, false, true}, + {GL_CULL_FACE, false, true}, + {GL_DEPTH_TEST, false, false}, + {GL_DITHER, true, true}, + {GL_POLYGON_OFFSET_FILL, false, true}, + {GL_SAMPLE_ALPHA_TO_COVERAGE, false, true}, + {GL_SAMPLE_COVERAGE, false, true}, + {GL_SCISSOR_TEST, false, true}, + {GL_STENCIL_TEST, false, false}, + {0, false, false}}; + + InitState init; + init.gl_version = "2.1"; + InitDecoder(init); + + for (int i = 0; test[i].gl_enum; i++) { + bool enable_state = test[i].default_state; + + // Test setting default state initially is ignored. + EnableDisableTest(test[i].gl_enum, enable_state, test[i].expect_set); + + // Test new and cached state changes. + for (int n = 0; n < 3; n++) { + enable_state = !enable_state; + EnableDisableTest(test[i].gl_enum, enable_state, test[i].expect_set); + EnableDisableTest(test[i].gl_enum, enable_state, test[i].expect_set); + } + } +} + +// TODO(vmiura): Tests for VAO restore. + +// TODO(vmiura): Tests for ContextState::RestoreAttribute(). + +// TODO(vmiura): Tests for ContextState::RestoreBufferBindings(). + +// TODO(vmiura): Tests for ContextState::RestoreProgramBindings(). + +// TODO(vmiura): Tests for ContextState::RestoreRenderbufferBindings(). + +// TODO(vmiura): Tests for ContextState::RestoreProgramBindings(). + +// TODO(vmiura): Tests for ContextState::RestoreGlobalState(). + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc new file mode 100644 index 00000000000..3dfa4758082 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc @@ -0,0 +1,2284 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +class GLES2DecoderGeometryInstancingTest : public GLES2DecoderWithShaderTest { + public: + GLES2DecoderGeometryInstancingTest() : GLES2DecoderWithShaderTest() {} + + virtual void SetUp() { + InitState init; + init.extensions = "GL_ANGLE_instanced_arrays"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + SetupDefaultProgram(); + } +}; + +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderGeometryInstancingTest, + ::testing::Bool()); + +void GLES2DecoderManualInitTest::DirtyStateMaskTest(GLuint color_bits, + bool depth_mask, + GLuint front_stencil_mask, + GLuint back_stencil_mask) { + ColorMask color_mask_cmd; + color_mask_cmd.Init((color_bits & 0x1000) != 0, + (color_bits & 0x0100) != 0, + (color_bits & 0x0010) != 0, + (color_bits & 0x0001) != 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(color_mask_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + DepthMask depth_mask_cmd; + depth_mask_cmd.Init(depth_mask); + EXPECT_EQ(error::kNoError, ExecuteCmd(depth_mask_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + StencilMaskSeparate front_stencil_mask_cmd; + front_stencil_mask_cmd.Init(GL_FRONT, front_stencil_mask); + EXPECT_EQ(error::kNoError, ExecuteCmd(front_stencil_mask_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + StencilMaskSeparate back_stencil_mask_cmd; + back_stencil_mask_cmd.Init(GL_BACK, back_stencil_mask); + EXPECT_EQ(error::kNoError, ExecuteCmd(back_stencil_mask_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupExpectationsForApplyingDirtyState( + false, // Framebuffer is RGB + true, // Framebuffer has depth + true, // Framebuffer has stencil + color_bits, // color bits + depth_mask, // depth mask + false, // depth enabled + front_stencil_mask, // front stencil mask + back_stencil_mask, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Test that with an RGB backbuffer if we set the color mask to 1,1,1,1 it is +// set to 1,1,1,0 at Draw time but is 1,1,1,1 at query time. +TEST_P(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMask) { + ColorMask cmd; + cmd.Init(true, true, true, true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_COLOR_WRITEMASK, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_COLOR_WRITEMASK, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_COLOR_WRITEMASK), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); + EXPECT_EQ(1, result->GetData()[1]); + EXPECT_EQ(1, result->GetData()[2]); + EXPECT_EQ(1, result->GetData()[3]); +} + +// Test that with no depth if we set DepthMask true that it's set to false at +// draw time but querying it returns true. +TEST_P(GLES2DecoderRGBBackbufferTest, RGBBackbufferDepthMask) { + EXPECT_CALL(*gl_, DepthMask(true)).Times(0).RetiresOnSaturation(); + DepthMask cmd; + cmd.Init(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_WRITEMASK, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_WRITEMASK, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_WRITEMASK), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +// Test that with no stencil if we set the stencil mask it's still set to 0 at +// draw time but gets our value if we query. +TEST_P(GLES2DecoderRGBBackbufferTest, RGBBackbufferStencilMask) { + const GLint kMask = 123; + EXPECT_CALL(*gl_, StencilMask(kMask)).Times(0).RetiresOnSaturation(); + StencilMask cmd; + cmd.Init(kMask); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_WRITEMASK, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_WRITEMASK, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_WRITEMASK), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(kMask, result->GetData()[0]); +} + +// Test that if an FBO is bound we get the correct masks. +TEST_P(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMaskFBO) { + ColorMask cmd; + cmd.Init(true, true, true, true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + DoEnableVertexAttribArray(2); + DoVertexAttribPointer(2, 2, GL_FLOAT, 0, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that no extra calls are made on the next draw. + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Setup Frame buffer. + // needs to be 1x1 or else it's not renderable. + const GLsizei kWidth = 1; + const GLsizei kHeight = 1; + const GLenum kFormat = GL_RGB; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + // Pass some data so the texture will be marked as cleared. + DoTexImage2D(GL_TEXTURE_2D, + 0, + kFormat, + kWidth, + kHeight, + 0, + kFormat, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_, + kServiceTextureId, + 0, + GL_NO_ERROR); + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + + // This time state needs to be set. + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that no extra calls are made on the next draw. + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Unbind + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); + + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, DepthEnableWithDepth) { + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + + Enable cmd; + cmd.Init(GL_DEPTH_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + true, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + true, // depth mask + true, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) { + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + + Enable cmd; + cmd.Init(GL_DEPTH_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, StencilEnableWithStencil) { + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + Enable cmd; + cmd.Init(GL_STENCIL_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + true, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + -1, // front stencil mask + -1, // back stencil mask + true); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) { + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + Enable cmd; + cmd.Init(GL_STENCIL_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, CachedColorMask) { + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.has_stencil = true; + init.request_alpha = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + SetupDefaultProgram(); + SetupAllNeededVertexBuffers(); + SetupTexture(); + + // Test all color_bits combinations twice. + for (int i = 0; i < 32; i++) { + GLuint color_bits = (i & 1 ? 0x0001 : 0x0000) | (i & 2 ? 0x0010 : 0x0000) | + (i & 4 ? 0x0100 : 0x0000) | (i & 8 ? 0x1000 : 0x0000); + + // Toggle depth_test to force ApplyDirtyState each time. + DirtyStateMaskTest(color_bits, false, 0xffffffff, 0xffffffff); + DirtyStateMaskTest(color_bits, true, 0xffffffff, 0xffffffff); + DirtyStateMaskTest(color_bits, false, 0xffffffff, 0xffffffff); + } +} + +TEST_P(GLES2DecoderManualInitTest, CachedDepthMask) { + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.has_stencil = true; + init.request_alpha = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + SetupDefaultProgram(); + SetupAllNeededVertexBuffers(); + SetupTexture(); + + // Test all depth_mask combinations twice. + for (int i = 0; i < 4; i++) { + bool depth_mask = (i & 1) == 1; + + // Toggle color masks to force ApplyDirtyState each time. + DirtyStateMaskTest(0x1010, depth_mask, 0xffffffff, 0xffffffff); + DirtyStateMaskTest(0x0101, depth_mask, 0xffffffff, 0xffffffff); + DirtyStateMaskTest(0x1010, depth_mask, 0xffffffff, 0xffffffff); + } +} + +TEST_P(GLES2DecoderManualInitTest, CachedStencilMask) { + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.has_stencil = true; + init.request_alpha = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + SetupDefaultProgram(); + SetupAllNeededVertexBuffers(); + SetupTexture(); + + // Test all stencil_mask combinations twice. + for (int i = 0; i < 4; i++) { + GLuint stencil_mask = (i & 1) ? 0xf0f0f0f0 : 0x0f0f0f0f; + + // Toggle color masks to force ApplyDirtyState each time. + DirtyStateMaskTest(0x1010, true, stencil_mask, 0xffffffff); + DirtyStateMaskTest(0x0101, true, stencil_mask, 0xffffffff); + DirtyStateMaskTest(0x1010, true, stencil_mask, 0xffffffff); + } + + for (int i = 0; i < 4; i++) { + GLuint stencil_mask = (i & 1) ? 0xf0f0f0f0 : 0x0f0f0f0f; + + // Toggle color masks to force ApplyDirtyState each time. + DirtyStateMaskTest(0x1010, true, 0xffffffff, stencil_mask); + DirtyStateMaskTest(0x0101, true, 0xffffffff, stencil_mask); + DirtyStateMaskTest(0x1010, true, 0xffffffff, stencil_mask); + } +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysNoAttributesSucceeds) { + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Tests when the math overflows (0x40000000 * sizeof GLfloat) +TEST_P(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OverflowFails) { + const GLsizei kLargeCount = 0x40000000; + SetupTexture(); + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kLargeCount); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(GetDecoder()->WasContextLost()); +} + +// Tests when the math overflows (0x7FFFFFFF + 1 = 0x8000000 verts) +TEST_P(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0PosToNegFails) { + const GLsizei kLargeCount = 0x7FFFFFFF; + SetupTexture(); + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kLargeCount); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(GetDecoder()->WasContextLost()); +} + +// Tests when the driver returns an error +TEST_P(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OOMFails) { + const GLsizei kFakeLargeCount = 0x1234; + SetupTexture(); + AddExpectationsForSimulatedAttrib0WithError( + kFakeLargeCount, 0, GL_OUT_OF_MEMORY); + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(GetDecoder()->WasContextLost()); +} + +// Test that we lose context. +TEST_P(GLES2DecoderManualInitTest, LoseContextWhenOOM) { + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + init.lose_context_when_out_of_memory = true; + InitDecoder(init); + SetupDefaultProgram(); + + const GLsizei kFakeLargeCount = 0x1234; + SetupTexture(); + AddExpectationsForSimulatedAttrib0WithError( + kFakeLargeCount, 0, GL_OUT_OF_MEMORY); + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); + // Other contexts in the group should be lost also. + EXPECT_CALL(*mock_decoder_, LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount); + // This context should be lost. + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysBadTextureUsesBlack) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + // This is an NPOT texture. As the default filtering requires mips + // this should trigger replacing with black textures before rendering. + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 3, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + { + InSequence sequence; + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL( + *gl_, BindTexture(GL_TEXTURE_2D, TestHelper::kServiceBlackTexture2dId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) + .Times(1) + .RetiresOnSaturation(); + } + SetupExpectationsForApplyingDefaultDirtyState(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysMissingAttributesFails) { + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, + DrawArraysMissingAttributesZeroCountSucceeds) { + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysValidAttributesSucceeds) { + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Same as DrawArraysValidAttributesSucceeds, but with workaround +// |init_vertex_attributes|. +TEST_P(GLES2DecoderManualInitTest, InitVertexAttributes) { + CommandLine command_line(0, NULL); + command_line.AppendSwitchASCII( + switches::kGpuDriverBugWorkarounds, + base::IntToString(gpu::INIT_VERTEX_ATTRIBUTES)); + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); + SetupDefaultProgram(); + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysDeletedBufferFails) { + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + DeleteVertexBuffer(); + + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysDeletedProgramSucceeds) { + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + DoDeleteProgram(client_program_id_, kServiceProgramId); + + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)).Times(1); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysWithInvalidModeFails) { + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0); + DrawArrays cmd; + cmd.Init(GL_QUADS, 0, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_POLYGON, 0, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysInvalidCountFails) { + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + // Try start > 0 + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 1, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Try with count > size + cmd.Init(GL_TRIANGLES, 0, kNumVertices + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Try with attrib offset > 0 + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Try with size > 2 (ie, vec3 instead of vec2) + DoVertexAttribPointer(1, 3, GL_FLOAT, 0, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Try with stride > 8 (vec2 + vec2 byte) + DoVertexAttribPointer(1, 2, GL_FLOAT, sizeof(GLfloat) * 3, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysInstancedANGLEFails) { + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, VertexAttribDivisorANGLEFails) { + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(_, _)) + .Times(0) + .RetiresOnSaturation(); + + VertexAttribDivisorANGLE cmd; + cmd.Init(0, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLENoAttributesFails) { + SetupTexture(); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLESimulatedAttrib0) { + SetupTexture(); + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); + + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, 3)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 1)) + .Times(1) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 3); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLEMissingAttributesFails) { + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLEMissingAttributesZeroCountSucceeds) { + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, 0, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLEValidAttributesSucceeds) { + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, 1)) + .Times(1) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLEWithInvalidModeFails) { + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_QUADS, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_POLYGON, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLEInvalidPrimcountFails) { + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, 1, -1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +// Per-instance data is twice as large, but number of instances is half +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLELargeInstanceSucceeds) { + SetupTexture(); + SetupVertexBuffer(); + SetupExpectationsForApplyingDefaultDirtyState(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL( + *gl_, + DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, kNumVertices / 2)) + .Times(1) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices / 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Per-instance data is twice as large, but divisor is twice +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLELargeDivisorSucceeds) { + SetupTexture(); + SetupVertexBuffer(); + SetupExpectationsForApplyingDefaultDirtyState(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 2); + EXPECT_CALL( + *gl_, + DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, DrawArraysInstancedANGLELargeFails) { + SetupTexture(); + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + cmd.Init(GL_TRIANGLES, 0, kNumVertices + 1, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Per-index data is twice as large, but number of indices is half +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLELargeIndexSucceeds) { + SetupTexture(); + SetupVertexBuffer(); + SetupExpectationsForApplyingDefaultDirtyState(); + DoVertexAttribPointer(1, 4, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL( + *gl_, + DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices / 2, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices / 2, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawArraysInstancedANGLENoDivisor0Fails) { + SetupTexture(); + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + DoVertexAttribDivisorANGLE(1, 1); + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawArraysInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsNoAttributesSucceeds) { + SetupTexture(); + SetupIndexBuffer(); + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + EXPECT_CALL(*gl_, + DrawElements(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2))) + .Times(1) + .RetiresOnSaturation(); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsMissingAttributesFails) { + SetupIndexBuffer(); + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, + DrawElementsMissingAttributesZeroCountSucceeds) { + SetupIndexBuffer(); + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsExtraAttributesFails) { + SetupIndexBuffer(); + DoEnableVertexAttribArray(6); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsValidAttributesSucceeds) { + SetupTexture(); + SetupVertexBuffer(); + SetupIndexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); + + EXPECT_CALL(*gl_, + DrawElements(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2))) + .Times(1) + .RetiresOnSaturation(); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsDeletedBufferFails) { + SetupVertexBuffer(); + SetupIndexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + DeleteIndexBuffer(); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsDeletedProgramSucceeds) { + SetupTexture(); + SetupIndexBuffer(); + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + DoDeleteProgram(client_program_id_, kServiceProgramId); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1); + EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)).Times(1); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsWithInvalidModeFails) { + SetupVertexBuffer(); + SetupIndexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_QUADS, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_POLYGON, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsInvalidCountFails) { + SetupVertexBuffer(); + SetupIndexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + // Try start > 0 + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, kNumIndices, GL_UNSIGNED_SHORT, 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Try with count > size + cmd.Init(GL_TRIANGLES, kNumIndices + 1, GL_UNSIGNED_SHORT, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsOutOfRangeIndicesFails) { + SetupVertexBuffer(); + SetupIndexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kInvalidIndexRangeCount, + GL_UNSIGNED_SHORT, + kInvalidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsOddOffsetForUint16Fails) { + SetupVertexBuffer(); + SetupIndexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, kInvalidIndexRangeCount, GL_UNSIGNED_SHORT, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsInstancedANGLEFails) { + SetupTexture(); + SetupVertexBuffer(); + SetupIndexBuffer(); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLENoAttributesFails) { + SetupTexture(); + SetupIndexBuffer(); + + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLESimulatedAttrib0) { + SetupTexture(); + SetupVertexBuffer(); + SetupIndexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); + + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL( + *gl_, + DrawElementsInstancedANGLE(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2), + 3)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 1)) + .Times(1) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + 3); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLEMissingAttributesFails) { + SetupIndexBuffer(); + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)).Times(0); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLEMissingAttributesZeroCountSucceeds) { + SetupIndexBuffer(); + DoEnableVertexAttribArray(1); + + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)).Times(0); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, kValidIndexRangeStart * 2, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLEValidAttributesSucceeds) { + SetupIndexBuffer(); + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); + + EXPECT_CALL( + *gl_, + DrawElementsInstancedANGLE(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2), + 1)) + .Times(1) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLEWithInvalidModeFails) { + SetupIndexBuffer(); + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)).Times(0); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_QUADS, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_INVALID_ENUM, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +// Per-instance data is twice as large, but number of instances is half +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLELargeInstanceSucceeds) { + SetupTexture(); + SetupIndexBuffer(); + SetupVertexBuffer(); + SetupExpectationsForApplyingDefaultDirtyState(); + // Add offset so we're sure we're accessing data near the end of the buffer. + DoVertexAttribPointer( + 1, + 2, + GL_FLOAT, + 0, + (kNumVertices - kMaxValidIndex - 1) * 2 * sizeof(GLfloat)); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL( + *gl_, + DrawElementsInstancedANGLE(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2), + kNumVertices / 2)) + .Times(1) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + kNumVertices / 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Per-instance data is twice as large, but divisor is twice +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLELargeDivisorSucceeds) { + SetupTexture(); + SetupIndexBuffer(); + SetupVertexBuffer(); + SetupExpectationsForApplyingDefaultDirtyState(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 2); + EXPECT_CALL( + *gl_, + DrawElementsInstancedANGLE(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2), + kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLELargeFails) { + SetupTexture(); + SetupIndexBuffer(); + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + kNumVertices + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + cmd.Init(GL_TRIANGLES, + kInvalidIndexRangeCount, + GL_UNSIGNED_SHORT, + kInvalidIndexRangeStart * 2, + kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLEInvalidPrimcountFails) { + SetupTexture(); + SetupIndexBuffer(); + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + -1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Per-index data is twice as large, but values of indices are smaller +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLELargeIndexSucceeds) { + SetupTexture(); + SetupIndexBuffer(); + SetupVertexBuffer(); + SetupExpectationsForApplyingDefaultDirtyState(); + DoVertexAttribPointer(1, 4, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + EXPECT_CALL( + *gl_, + DrawElementsInstancedANGLE(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2), + kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderGeometryInstancingTest, + DrawElementsInstancedANGLENoDivisor0Fails) { + SetupTexture(); + SetupIndexBuffer(); + SetupVertexBuffer(); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoVertexAttribDivisorANGLE(0, 1); + DoVertexAttribDivisorANGLE(1, 1); + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + DrawElementsInstancedANGLE cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2, + kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawArraysClearsAfterTexImage2DNULL) { + SetupAllNeededVertexBuffers(); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + // Create an uncleared texture with 2 levels. + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + // Expect 2 levels will be cleared. + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 1, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 1, + 1); + SetupExpectationsForApplyingDefaultDirtyState(); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // But not again + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawElementsClearsAfterTexImage2DNULL) { + SetupAllNeededVertexBuffers(); + SetupIndexBuffer(); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + // Create an uncleared texture with 2 levels. + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + // Expect 2 levels will be cleared. + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 1, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 1, + 1); + SetupExpectationsForApplyingDefaultDirtyState(); + + EXPECT_CALL(*gl_, + DrawElements(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2))) + .Times(1) + .RetiresOnSaturation(); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // But not again + EXPECT_CALL(*gl_, + DrawElements(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + BufferOffset(kValidIndexRangeStart * 2))) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawClearsAfterTexImage2DNULLInFBO) { + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + SetupAllNeededVertexBuffers(); + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + // Setup "render from" texture. + SetupTexture(); + + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target + GL_COLOR_BUFFER_BIT, // clear bits + 0, + 0, + 0, + 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // But not again. + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawWitFBOThatCantClearDoesNotDraw) { + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + // Setup "render from" texture. + SetupTexture(); + + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_UNSUPPORTED)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, DrawClearsAfterRenderbufferStorageInFBO) { + SetupTexture(); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoRenderbufferStorage( + GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 100, 50, GL_NO_ERROR); + DoFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_, + kServiceRenderbufferId, + GL_NO_ERROR); + + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target + GL_COLOR_BUFFER_BIT, // clear bits + 0, + 0, + 0, + 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, DrawArraysClearsAfterTexImage2DNULLCubemap) { + InitState init; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + InitDecoder(init); + + static const GLenum faces[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + }; + SetupCubemapProgram(); + DoBindTexture(GL_TEXTURE_CUBE_MAP, client_texture_id_, kServiceTextureId); + // Fill out all the faces for 2 levels, leave 2 uncleared. + for (int ii = 0; ii < 6; ++ii) { + GLenum face = faces[ii]; + int32 shm_id = + (face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ? 0 : kSharedMemoryId; + uint32 shm_offset = + (face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ? 0 : kSharedMemoryOffset; + DoTexImage2D(face, + 0, + GL_RGBA, + 2, + 2, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + shm_id, + shm_offset); + DoTexImage2D(face, + 1, + GL_RGBA, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + shm_id, + shm_offset); + } + // Expect 2 levels will be cleared. + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + 1, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 1, + 1); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, + DrawClearsAfterRenderbuffersWithMultipleAttachments) { + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoRenderbufferStorage(GL_RENDERBUFFER, + GL_DEPTH_COMPONENT16, + GL_DEPTH_COMPONENT, + 1, + 1, + GL_NO_ERROR); + DoFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + client_renderbuffer_id_, + kServiceRenderbufferId, + GL_NO_ERROR); + + SetupTexture(); + SetupExpectationsForFramebufferClearing( + GL_FRAMEBUFFER, // target + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, // clear bits + 0, + 0, + 0, + 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + true, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + true, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, + DrawingWithFBOTwiceChecksForFBOCompleteOnce) { + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + SetupAllNeededVertexBuffers(); + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture that is cleared. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + // Setup "render from" texture. + SetupTexture(); + + // Make sure we check for framebuffer complete. + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // But not again. + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, DrawClearsDepthTexture) { + InitState init; + init.extensions = "GL_ANGLE_depth_texture"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + + SetupDefaultProgram(); + SetupAllNeededVertexBuffers(); + const GLenum attachment = GL_DEPTH_ATTACHMENT; + const GLenum target = GL_TEXTURE_2D; + const GLint level = 0; + DoBindTexture(target, client_texture_id_, kServiceTextureId); + + // Create a depth texture. + DoTexImage2D(target, + level, + GL_DEPTH_COMPONENT, + 1, + 1, + 0, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, + 0, + 0); + + // Enable GL_SCISSOR_TEST to make sure we disable it in the clear, + // then re-enable it. + DoEnableDisable(GL_SCISSOR_TEST, true); + + EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _)) + .Times(1) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, + attachment, + target, + kServiceTextureId, + level)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, ClearStencil(0)).Times(1).RetiresOnSaturation(); + SetupExpectationsForStencilMask(-1, -1); + EXPECT_CALL(*gl_, ClearDepth(1.0f)).Times(1).RetiresOnSaturation(); + SetupExpectationsForDepthMask(true); + SetupExpectationsForEnableDisable(GL_SCISSOR_TEST, false); + + EXPECT_CALL(*gl_, Clear(GL_DEPTH_BUFFER_BIT)).Times(1).RetiresOnSaturation(); + + SetupExpectationsForRestoreClearState(0.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, true); + + EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, _)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0)) + .Times(1) + .RetiresOnSaturation(); + + SetupExpectationsForApplyingDefaultDirtyState(); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc new file mode 100644 index 00000000000..571573add5b --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc @@ -0,0 +1,2331 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +class GLES2DecoderTestWithExtensionsOnGLES2 : public GLES2DecoderTest { + public: + GLES2DecoderTestWithExtensionsOnGLES2() {} + + virtual void SetUp() {} + void Init(const char* extensions) { + InitState init; + init.extensions = extensions; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + InitDecoder(init); + } +}; + +TEST_P(GLES2DecoderTest, CheckFramebufferStatusWithNoBoundTarget) { + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)).Times(0); + CheckFramebufferStatus::Result* result = + static_cast<CheckFramebufferStatus::Result*>(shared_memory_address_); + *result = 0; + CheckFramebufferStatus cmd; + cmd.Init(GL_FRAMEBUFFER, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), *result); +} + +TEST_P(GLES2DecoderWithShaderTest, BindAndDeleteFramebuffer) { + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoDeleteFramebuffer(client_framebuffer_id_, + kServiceFramebufferId, + true, + GL_FRAMEBUFFER, + 0, + true, + GL_FRAMEBUFFER, + 0); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, FramebufferRenderbufferWithNoBoundTarget) { + EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)).Times(0); + FramebufferRenderbuffer cmd; + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, FramebufferTexture2DWithNoBoundTarget) { + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); + FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithNoBoundTarget) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _)) + .Times(0); + GetFramebufferAttachmentParameteriv cmd; + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithRenderbuffer) { + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + GetFramebufferAttachmentParameteriv::Result* result = + static_cast<GetFramebufferAttachmentParameteriv::Result*>( + shared_memory_address_); + result->size = 0; + const GLint* result_value = result->GetData(); + FramebufferRenderbuffer fbrb_cmd; + GetFramebufferAttachmentParameteriv cmd; + fbrb_cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(static_cast<GLuint>(*result_value), client_renderbuffer_id_); +} + +TEST_P(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithTexture) { + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kServiceTextureId, + 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + GetFramebufferAttachmentParameteriv::Result* result = + static_cast<GetFramebufferAttachmentParameteriv::Result*>( + shared_memory_address_); + result->SetNumResults(0); + const GLint* result_value = result->GetData(); + FramebufferTexture2D fbtex_cmd; + GetFramebufferAttachmentParameteriv cmd; + fbtex_cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(static_cast<GLuint>(*result_value), client_texture_id_); +} + +TEST_P(GLES2DecoderTest, GetRenderbufferParameterivWithNoBoundTarget) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetRenderbufferParameterivEXT(_, _, _)).Times(0); + GetRenderbufferParameteriv cmd; + cmd.Init(GL_RENDERBUFFER, + GL_RENDERBUFFER_WIDTH, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, RenderbufferStorageWithNoBoundTarget) { + EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0); + RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 3, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +namespace { + +// A class to emulate glReadPixels +class ReadPixelsEmulator { + public: + // pack_alignment is the alignment you want ReadPixels to use + // when copying. The actual data passed in pixels should be contiguous. + ReadPixelsEmulator(GLsizei width, + GLsizei height, + GLint bytes_per_pixel, + const void* src_pixels, + const void* expected_pixels, + GLint pack_alignment) + : width_(width), + height_(height), + pack_alignment_(pack_alignment), + bytes_per_pixel_(bytes_per_pixel), + src_pixels_(reinterpret_cast<const int8*>(src_pixels)), + expected_pixels_(reinterpret_cast<const int8*>(expected_pixels)) {} + + void ReadPixels(GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + void* pixels) const { + DCHECK_GE(x, 0); + DCHECK_GE(y, 0); + DCHECK_LE(x + width, width_); + DCHECK_LE(y + height, height_); + for (GLint yy = 0; yy < height; ++yy) { + const int8* src = GetPixelAddress(src_pixels_, x, y + yy); + const void* dst = ComputePackAlignmentAddress(0, yy, width, pixels); + memcpy(const_cast<void*>(dst), src, width * bytes_per_pixel_); + } + } + + bool CompareRowSegment(GLint x, + GLint y, + GLsizei width, + const void* data) const { + DCHECK(x + width <= width_ || width == 0); + return memcmp(data, + GetPixelAddress(expected_pixels_, x, y), + width * bytes_per_pixel_) == 0; + } + + // Helper to compute address of pixel in pack aligned data. + const void* ComputePackAlignmentAddress(GLint x, + GLint y, + GLsizei width, + const void* address) const { + GLint unpadded_row_size = ComputeImageDataSize(width, 1); + GLint two_rows_size = ComputeImageDataSize(width, 2); + GLsizei padded_row_size = two_rows_size - unpadded_row_size; + GLint offset = y * padded_row_size + x * bytes_per_pixel_; + return static_cast<const int8*>(address) + offset; + } + + GLint ComputeImageDataSize(GLint width, GLint height) const { + GLint row_size = width * bytes_per_pixel_; + if (height > 1) { + GLint temp = row_size + pack_alignment_ - 1; + GLint padded_row_size = (temp / pack_alignment_) * pack_alignment_; + GLint size_of_all_but_last_row = (height - 1) * padded_row_size; + return size_of_all_but_last_row + row_size; + } else { + return height * row_size; + } + } + + private: + const int8* GetPixelAddress(const int8* base, GLint x, GLint y) const { + return base + (width_ * y + x) * bytes_per_pixel_; + } + + GLsizei width_; + GLsizei height_; + GLint pack_alignment_; + GLint bytes_per_pixel_; + const int8* src_pixels_; + const int8* expected_pixels_; +}; + +} // anonymous namespace + +void GLES2DecoderTest::CheckReadPixelsOutOfRange(GLint in_read_x, + GLint in_read_y, + GLsizei in_read_width, + GLsizei in_read_height, + bool init) { + const GLsizei kWidth = 5; + const GLsizei kHeight = 3; + const GLint kBytesPerPixel = 3; + const GLint kPackAlignment = 4; + const GLenum kFormat = GL_RGB; + static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { + 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13, + 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28, + 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34, + }; + + ClearSharedMemory(); + + // We need to setup an FBO so we can know the max size that ReadPixels will + // access + if (init) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 0, + kFormat, + kWidth, + kHeight, + 0, + kFormat, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_, + kServiceTextureId, + 0, + GL_NO_ERROR); + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + } + + ReadPixelsEmulator emu( + kWidth, kHeight, kBytesPerPixel, kSrcPixels, kSrcPixels, kPackAlignment); + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + void* dest = &result[1]; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + // ReadPixels will be called for valid size only even though the command + // is requesting a larger size. + GLint read_x = std::max(0, in_read_x); + GLint read_y = std::max(0, in_read_y); + GLint read_end_x = std::max(0, std::min(kWidth, in_read_x + in_read_width)); + GLint read_end_y = std::max(0, std::min(kHeight, in_read_y + in_read_height)); + GLint read_width = read_end_x - read_x; + GLint read_height = read_end_y - read_y; + if (read_width > 0 && read_height > 0) { + for (GLint yy = read_y; yy < read_end_y; ++yy) { + EXPECT_CALL( + *gl_, + ReadPixels(read_x, yy, read_width, 1, kFormat, GL_UNSIGNED_BYTE, _)) + .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels)) + .RetiresOnSaturation(); + } + } + ReadPixels cmd; + cmd.Init(in_read_x, + in_read_y, + in_read_width, + in_read_height, + kFormat, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + GLint unpadded_row_size = emu.ComputeImageDataSize(in_read_width, 1); + scoped_ptr<int8[]> zero(new int8[unpadded_row_size]); + scoped_ptr<int8[]> pack(new int8[kPackAlignment]); + memset(zero.get(), 0, unpadded_row_size); + memset(pack.get(), kInitialMemoryValue, kPackAlignment); + for (GLint yy = 0; yy < in_read_height; ++yy) { + const int8* row = static_cast<const int8*>( + emu.ComputePackAlignmentAddress(0, yy, in_read_width, dest)); + GLint y = in_read_y + yy; + if (y < 0 || y >= kHeight) { + EXPECT_EQ(0, memcmp(zero.get(), row, unpadded_row_size)); + } else { + // check off left. + GLint num_left_pixels = std::max(-in_read_x, 0); + GLint num_left_bytes = num_left_pixels * kBytesPerPixel; + EXPECT_EQ(0, memcmp(zero.get(), row, num_left_bytes)); + + // check off right. + GLint num_right_pixels = std::max(in_read_x + in_read_width - kWidth, 0); + GLint num_right_bytes = num_right_pixels * kBytesPerPixel; + EXPECT_EQ(0, + memcmp(zero.get(), + row + unpadded_row_size - num_right_bytes, + num_right_bytes)); + + // check middle. + GLint x = std::max(in_read_x, 0); + GLint num_middle_pixels = + std::max(in_read_width - num_left_pixels - num_right_pixels, 0); + EXPECT_TRUE( + emu.CompareRowSegment(x, y, num_middle_pixels, row + num_left_bytes)); + } + + // check padding + if (yy != in_read_height - 1) { + GLint num_padding_bytes = + (kPackAlignment - 1) - (unpadded_row_size % kPackAlignment); + EXPECT_EQ(0, + memcmp(pack.get(), row + unpadded_row_size, num_padding_bytes)); + } + } +} + +TEST_P(GLES2DecoderTest, ReadPixels) { + const GLsizei kWidth = 5; + const GLsizei kHeight = 3; + const GLint kBytesPerPixel = 3; + const GLint kPackAlignment = 4; + static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { + 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13, + 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28, + 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34, + }; + + surface_->SetSize(gfx::Size(INT_MAX, INT_MAX)); + + ReadPixelsEmulator emu( + kWidth, kHeight, kBytesPerPixel, kSrcPixels, kSrcPixels, kPackAlignment); + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + void* dest = &result[1]; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _)) + .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels)); + ReadPixels cmd; + cmd.Init(0, + 0, + kWidth, + kHeight, + GL_RGB, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + for (GLint yy = 0; yy < kHeight; ++yy) { + EXPECT_TRUE(emu.CompareRowSegment( + 0, yy, kWidth, emu.ComputePackAlignmentAddress(0, yy, kWidth, dest))); + } +} + +TEST_P(GLES2DecoderRGBBackbufferTest, ReadPixelsNoAlphaBackbuffer) { + const GLsizei kWidth = 3; + const GLsizei kHeight = 3; + const GLint kBytesPerPixel = 4; + const GLint kPackAlignment = 4; + static const uint8 kExpectedPixels[kWidth * kHeight * kBytesPerPixel] = { + 12, 13, 14, 255, 19, 18, 19, 255, 13, 14, 18, 255, + 29, 28, 23, 255, 21, 22, 21, 255, 28, 23, 22, 255, + 31, 34, 39, 255, 32, 37, 32, 255, 34, 39, 37, 255, + }; + static const uint8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { + 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 29, 28, 23, 22, 21, 22, + 21, 29, 28, 23, 22, 21, 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, + }; + + surface_->SetSize(gfx::Size(INT_MAX, INT_MAX)); + + ReadPixelsEmulator emu(kWidth, + kHeight, + kBytesPerPixel, + kSrcPixels, + kExpectedPixels, + kPackAlignment); + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + void* dest = &result[1]; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + ReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, _)) + .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels)); + ReadPixels cmd; + cmd.Init(0, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + for (GLint yy = 0; yy < kHeight; ++yy) { + EXPECT_TRUE(emu.CompareRowSegment( + 0, yy, kWidth, emu.ComputePackAlignmentAddress(0, yy, kWidth, dest))); + } +} + +TEST_P(GLES2DecoderTest, ReadPixelsOutOfRange) { + static GLint tests[][4] = { + { + -2, -1, 9, 5, + }, // out of range on all sides + { + 2, 1, 9, 5, + }, // out of range on right, bottom + { + -7, -4, 9, 5, + }, // out of range on left, top + { + 0, -5, 9, 5, + }, // completely off top + { + 0, 3, 9, 5, + }, // completely off bottom + { + -9, 0, 9, 5, + }, // completely off left + { + 5, 0, 9, 5, + }, // completely off right + }; + + for (size_t tt = 0; tt < arraysize(tests); ++tt) { + CheckReadPixelsOutOfRange( + tests[tt][0], tests[tt][1], tests[tt][2], tests[tt][3], tt == 0); + } +} + +TEST_P(GLES2DecoderTest, ReadPixelsInvalidArgs) { + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + EXPECT_CALL(*gl_, ReadPixels(_, _, _, _, _, _, _)).Times(0); + ReadPixels cmd; + cmd.Init(0, + 0, + -1, + 1, + GL_RGB, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(0, + 0, + 1, + -1, + GL_RGB, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(0, + 0, + 1, + 1, + GL_RGB, + GL_INT, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(0, + 0, + 1, + 1, + GL_RGB, + GL_UNSIGNED_BYTE, + kInvalidSharedMemoryId, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(0, + 0, + 1, + 1, + GL_RGB, + GL_UNSIGNED_BYTE, + pixels_shm_id, + kInvalidSharedMemoryOffset, + result_shm_id, + result_shm_offset, + false); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(0, + 0, + 1, + 1, + GL_RGB, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + kInvalidSharedMemoryId, + result_shm_offset, + false); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(0, + 0, + 1, + 1, + GL_RGB, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + kInvalidSharedMemoryOffset, + false); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderManualInitTest, ReadPixelsAsyncError) { + InitState init; + init.extensions = "GL_ARB_sync"; + init.gl_version = "opengl es 3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); + + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + + const GLsizei kWidth = 4; + const GLsizei kHeight = 4; + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + + EXPECT_CALL(*gl_, GetError()) + // first error check must pass to get to the test + .WillOnce(Return(GL_NO_ERROR)) + // second check is after BufferData, simulate fail here + .WillOnce(Return(GL_INVALID_OPERATION)) + // third error check is fall-through call to sync ReadPixels + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, + ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _)) + .Times(1); + EXPECT_CALL(*gl_, GenBuffersARB(1, _)).Times(1); + EXPECT_CALL(*gl_, BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, _)).Times(2); + EXPECT_CALL(*gl_, + BufferData(GL_PIXEL_PACK_BUFFER_ARB, _, NULL, GL_STREAM_READ)) + .Times(1); + + ReadPixels cmd; + cmd.Init(0, + 0, + kWidth, + kHeight, + GL_RGB, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +// Check that if a renderbuffer is attached and GL returns +// GL_FRAMEBUFFER_COMPLETE that the buffer is cleared and state is restored. +TEST_P(GLES2DecoderTest, FramebufferRenderbufferClearColor) { + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + ClearColor color_cmd; + ColorMask color_mask_cmd; + Enable enable_cmd; + FramebufferRenderbuffer cmd; + color_cmd.Init(0.1f, 0.2f, 0.3f, 0.4f); + color_mask_cmd.Init(0, 1, 0, 1); + enable_cmd.Init(GL_SCISSOR_TEST); + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); + InSequence sequence; + EXPECT_CALL(*gl_, ClearColor(0.1f, 0.2f, 0.3f, 0.4f)) + .Times(1) + .RetiresOnSaturation(); + SetupExpectationsForEnableDisable(GL_SCISSOR_TEST, true); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(color_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(color_mask_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(enable_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, FramebufferRenderbufferClearDepth) { + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + ClearDepthf depth_cmd; + DepthMask depth_mask_cmd; + FramebufferRenderbuffer cmd; + depth_cmd.Init(0.5f); + depth_mask_cmd.Init(false); + cmd.Init(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + client_renderbuffer_id_); + InSequence sequence; + EXPECT_CALL(*gl_, ClearDepth(0.5f)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(depth_mask_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, FramebufferRenderbufferClearStencil) { + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + ClearStencil stencil_cmd; + StencilMaskSeparate stencil_mask_separate_cmd; + FramebufferRenderbuffer cmd; + stencil_cmd.Init(123); + stencil_mask_separate_cmd.Init(GL_BACK, 0x1234u); + cmd.Init(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + client_renderbuffer_id_); + InSequence sequence; + EXPECT_CALL(*gl_, ClearStencil(123)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_mask_separate_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +#if 0 // Turn this test on once we allow GL_DEPTH_STENCIL_ATTACHMENT +TEST_P(GLES2DecoderTest, FramebufferRenderbufferClearDepthStencil) { + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, + kServiceFramebufferId); + ClearDepthf depth_cmd; + ClearStencil stencil_cmd; + FramebufferRenderbuffer cmd; + depth_cmd.Init(0.5f); + stencil_cmd.Init(123); + cmd.Init( + GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + client_renderbuffer_id_); + InSequence sequence; + EXPECT_CALL(*gl_, ClearDepth(0.5f)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ClearStencil(123)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( + GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} +#endif + +TEST_P(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) { + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) { + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) { + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) { + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) { + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) { + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, PackedDepthStencilReportsCorrectValues) { + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, PackedDepthStencilNoRequestedStencil) { + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferDepth) { + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + EXPECT_CALL( + *gl_, + RenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50)) + .Times(1) + .RetiresOnSaturation(); + RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + FramebufferRenderbuffer fbrb_cmd; + fbrb_cmd.Init(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferStencil) { + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + EXPECT_CALL( + *gl_, + RenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50)) + .Times(1) + .RetiresOnSaturation(); + RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + FramebufferRenderbuffer fbrb_cmd; + fbrb_cmd.Init(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} + +TEST_P(GLES2DecoderTest, FramebufferRenderbufferGLError) { + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + FramebufferRenderbuffer cmd; + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); +} + +TEST_P(GLES2DecoderTest, FramebufferTexture2DGLError) { + const GLsizei kWidth = 5; + const GLsizei kHeight = 3; + const GLenum kFormat = GL_RGB; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 0, + kFormat, + kWidth, + kHeight, + 0, + kFormat, + GL_UNSIGNED_BYTE, + 0, + 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kServiceTextureId, + 0)) + .Times(1) + .RetiresOnSaturation(); + FramebufferTexture2D fbtex_cmd; + fbtex_cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); +} + +TEST_P(GLES2DecoderTest, RenderbufferStorageGLError) { + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, RenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA, 100, 50)) + .Times(1) + .RetiresOnSaturation(); + RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 100, 50); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); +} + +TEST_P(GLES2DecoderTest, RenderbufferStorageBadArgs) { + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, TestHelper::kMaxRenderbufferSize + 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 1, TestHelper::kMaxRenderbufferSize + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, + RenderbufferStorageMultisampleCHROMIUMGLError) { + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL( + *gl_, + RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 1, GL_RGBA, 100, 50)) + .Times(1) + .RetiresOnSaturation(); + RenderbufferStorageMultisampleCHROMIUM cmd; + cmd.Init(GL_RENDERBUFFER, 1, GL_RGBA4, 100, 50); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, + RenderbufferStorageMultisampleCHROMIUMBadArgs) { + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + EXPECT_CALL(*gl_, RenderbufferStorageMultisampleEXT(_, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + RenderbufferStorageMultisampleCHROMIUM cmd; + cmd.Init(GL_RENDERBUFFER, + TestHelper::kMaxSamples + 1, + GL_RGBA4, + TestHelper::kMaxRenderbufferSize, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA4, + TestHelper::kMaxRenderbufferSize + 1, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA4, + 1, + TestHelper::kMaxRenderbufferSize + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUM) { + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + InitDecoder(init); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + InSequence sequence; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL( + *gl_, + RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA, + TestHelper::kMaxRenderbufferSize, + 1)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + RenderbufferStorageMultisampleCHROMIUM cmd; + cmd.Init(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA4, + TestHelper::kMaxRenderbufferSize, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, + RenderbufferStorageMultisampleEXTNotSupported) { + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + InSequence sequence; + // GL_EXT_framebuffer_multisample uses RenderbufferStorageMultisampleCHROMIUM. + RenderbufferStorageMultisampleEXT cmd; + cmd.Init(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA4, + TestHelper::kMaxRenderbufferSize, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +class GLES2DecoderMultisampledRenderToTextureTest + : public GLES2DecoderTestWithExtensionsOnGLES2 { + public: + void TestNotCompatibleWithRenderbufferStorageMultisampleCHROMIUM() { + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + RenderbufferStorageMultisampleCHROMIUM cmd; + cmd.Init(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA4, + TestHelper::kMaxRenderbufferSize, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + } + + void TestRenderbufferStorageMultisampleEXT(const char* extension) { + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + InSequence sequence; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + if (strstr(extension, "GL_IMG_multisampled_render_to_texture")) { + EXPECT_CALL( + *gl_, + RenderbufferStorageMultisampleIMG(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA, + TestHelper::kMaxRenderbufferSize, + 1)) + .Times(1) + .RetiresOnSaturation(); + } else { + EXPECT_CALL( + *gl_, + RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA, + TestHelper::kMaxRenderbufferSize, + 1)) + .Times(1) + .RetiresOnSaturation(); + } + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + RenderbufferStorageMultisampleEXT cmd; + cmd.Init(GL_RENDERBUFFER, + TestHelper::kMaxSamples, + GL_RGBA4, + TestHelper::kMaxRenderbufferSize, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } +}; + +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderMultisampledRenderToTextureTest, + ::testing::Bool()); + +TEST_P(GLES2DecoderMultisampledRenderToTextureTest, + NotCompatibleWithRenderbufferStorageMultisampleCHROMIUM_EXT) { + Init("GL_EXT_multisampled_render_to_texture"); + TestNotCompatibleWithRenderbufferStorageMultisampleCHROMIUM(); +} + +TEST_P(GLES2DecoderMultisampledRenderToTextureTest, + NotCompatibleWithRenderbufferStorageMultisampleCHROMIUM_IMG) { + Init("GL_IMG_multisampled_render_to_texture"); + TestNotCompatibleWithRenderbufferStorageMultisampleCHROMIUM(); +} + +TEST_P(GLES2DecoderMultisampledRenderToTextureTest, + RenderbufferStorageMultisampleEXT_EXT) { + Init("GL_EXT_multisampled_render_to_texture"); + TestRenderbufferStorageMultisampleEXT( + "GL_EXT_multisampled_render_to_texture"); +} + +TEST_P(GLES2DecoderMultisampledRenderToTextureTest, + RenderbufferStorageMultisampleEXT_IMG) { + Init("GL_IMG_multisampled_render_to_texture"); + TestRenderbufferStorageMultisampleEXT( + "GL_IMG_multisampled_render_to_texture"); +} + +TEST_P(GLES2DecoderTest, ReadPixelsGLError) { + GLenum kFormat = GL_RGBA; + GLint x = 0; + GLint y = 0; + GLsizei width = 2; + GLsizei height = 4; + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + ReadPixels(x, y, width, height, kFormat, GL_UNSIGNED_BYTE, _)) + .Times(1) + .RetiresOnSaturation(); + ReadPixels cmd; + cmd.Init(x, + y, + width, + height, + kFormat, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnClear) { + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + // Setup "render from" texture. + SetupTexture(); + + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target + GL_COLOR_BUFFER_BIT, // clear bits + 0, + 0, + 0, + 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, Clear(GL_COLOR_BUFFER_BIT)).Times(1).RetiresOnSaturation(); + + Clear cmd; + cmd.Init(GL_COLOR_BUFFER_BIT); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnReadPixels) { + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + // Setup "render from" texture. + SetupTexture(); + + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target + GL_COLOR_BUFFER_BIT, // clear bits + 0, + 0, + 0, + 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, _)) + .Times(1) + .RetiresOnSaturation(); + typedef ReadPixels::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result); + ReadPixels cmd; + cmd.Init(0, + 0, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, + UnClearedAttachmentsGetClearedOnReadPixelsAndDrawBufferGetsRestored) { + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render from" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_READ_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_READ_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + // Enable GL_SCISSOR_TEST to make sure we disable it in the clear, + // then re-enable after. + DoEnableDisable(GL_SCISSOR_TEST, true); + + SetupExpectationsForFramebufferClearingMulti( + kServiceFramebufferId, // read framebuffer service id + 0, // backbuffer service id + GL_READ_FRAMEBUFFER, // target + GL_COLOR_BUFFER_BIT, // clear bits + 0, + 0, + 0, + 0, // color + 0, // stencil + 1.0f, // depth + true); // scissor test + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, _)) + .Times(1) + .RetiresOnSaturation(); + typedef ReadPixels::Result Result; + uint32 result_shm_id = kSharedMemoryId; + uint32 result_shm_offset = kSharedMemoryOffset; + uint32 pixels_shm_id = kSharedMemoryId; + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(Result); + ReadPixels cmd; + cmd.Init(0, + 0, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + pixels_shm_id, + pixels_shm_offset, + result_shm_id, + result_shm_offset, + false); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, CopyTexImageWithInCompleteFBOFails) { + GLenum target = GL_TEXTURE_2D; + GLint level = 0; + GLenum internal_format = GL_RGBA; + GLsizei width = 2; + GLsizei height = 4; + SetupTexture(); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 0, 0, GL_NO_ERROR); + DoFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_, + kServiceRenderbufferId, + GL_NO_ERROR); + + EXPECT_CALL(*gl_, CopyTexImage2D(_, _, _, _, _, _, _, _)) + .Times(0) + .RetiresOnSaturation(); + CopyTexImage2D cmd; + cmd.Init(target, level, internal_format, 0, 0, width, height); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, GetGLError()); +} + +void GLES2DecoderWithShaderTest::CheckRenderbufferChangesMarkFBOAsNotComplete( + bool bound_fbo) { + FramebufferManager* framebuffer_manager = group().framebuffer_manager(); + SetupTexture(); + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 1, 1, GL_NO_ERROR); + DoFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_, + kServiceRenderbufferId, + GL_NO_ERROR); + + if (!bound_fbo) { + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); + } + + Framebuffer* framebuffer = + framebuffer_manager->GetFramebuffer(client_framebuffer_id_); + ASSERT_TRUE(framebuffer != NULL); + framebuffer_manager->MarkAsComplete(framebuffer); + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + + // Test that renderbufferStorage marks fbo as not complete. + DoRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 1, 1, GL_NO_ERROR); + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); + framebuffer_manager->MarkAsComplete(framebuffer); + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + + // Test deleting renderbuffer marks fbo as not complete. + DoDeleteRenderbuffer(client_renderbuffer_id_, kServiceRenderbufferId); + if (bound_fbo) { + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); + } else { + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + } + // Cleanup + DoDeleteFramebuffer(client_framebuffer_id_, + kServiceFramebufferId, + bound_fbo, + GL_FRAMEBUFFER, + 0, + bound_fbo, + GL_FRAMEBUFFER, + 0); +} + +TEST_P(GLES2DecoderWithShaderTest, + RenderbufferChangesMarkFBOAsNotCompleteBoundFBO) { + CheckRenderbufferChangesMarkFBOAsNotComplete(true); +} + +TEST_P(GLES2DecoderWithShaderTest, + RenderbufferChangesMarkFBOAsNotCompleteUnboundFBO) { + CheckRenderbufferChangesMarkFBOAsNotComplete(false); +} + +void GLES2DecoderWithShaderTest::CheckTextureChangesMarkFBOAsNotComplete( + bool bound_fbo) { + FramebufferManager* framebuffer_manager = group().framebuffer_manager(); + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + SetupTexture(); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + DoBindRenderbuffer( + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoRenderbufferStorage(GL_RENDERBUFFER, + GL_DEPTH_COMPONENT16, + GL_DEPTH_COMPONENT, + 1, + 1, + GL_NO_ERROR); + DoFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + client_renderbuffer_id_, + kServiceRenderbufferId, + GL_NO_ERROR); + + if (!bound_fbo) { + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); + } + + Framebuffer* framebuffer = + framebuffer_manager->GetFramebuffer(client_framebuffer_id_); + ASSERT_TRUE(framebuffer != NULL); + framebuffer_manager->MarkAsComplete(framebuffer); + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + + // Test TexImage2D marks fbo as not complete. + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, 0, 0); + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); + framebuffer_manager->MarkAsComplete(framebuffer); + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + + // Test CopyImage2D marks fbo as not complete. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1, 1, 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + CopyTexImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); + + // Test deleting texture marks fbo as not complete. + framebuffer_manager->MarkAsComplete(framebuffer); + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + DoDeleteTexture(kFBOClientTextureId, kFBOServiceTextureId); + + if (bound_fbo) { + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); + } else { + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + } + // Cleanup + DoDeleteFramebuffer(client_framebuffer_id_, + kServiceFramebufferId, + bound_fbo, + GL_FRAMEBUFFER, + 0, + bound_fbo, + GL_FRAMEBUFFER, + 0); +} + +TEST_P(GLES2DecoderWithShaderTest, TextureChangesMarkFBOAsNotCompleteBoundFBO) { + CheckTextureChangesMarkFBOAsNotComplete(true); +} + +TEST_P(GLES2DecoderWithShaderTest, + TextureChangesMarkFBOAsNotCompleteUnboundFBO) { + CheckTextureChangesMarkFBOAsNotComplete(false); +} + +TEST_P(GLES2DecoderTest, CanChangeSurface) { + scoped_refptr<GLSurfaceMock> other_surface(new GLSurfaceMock); + EXPECT_CALL(*other_surface.get(), GetBackingFrameBufferObject()) + .WillOnce(Return(7)); + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 7)); + + decoder_->SetSurface(other_surface); +} + +TEST_P(GLES2DecoderTest, DrawBuffersEXTImmediateSuccceeds) { + const GLsizei count = 1; + const GLenum bufs[] = {GL_COLOR_ATTACHMENT0}; + DrawBuffersEXTImmediate& cmd = *GetImmediateAs<DrawBuffersEXTImmediate>(); + cmd.Init(count, bufs); + + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, DrawBuffersARB(count, _)).Times(1).RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, DrawBuffersEXTImmediateFails) { + const GLsizei count = 1; + const GLenum bufs[] = {GL_COLOR_ATTACHMENT1_EXT}; + DrawBuffersEXTImmediate& cmd = *GetImmediateAs<DrawBuffersEXTImmediate>(); + cmd.Init(count, bufs); + + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs))); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, DrawBuffersEXTImmediateBackbuffer) { + const GLsizei count = 1; + const GLenum bufs[] = {GL_BACK}; + DrawBuffersEXTImmediate& cmd = *GetImmediateAs<DrawBuffersEXTImmediate>(); + cmd.Init(count, bufs); + + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs))); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); // unbind + + EXPECT_CALL(*gl_, DrawBuffersARB(count, _)).Times(1).RetiresOnSaturation(); + + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, InvalidateFramebufferBinding) { + InitState init; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); + + // EXPECT_EQ can't be used to compare function pointers + EXPECT_TRUE( + gfx::MockGLInterface::GetGLProcAddress("glInvalidateFramebuffer") == + gfx::g_driver_gl.fn.glDiscardFramebufferEXTFn); + EXPECT_TRUE( + gfx::MockGLInterface::GetGLProcAddress("glInvalidateFramebuffer") != + gfx::MockGLInterface::GetGLProcAddress("glDiscardFramebufferEXT")); +} + +TEST_P(GLES2DecoderManualInitTest, DiscardFramebufferEXT) { + InitState init; + init.extensions = "GL_EXT_discard_framebuffer"; + init.gl_version = "opengl es 2.0"; + InitDecoder(init); + + // EXPECT_EQ can't be used to compare function pointers + EXPECT_TRUE( + gfx::MockGLInterface::GetGLProcAddress("glDiscardFramebufferEXT") == + gfx::g_driver_gl.fn.glDiscardFramebufferEXTFn); + + const GLenum target = GL_FRAMEBUFFER; + const GLsizei count = 1; + const GLenum attachments[] = {GL_COLOR_ATTACHMENT0}; + + SetupTexture(); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_, + kServiceTextureId, + 0, + GL_NO_ERROR); + FramebufferManager* framebuffer_manager = group().framebuffer_manager(); + Framebuffer* framebuffer = + framebuffer_manager->GetFramebuffer(client_framebuffer_id_); + EXPECT_TRUE(framebuffer->IsCleared()); + + EXPECT_CALL(*gl_, DiscardFramebufferEXT(target, count, _)) + .Times(1) + .RetiresOnSaturation(); + DiscardFramebufferEXTImmediate& cmd = + *GetImmediateAs<DiscardFramebufferEXTImmediate>(); + cmd.Init(target, count, attachments); + + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(attachments))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_FALSE(framebuffer->IsCleared()); +} + +TEST_P(GLES2DecoderTest, DiscardFramebufferEXTUnsupported) { + const GLenum target = GL_FRAMEBUFFER; + const GLsizei count = 1; + const GLenum attachments[] = {GL_COLOR_EXT}; + DiscardFramebufferEXTImmediate& cmd = + *GetImmediateAs<DiscardFramebufferEXTImmediate>(); + cmd.Init(target, count, attachments); + + // Should not result into a call into GL. + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(attachments))); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, + DiscardedAttachmentsEXTMarksFramebufferIncomplete) { + InitState init; + init.extensions = "GL_EXT_discard_framebuffer"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); + + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + // Setup "render from" texture. + SetupTexture(); + + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target + GL_COLOR_BUFFER_BIT, // clear bits + 0, + 0, + 0, + 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, Clear(GL_COLOR_BUFFER_BIT)).Times(1).RetiresOnSaturation(); + + Clear clear_cmd; + clear_cmd.Init(GL_COLOR_BUFFER_BIT); + EXPECT_EQ(error::kNoError, ExecuteCmd(clear_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that framebuffer is cleared and complete. + FramebufferManager* framebuffer_manager = group().framebuffer_manager(); + Framebuffer* framebuffer = + framebuffer_manager->GetFramebuffer(client_framebuffer_id_); + EXPECT_TRUE(framebuffer->IsCleared()); + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer)); + + // Check that Discard GL_COLOR_ATTACHMENT0, sets the attachment as uncleared + // and the framebuffer as incomplete. + EXPECT_TRUE( + gfx::MockGLInterface::GetGLProcAddress("glDiscardFramebufferEXT") == + gfx::g_driver_gl.fn.glDiscardFramebufferEXTFn); + + const GLenum target = GL_FRAMEBUFFER; + const GLsizei count = 1; + const GLenum attachments[] = {GL_COLOR_ATTACHMENT0}; + + DiscardFramebufferEXTImmediate& discard_cmd = + *GetImmediateAs<DiscardFramebufferEXTImmediate>(); + discard_cmd.Init(target, count, attachments); + + EXPECT_CALL(*gl_, DiscardFramebufferEXT(target, count, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(discard_cmd, sizeof(attachments))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_FALSE(framebuffer->IsCleared()); + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer)); +} + +TEST_P(GLES2DecoderManualInitTest, ReadFormatExtension) { + InitState init; + init.extensions = "GL_OES_read_format"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()).Times(6).RetiresOnSaturation(); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + GetIntegerv cmd; + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(1).RetiresOnSaturation(); + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_FORMAT, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(1).RetiresOnSaturation(); + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_TYPE, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, NoReadFormatExtension) { + InitState init; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + GetIntegerv cmd; + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kFBOClientTextureId, + kFBOServiceTextureId, + 0, + GL_NO_ERROR); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation(); + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_FORMAT, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation(); + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_TYPE, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// TODO(gman): PixelStorei + +// TODO(gman): SwapBuffers + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc new file mode 100644 index 00000000000..ce123827fed --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc @@ -0,0 +1,1046 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +TEST_P(GLES2DecoderWithShaderTest, GetProgramInfoCHROMIUMValidArgs) { + const uint32 kBucketId = 123; + GetProgramInfoCHROMIUM cmd; + cmd.Init(client_program_id_, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + EXPECT_GT(bucket->size(), 0u); +} + +TEST_P(GLES2DecoderWithShaderTest, GetProgramInfoCHROMIUMInvalidArgs) { + const uint32 kBucketId = 123; + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + EXPECT_TRUE(bucket == NULL); + GetProgramInfoCHROMIUM cmd; + cmd.Init(kInvalidClientId, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + bucket = decoder_->GetBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + EXPECT_EQ(sizeof(ProgramInfoHeader), bucket->size()); + ProgramInfoHeader* info = + bucket->GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader)); + ASSERT_TRUE(info != 0); + EXPECT_EQ(0u, info->link_status); + EXPECT_EQ(0u, info->num_attribs); + EXPECT_EQ(0u, info->num_uniforms); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformivSucceeds) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformiv cmd; + cmd.Init(client_program_id_, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformiv(kServiceProgramId, kUniform2RealLocation, _)) + .Times(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), + result->size); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformivArrayElementSucceeds) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformiv cmd; + cmd.Init(client_program_id_, + kUniform2ElementFakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, + GetUniformiv(kServiceProgramId, kUniform2ElementRealLocation, _)) + .Times(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), + result->size); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformivBadProgramFails) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformiv cmd; + // non-existant program + cmd.Init(kInvalidClientId, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformiv(_, _, _)).Times(0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +// Valid id that is not a program. The GL spec requires a different error for +// this case. +#if GLES2_TEST_SHADER_VS_PROGRAM_IDS + result->size = kInitialResult; + cmd.Init(client_shader_id_, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS + // Unlinked program + EXPECT_CALL(*gl_, CreateProgram()) + .Times(1) + .WillOnce(Return(kNewServiceId)) + .RetiresOnSaturation(); + CreateProgram cmd2; + cmd2.Init(kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + result->size = kInitialResult; + cmd.Init(kNewClientId, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformivBadLocationFails) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformiv cmd; + // invalid location + cmd.Init(client_program_id_, + kInvalidUniformLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformiv(_, _, _)).Times(0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformivBadSharedMemoryFails) { + GetUniformiv cmd; + cmd.Init(client_program_id_, + kUniform2FakeLocation, + kInvalidSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformiv(_, _, _)).Times(0); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + kUniform2FakeLocation, + kSharedMemoryId, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +}; + +TEST_P(GLES2DecoderWithShaderTest, GetUniformfvSucceeds) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformfv cmd; + cmd.Init(client_program_id_, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformfv(kServiceProgramId, kUniform2RealLocation, _)) + .Times(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), + result->size); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformfvArrayElementSucceeds) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformfv cmd; + cmd.Init(client_program_id_, + kUniform2ElementFakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, + GetUniformfv(kServiceProgramId, kUniform2ElementRealLocation, _)) + .Times(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GLES2Util::GetGLDataTypeSizeForUniforms(kUniform2Type), + result->size); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformfvBadProgramFails) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformfv cmd; + // non-existant program + cmd.Init(kInvalidClientId, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformfv(_, _, _)).Times(0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +// Valid id that is not a program. The GL spec requires a different error for +// this case. +#if GLES2_TEST_SHADER_VS_PROGRAM_IDS + result->size = kInitialResult; + cmd.Init(client_shader_id_, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS + // Unlinked program + EXPECT_CALL(*gl_, CreateProgram()) + .Times(1) + .WillOnce(Return(kNewServiceId)) + .RetiresOnSaturation(); + CreateProgram cmd2; + cmd2.Init(kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + result->size = kInitialResult; + cmd.Init(kNewClientId, + kUniform2FakeLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformfvBadLocationFails) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); + result->size = 0; + GetUniformfv cmd; + // invalid location + cmd.Init(client_program_id_, + kInvalidUniformLocation, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformfv(_, _, _)).Times(0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformfvBadSharedMemoryFails) { + GetUniformfv cmd; + cmd.Init(client_program_id_, + kUniform2FakeLocation, + kInvalidSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetUniformfv(_, _, _)).Times(0); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + kUniform2FakeLocation, + kSharedMemoryId, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +}; + +TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersSucceeds) { + GetAttachedShaders cmd; + typedef GetAttachedShaders::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + EXPECT_CALL(*gl_, GetAttachedShaders(kServiceProgramId, 1, _, _)).WillOnce( + DoAll(SetArgumentPointee<2>(1), SetArgumentPointee<3>(kServiceShaderId))); + cmd.Init(client_program_id_, + shared_memory_id_, + shared_memory_offset_, + Result::ComputeSize(1)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(client_shader_id_, result->GetData()[0]); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersResultNotInitFail) { + GetAttachedShaders cmd; + typedef GetAttachedShaders::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 1; + EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)).Times(0); + cmd.Init(client_program_id_, + shared_memory_id_, + shared_memory_offset_, + Result::ComputeSize(1)); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersBadProgramFails) { + GetAttachedShaders cmd; + typedef GetAttachedShaders::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)).Times(0); + cmd.Init(kInvalidClientId, + shared_memory_id_, + shared_memory_offset_, + Result::ComputeSize(1)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0U, result->size); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersBadSharedMemoryFails) { + GetAttachedShaders cmd; + typedef GetAttachedShaders::Result Result; + cmd.Init(client_program_id_, + kInvalidSharedMemoryId, + shared_memory_offset_, + Result::ComputeSize(1)); + EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)).Times(0); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + shared_memory_id_, + kInvalidSharedMemoryOffset, + Result::ComputeSize(1)); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatSucceeds) { + ScopedGLImplementationSetter gl_impl(::gfx::kGLImplementationEGLGLES2); + GetShaderPrecisionFormat cmd; + typedef GetShaderPrecisionFormat::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + const GLint range[2] = {62, 62}; + const GLint precision = 16; + EXPECT_CALL(*gl_, GetShaderPrecisionFormat(_, _, _, _)) + .WillOnce(DoAll(SetArrayArgument<2>(range, range + 2), + SetArgumentPointee<3>(precision))) + .RetiresOnSaturation(); + cmd.Init(GL_VERTEX_SHADER, + GL_HIGH_FLOAT, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_NE(0, result->success); + EXPECT_EQ(range[0], result->min_range); + EXPECT_EQ(range[1], result->max_range); + EXPECT_EQ(precision, result->precision); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatResultNotInitFails) { + GetShaderPrecisionFormat cmd; + typedef GetShaderPrecisionFormat::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 1; + // NOTE: GL might not be called. There is no Desktop OpenGL equivalent + cmd.Init(GL_VERTEX_SHADER, + GL_HIGH_FLOAT, + shared_memory_id_, + shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatBadArgsFails) { + typedef GetShaderPrecisionFormat::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + GetShaderPrecisionFormat cmd; + cmd.Init( + GL_TEXTURE_2D, GL_HIGH_FLOAT, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + result->success = 0; + cmd.Init(GL_VERTEX_SHADER, + GL_TEXTURE_2D, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, + GetShaderPrecisionFormatBadSharedMemoryFails) { + GetShaderPrecisionFormat cmd; + cmd.Init(GL_VERTEX_SHADER, + GL_HIGH_FLOAT, + kInvalidSharedMemoryId, + shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(GL_VERTEX_SHADER, + GL_TEXTURE_2D, + shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformSucceeds) { + const GLuint kUniformIndex = 1; + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + cmd.Init(client_program_id_, + kUniformIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_NE(0, result->success); + EXPECT_EQ(kUniform2Size, result->size); + EXPECT_EQ(kUniform2Type, result->type); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + EXPECT_EQ( + 0, + memcmp( + bucket->GetData(0, bucket->size()), kUniform2Name, bucket->size())); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformResultNotInitFails) { + const GLuint kUniformIndex = 1; + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 1; + cmd.Init(client_program_id_, + kUniformIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBadProgramFails) { + const GLuint kUniformIndex = 1; + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + cmd.Init(kInvalidClientId, + kUniformIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +#if GLES2_TEST_SHADER_VS_PROGRAM_IDS + result->success = 0; + cmd.Init(client_shader_id_, + kUniformIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBadIndexFails) { + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + cmd.Init(client_program_id_, + kBadUniformIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBadSharedMemoryFails) { + const GLuint kUniformIndex = 1; + const uint32 kBucketId = 123; + GetActiveUniform cmd; + cmd.Init(client_program_id_, + kUniformIndex, + kBucketId, + kInvalidSharedMemoryId, + shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + kUniformIndex, + kBucketId, + shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribSucceeds) { + const GLuint kAttribIndex = 1; + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + cmd.Init(client_program_id_, + kAttribIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_NE(0, result->success); + EXPECT_EQ(kAttrib2Size, result->size); + EXPECT_EQ(kAttrib2Type, result->type); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + EXPECT_EQ( + 0, + memcmp(bucket->GetData(0, bucket->size()), kAttrib2Name, bucket->size())); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribResultNotInitFails) { + const GLuint kAttribIndex = 1; + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 1; + cmd.Init(client_program_id_, + kAttribIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribBadProgramFails) { + const GLuint kAttribIndex = 1; + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + cmd.Init(kInvalidClientId, + kAttribIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +#if GLES2_TEST_SHADER_VS_PROGRAM_IDS + result->success = 0; + cmd.Init(client_shader_id_, + kAttribIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribBadIndexFails) { + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->success = 0; + cmd.Init(client_program_id_, + kBadAttribIndex, + kBucketId, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribBadSharedMemoryFails) { + const GLuint kAttribIndex = 1; + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + cmd.Init(client_program_id_, + kAttribIndex, + kBucketId, + kInvalidSharedMemoryId, + shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + kAttribIndex, + kBucketId, + shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogValidArgs) { + const char* kInfo = "hello"; + const uint32 kBucketId = 123; + CompileShader compile_cmd; + GetShaderInfoLog cmd; + EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _)); + EXPECT_CALL(*gl_, CompileShader(kServiceShaderId)); + EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _)) + .WillOnce(SetArgumentPointee<2>(GL_FALSE)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_INFO_LOG_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(strlen(kInfo) + 1)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetShaderInfoLog(kServiceShaderId, strlen(kInfo) + 1, _, _)) + .WillOnce(DoAll(SetArgumentPointee<2>(strlen(kInfo)), + SetArrayArgument<3>(kInfo, kInfo + strlen(kInfo) + 1))); + compile_cmd.Init(client_shader_id_); + cmd.Init(client_shader_id_, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(compile_cmd)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + EXPECT_EQ(strlen(kInfo) + 1, bucket->size()); + EXPECT_EQ(0, + memcmp(bucket->GetData(0, bucket->size()), kInfo, bucket->size())); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogInvalidArgs) { + const uint32 kBucketId = 123; + GetShaderInfoLog cmd; + cmd.Init(kInvalidClientId, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest, CompileShaderValidArgs) { + EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _)); + EXPECT_CALL(*gl_, CompileShader(kServiceShaderId)); + EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _)) + .WillOnce(SetArgumentPointee<2>(GL_TRUE)) + .RetiresOnSaturation(); + CompileShader cmd; + cmd.Init(client_shader_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, CompileShaderInvalidArgs) { + CompileShader cmd; + cmd.Init(kInvalidClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +#if GLES2_TEST_SHADER_VS_PROGRAM_IDS + cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS +} + +TEST_P(GLES2DecoderTest, ShaderSourceBucketAndGetShaderSourceValidArgs) { + const uint32 kInBucketId = 123; + const uint32 kOutBucketId = 125; + const char kSource[] = "hello"; + const uint32 kSourceSize = sizeof(kSource) - 1; + SetBucketAsCString(kInBucketId, kSource); + ShaderSourceBucket cmd; + cmd.Init(client_shader_id_, kInBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + ClearSharedMemory(); + GetShaderSource get_cmd; + get_cmd.Init(client_shader_id_, kOutBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(get_cmd)); + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kOutBucketId); + ASSERT_TRUE(bucket != NULL); + EXPECT_EQ(kSourceSize + 1, bucket->size()); + EXPECT_EQ( + 0, memcmp(bucket->GetData(0, bucket->size()), kSource, bucket->size())); +} + +TEST_P(GLES2DecoderTest, ShaderSourceBucketInvalidArgs) { + const uint32 kBucketId = 123; + const char kSource[] = "hello"; + const uint32 kSourceSize = sizeof(kSource) - 1; + memcpy(shared_memory_address_, kSource, kSourceSize); + ShaderSourceBucket cmd; + // Test no bucket. + cmd.Init(client_texture_id_, kBucketId); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + // Test invalid client. + SetBucketAsCString(kBucketId, kSource); + cmd.Init(kInvalidClientId, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +#if GLES2_TEST_SHADER_VS_PROGRAM_IDS + SetBucketAsCString(kBucketId, kSource); + cmd.Init( + client_program_id_, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS +} + +TEST_P(GLES2DecoderTest, ShaderSourceStripComments) { + const uint32 kInBucketId = 123; + const char kSource[] = "hello/*te\ast*/world//a\ab"; + SetBucketAsCString(kInBucketId, kSource); + ShaderSourceBucket cmd; + cmd.Init(client_shader_id_, kInBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, Uniform1iValidArgs) { + EXPECT_CALL(*gl_, Uniform1i(kUniform1RealLocation, 2)); + Uniform1i cmd; + cmd.Init(kUniform1FakeLocation, 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, Uniform1ivImmediateValidArgs) { + Uniform1ivImmediate& cmd = *GetImmediateAs<Uniform1ivImmediate>(); + EXPECT_CALL(*gl_, + Uniform1iv(kUniform1RealLocation, + 1, + reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); + GLint temp[1 * 2] = { + 0, + }; + cmd.Init(kUniform1FakeLocation, 1, &temp[0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); +} + +TEST_P(GLES2DecoderWithShaderTest, Uniform1ivImmediateInvalidValidArgs) { + EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); + Uniform1ivImmediate& cmd = *GetImmediateAs<Uniform1ivImmediate>(); + GLint temp[1 * 2] = { + 0, + }; + cmd.Init(kUniform1FakeLocation, 2, &temp[0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, Uniform1ivZeroCount) { + EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); + Uniform1ivImmediate& cmd = *GetImmediateAs<Uniform1ivImmediate>(); + GLint temp = 0; + cmd.Init(kUniform1FakeLocation, 0, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, Uniform1iSamplerIsLmited) { + EXPECT_CALL(*gl_, Uniform1i(_, _)).Times(0); + Uniform1i cmd; + cmd.Init(kUniform1FakeLocation, kNumTextureUnits); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, Uniform1ivSamplerIsLimited) { + EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); + Uniform1ivImmediate& cmd = *GetImmediateAs<Uniform1ivImmediate>(); + GLint temp[] = {kNumTextureUnits}; + cmd.Init(kUniform1FakeLocation, 1, &temp[0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest, BindAttribLocationBucket) { + const uint32 kBucketId = 123; + const GLint kLocation = 2; + const char* kName = "testing"; + EXPECT_CALL(*gl_, + BindAttribLocation(kServiceProgramId, kLocation, StrEq(kName))) + .Times(1); + SetBucketAsCString(kBucketId, kName); + BindAttribLocationBucket cmd; + cmd.Init(client_program_id_, kLocation, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, BindAttribLocationBucketInvalidArgs) { + const uint32 kBucketId = 123; + const GLint kLocation = 2; + const char* kName = "testing"; + EXPECT_CALL(*gl_, BindAttribLocation(_, _, _)).Times(0); + BindAttribLocationBucket cmd; + // check bucket does not exist. + cmd.Init(client_program_id_, kLocation, kBucketId); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + // check bucket is empty. + SetBucketAsCString(kBucketId, NULL); + cmd.Init(client_program_id_, kLocation, kBucketId); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + // Check bad program id + SetBucketAsCString(kBucketId, kName); + cmd.Init(kInvalidClientId, kLocation, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderWithShaderTest, GetAttribLocation) { + const uint32 kBucketId = 123; + const char* kNonExistentName = "foobar"; + typedef GetAttribLocation::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + SetBucketAsCString(kBucketId, kAttrib2Name); + *result = -1; + GetAttribLocation cmd; + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(kAttrib2Location, *result); + SetBucketAsCString(kBucketId, kNonExistentName); + *result = -1; + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); +} + +TEST_P(GLES2DecoderWithShaderTest, GetAttribLocationInvalidArgs) { + const uint32 kBucketId = 123; + typedef GetAttribLocation::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = -1; + GetAttribLocation cmd; + // Check no bucket + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); + // Check bad program id. + SetBucketAsCString(kBucketId, kAttrib2Name); + cmd.Init(kInvalidClientId, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + *result = -1; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + // Check bad memory + cmd.Init(client_program_id_, + kBucketId, + kInvalidSharedMemoryId, + kSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + kBucketId, + kSharedMemoryId, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformLocation) { + const uint32 kBucketId = 123; + const char* kNonExistentName = "foobar"; + typedef GetUniformLocation::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + SetBucketAsCString(kBucketId, kUniform2Name); + *result = -1; + GetUniformLocation cmd; + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(kUniform2FakeLocation, *result); + SetBucketAsCString(kBucketId, kNonExistentName); + *result = -1; + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); +} + +TEST_P(GLES2DecoderWithShaderTest, GetUniformLocationInvalidArgs) { + const uint32 kBucketId = 123; + typedef GetUniformLocation::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = -1; + GetUniformLocation cmd; + // Check no bucket + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); + // Check bad program id. + SetBucketAsCString(kBucketId, kUniform2Name); + cmd.Init(kInvalidClientId, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + *result = -1; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + // Check bad memory + cmd.Init(client_program_id_, + kBucketId, + kInvalidSharedMemoryId, + kSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + kBucketId, + kSharedMemoryId, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, BindUniformLocationCHROMIUMBucket) { + const uint32 kBucketId = 123; + const GLint kLocation = 2; + const char* kName = "testing"; + const char* kBadName1 = "gl_testing"; + const char* kBadName2 = "testing[1]"; + + SetBucketAsCString(kBucketId, kName); + BindUniformLocationCHROMIUMBucket cmd; + cmd.Init(client_program_id_, + kLocation, + kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + // check negative location + SetBucketAsCString(kBucketId, kName); + cmd.Init(client_program_id_, -1, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + // check highest location + SetBucketAsCString(kBucketId, kName); + GLint kMaxLocation = + (kMaxFragmentUniformVectors + kMaxVertexUniformVectors) * 4 - 1; + cmd.Init(client_program_id_, + kMaxLocation, + kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + // check too high location + SetBucketAsCString(kBucketId, kName); + cmd.Init(client_program_id_, + kMaxLocation + 1, + kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + // check bad name "gl_..." + SetBucketAsCString(kBucketId, kBadName1); + cmd.Init(client_program_id_, + kLocation, + kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + // check bad name "name[1]" non zero + SetBucketAsCString(kBucketId, kBadName2); + cmd.Init(client_program_id_, + kLocation, + kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, ClearUniformsBeforeFirstProgramUse) { + CommandLine command_line(0, NULL); + command_line.AppendSwitchASCII( + switches::kGpuDriverBugWorkarounds, + base::IntToString(gpu::CLEAR_UNIFORMS_BEFORE_FIRST_PROGRAM_USE)); + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); + { + static AttribInfo attribs[] = { + { + kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, + }, + { + kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, + }, + { + kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, + }, + }; + static UniformInfo uniforms[] = { + {kUniform1Name, kUniform1Size, kUniform1Type, kUniform1FakeLocation, + kUniform1RealLocation, kUniform1DesiredLocation}, + {kUniform2Name, kUniform2Size, kUniform2Type, kUniform2FakeLocation, + kUniform2RealLocation, kUniform2DesiredLocation}, + {kUniform3Name, kUniform3Size, kUniform3Type, kUniform3FakeLocation, + kUniform3RealLocation, kUniform3DesiredLocation}, + }; + SetupShader(attribs, + arraysize(attribs), + uniforms, + arraysize(uniforms), + client_program_id_, + kServiceProgramId, + client_vertex_shader_id_, + kServiceVertexShaderId, + client_fragment_shader_id_, + kServiceFragmentShaderId); + TestHelper::SetupExpectationsForClearingUniforms( + gl_.get(), uniforms, arraysize(uniforms)); + } + + { + EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) + .Times(1) + .RetiresOnSaturation(); + cmds::UseProgram cmd; + cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } +} + +// TODO(gman): DeleteProgram + +// TODO(gman): UseProgram + +// TODO(gman): DeleteShader + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc new file mode 100644 index 00000000000..67618138982 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc @@ -0,0 +1,2831 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" + +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +TEST_P(GLES2DecoderTest, GenerateMipmapWrongFormatsFails) { + EXPECT_CALL(*gl_, GenerateMipmapEXT(_)).Times(0); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + GenerateMipmap cmd; + cmd.Init(GL_TEXTURE_2D); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, GenerateMipmapHandlesOutOfMemory) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + TextureManager* manager = group().texture_manager(); + TextureRef* texture_ref = manager->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + GLint width = 0; + GLint height = 0; + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 2, &width, &height)); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 16, + 16, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, GenerateMipmapEXT(GL_TEXTURE_2D)).Times(1); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + GenerateMipmap cmd; + cmd.Init(GL_TEXTURE_2D); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 2, &width, &height)); +} + +TEST_P(GLES2DecoderTest, GenerateMipmapClearsUnclearedTexture) { + EXPECT_CALL(*gl_, GenerateMipmapEXT(_)).Times(0); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + EXPECT_CALL(*gl_, GenerateMipmapEXT(GL_TEXTURE_2D)); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + GenerateMipmap cmd; + cmd.Init(GL_TEXTURE_2D); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Same as GenerateMipmapClearsUnclearedTexture, but with workaround +// |set_texture_filters_before_generating_mipmap|. +TEST_P(GLES2DecoderManualInitTest, SetTextureFiltersBeforeGenerateMipmap) { + CommandLine command_line(0, NULL); + command_line.AppendSwitchASCII( + switches::kGpuDriverBugWorkarounds, + base::IntToString(gpu::SET_TEXTURE_FILTER_BEFORE_GENERATING_MIPMAP)); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); + + EXPECT_CALL(*gl_, GenerateMipmapEXT(_)).Times(0); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + EXPECT_CALL( + *gl_, + TexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GenerateMipmapEXT(GL_TEXTURE_2D)); + EXPECT_CALL( + *gl_, + TexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + GenerateMipmap cmd; + cmd.Init(GL_TEXTURE_2D); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, ActiveTextureValidArgs) { + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE1)); + SpecializedSetup<ActiveTexture, 0>(true); + ActiveTexture cmd; + cmd.Init(GL_TEXTURE1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, ActiveTextureInvalidArgs) { + EXPECT_CALL(*gl_, ActiveTexture(_)).Times(0); + SpecializedSetup<ActiveTexture, 0>(false); + ActiveTexture cmd; + cmd.Init(GL_TEXTURE0 - 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(kNumTextureUnits); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderTest, TexSubImage2DValidArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 1, + GL_RGBA, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 1, + 1, + 0, + kWidth - 1, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 1, + 1, + 0, + kWidth - 1, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, TexSubImage2DBadArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 1, + GL_RGBA, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + 0, + 0); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE0, + 1, + 0, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth, + kHeight, + GL_TRUE, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_INT, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + -1, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 1, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + -1, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 1, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth + 1, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth, + kHeight + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth, + kHeight, + GL_RGB, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_SHORT_4_4_4_4, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kInvalidSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(GL_TEXTURE_2D, + 1, + 0, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kInvalidSharedMemoryOffset, + GL_FALSE); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, CopyTexSubImage2DValidArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 1, + GL_RGBA, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, + CopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight)) + .Times(1) + .RetiresOnSaturation(); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, CopyTexSubImage2DBadArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 1, + GL_RGBA, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + 0, + 0); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE0, 1, 0, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, -1, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 1, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, -1, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 1, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth + 1, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest, TexImage2DRedefinitionSucceeds) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + EXPECT_CALL(*gl_, GetError()).WillRepeatedly(Return(GL_NO_ERROR)); + for (int ii = 0; ii < 2; ++ii) { + TexImage2D cmd; + if (ii == 0) { + EXPECT_CALL(*gl_, + TexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + _)) + .Times(1) + .RetiresOnSaturation(); + cmd.Init(GL_TEXTURE_2D, + 0, + GL_RGBA, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + } else { + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + kWidth, + kHeight); + cmd.Init(GL_TEXTURE_2D, + 0, + GL_RGBA, + kWidth, + kHeight, + GL_RGBA, + GL_UNSIGNED_BYTE, + 0, + 0); + } + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 0, + 0, + kWidth, + kHeight - 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + // Consider this TexSubImage2D command part of the previous TexImage2D + // (last GL_TRUE argument). It will be skipped if there are bugs in the + // redefinition case. + TexSubImage2D cmd2; + cmd2.Init(GL_TEXTURE_2D, + 0, + 0, + 0, + kWidth, + kHeight - 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_TRUE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + } +} + +TEST_P(GLES2DecoderTest, TexImage2DGLError) { + GLenum target = GL_TEXTURE_2D; + GLint level = 0; + GLenum internal_format = GL_RGBA; + GLsizei width = 2; + GLsizei height = 4; + GLint border = 0; + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + TextureManager* manager = group().texture_manager(); + TextureRef* texture_ref = manager->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + TexImage2D(target, + level, + internal_format, + width, + height, + border, + format, + type, + _)) + .Times(1) + .RetiresOnSaturation(); + TexImage2D cmd; + cmd.Init(target, + level, + internal_format, + width, + height, + format, + type, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); +} + +TEST_P(GLES2DecoderTest, CopyTexImage2DGLError) { + GLenum target = GL_TEXTURE_2D; + GLint level = 0; + GLenum internal_format = GL_RGBA; + GLsizei width = 2; + GLsizei height = 4; + GLint border = 0; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + TextureManager* manager = group().texture_manager(); + TextureRef* texture_ref = manager->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_OUT_OF_MEMORY)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + CopyTexImage2D( + target, level, internal_format, 0, 0, width, height, border)) + .Times(1) + .RetiresOnSaturation(); + CopyTexImage2D cmd; + cmd.Init(target, level, internal_format, 0, 0, width, height); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, level, &width, &height)); +} + +TEST_P(GLES2DecoderManualInitTest, CompressedTexImage2DBucketBadBucket) { + InitState init; + init.extensions = "GL_EXT_texture_compression_s3tc"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + const uint32 kBadBucketId = 123; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + CompressedTexImage2DBucket cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, + 4, + 4, + kBadBucketId); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + CompressedTexSubImage2DBucket cmd2; + cmd2.Init(GL_TEXTURE_2D, + 0, + 0, + 0, + 4, + 4, + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, + kBadBucketId); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +namespace { + +struct S3TCTestData { + GLenum format; + size_t block_size; +}; + +} // anonymous namespace. + +TEST_P(GLES2DecoderManualInitTest, CompressedTexImage2DS3TC) { + InitState init; + init.extensions = "GL_EXT_texture_compression_s3tc"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + const uint32 kBucketId = 123; + CommonDecoder::Bucket* bucket = decoder_->CreateBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + + static const S3TCTestData test_data[] = { + { + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8, + }, + { + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, + }, + { + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16, + }, + { + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 16, + }, + }; + + for (size_t ii = 0; ii < arraysize(test_data); ++ii) { + const S3TCTestData& test = test_data[ii]; + CompressedTexImage2DBucket cmd; + // test small width. + DoCompressedTexImage2D( + GL_TEXTURE_2D, 0, test.format, 2, 4, 0, test.block_size, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // test bad width. + cmd.Init(GL_TEXTURE_2D, 0, test.format, 5, 4, kBucketId); + bucket->SetSize(test.block_size * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // test small height. + DoCompressedTexImage2D( + GL_TEXTURE_2D, 0, test.format, 4, 2, 0, test.block_size, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // test too bad height. + cmd.Init(GL_TEXTURE_2D, 0, test.format, 4, 5, kBucketId); + bucket->SetSize(test.block_size * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // test small for level 0. + DoCompressedTexImage2D( + GL_TEXTURE_2D, 0, test.format, 1, 1, 0, test.block_size, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // test small for level 0. + DoCompressedTexImage2D( + GL_TEXTURE_2D, 0, test.format, 2, 2, 0, test.block_size, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // test size too large. + cmd.Init(GL_TEXTURE_2D, 0, test.format, 4, 4, kBucketId); + bucket->SetSize(test.block_size * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + // test size too small. + cmd.Init(GL_TEXTURE_2D, 0, test.format, 4, 4, kBucketId); + bucket->SetSize(test.block_size / 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + // test with 3 mips. + DoCompressedTexImage2D( + GL_TEXTURE_2D, 0, test.format, 4, 4, 0, test.block_size, kBucketId); + DoCompressedTexImage2D( + GL_TEXTURE_2D, 1, test.format, 2, 2, 0, test.block_size, kBucketId); + DoCompressedTexImage2D( + GL_TEXTURE_2D, 2, test.format, 1, 1, 0, test.block_size, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Test a 16x16 + DoCompressedTexImage2D(GL_TEXTURE_2D, + 0, + test.format, + 16, + 16, + 0, + test.block_size * 4 * 4, + kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + CompressedTexSubImage2DBucket sub_cmd; + bucket->SetSize(test.block_size); + // Test sub image bad xoffset + sub_cmd.Init(GL_TEXTURE_2D, 0, 1, 0, 4, 4, test.format, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Test sub image bad yoffset + sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 2, 4, 4, test.format, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Test sub image bad width + bucket->SetSize(test.block_size * 2); + sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 5, 4, test.format, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Test sub image bad height + sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 4, 5, test.format, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Test sub image bad size + bucket->SetSize(test.block_size + 1); + sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 4, 4, test.format, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + for (GLint yoffset = 0; yoffset <= 8; yoffset += 4) { + for (GLint xoffset = 0; xoffset <= 8; xoffset += 4) { + for (GLsizei height = 4; height <= 8; height += 4) { + for (GLsizei width = 4; width <= 8; width += 4) { + GLsizei size = test.block_size * (width / 4) * (height / 4); + bucket->SetSize(size); + EXPECT_CALL(*gl_, + CompressedTexSubImage2D(GL_TEXTURE_2D, + 0, + xoffset, + yoffset, + width, + height, + test.format, + size, + _)) + .Times(1) + .RetiresOnSaturation(); + sub_cmd.Init(GL_TEXTURE_2D, + 0, + xoffset, + yoffset, + width, + height, + test.format, + kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + } + } + } + } +} + +TEST_P(GLES2DecoderManualInitTest, CompressedTexImage2DETC1) { + InitState init; + init.extensions = "GL_OES_compressed_ETC1_RGB8_texture"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + const uint32 kBucketId = 123; + CommonDecoder::Bucket* bucket = decoder_->CreateBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + + const GLenum kFormat = GL_ETC1_RGB8_OES; + const size_t kBlockSize = 8; + + CompressedTexImage2DBucket cmd; + // test small width. + DoCompressedTexImage2D(GL_TEXTURE_2D, 0, kFormat, 4, 8, 0, 16, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // test small height. + DoCompressedTexImage2D(GL_TEXTURE_2D, 0, kFormat, 8, 4, 0, 16, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // test size too large. + cmd.Init(GL_TEXTURE_2D, 0, kFormat, 4, 4, kBucketId); + bucket->SetSize(kBlockSize * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + // test size too small. + cmd.Init(GL_TEXTURE_2D, 0, kFormat, 4, 4, kBucketId); + bucket->SetSize(kBlockSize / 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + + // Test a 16x16 + DoCompressedTexImage2D( + GL_TEXTURE_2D, 0, kFormat, 16, 16, 0, kBlockSize * 16, kBucketId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Test CompressedTexSubImage not allowed + CompressedTexSubImage2DBucket sub_cmd; + bucket->SetSize(kBlockSize); + sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 4, 4, kFormat, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Test TexSubImage not allowed for ETC1 compressed texture + TextureRef* texture_ref = GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + GLenum type, internal_format; + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(kFormat, internal_format); + TexSubImage2D texsub_cmd; + texsub_cmd.Init(GL_TEXTURE_2D, + 0, + 0, + 0, + 4, + 4, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(texsub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Test CopyTexSubImage not allowed for ETC1 compressed texture + CopyTexSubImage2D copy_cmd; + copy_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4); + EXPECT_EQ(error::kNoError, ExecuteCmd(copy_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, EGLImageExternalBindTexture) { + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kNewServiceId)); + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + BindTexture cmd; + cmd.Init(GL_TEXTURE_EXTERNAL_OES, kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + TextureRef* texture_ref = GetTexture(kNewClientId); + EXPECT_TRUE(texture_ref != NULL); + EXPECT_TRUE(texture_ref->texture()->target() == GL_TEXTURE_EXTERNAL_OES); +} + +TEST_P(GLES2DecoderManualInitTest, EGLImageExternalGetBinding) { + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, + GetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd; + cmd.Init(GL_TEXTURE_BINDING_EXTERNAL_OES, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_TEXTURE_BINDING_EXTERNAL_OES), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(client_texture_id_, (uint32)result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, EGLImageExternalTextureDefaults) { + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); + + TextureRef* texture_ref = GetTexture(client_texture_id_); + EXPECT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES); + EXPECT_TRUE(texture->min_filter() == GL_LINEAR); + EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_P(GLES2DecoderManualInitTest, EGLImageExternalTextureParam) { + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); + + EXPECT_CALL(*gl_, + TexParameteri( + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + EXPECT_CALL( + *gl_, + TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + EXPECT_CALL( + *gl_, + TexParameteri( + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + EXPECT_CALL( + *gl_, + TexParameteri( + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + TexParameteri cmd; + cmd.Init(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TextureRef* texture_ref = GetTexture(client_texture_id_); + EXPECT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES); + EXPECT_TRUE(texture->min_filter() == GL_LINEAR); + EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_P(GLES2DecoderManualInitTest, EGLImageExternalTextureParamInvalid) { + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); + + TexParameteri cmd; + cmd.Init(GL_TEXTURE_EXTERNAL_OES, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST_MIPMAP_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + cmd.Init(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_REPEAT); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + cmd.Init(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_REPEAT); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + TextureRef* texture_ref = GetTexture(client_texture_id_); + EXPECT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_TRUE(texture->target() == GL_TEXTURE_EXTERNAL_OES); + EXPECT_TRUE(texture->min_filter() == GL_LINEAR); + EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_P(GLES2DecoderManualInitTest, EGLImageExternalTexImage2DError) { + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + GLenum target = GL_TEXTURE_EXTERNAL_OES; + GLint level = 0; + GLenum internal_format = GL_RGBA; + GLsizei width = 2; + GLsizei height = 4; + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); + ASSERT_TRUE(GetTexture(client_texture_id_) != NULL); + TexImage2D cmd; + cmd.Init(target, + level, + internal_format, + width, + height, + format, + type, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + // TexImage2D is not allowed with GL_TEXTURE_EXTERNAL_OES targets. + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, DefaultTextureZero) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + BindTexture cmd2; + cmd2.Init(GL_TEXTURE_CUBE_MAP, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_CUBE_MAP, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, DefaultTextureBGR) { + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL( + *gl_, BindTexture(GL_TEXTURE_2D, TestHelper::kServiceDefaultTexture2dId)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + BindTexture cmd2; + cmd2.Init(GL_TEXTURE_CUBE_MAP, 0); + EXPECT_CALL(*gl_, + BindTexture(GL_TEXTURE_CUBE_MAP, + TestHelper::kServiceDefaultTextureCubemapId)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// Test that default texture 0 is immutable. +TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameterf) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TexParameterf cmd2; + cmd2.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_CUBE_MAP, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_CUBE_MAP, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TexParameterf cmd2; + cmd2.Init(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } +} + +TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameteri) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TexParameteri cmd2; + cmd2.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_CUBE_MAP, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_CUBE_MAP, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TexParameteri cmd2; + cmd2.Init(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } +} + +TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameterfv) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + GLfloat data = GL_NEAREST; + TexParameterfvImmediate& cmd2 = + *GetImmediateAs<TexParameterfvImmediate>(); + cmd2.Init(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + &data); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd2, sizeof(data))); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_CUBE_MAP, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_CUBE_MAP, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + GLfloat data = GL_NEAREST; + TexParameterfvImmediate& cmd2 = + *GetImmediateAs<TexParameterfvImmediate>(); + cmd2.Init(GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_MAG_FILTER, + &data); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd2, sizeof(data))); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } +} + +TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameteriv) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + GLfloat data = GL_NEAREST; + TexParameterfvImmediate& cmd2 = + *GetImmediateAs<TexParameterfvImmediate>(); + cmd2.Init(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + &data); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd2, sizeof(data))); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } + + { + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_CUBE_MAP, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_CUBE_MAP, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + GLfloat data = GL_NEAREST; + TexParameterfvImmediate& cmd2 = + *GetImmediateAs<TexParameterfvImmediate>(); + cmd2.Init(GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_MAG_FILTER, + &data); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd2, sizeof(data))); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + } +} + +TEST_P(GLES2DecoderManualInitTest, NoDefaultTexImage2D) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TexImage2D cmd2; + cmd2.Init(GL_TEXTURE_2D, + 0, + GL_RGBA, + 2, + 2, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, NoDefaultTexSubImage2D) { + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); + + BindTexture cmd1; + cmd1.Init(GL_TEXTURE_2D, 0); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, 0)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TexSubImage2D cmd2; + cmd2.Init(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleBindTexture) { + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_RECTANGLE_ARB, kNewServiceId)); + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + BindTexture cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + Texture* texture = GetTexture(kNewClientId)->texture(); + EXPECT_TRUE(texture != NULL); + EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); +} + +TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleGetBinding) { + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, + GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd; + cmd.Init(GL_TEXTURE_BINDING_RECTANGLE_ARB, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_TEXTURE_BINDING_RECTANGLE_ARB), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(client_texture_id_, (uint32)result->GetData()[0]); +} + +TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTextureDefaults) { + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + Texture* texture = GetTexture(client_texture_id_)->texture(); + EXPECT_TRUE(texture != NULL); + EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); + EXPECT_TRUE(texture->min_filter() == GL_LINEAR); + EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParam) { + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + EXPECT_CALL(*gl_, + TexParameteri( + GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + EXPECT_CALL(*gl_, + TexParameteri( + GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + EXPECT_CALL( + *gl_, + TexParameteri( + GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + EXPECT_CALL( + *gl_, + TexParameteri( + GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + TexParameteri cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + Texture* texture = GetTexture(client_texture_id_)->texture(); + EXPECT_TRUE(texture != NULL); + EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); + EXPECT_TRUE(texture->min_filter() == GL_LINEAR); + EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParamInvalid) { + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + TexParameteri cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST_MIPMAP_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + Texture* texture = GetTexture(client_texture_id_)->texture(); + EXPECT_TRUE(texture != NULL); + EXPECT_TRUE(texture->target() == GL_TEXTURE_RECTANGLE_ARB); + EXPECT_TRUE(texture->min_filter() == GL_LINEAR); + EXPECT_TRUE(texture->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(texture->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTexImage2DError) { + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + GLenum target = GL_TEXTURE_RECTANGLE_ARB; + GLint level = 0; + GLenum internal_format = GL_RGBA; + GLsizei width = 2; + GLsizei height = 4; + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + ASSERT_TRUE(GetTexture(client_texture_id_) != NULL); + TexImage2D cmd; + cmd.Init(target, + level, + internal_format, + width, + height, + format, + type, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + // TexImage2D is not allowed with GL_TEXTURE_RECTANGLE_ARB targets. + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, TexSubImage2DClearsAfterTexImage2DNULL) { + InitState init; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + InitDecoder(init); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + // Test if we call it again it does not clear. + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, TexSubImage2DDoesNotClearAfterTexImage2DNULLThenData) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 2, + 2, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + // Test if we call it again it does not clear. + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P( + GLES2DecoderManualInitTest, + TexSubImage2DDoesNotClearAfterTexImage2DNULLThenDataWithTexImage2DIsFaster) { + CommandLine command_line(0, NULL); + command_line.AppendSwitchASCII( + switches::kGpuDriverBugWorkarounds, + base::IntToString(gpu::TEXSUBIMAGE2D_FASTER_THAN_TEXIMAGE2D)); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + + { + // Uses texSubimage internally because the above workaround is active and + // the update is for the full size of the texture. + EXPECT_CALL(*gl_, + TexSubImage2D( + GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, _)) + .Times(1) + .RetiresOnSaturation(); + cmds::TexImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + GL_RGBA, + 2, + 2, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + // Test if we call it again it does not clear. + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, TexSubImage2DClearsAfterTexImage2DWithDataThenNULL) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + // Put in data (so it should be marked as cleared) + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 2, + 2, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + // Put in no data. + TexImage2D tex_cmd; + tex_cmd.Init( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + // It won't actually call TexImage2D, just mark it as uncleared. + EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); + // Next call to TexSubImage2d should clear. + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + 1, + 1, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, CopyTexImage2DMarksTextureAsCleared) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + + TextureManager* manager = group().texture_manager(); + TextureRef* texture_ref = manager->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + CopyTexImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + EXPECT_TRUE(texture->SafeToRenderFrom()); +} + +TEST_P(GLES2DecoderTest, CopyTexSubImage2DClearsUnclearedTexture) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA, + GL_RGBA, + GL_UNSIGNED_BYTE, + 2, + 2); + EXPECT_CALL(*gl_, CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)) + .Times(1) + .RetiresOnSaturation(); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderManualInitTest, CompressedImage2DMarksTextureAsCleared) { + InitState init; + init.extensions = "GL_EXT_texture_compression_s3tc"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL( + *gl_, + CompressedTexImage2D( + GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 8, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + CompressedTexImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 4, + 4, + 8, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + TextureManager* manager = group().texture_manager(); + TextureRef* texture_ref = manager->GetTexture(client_texture_id_); + EXPECT_TRUE(texture_ref->texture()->SafeToRenderFrom()); +} + +TEST_P(GLES2DecoderTest, TextureUsageAngleExtNotEnabledByDefault) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + + TexParameteri cmd; + cmd.Init( + GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderTest, ProduceAndConsumeTextureCHROMIUM) { + Mailbox mailbox = Mailbox::Generate(); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + ProduceTextureCHROMIUMImmediate& produce_cmd = + *GetImmediateAs<ProduceTextureCHROMIUMImmediate>(); + produce_cmd.Init(GL_TEXTURE_2D, mailbox.name); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(produce_cmd, sizeof(mailbox.name))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Texture didn't change. + GLsizei width; + GLsizei height; + GLenum type; + GLenum internal_format; + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); + EXPECT_EQ(2, width); + EXPECT_EQ(4, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + // Service ID has not changed. + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + // Create new texture for consume. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)) + .RetiresOnSaturation(); + DoBindTexture(GL_TEXTURE_2D, kNewClientId, kNewServiceId); + + // Assigns and binds original service size texture ID. + EXPECT_CALL(*gl_, DeleteTextures(1, _)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) + .Times(1) + .RetiresOnSaturation(); + + ConsumeTextureCHROMIUMImmediate& consume_cmd = + *GetImmediateAs<ConsumeTextureCHROMIUMImmediate>(); + consume_cmd.Init(GL_TEXTURE_2D, mailbox.name); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(consume_cmd, sizeof(mailbox.name))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Texture is redefined. + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); + EXPECT_EQ(2, width); + EXPECT_EQ(4, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + // Service ID is restored. + EXPECT_EQ(kServiceTextureId, texture->service_id()); +} + +TEST_P(GLES2DecoderTest, ProduceAndConsumeDirectTextureCHROMIUM) { + Mailbox mailbox = Mailbox::Generate(); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + ProduceTextureDirectCHROMIUMImmediate& produce_cmd = + *GetImmediateAs<ProduceTextureDirectCHROMIUMImmediate>(); + produce_cmd.Init(client_texture_id_, GL_TEXTURE_2D, mailbox.name); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(produce_cmd, sizeof(mailbox.name))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Texture didn't change. + GLsizei width; + GLsizei height; + GLenum type; + GLenum internal_format; + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); + EXPECT_EQ(2, width); + EXPECT_EQ(4, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + // Service ID has not changed. + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + // Consume the texture into a new client ID. + GLuint new_texture_id = kNewClientId; + CreateAndConsumeTextureCHROMIUMImmediate& consume_cmd = + *GetImmediateAs<CreateAndConsumeTextureCHROMIUMImmediate>(); + consume_cmd.Init(GL_TEXTURE_2D, new_texture_id, mailbox.name); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(consume_cmd, sizeof(mailbox.name))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Make sure the new client ID is associated with the produced service ID. + texture_ref = group().texture_manager()->GetTexture(new_texture_id); + ASSERT_TRUE(texture_ref != NULL); + texture = texture_ref->texture(); + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + DoBindTexture(GL_TEXTURE_2D, kNewClientId, kServiceTextureId); + + // Texture is redefined. + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); + EXPECT_EQ(2, width); + EXPECT_EQ(4, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); +} + +TEST_P(GLES2DecoderTest, ProduceTextureCHROMIUMInvalidTarget) { + Mailbox mailbox = Mailbox::Generate(); + + DoBindTexture(GL_TEXTURE_CUBE_MAP, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 3, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, 0, 0); + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + ProduceTextureDirectCHROMIUMImmediate& produce_cmd = + *GetImmediateAs<ProduceTextureDirectCHROMIUMImmediate>(); + produce_cmd.Init(client_texture_id_, GL_TEXTURE_2D, mailbox.name); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(produce_cmd, sizeof(mailbox.name))); + + // ProduceTexture should fail it the texture and produce targets don't match. + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, DepthTextureBadArgs) { + InitState init; + init.extensions = "GL_ANGLE_depth_texture"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + // Check trying to upload data fails. + TexImage2D tex_cmd; + tex_cmd.Init(GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT, + 1, + 1, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, + kSharedMemoryId, + kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + // Try level > 0. + tex_cmd.Init(GL_TEXTURE_2D, + 1, + GL_DEPTH_COMPONENT, + 1, + 1, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, + 0, + 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + // Make a 1 pixel depth texture. + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT, + 1, + 1, + 0, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, + 0, + 0); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that trying to update it fails. + TexSubImage2D tex_sub_cmd; + tex_sub_cmd.Init(GL_TEXTURE_2D, + 0, + 0, + 0, + 1, + 1, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(tex_sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Check that trying to CopyTexImage2D fails + CopyTexImage2D copy_tex_cmd; + copy_tex_cmd.Init(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(copy_tex_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Check that trying to CopyTexSubImage2D fails + CopyTexSubImage2D copy_sub_cmd; + copy_sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(copy_sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, GenerateMipmapDepthTexture) { + InitState init; + init.extensions = "GL_ANGLE_depth_texture"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT, + 2, + 2, + 0, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, + 0, + 0); + GenerateMipmap cmd; + cmd.Init(GL_TEXTURE_2D); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, BindTexImage2DCHROMIUM) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0).get(), 1); + EXPECT_FALSE(group().image_manager()->LookupImage(1) == NULL); + + GLsizei width; + GLsizei height; + GLenum type; + GLenum internal_format; + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Bind image to texture. + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; + bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should now be set. + EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Define new texture image. + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should no longer be set. + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); +} + +TEST_P(GLES2DecoderTest, BindTexImage2DCHROMIUMCubeMapNotAllowed) { + group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0).get(), 1); + DoBindTexture(GL_TEXTURE_CUBE_MAP, client_texture_id_, kServiceTextureId); + + BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; + bind_tex_image_2d_cmd.Init(GL_TEXTURE_CUBE_MAP, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderTest, OrphanGLImageWithTexImage2D) { + group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0).get(), 1); + DoBindTexture(GL_TEXTURE_CUBE_MAP, client_texture_id_, kServiceTextureId); + + BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; + bind_tex_image_2d_cmd.Init(GL_TEXTURE_CUBE_MAP, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); +} + +TEST_P(GLES2DecoderTest, ReleaseTexImage2DCHROMIUM) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0).get(), 1); + EXPECT_FALSE(group().image_manager()->LookupImage(1) == NULL); + + GLsizei width; + GLsizei height; + GLenum type; + GLenum internal_format; + + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Bind image to texture. + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; + bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should now be set. + EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Release image from texture. + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + ReleaseTexImage2DCHROMIUM release_tex_image_2d_cmd; + release_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(release_tex_image_2d_cmd)); + EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should no longer be set. + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); +} + +class MockGLImage : public gfx::GLImage { + public: + MockGLImage() {} + + // Overridden from gfx::GLImage: + MOCK_METHOD0(Destroy, void()); + MOCK_METHOD0(GetSize, gfx::Size()); + MOCK_METHOD1(BindTexImage, bool(unsigned)); + MOCK_METHOD1(ReleaseTexImage, void(unsigned)); + MOCK_METHOD0(WillUseTexImage, void()); + MOCK_METHOD0(DidUseTexImage, void()); + MOCK_METHOD0(WillModifyTexImage, void()); + MOCK_METHOD0(DidModifyTexImage, void()); + + protected: + virtual ~MockGLImage() {} +}; + +TEST_P(GLES2DecoderWithShaderTest, UseTexImage) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + kSharedMemoryId, + kSharedMemoryOffset); + + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != NULL); + Texture* texture = texture_ref->texture(); + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + const int32 kImageId = 1; + scoped_refptr<MockGLImage> image(new MockGLImage); + group().image_manager()->AddImage(image.get(), kImageId); + + // Bind image to texture. + EXPECT_CALL(*image, BindTexImage(GL_TEXTURE_2D)) + .Times(1) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + EXPECT_CALL(*image, GetSize()) + .Times(1) + .WillOnce(Return(gfx::Size(1, 1))) + .RetiresOnSaturation(); + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; + bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, kImageId); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); + + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(3).RetiresOnSaturation(); + EXPECT_CALL(*image, WillUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*image, DidUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) + .Times(2) + .RetiresOnSaturation(); + // Image will be 'in use' as long as bound to a framebuffer. + EXPECT_CALL(*image, WillUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + kServiceTextureId, + 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + FramebufferTexture2D fbtex_cmd; + fbtex_cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) + .Times(2) + .RetiresOnSaturation(); + // Image should no longer be 'in use' after being unbound from framebuffer. + EXPECT_CALL(*image, DidUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + FramebufferRenderbuffer fbrb_cmd; + fbrb_cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); +} + +TEST_P(GLES2DecoderManualInitTest, DrawWithGLImageExternal) { + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); + + TextureRef* texture_ref = GetTexture(client_texture_id_); + scoped_refptr<MockGLImage> image(new MockGLImage); + group().texture_manager()->SetTarget(texture_ref, GL_TEXTURE_EXTERNAL_OES); + group().texture_manager()->SetLevelInfo(texture_ref, + GL_TEXTURE_EXTERNAL_OES, + 0, + GL_RGBA, + 0, + 0, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + group().texture_manager()->SetLevelImage( + texture_ref, GL_TEXTURE_EXTERNAL_OES, 0, image); + + DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupSamplerExternalProgram(); + SetupIndexBuffer(); + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + EXPECT_TRUE(group().texture_manager()->CanRender(texture_ref)); + + InSequence s; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*image, WillUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*image, DidUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + DrawElements cmd; + cmd.Init(GL_TRIANGLES, + kValidIndexRangeCount, + GL_UNSIGNED_SHORT, + kValidIndexRangeStart * 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES2) { + InitState init; + init.extensions = "GL_OES_texture_float"; + init.gl_version = "opengl es 2.0"; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 17, 0, GL_LUMINANCE, GL_FLOAT, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 17, 0, GL_ALPHA, GL_FLOAT, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_LUMINANCE_ALPHA, + 16, + 17, + 0, + GL_LUMINANCE_ALPHA, + GL_FLOAT, + 0, + 0); +} + +TEST_P(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES3) { + InitState init; + init.extensions = "GL_OES_texture_float GL_EXT_color_buffer_float"; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 17, 0, GL_LUMINANCE, GL_FLOAT, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 17, 0, GL_ALPHA, GL_FLOAT, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_LUMINANCE_ALPHA, + 16, + 17, + 0, + GL_LUMINANCE_ALPHA, + GL_FLOAT, + 0, + 0); +} + +TEST_P(GLES2DecoderManualInitTest, TexSubImage2DFloatOnGLES3) { + InitState init; + init.extensions = "GL_OES_texture_float GL_EXT_color_buffer_float"; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); + const int kWidth = 8; + const int kHeight = 4; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA32F, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_FLOAT, + 0, + 0); + EXPECT_CALL(*gl_, + TexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA32F, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_FLOAT, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + 0, + 0, + kWidth, + kHeight, + GL_RGBA, + GL_FLOAT, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, TexSubImage2DFloatDoesClearOnGLES3) { + InitState init; + init.extensions = "GL_OES_texture_float GL_EXT_color_buffer_float"; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); + const int kWidth = 8; + const int kHeight = 4; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA32F, + kWidth, + kHeight, + 0, + GL_RGBA, + GL_FLOAT, + 0, + 0); + SetupClearTextureExpectations(kServiceTextureId, + kServiceTextureId, + GL_TEXTURE_2D, + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + GL_RGBA, + GL_FLOAT, + kWidth, + kHeight); + EXPECT_CALL(*gl_, + TexSubImage2D(GL_TEXTURE_2D, + 0, + 1, + 0, + kWidth - 1, + kHeight, + GL_RGBA, + GL_FLOAT, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, + 0, + 1, + 0, + kWidth - 1, + kHeight, + GL_RGBA, + GL_FLOAT, + kSharedMemoryId, + kSharedMemoryOffset, + GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderManualInitTest, TexImage2DFloatConvertsFormatDesktop) { + InitState init; + init.extensions = "GL_ARB_texture_float"; + init.gl_version = "2.1"; + InitDecoder(init); + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0); + DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, + 0, + GL_RGBA, + 16, + 17, + 0, + GL_RGBA, + GL_FLOAT, + 0, + 0, + GL_RGBA32F_ARB); + DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, + 0, + GL_RGB, + 16, + 17, + 0, + GL_RGB, + GL_FLOAT, + 0, + 0, + GL_RGB32F_ARB); + DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, + 0, + GL_LUMINANCE, + 16, + 17, + 0, + GL_LUMINANCE, + GL_FLOAT, + 0, + 0, + GL_LUMINANCE32F_ARB); + DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, + 0, + GL_ALPHA, + 16, + 17, + 0, + GL_ALPHA, + GL_FLOAT, + 0, + 0, + GL_ALPHA32F_ARB); + DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, + 0, + GL_LUMINANCE_ALPHA, + 16, + 17, + 0, + GL_LUMINANCE_ALPHA, + GL_FLOAT, + 0, + 0, + GL_LUMINANCE_ALPHA32F_ARB); +} + +class GLES2DecoderCompressedFormatsTest : public GLES2DecoderManualInitTest { + public: + GLES2DecoderCompressedFormatsTest() {} + + static bool ValueInArray(GLint value, GLint* array, GLint count) { + for (GLint ii = 0; ii < count; ++ii) { + if (array[ii] == value) { + return true; + } + } + return false; + } + + void CheckFormats(const char* extension, const GLenum* formats, int count) { + InitState init; + init.extensions = extension; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + GetIntegerv cmd; + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation(); + cmd.Init(GL_NUM_COMPRESSED_TEXTURE_FORMATS, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + GLint num_formats = result->GetData()[0]; + EXPECT_EQ(count, num_formats); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + result->size = 0; + cmd.Init(GL_COMPRESSED_TEXTURE_FORMATS, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(num_formats, result->GetNumResults()); + + for (int i = 0; i < count; ++i) { + EXPECT_TRUE( + ValueInArray(formats[i], result->GetData(), result->GetNumResults())); + } + + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } +}; + +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderCompressedFormatsTest, + ::testing::Bool()); + +TEST_P(GLES2DecoderCompressedFormatsTest, GetCompressedTextureFormatsS3TC) { + const GLenum formats[] = { + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}; + CheckFormats("GL_EXT_texture_compression_s3tc", formats, 4); +} + +TEST_P(GLES2DecoderCompressedFormatsTest, GetCompressedTextureFormatsATC) { + const GLenum formats[] = {GL_ATC_RGB_AMD, GL_ATC_RGBA_EXPLICIT_ALPHA_AMD, + GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD}; + CheckFormats("GL_AMD_compressed_ATC_texture", formats, 3); +} + +TEST_P(GLES2DecoderCompressedFormatsTest, GetCompressedTextureFormatsPVRTC) { + const GLenum formats[] = { + GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, + GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}; + CheckFormats("GL_IMG_texture_compression_pvrtc", formats, 4); +} + +TEST_P(GLES2DecoderCompressedFormatsTest, GetCompressedTextureFormatsETC1) { + const GLenum formats[] = {GL_ETC1_RGB8_OES}; + CheckFormats("GL_OES_compressed_ETC1_RGB8_texture", formats, 1); +} + +TEST_P(GLES2DecoderManualInitTest, GetNoCompressedTextureFormats) { + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + GetIntegerv cmd; + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation(); + cmd.Init(GL_NUM_COMPRESSED_TEXTURE_FORMATS, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + GLint num_formats = result->GetData()[0]; + EXPECT_EQ(0, num_formats); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + result->size = 0; + cmd.Init( + GL_COMPRESSED_TEXTURE_FORMATS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(num_formats, result->GetNumResults()); + + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +// TODO(gman): Complete this test. +// TEST_P(GLES2DecoderTest, CompressedTexImage2DGLError) { +// } + +// TODO(gman): CompressedTexImage2D + +// TODO(gman): CompressedTexImage2DImmediate + +// TODO(gman): CompressedTexSubImage2DImmediate + +// TODO(gman): TexImage2D + +// TODO(gman): TexImage2DImmediate + +// TODO(gman): TexSubImage2DImmediate + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index 7e417882471..cbdf48f79ae 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -1,9 +1,11 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_AUTOGEN_H_ @@ -23,7 +25,6 @@ ValueValidator<GLenum> dst_blend_factor; ValueValidator<GLenum> equation; ValueValidator<GLenum> face_mode; ValueValidator<GLenum> face_type; -ValueValidator<GLboolean> false_only; ValueValidator<GLenum> frame_buffer_parameter; ValueValidator<GLenum> frame_buffer_target; ValueValidator<GLenum> g_l_state; @@ -53,7 +54,6 @@ ValueValidator<GLenum> src_blend_factor; ValueValidator<GLenum> stencil_op; ValueValidator<GLenum> string_type; ValueValidator<GLenum> texture_bind_target; -ValueValidator<GLint> texture_border; ValueValidator<GLenum> texture_format; ValueValidator<GLenum> texture_internal_format; ValueValidator<GLenum> texture_internal_format_storage; @@ -68,7 +68,5 @@ ValueValidator<GLint> vertex_attrib_size; ValueValidator<GLenum> vertex_attrib_type; ValueValidator<GLenum> vertex_attribute; ValueValidator<GLenum> vertex_pointer; -ValueValidator<GLint> zero_only; #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_AUTOGEN_H_ - diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 8975d202a6b..e344c30f875 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -1,675 +1,480 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is auto-generated from // gpu/command_buffer/build_gles2_cmd_buffer.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename // DO NOT EDIT! -#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ // NOLINT -#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ // NOLINT +#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ static const GLenum valid_attachment_table[] = { - GL_COLOR_ATTACHMENT0, - GL_DEPTH_ATTACHMENT, - GL_STENCIL_ATTACHMENT, + GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, }; static const GLenum valid_backbuffer_attachment_table[] = { - GL_COLOR_EXT, - GL_DEPTH_EXT, - GL_STENCIL_EXT, + GL_COLOR_EXT, GL_DEPTH_EXT, GL_STENCIL_EXT, }; static const GLenum valid_blit_filter_table[] = { - GL_NEAREST, - GL_LINEAR, + GL_NEAREST, GL_LINEAR, }; static const GLenum valid_buffer_parameter_table[] = { - GL_BUFFER_SIZE, - GL_BUFFER_USAGE, + GL_BUFFER_SIZE, GL_BUFFER_USAGE, }; static const GLenum valid_buffer_target_table[] = { - GL_ARRAY_BUFFER, - GL_ELEMENT_ARRAY_BUFFER, + GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, }; static const GLenum valid_buffer_usage_table[] = { - GL_STREAM_DRAW, - GL_STATIC_DRAW, - GL_DYNAMIC_DRAW, + GL_STREAM_DRAW, GL_STATIC_DRAW, GL_DYNAMIC_DRAW, }; static const GLenum valid_capability_table[] = { - GL_BLEND, - GL_CULL_FACE, - GL_DEPTH_TEST, - GL_DITHER, - GL_POLYGON_OFFSET_FILL, - GL_SAMPLE_ALPHA_TO_COVERAGE, - GL_SAMPLE_COVERAGE, - GL_SCISSOR_TEST, - GL_STENCIL_TEST, + GL_BLEND, GL_CULL_FACE, GL_DEPTH_TEST, + GL_DITHER, GL_POLYGON_OFFSET_FILL, GL_SAMPLE_ALPHA_TO_COVERAGE, + GL_SAMPLE_COVERAGE, GL_SCISSOR_TEST, GL_STENCIL_TEST, }; static const GLenum valid_cmp_function_table[] = { - GL_NEVER, - GL_LESS, - GL_EQUAL, - GL_LEQUAL, - GL_GREATER, - GL_NOTEQUAL, - GL_GEQUAL, - GL_ALWAYS, + GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, + GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS, }; static const GLenum valid_draw_mode_table[] = { - GL_POINTS, - GL_LINE_STRIP, - GL_LINE_LOOP, - GL_LINES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN, - GL_TRIANGLES, + GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, + GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, }; static const GLenum valid_dst_blend_factor_table[] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_CONSTANT_COLOR, - GL_ONE_MINUS_CONSTANT_COLOR, - GL_CONSTANT_ALPHA, - GL_ONE_MINUS_CONSTANT_ALPHA, + GL_ZERO, GL_ONE, + GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, + GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, + GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, + GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, }; static const GLenum valid_equation_table[] = { - GL_FUNC_ADD, - GL_FUNC_SUBTRACT, - GL_FUNC_REVERSE_SUBTRACT, + GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, }; static const GLenum valid_face_mode_table[] = { - GL_CW, - GL_CCW, + GL_CW, GL_CCW, }; static const GLenum valid_face_type_table[] = { - GL_FRONT, - GL_BACK, - GL_FRONT_AND_BACK, -}; - -static const GLboolean valid_false_only_table[] = { - false, + GL_FRONT, GL_BACK, GL_FRONT_AND_BACK, }; static const GLenum valid_frame_buffer_parameter_table[] = { - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, }; static const GLenum valid_frame_buffer_target_table[] = { - GL_FRAMEBUFFER, + GL_FRAMEBUFFER, }; static const GLenum valid_g_l_state_table[] = { - GL_ACTIVE_TEXTURE, - GL_ALIASED_LINE_WIDTH_RANGE, - GL_ALIASED_POINT_SIZE_RANGE, - GL_ALPHA_BITS, - GL_ARRAY_BUFFER_BINDING, - GL_BLUE_BITS, - GL_COMPRESSED_TEXTURE_FORMATS, - GL_CURRENT_PROGRAM, - GL_DEPTH_BITS, - GL_DEPTH_RANGE, - GL_ELEMENT_ARRAY_BUFFER_BINDING, - GL_FRAMEBUFFER_BINDING, - GL_GENERATE_MIPMAP_HINT, - GL_GREEN_BITS, - GL_IMPLEMENTATION_COLOR_READ_FORMAT, - GL_IMPLEMENTATION_COLOR_READ_TYPE, - GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, - GL_MAX_CUBE_MAP_TEXTURE_SIZE, - GL_MAX_FRAGMENT_UNIFORM_VECTORS, - GL_MAX_RENDERBUFFER_SIZE, - GL_MAX_TEXTURE_IMAGE_UNITS, - GL_MAX_TEXTURE_SIZE, - GL_MAX_VARYING_VECTORS, - GL_MAX_VERTEX_ATTRIBS, - GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, - GL_MAX_VERTEX_UNIFORM_VECTORS, - GL_MAX_VIEWPORT_DIMS, - GL_NUM_COMPRESSED_TEXTURE_FORMATS, - GL_NUM_SHADER_BINARY_FORMATS, - GL_PACK_ALIGNMENT, - GL_RED_BITS, - GL_RENDERBUFFER_BINDING, - GL_SAMPLE_BUFFERS, - GL_SAMPLE_COVERAGE_INVERT, - GL_SAMPLE_COVERAGE_VALUE, - GL_SAMPLES, - GL_SCISSOR_BOX, - GL_SHADER_BINARY_FORMATS, - GL_SHADER_COMPILER, - GL_SUBPIXEL_BITS, - GL_STENCIL_BITS, - GL_TEXTURE_BINDING_2D, - GL_TEXTURE_BINDING_CUBE_MAP, - GL_UNPACK_ALIGNMENT, - GL_UNPACK_FLIP_Y_CHROMIUM, - GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, - GL_VERTEX_ARRAY_BINDING_OES, - GL_VIEWPORT, - GL_BLEND_COLOR, - GL_BLEND_EQUATION_RGB, - GL_BLEND_EQUATION_ALPHA, - GL_BLEND_SRC_RGB, - GL_BLEND_DST_RGB, - GL_BLEND_SRC_ALPHA, - GL_BLEND_DST_ALPHA, - GL_COLOR_CLEAR_VALUE, - GL_DEPTH_CLEAR_VALUE, - GL_STENCIL_CLEAR_VALUE, - GL_COLOR_WRITEMASK, - GL_CULL_FACE_MODE, - GL_DEPTH_FUNC, - GL_DEPTH_WRITEMASK, - GL_DEPTH_RANGE, - GL_FRONT_FACE, - GL_GENERATE_MIPMAP_HINT, - GL_LINE_WIDTH, - GL_PACK_ALIGNMENT, - GL_UNPACK_ALIGNMENT, - GL_POLYGON_OFFSET_FACTOR, - GL_POLYGON_OFFSET_UNITS, - GL_SAMPLE_COVERAGE_VALUE, - GL_SAMPLE_COVERAGE_INVERT, - GL_SCISSOR_BOX, - GL_STENCIL_FUNC, - GL_STENCIL_REF, - GL_STENCIL_VALUE_MASK, - GL_STENCIL_BACK_FUNC, - GL_STENCIL_BACK_REF, - GL_STENCIL_BACK_VALUE_MASK, - GL_STENCIL_WRITEMASK, - GL_STENCIL_BACK_WRITEMASK, - GL_STENCIL_FAIL, - GL_STENCIL_PASS_DEPTH_FAIL, - GL_STENCIL_PASS_DEPTH_PASS, - GL_STENCIL_BACK_FAIL, - GL_STENCIL_BACK_PASS_DEPTH_FAIL, - GL_STENCIL_BACK_PASS_DEPTH_PASS, - GL_VIEWPORT, - GL_BLEND, - GL_CULL_FACE, - GL_DEPTH_TEST, - GL_DITHER, - GL_POLYGON_OFFSET_FILL, - GL_SAMPLE_ALPHA_TO_COVERAGE, - GL_SAMPLE_COVERAGE, - GL_SCISSOR_TEST, - GL_STENCIL_TEST, + GL_ACTIVE_TEXTURE, + GL_ALIASED_LINE_WIDTH_RANGE, + GL_ALIASED_POINT_SIZE_RANGE, + GL_ALPHA_BITS, + GL_ARRAY_BUFFER_BINDING, + GL_BLUE_BITS, + GL_COMPRESSED_TEXTURE_FORMATS, + GL_CURRENT_PROGRAM, + GL_DEPTH_BITS, + GL_DEPTH_RANGE, + GL_ELEMENT_ARRAY_BUFFER_BINDING, + GL_FRAMEBUFFER_BINDING, + GL_GENERATE_MIPMAP_HINT, + GL_GREEN_BITS, + GL_IMPLEMENTATION_COLOR_READ_FORMAT, + GL_IMPLEMENTATION_COLOR_READ_TYPE, + GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, + GL_MAX_CUBE_MAP_TEXTURE_SIZE, + GL_MAX_FRAGMENT_UNIFORM_VECTORS, + GL_MAX_RENDERBUFFER_SIZE, + GL_MAX_TEXTURE_IMAGE_UNITS, + GL_MAX_TEXTURE_SIZE, + GL_MAX_VARYING_VECTORS, + GL_MAX_VERTEX_ATTRIBS, + GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, + GL_MAX_VERTEX_UNIFORM_VECTORS, + GL_MAX_VIEWPORT_DIMS, + GL_NUM_COMPRESSED_TEXTURE_FORMATS, + GL_NUM_SHADER_BINARY_FORMATS, + GL_PACK_ALIGNMENT, + GL_RED_BITS, + GL_RENDERBUFFER_BINDING, + GL_SAMPLE_BUFFERS, + GL_SAMPLE_COVERAGE_INVERT, + GL_SAMPLE_COVERAGE_VALUE, + GL_SAMPLES, + GL_SCISSOR_BOX, + GL_SHADER_BINARY_FORMATS, + GL_SHADER_COMPILER, + GL_SUBPIXEL_BITS, + GL_STENCIL_BITS, + GL_TEXTURE_BINDING_2D, + GL_TEXTURE_BINDING_CUBE_MAP, + GL_UNPACK_ALIGNMENT, + GL_UNPACK_FLIP_Y_CHROMIUM, + GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, + GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, + GL_BIND_GENERATES_RESOURCE_CHROMIUM, + GL_VERTEX_ARRAY_BINDING_OES, + GL_VIEWPORT, + GL_BLEND_COLOR, + GL_BLEND_EQUATION_RGB, + GL_BLEND_EQUATION_ALPHA, + GL_BLEND_SRC_RGB, + GL_BLEND_DST_RGB, + GL_BLEND_SRC_ALPHA, + GL_BLEND_DST_ALPHA, + GL_COLOR_CLEAR_VALUE, + GL_DEPTH_CLEAR_VALUE, + GL_STENCIL_CLEAR_VALUE, + GL_COLOR_WRITEMASK, + GL_CULL_FACE_MODE, + GL_DEPTH_FUNC, + GL_DEPTH_WRITEMASK, + GL_FRONT_FACE, + GL_LINE_WIDTH, + GL_POLYGON_OFFSET_FACTOR, + GL_POLYGON_OFFSET_UNITS, + GL_STENCIL_FUNC, + GL_STENCIL_REF, + GL_STENCIL_VALUE_MASK, + GL_STENCIL_BACK_FUNC, + GL_STENCIL_BACK_REF, + GL_STENCIL_BACK_VALUE_MASK, + GL_STENCIL_WRITEMASK, + GL_STENCIL_BACK_WRITEMASK, + GL_STENCIL_FAIL, + GL_STENCIL_PASS_DEPTH_FAIL, + GL_STENCIL_PASS_DEPTH_PASS, + GL_STENCIL_BACK_FAIL, + GL_STENCIL_BACK_PASS_DEPTH_FAIL, + GL_STENCIL_BACK_PASS_DEPTH_PASS, + GL_BLEND, + GL_CULL_FACE, + GL_DEPTH_TEST, + GL_DITHER, + GL_POLYGON_OFFSET_FILL, + GL_SAMPLE_ALPHA_TO_COVERAGE, + GL_SAMPLE_COVERAGE, + GL_SCISSOR_TEST, + GL_STENCIL_TEST, }; static const GLenum valid_get_max_index_type_table[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT, - GL_UNSIGNED_INT, + GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, }; static const GLenum valid_get_tex_param_target_table[] = { - GL_TEXTURE_2D, - GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, }; static const GLenum valid_hint_mode_table[] = { - GL_FASTEST, - GL_NICEST, - GL_DONT_CARE, + GL_FASTEST, GL_NICEST, GL_DONT_CARE, }; static const GLenum valid_hint_target_table[] = { - GL_GENERATE_MIPMAP_HINT, + GL_GENERATE_MIPMAP_HINT, }; static const GLenum valid_index_type_table[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT, + GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, }; static const GLenum valid_pixel_store_table[] = { - GL_PACK_ALIGNMENT, - GL_UNPACK_ALIGNMENT, - GL_UNPACK_FLIP_Y_CHROMIUM, - GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, + GL_PACK_ALIGNMENT, + GL_UNPACK_ALIGNMENT, + GL_UNPACK_FLIP_Y_CHROMIUM, + GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, + GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, }; static const GLint valid_pixel_store_alignment_table[] = { - 1, - 2, - 4, - 8, + 1, 2, 4, 8, }; static const GLenum valid_pixel_type_table[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_5_6_5, - GL_UNSIGNED_SHORT_4_4_4_4, - GL_UNSIGNED_SHORT_5_5_5_1, + GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, + GL_UNSIGNED_SHORT_5_5_5_1, }; static const GLenum valid_program_parameter_table[] = { - GL_DELETE_STATUS, - GL_LINK_STATUS, - GL_VALIDATE_STATUS, - GL_INFO_LOG_LENGTH, - GL_ATTACHED_SHADERS, - GL_ACTIVE_ATTRIBUTES, - GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, - GL_ACTIVE_UNIFORMS, - GL_ACTIVE_UNIFORM_MAX_LENGTH, + GL_DELETE_STATUS, GL_LINK_STATUS, + GL_VALIDATE_STATUS, GL_INFO_LOG_LENGTH, + GL_ATTACHED_SHADERS, GL_ACTIVE_ATTRIBUTES, + GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, GL_ACTIVE_UNIFORMS, + GL_ACTIVE_UNIFORM_MAX_LENGTH, }; static const GLenum valid_query_object_parameter_table[] = { - GL_QUERY_RESULT_EXT, - GL_QUERY_RESULT_AVAILABLE_EXT, + GL_QUERY_RESULT_EXT, GL_QUERY_RESULT_AVAILABLE_EXT, }; static const GLenum valid_query_parameter_table[] = { - GL_CURRENT_QUERY_EXT, + GL_CURRENT_QUERY_EXT, }; static const GLenum valid_query_target_table[] = { - GL_ANY_SAMPLES_PASSED_EXT, - GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, - GL_COMMANDS_ISSUED_CHROMIUM, - GL_LATENCY_QUERY_CHROMIUM, - GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, - GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, + GL_ANY_SAMPLES_PASSED_EXT, + GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, + GL_COMMANDS_ISSUED_CHROMIUM, + GL_LATENCY_QUERY_CHROMIUM, + GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, + GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, + GL_COMMANDS_COMPLETED_CHROMIUM, }; static const GLenum valid_read_pixel_format_table[] = { - GL_ALPHA, - GL_RGB, - GL_RGBA, + GL_ALPHA, GL_RGB, GL_RGBA, }; static const GLenum valid_read_pixel_type_table[] = { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_5_6_5, - GL_UNSIGNED_SHORT_4_4_4_4, - GL_UNSIGNED_SHORT_5_5_5_1, + GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, + GL_UNSIGNED_SHORT_5_5_5_1, }; static const GLenum valid_render_buffer_format_table[] = { - GL_RGBA4, - GL_RGB565, - GL_RGB5_A1, - GL_DEPTH_COMPONENT16, - GL_STENCIL_INDEX8, + GL_RGBA4, GL_RGB565, GL_RGB5_A1, GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX8, }; static const GLenum valid_render_buffer_parameter_table[] = { - GL_RENDERBUFFER_RED_SIZE, - GL_RENDERBUFFER_GREEN_SIZE, - GL_RENDERBUFFER_BLUE_SIZE, - GL_RENDERBUFFER_ALPHA_SIZE, - GL_RENDERBUFFER_DEPTH_SIZE, - GL_RENDERBUFFER_STENCIL_SIZE, - GL_RENDERBUFFER_WIDTH, - GL_RENDERBUFFER_HEIGHT, - GL_RENDERBUFFER_INTERNAL_FORMAT, + GL_RENDERBUFFER_RED_SIZE, GL_RENDERBUFFER_GREEN_SIZE, + GL_RENDERBUFFER_BLUE_SIZE, GL_RENDERBUFFER_ALPHA_SIZE, + GL_RENDERBUFFER_DEPTH_SIZE, GL_RENDERBUFFER_STENCIL_SIZE, + GL_RENDERBUFFER_WIDTH, GL_RENDERBUFFER_HEIGHT, + GL_RENDERBUFFER_INTERNAL_FORMAT, }; static const GLenum valid_render_buffer_target_table[] = { - GL_RENDERBUFFER, + GL_RENDERBUFFER, }; static const GLenum valid_reset_status_table[] = { - GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB, - GL_UNKNOWN_CONTEXT_RESET_ARB, + GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB, + GL_UNKNOWN_CONTEXT_RESET_ARB, }; static const GLenum valid_shader_parameter_table[] = { - GL_SHADER_TYPE, - GL_DELETE_STATUS, - GL_COMPILE_STATUS, - GL_INFO_LOG_LENGTH, - GL_SHADER_SOURCE_LENGTH, - GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, + GL_SHADER_TYPE, GL_DELETE_STATUS, + GL_COMPILE_STATUS, GL_INFO_LOG_LENGTH, + GL_SHADER_SOURCE_LENGTH, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, }; static const GLenum valid_shader_precision_table[] = { - GL_LOW_FLOAT, - GL_MEDIUM_FLOAT, - GL_HIGH_FLOAT, - GL_LOW_INT, - GL_MEDIUM_INT, - GL_HIGH_INT, + GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, + GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT, }; static const GLenum valid_shader_type_table[] = { - GL_VERTEX_SHADER, - GL_FRAGMENT_SHADER, + GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, }; static const GLenum valid_src_blend_factor_table[] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_CONSTANT_COLOR, - GL_ONE_MINUS_CONSTANT_COLOR, - GL_CONSTANT_ALPHA, - GL_ONE_MINUS_CONSTANT_ALPHA, - GL_SRC_ALPHA_SATURATE, + GL_ZERO, GL_ONE, + GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, + GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, + GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, + GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, + GL_SRC_ALPHA_SATURATE, }; static const GLenum valid_stencil_op_table[] = { - GL_KEEP, - GL_ZERO, - GL_REPLACE, - GL_INCR, - GL_INCR_WRAP, - GL_DECR, - GL_DECR_WRAP, - GL_INVERT, + GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, + GL_INCR_WRAP, GL_DECR, GL_DECR_WRAP, GL_INVERT, }; static const GLenum valid_string_type_table[] = { - GL_VENDOR, - GL_RENDERER, - GL_VERSION, - GL_SHADING_LANGUAGE_VERSION, - GL_EXTENSIONS, + GL_VENDOR, GL_RENDERER, GL_VERSION, + GL_SHADING_LANGUAGE_VERSION, GL_EXTENSIONS, }; static const GLenum valid_texture_bind_target_table[] = { - GL_TEXTURE_2D, - GL_TEXTURE_CUBE_MAP, -}; - -static const GLint valid_texture_border_table[] = { - 0, + GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, }; static const GLenum valid_texture_format_table[] = { - GL_ALPHA, - GL_LUMINANCE, - GL_LUMINANCE_ALPHA, - GL_RGB, - GL_RGBA, + GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA, }; static const GLenum valid_texture_internal_format_table[] = { - GL_ALPHA, - GL_LUMINANCE, - GL_LUMINANCE_ALPHA, - GL_RGB, - GL_RGBA, + GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA, }; static const GLenum valid_texture_internal_format_storage_table[] = { - GL_RGB565, - GL_RGBA4, - GL_RGB5_A1, - GL_ALPHA8_EXT, - GL_LUMINANCE8_EXT, - GL_LUMINANCE8_ALPHA8_EXT, - GL_RGB8_OES, - GL_RGBA8_OES, + GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_ALPHA8_EXT, + GL_LUMINANCE8_EXT, GL_LUMINANCE8_ALPHA8_EXT, GL_RGB8_OES, GL_RGBA8_OES, }; static const GLenum valid_texture_mag_filter_mode_table[] = { - GL_NEAREST, - GL_LINEAR, + GL_NEAREST, GL_LINEAR, }; static const GLenum valid_texture_min_filter_mode_table[] = { - GL_NEAREST, - GL_LINEAR, - GL_NEAREST_MIPMAP_NEAREST, - GL_LINEAR_MIPMAP_NEAREST, - GL_NEAREST_MIPMAP_LINEAR, - GL_LINEAR_MIPMAP_LINEAR, + GL_NEAREST, GL_LINEAR, + GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, + GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR, }; static const GLenum valid_texture_parameter_table[] = { - GL_TEXTURE_MAG_FILTER, - GL_TEXTURE_MIN_FILTER, - GL_TEXTURE_POOL_CHROMIUM, - GL_TEXTURE_WRAP_S, - GL_TEXTURE_WRAP_T, + GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_POOL_CHROMIUM, + GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, }; static const GLenum valid_texture_pool_table[] = { - GL_TEXTURE_POOL_MANAGED_CHROMIUM, - GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, + GL_TEXTURE_POOL_MANAGED_CHROMIUM, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, }; static const GLenum valid_texture_target_table[] = { - GL_TEXTURE_2D, - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, }; static const GLenum valid_texture_usage_table[] = { - GL_NONE, - GL_FRAMEBUFFER_ATTACHMENT_ANGLE, + GL_NONE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, }; static const GLenum valid_texture_wrap_mode_table[] = { - GL_CLAMP_TO_EDGE, - GL_MIRRORED_REPEAT, - GL_REPEAT, + GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT, GL_REPEAT, }; static const GLint valid_vertex_attrib_size_table[] = { - 1, - 2, - 3, - 4, + 1, 2, 3, 4, }; static const GLenum valid_vertex_attrib_type_table[] = { - GL_BYTE, - GL_UNSIGNED_BYTE, - GL_SHORT, - GL_UNSIGNED_SHORT, - GL_FLOAT, + GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT, }; static const GLenum valid_vertex_attribute_table[] = { - GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, - GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, - GL_VERTEX_ATTRIB_ARRAY_ENABLED, - GL_VERTEX_ATTRIB_ARRAY_SIZE, - GL_VERTEX_ATTRIB_ARRAY_STRIDE, - GL_VERTEX_ATTRIB_ARRAY_TYPE, - GL_CURRENT_VERTEX_ATTRIB, + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, + GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_VERTEX_ATTRIB_ARRAY_SIZE, + GL_VERTEX_ATTRIB_ARRAY_STRIDE, GL_VERTEX_ATTRIB_ARRAY_TYPE, + GL_CURRENT_VERTEX_ATTRIB, }; static const GLenum valid_vertex_pointer_table[] = { - GL_VERTEX_ATTRIB_ARRAY_POINTER, -}; - -static const GLint valid_zero_only_table[] = { - 0, + GL_VERTEX_ATTRIB_ARRAY_POINTER, }; Validators::Validators() - : attachment( - valid_attachment_table, arraysize(valid_attachment_table)), - backbuffer_attachment( - valid_backbuffer_attachment_table, arraysize( - valid_backbuffer_attachment_table)), - blit_filter( - valid_blit_filter_table, arraysize(valid_blit_filter_table)), - buffer_parameter( - valid_buffer_parameter_table, arraysize( - valid_buffer_parameter_table)), - buffer_target( - valid_buffer_target_table, arraysize(valid_buffer_target_table)), - buffer_usage( - valid_buffer_usage_table, arraysize(valid_buffer_usage_table)), - capability( - valid_capability_table, arraysize(valid_capability_table)), - cmp_function( - valid_cmp_function_table, arraysize(valid_cmp_function_table)), + : attachment(valid_attachment_table, arraysize(valid_attachment_table)), + backbuffer_attachment(valid_backbuffer_attachment_table, + arraysize(valid_backbuffer_attachment_table)), + blit_filter(valid_blit_filter_table, arraysize(valid_blit_filter_table)), + buffer_parameter(valid_buffer_parameter_table, + arraysize(valid_buffer_parameter_table)), + buffer_target(valid_buffer_target_table, + arraysize(valid_buffer_target_table)), + buffer_usage(valid_buffer_usage_table, + arraysize(valid_buffer_usage_table)), + capability(valid_capability_table, arraysize(valid_capability_table)), + cmp_function(valid_cmp_function_table, + arraysize(valid_cmp_function_table)), compressed_texture_format(), - draw_mode( - valid_draw_mode_table, arraysize(valid_draw_mode_table)), - dst_blend_factor( - valid_dst_blend_factor_table, arraysize( - valid_dst_blend_factor_table)), - equation( - valid_equation_table, arraysize(valid_equation_table)), - face_mode( - valid_face_mode_table, arraysize(valid_face_mode_table)), - face_type( - valid_face_type_table, arraysize(valid_face_type_table)), - false_only( - valid_false_only_table, arraysize(valid_false_only_table)), - frame_buffer_parameter( - valid_frame_buffer_parameter_table, arraysize( - valid_frame_buffer_parameter_table)), - frame_buffer_target( - valid_frame_buffer_target_table, arraysize( - valid_frame_buffer_target_table)), - g_l_state( - valid_g_l_state_table, arraysize(valid_g_l_state_table)), - get_max_index_type( - valid_get_max_index_type_table, arraysize( - valid_get_max_index_type_table)), - get_tex_param_target( - valid_get_tex_param_target_table, arraysize( - valid_get_tex_param_target_table)), - hint_mode( - valid_hint_mode_table, arraysize(valid_hint_mode_table)), - hint_target( - valid_hint_target_table, arraysize(valid_hint_target_table)), - index_type( - valid_index_type_table, arraysize(valid_index_type_table)), - pixel_store( - valid_pixel_store_table, arraysize(valid_pixel_store_table)), - pixel_store_alignment( - valid_pixel_store_alignment_table, arraysize( - valid_pixel_store_alignment_table)), - pixel_type( - valid_pixel_type_table, arraysize(valid_pixel_type_table)), - program_parameter( - valid_program_parameter_table, arraysize( - valid_program_parameter_table)), - query_object_parameter( - valid_query_object_parameter_table, arraysize( - valid_query_object_parameter_table)), - query_parameter( - valid_query_parameter_table, arraysize(valid_query_parameter_table)), - query_target( - valid_query_target_table, arraysize(valid_query_target_table)), - read_pixel_format( - valid_read_pixel_format_table, arraysize( - valid_read_pixel_format_table)), - read_pixel_type( - valid_read_pixel_type_table, arraysize(valid_read_pixel_type_table)), - render_buffer_format( - valid_render_buffer_format_table, arraysize( - valid_render_buffer_format_table)), - render_buffer_parameter( - valid_render_buffer_parameter_table, arraysize( - valid_render_buffer_parameter_table)), - render_buffer_target( - valid_render_buffer_target_table, arraysize( - valid_render_buffer_target_table)), - reset_status( - valid_reset_status_table, arraysize(valid_reset_status_table)), + draw_mode(valid_draw_mode_table, arraysize(valid_draw_mode_table)), + dst_blend_factor(valid_dst_blend_factor_table, + arraysize(valid_dst_blend_factor_table)), + equation(valid_equation_table, arraysize(valid_equation_table)), + face_mode(valid_face_mode_table, arraysize(valid_face_mode_table)), + face_type(valid_face_type_table, arraysize(valid_face_type_table)), + frame_buffer_parameter(valid_frame_buffer_parameter_table, + arraysize(valid_frame_buffer_parameter_table)), + frame_buffer_target(valid_frame_buffer_target_table, + arraysize(valid_frame_buffer_target_table)), + g_l_state(valid_g_l_state_table, arraysize(valid_g_l_state_table)), + get_max_index_type(valid_get_max_index_type_table, + arraysize(valid_get_max_index_type_table)), + get_tex_param_target(valid_get_tex_param_target_table, + arraysize(valid_get_tex_param_target_table)), + hint_mode(valid_hint_mode_table, arraysize(valid_hint_mode_table)), + hint_target(valid_hint_target_table, arraysize(valid_hint_target_table)), + index_type(valid_index_type_table, arraysize(valid_index_type_table)), + pixel_store(valid_pixel_store_table, arraysize(valid_pixel_store_table)), + pixel_store_alignment(valid_pixel_store_alignment_table, + arraysize(valid_pixel_store_alignment_table)), + pixel_type(valid_pixel_type_table, arraysize(valid_pixel_type_table)), + program_parameter(valid_program_parameter_table, + arraysize(valid_program_parameter_table)), + query_object_parameter(valid_query_object_parameter_table, + arraysize(valid_query_object_parameter_table)), + query_parameter(valid_query_parameter_table, + arraysize(valid_query_parameter_table)), + query_target(valid_query_target_table, + arraysize(valid_query_target_table)), + read_pixel_format(valid_read_pixel_format_table, + arraysize(valid_read_pixel_format_table)), + read_pixel_type(valid_read_pixel_type_table, + arraysize(valid_read_pixel_type_table)), + render_buffer_format(valid_render_buffer_format_table, + arraysize(valid_render_buffer_format_table)), + render_buffer_parameter(valid_render_buffer_parameter_table, + arraysize(valid_render_buffer_parameter_table)), + render_buffer_target(valid_render_buffer_target_table, + arraysize(valid_render_buffer_target_table)), + reset_status(valid_reset_status_table, + arraysize(valid_reset_status_table)), shader_binary_format(), - shader_parameter( - valid_shader_parameter_table, arraysize( - valid_shader_parameter_table)), - shader_precision( - valid_shader_precision_table, arraysize( - valid_shader_precision_table)), - shader_type( - valid_shader_type_table, arraysize(valid_shader_type_table)), - src_blend_factor( - valid_src_blend_factor_table, arraysize( - valid_src_blend_factor_table)), - stencil_op( - valid_stencil_op_table, arraysize(valid_stencil_op_table)), - string_type( - valid_string_type_table, arraysize(valid_string_type_table)), - texture_bind_target( - valid_texture_bind_target_table, arraysize( - valid_texture_bind_target_table)), - texture_border( - valid_texture_border_table, arraysize(valid_texture_border_table)), - texture_format( - valid_texture_format_table, arraysize(valid_texture_format_table)), - texture_internal_format( - valid_texture_internal_format_table, arraysize( - valid_texture_internal_format_table)), + shader_parameter(valid_shader_parameter_table, + arraysize(valid_shader_parameter_table)), + shader_precision(valid_shader_precision_table, + arraysize(valid_shader_precision_table)), + shader_type(valid_shader_type_table, arraysize(valid_shader_type_table)), + src_blend_factor(valid_src_blend_factor_table, + arraysize(valid_src_blend_factor_table)), + stencil_op(valid_stencil_op_table, arraysize(valid_stencil_op_table)), + string_type(valid_string_type_table, arraysize(valid_string_type_table)), + texture_bind_target(valid_texture_bind_target_table, + arraysize(valid_texture_bind_target_table)), + texture_format(valid_texture_format_table, + arraysize(valid_texture_format_table)), + texture_internal_format(valid_texture_internal_format_table, + arraysize(valid_texture_internal_format_table)), texture_internal_format_storage( - valid_texture_internal_format_storage_table, arraysize( - valid_texture_internal_format_storage_table)), - texture_mag_filter_mode( - valid_texture_mag_filter_mode_table, arraysize( - valid_texture_mag_filter_mode_table)), - texture_min_filter_mode( - valid_texture_min_filter_mode_table, arraysize( - valid_texture_min_filter_mode_table)), - texture_parameter( - valid_texture_parameter_table, arraysize( - valid_texture_parameter_table)), - texture_pool( - valid_texture_pool_table, arraysize(valid_texture_pool_table)), - texture_target( - valid_texture_target_table, arraysize(valid_texture_target_table)), - texture_usage( - valid_texture_usage_table, arraysize(valid_texture_usage_table)), - texture_wrap_mode( - valid_texture_wrap_mode_table, arraysize( - valid_texture_wrap_mode_table)), - vertex_attrib_size( - valid_vertex_attrib_size_table, arraysize( - valid_vertex_attrib_size_table)), - vertex_attrib_type( - valid_vertex_attrib_type_table, arraysize( - valid_vertex_attrib_type_table)), - vertex_attribute( - valid_vertex_attribute_table, arraysize( - valid_vertex_attribute_table)), - vertex_pointer( - valid_vertex_pointer_table, arraysize(valid_vertex_pointer_table)), - zero_only( - valid_zero_only_table, arraysize(valid_zero_only_table)) { + valid_texture_internal_format_storage_table, + arraysize(valid_texture_internal_format_storage_table)), + texture_mag_filter_mode(valid_texture_mag_filter_mode_table, + arraysize(valid_texture_mag_filter_mode_table)), + texture_min_filter_mode(valid_texture_min_filter_mode_table, + arraysize(valid_texture_min_filter_mode_table)), + texture_parameter(valid_texture_parameter_table, + arraysize(valid_texture_parameter_table)), + texture_pool(valid_texture_pool_table, + arraysize(valid_texture_pool_table)), + texture_target(valid_texture_target_table, + arraysize(valid_texture_target_table)), + texture_usage(valid_texture_usage_table, + arraysize(valid_texture_usage_table)), + texture_wrap_mode(valid_texture_wrap_mode_table, + arraysize(valid_texture_wrap_mode_table)), + vertex_attrib_size(valid_vertex_attrib_size_table, + arraysize(valid_vertex_attrib_size_table)), + vertex_attrib_type(valid_vertex_attrib_type_table, + arraysize(valid_vertex_attrib_type_table)), + vertex_attribute(valid_vertex_attribute_table, + arraysize(valid_vertex_attribute_table)), + vertex_pointer(valid_vertex_pointer_table, + arraysize(valid_vertex_pointer_table)) { } -#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ // NOLINT - +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ diff --git a/chromium/gpu/command_buffer/service/gpu_control_service.cc b/chromium/gpu/command_buffer/service/gpu_control_service.cc index 7c0eb8c8044..f9f19eb2592 100644 --- a/chromium/gpu/command_buffer/service/gpu_control_service.cc +++ b/chromium/gpu/command_buffer/service/gpu_control_service.cc @@ -4,84 +4,21 @@ #include "gpu/command_buffer/service/gpu_control_service.h" -#include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" #include "gpu/command_buffer/service/gpu_memory_buffer_manager.h" -#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/query_manager.h" namespace gpu { GpuControlService::GpuControlService( GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager, - GpuMemoryBufferFactory* gpu_memory_buffer_factory, - gles2::MailboxManager* mailbox_manager, - gles2::QueryManager* query_manager, - const gpu::Capabilities& decoder_capabilities) + gles2::QueryManager* query_manager) : gpu_memory_buffer_manager_(gpu_memory_buffer_manager), - gpu_memory_buffer_factory_(gpu_memory_buffer_factory), - mailbox_manager_(mailbox_manager), - query_manager_(query_manager), - capabilities_(decoder_capabilities) { - capabilities_.map_image = - gpu_memory_buffer_manager_ && gpu_memory_buffer_factory_; + query_manager_(query_manager) { } GpuControlService::~GpuControlService() { } -gpu::Capabilities GpuControlService::GetCapabilities() { - return capabilities_; -} - -gfx::GpuMemoryBuffer* GpuControlService::CreateGpuMemoryBuffer( - size_t width, - size_t height, - unsigned internalformat, - int32* id) { - *id = -1; - - CHECK(gpu_memory_buffer_factory_) << "No GPU memory buffer factory provided"; - linked_ptr<gfx::GpuMemoryBuffer> buffer = make_linked_ptr( - gpu_memory_buffer_factory_->CreateGpuMemoryBuffer(width, - height, - internalformat)); - if (!buffer.get()) - return NULL; - - static int32 next_id = 1; - *id = next_id++; - - if (!RegisterGpuMemoryBuffer(*id, - buffer->GetHandle(), - width, - height, - internalformat)) { - *id = -1; - return NULL; - } - - gpu_memory_buffers_[*id] = buffer; - return buffer.get(); -} - -void GpuControlService::DestroyGpuMemoryBuffer(int32 id) { - GpuMemoryBufferMap::iterator it = gpu_memory_buffers_.find(id); - if (it != gpu_memory_buffers_.end()) - gpu_memory_buffers_.erase(it); - - gpu_memory_buffer_manager_->DestroyGpuMemoryBuffer(id); -} - -uint32 GpuControlService::InsertSyncPoint() { - NOTREACHED(); - return 0u; -} - -void GpuControlService::SignalSyncPoint(uint32 sync_point, - const base::Closure& callback) { - NOTREACHED(); -} - void GpuControlService::SignalQuery(uint32 query_id, const base::Closure& callback) { DCHECK(query_manager_); @@ -92,42 +29,18 @@ void GpuControlService::SignalQuery(uint32 query_id, query->AddCallback(callback); } -void GpuControlService::SetSurfaceVisible(bool visible) { - NOTREACHED(); -} - -void GpuControlService::SendManagedMemoryStats( - const ManagedMemoryStats& stats) { - NOTREACHED(); -} - -void GpuControlService::Echo(const base::Closure& callback) { - NOTREACHED(); -} - -bool GpuControlService::RegisterGpuMemoryBuffer( +void GpuControlService::RegisterGpuMemoryBuffer( int32 id, gfx::GpuMemoryBufferHandle buffer, size_t width, size_t height, unsigned internalformat) { - return gpu_memory_buffer_manager_->RegisterGpuMemoryBuffer(id, - buffer, - width, - height, - internalformat); + gpu_memory_buffer_manager_->RegisterGpuMemoryBuffer( + id, buffer, width, height, internalformat); } -bool GpuControlService::GenerateMailboxNames( - unsigned num, std::vector<gpu::Mailbox>* names) { - DCHECK(names->empty()); - names->resize(num); - for (unsigned i = 0; i < num; ++i) { - gles2::MailboxName name; - mailbox_manager_->GenerateMailboxName(&name); - (*names)[i].SetName(name.key); - } - return true; +void GpuControlService::UnregisterGpuMemoryBuffer(int32 id) { + gpu_memory_buffer_manager_->UnregisterGpuMemoryBuffer(id); } } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gpu_control_service.h b/chromium/gpu/command_buffer/service/gpu_control_service.h index 3764ad42136..9a64946384f 100644 --- a/chromium/gpu/command_buffer/service/gpu_control_service.h +++ b/chromium/gpu/command_buffer/service/gpu_control_service.h @@ -5,67 +5,36 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_CONTROL_SERVICE_H_ #define GPU_COMMAND_BUFFER_SERVICE_GPU_CONTROL_SERVICE_H_ -#include <map> - -#include "base/memory/linked_ptr.h" -#include "gpu/command_buffer/common/gpu_control.h" +#include "base/callback.h" +#include "gpu/command_buffer/common/capabilities.h" +#include "gpu/gpu_export.h" #include "ui/gfx/gpu_memory_buffer.h" namespace gpu { -class GpuMemoryBufferFactory; class GpuMemoryBufferManagerInterface; namespace gles2 { -class MailboxManager; class QueryManager; } -class GPU_EXPORT GpuControlService : public GpuControl { +class GPU_EXPORT GpuControlService { public: GpuControlService(GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager, - GpuMemoryBufferFactory* gpu_memory_buffer_factory, - gles2::MailboxManager* mailbox_manager, - gles2::QueryManager* query_manager, - const gpu::Capabilities& decoder_capabilities); + gles2::QueryManager* query_manager); virtual ~GpuControlService(); + void SignalQuery(uint32 query, const base::Closure& callback); - // GpuControl implementation. - virtual gpu::Capabilities GetCapabilities() OVERRIDE; - virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( - size_t width, - size_t height, - unsigned internalformat, - int32* id) OVERRIDE; - virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE; - virtual bool GenerateMailboxNames(unsigned num, - std::vector<gpu::Mailbox>* names) OVERRIDE; - virtual uint32 InsertSyncPoint() OVERRIDE; - virtual void SignalSyncPoint(uint32 sync_point, - const base::Closure& callback) OVERRIDE; - virtual void SignalQuery(uint32 query, - const base::Closure& callback) OVERRIDE; - virtual void SetSurfaceVisible(bool visible) OVERRIDE; - virtual void SendManagedMemoryStats(const ManagedMemoryStats& stats) - OVERRIDE; - virtual void Echo(const base::Closure& callback) OVERRIDE; - - // Register an existing gpu memory buffer and get an ID that can be used - // to identify it in the command buffer. - bool RegisterGpuMemoryBuffer(int32 id, + void RegisterGpuMemoryBuffer(int32 id, gfx::GpuMemoryBufferHandle buffer, size_t width, size_t height, unsigned internalformat); + void UnregisterGpuMemoryBuffer(int32 id); private: GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager_; - GpuMemoryBufferFactory* gpu_memory_buffer_factory_; - gles2::MailboxManager* mailbox_manager_; gles2::QueryManager* query_manager_; - typedef std::map<int32, linked_ptr<gfx::GpuMemoryBuffer> > GpuMemoryBufferMap; - GpuMemoryBufferMap gpu_memory_buffers_; - gpu::Capabilities capabilities_; DISALLOW_COPY_AND_ASSIGN(GpuControlService); }; diff --git a/chromium/gpu/command_buffer/service/gpu_memory_buffer_manager.h b/chromium/gpu/command_buffer/service/gpu_memory_buffer_manager.h index fb44ede7ed5..3ddcaad9981 100644 --- a/chromium/gpu/command_buffer/service/gpu_memory_buffer_manager.h +++ b/chromium/gpu/command_buffer/service/gpu_memory_buffer_manager.h @@ -15,12 +15,12 @@ class GPU_EXPORT GpuMemoryBufferManagerInterface { public: virtual ~GpuMemoryBufferManagerInterface() {} - virtual bool RegisterGpuMemoryBuffer(int32 id, + virtual void RegisterGpuMemoryBuffer(int32 id, gfx::GpuMemoryBufferHandle buffer, size_t width, size_t height, unsigned internalformat) = 0; - virtual void DestroyGpuMemoryBuffer(int32 id) = 0; + virtual void UnregisterGpuMemoryBuffer(int32 id) = 0; }; } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gpu_scheduler.cc b/chromium/gpu/command_buffer/service/gpu_scheduler.cc index a40e9899842..3d159b66768 100644 --- a/chromium/gpu/command_buffer/service/gpu_scheduler.cc +++ b/chromium/gpu/command_buffer/service/gpu_scheduler.cc @@ -28,7 +28,7 @@ const int64 kUnscheduleFenceTimeOutDelay = 10000; const int64 kRescheduleTimeOutDelay = 1000; #endif -GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, +GpuScheduler::GpuScheduler(CommandBufferServiceBase* command_buffer, AsyncAPIInterface* handler, gles2::GLES2Decoder* decoder) : command_buffer_(command_buffer), @@ -47,7 +47,7 @@ void GpuScheduler::PutChanged() { "gpu", "GpuScheduler:PutChanged", "decoder", decoder_ ? decoder_->GetLogger()->GetLogPrefix() : "None"); - CommandBuffer::State state = command_buffer_->GetState(); + CommandBuffer::State state = command_buffer_->GetLastState(); // If there is no parser, exit. if (!parser_.get()) { @@ -69,6 +69,8 @@ void GpuScheduler::PutChanged() { base::TimeTicks begin_time(base::TimeTicks::HighResNow()); error::Error error = error::kNoError; + if (decoder_) + decoder_->BeginDecoding(); while (!parser_->IsEmpty()) { if (IsPreempted()) break; @@ -108,6 +110,7 @@ void GpuScheduler::PutChanged() { command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); command_buffer_->SetParseError(error::kLostContext); } + decoder_->EndDecoding(); decoder_->AddProcessingCommandsTime( base::TimeTicks::HighResNow() - begin_time); } @@ -178,7 +181,7 @@ void GpuScheduler::SetSchedulingChangedCallback( scheduling_changed_callback_ = callback; } -Buffer GpuScheduler::GetSharedMemoryBuffer(int32 shm_id) { +scoped_refptr<Buffer> GpuScheduler::GetSharedMemoryBuffer(int32 shm_id) { return command_buffer_->GetTransferBuffer(shm_id); } @@ -187,8 +190,9 @@ void GpuScheduler::set_token(int32 token) { } bool GpuScheduler::SetGetBuffer(int32 transfer_buffer_id) { - Buffer ring_buffer = command_buffer_->GetTransferBuffer(transfer_buffer_id); - if (!ring_buffer.ptr) { + scoped_refptr<Buffer> ring_buffer = + command_buffer_->GetTransferBuffer(transfer_buffer_id); + if (!ring_buffer) { return false; } @@ -197,10 +201,7 @@ bool GpuScheduler::SetGetBuffer(int32 transfer_buffer_id) { } parser_->SetBuffer( - ring_buffer.ptr, - ring_buffer.size, - 0, - ring_buffer.size); + ring_buffer->memory(), ring_buffer->size(), 0, ring_buffer->size()); SetGetOffset(0); return true; diff --git a/chromium/gpu/command_buffer/service/gpu_scheduler.h b/chromium/gpu/command_buffer/service/gpu_scheduler.h index 8fb791cd3fd..5e073ca54e5 100644 --- a/chromium/gpu/command_buffer/service/gpu_scheduler.h +++ b/chromium/gpu/command_buffer/service/gpu_scheduler.h @@ -15,9 +15,9 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/memory/weak_ptr.h" -#include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/cmd_parser.h" +#include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/gpu_export.h" @@ -52,7 +52,7 @@ class GPU_EXPORT GpuScheduler : NON_EXPORTED_BASE(public CommandBufferEngine), public base::SupportsWeakPtr<GpuScheduler> { public: - GpuScheduler(CommandBuffer* command_buffer, + GpuScheduler(CommandBufferServiceBase* command_buffer, AsyncAPIInterface* handler, gles2::GLES2Decoder* decoder); @@ -83,7 +83,7 @@ class GPU_EXPORT GpuScheduler void SetSchedulingChangedCallback(const SchedulingChangedCallback& callback); // Implementation of CommandBufferEngine. - virtual Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE; + virtual scoped_refptr<Buffer> GetSharedMemoryBuffer(int32 shm_id) OVERRIDE; virtual void set_token(int32 token) OVERRIDE; virtual bool SetGetBuffer(int32 transfer_buffer_id) OVERRIDE; virtual bool SetGetOffset(int32 offset) OVERRIDE; @@ -114,7 +114,7 @@ class GPU_EXPORT GpuScheduler // The GpuScheduler holds a weak reference to the CommandBuffer. The // CommandBuffer owns the GpuScheduler and holds a strong reference to it // through the ProcessCommands callback. - CommandBuffer* command_buffer_; + CommandBufferServiceBase* command_buffer_; // The parser uses this to execute commands. AsyncAPIInterface* handler_; diff --git a/chromium/gpu/command_buffer/service/gpu_scheduler_unittest.cc b/chromium/gpu/command_buffer/service/gpu_scheduler_unittest.cc index 84e40c7c658..80e177aa489 100644 --- a/chromium/gpu/command_buffer/service/gpu_scheduler_unittest.cc +++ b/chromium/gpu/command_buffer/service/gpu_scheduler_unittest.cc @@ -33,18 +33,18 @@ class GpuSchedulerTest : public testing::Test { static const int32 kTransferBufferId = 123; virtual void SetUp() { - shared_memory_.reset(new ::base::SharedMemory); - shared_memory_->CreateAndMapAnonymous(kRingBufferSize); - buffer_ = static_cast<int32*>(shared_memory_->memory()); - shared_memory_buffer_.ptr = buffer_; - shared_memory_buffer_.size = kRingBufferSize; + scoped_ptr<base::SharedMemory> shared_memory(new ::base::SharedMemory); + shared_memory->CreateAndMapAnonymous(kRingBufferSize); + buffer_ = static_cast<int32*>(shared_memory->memory()); + shared_memory_buffer_ = + MakeBufferFromSharedMemory(shared_memory.Pass(), kRingBufferSize); memset(buffer_, 0, kRingBufferSize); command_buffer_.reset(new MockCommandBuffer); CommandBuffer::State default_state; default_state.num_entries = kRingBufferEntries; - ON_CALL(*command_buffer_.get(), GetState()) + ON_CALL(*command_buffer_.get(), GetLastState()) .WillByDefault(Return(default_state)); decoder_.reset(new gles2::MockGLES2Decoder()); @@ -64,7 +64,7 @@ class GpuSchedulerTest : public testing::Test { } error::Error GetError() { - return command_buffer_->GetState().error; + return command_buffer_->GetLastState().error; } #if defined(OS_MACOSX) @@ -72,8 +72,7 @@ class GpuSchedulerTest : public testing::Test { #endif base::MessageLoop message_loop; scoped_ptr<MockCommandBuffer> command_buffer_; - scoped_ptr<base::SharedMemory> shared_memory_; - Buffer shared_memory_buffer_; + scoped_refptr<Buffer> shared_memory_buffer_; int32* buffer_; scoped_ptr<gles2::MockGLES2Decoder> decoder_; scoped_ptr<GpuScheduler> scheduler_; @@ -83,7 +82,7 @@ TEST_F(GpuSchedulerTest, SchedulerDoesNothingIfRingBufferIsEmpty) { CommandBuffer::State state; state.put_offset = 0; - EXPECT_CALL(*command_buffer_, GetState()) + EXPECT_CALL(*command_buffer_, GetLastState()) .WillRepeatedly(Return(state)); EXPECT_CALL(*command_buffer_, SetParseError(_)) @@ -119,7 +118,7 @@ TEST_F(GpuSchedulerTest, ProcessesOneCommand) { CommandBuffer::State state; state.put_offset = 2; - EXPECT_CALL(*command_buffer_, GetState()) + EXPECT_CALL(*command_buffer_, GetLastState()) .WillRepeatedly(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(2)); @@ -143,7 +142,7 @@ TEST_F(GpuSchedulerTest, ProcessesTwoCommands) { CommandBuffer::State state; state.put_offset = 3; - EXPECT_CALL(*command_buffer_, GetState()) + EXPECT_CALL(*command_buffer_, GetLastState()) .WillRepeatedly(Return(state)); EXPECT_CALL(*decoder_, DoCommand(7, 1, &buffer_[0])) @@ -165,7 +164,7 @@ TEST_F(GpuSchedulerTest, SetsErrorCodeOnCommandBuffer) { CommandBuffer::State state; state.put_offset = 1; - EXPECT_CALL(*command_buffer_, GetState()) + EXPECT_CALL(*command_buffer_, GetLastState()) .WillRepeatedly(Return(state)); EXPECT_CALL(*decoder_, DoCommand(7, 0, &buffer_[0])) @@ -186,7 +185,7 @@ TEST_F(GpuSchedulerTest, ProcessCommandsDoesNothingAfterError) { CommandBuffer::State state; state.error = error::kGenericError; - EXPECT_CALL(*command_buffer_, GetState()) + EXPECT_CALL(*command_buffer_, GetLastState()) .WillRepeatedly(Return(state)); scheduler_->PutChanged(); @@ -196,7 +195,7 @@ TEST_F(GpuSchedulerTest, CanGetAddressOfSharedMemory) { EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7)) .WillOnce(Return(shared_memory_buffer_)); - EXPECT_EQ(&buffer_[0], scheduler_->GetSharedMemoryBuffer(7).ptr); + EXPECT_EQ(&buffer_[0], scheduler_->GetSharedMemoryBuffer(7)->memory()); } ACTION_P2(SetPointee, address, value) { @@ -207,7 +206,7 @@ TEST_F(GpuSchedulerTest, CanGetSizeOfSharedMemory) { EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7)) .WillOnce(Return(shared_memory_buffer_)); - EXPECT_EQ(kRingBufferSize, scheduler_->GetSharedMemoryBuffer(7).size); + EXPECT_EQ(kRingBufferSize, scheduler_->GetSharedMemoryBuffer(7)->size()); } TEST_F(GpuSchedulerTest, SetTokenForwardsToCommandBuffer) { diff --git a/chromium/gpu/command_buffer/service/gpu_service_test.cc b/chromium/gpu/command_buffer/service/gpu_service_test.cc new file mode 100644 index 00000000000..a51a54c7a48 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_service_test.cc @@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gpu_service_test.h" + +#include "gpu/command_buffer/service/test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_context_stub_with_extensions.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface.h" + +namespace gpu { +namespace gles2 { + +GpuServiceTest::GpuServiceTest() : ran_setup_(false), ran_teardown_(false) { +} + +GpuServiceTest::~GpuServiceTest() { + DCHECK(ran_teardown_); +} + +void GpuServiceTest::SetUp() { + testing::Test::SetUp(); + + gfx::SetGLGetProcAddressProc(gfx::MockGLInterface::GetGLProcAddress); + gfx::GLSurface::InitializeOneOffWithMockBindingsForTests(); + gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); + ::gfx::MockGLInterface::SetGLInterface(gl_.get()); + + context_ = new gfx::GLContextStubWithExtensions; + context_->AddExtensionsString(NULL); + context_->SetGLVersionString("3.0"); + gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_); + ran_setup_ = true; +} + +void GpuServiceTest::TearDown() { + DCHECK(ran_setup_); + ::gfx::MockGLInterface::SetGLInterface(NULL); + gl_.reset(); + gfx::ClearGLBindings(); + ran_teardown_ = true; + + testing::Test::TearDown(); +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gpu_service_test.h b/chromium/gpu/command_buffer/service/gpu_service_test.h new file mode 100644 index 00000000000..f37178784b1 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_service_test.h @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_SERVICE_TEST_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GPU_SERVICE_TEST_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_mock.h" + +namespace gfx { +class GLContextStubWithExtensions; +} + +namespace gpu { +namespace gles2 { + +// Base class for tests that need mock GL bindings. +class GpuServiceTest : public testing::Test { + public: + GpuServiceTest(); + virtual ~GpuServiceTest(); + + protected: + virtual void SetUp() OVERRIDE; + virtual void TearDown() OVERRIDE; + + scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; + + private: + bool ran_setup_; + bool ran_teardown_; + scoped_refptr<gfx::GLContextStubWithExtensions> context_; +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_ diff --git a/chromium/gpu/command_buffer/service/gpu_switches.cc b/chromium/gpu/command_buffer/service/gpu_switches.cc index bff23c31391..0491c413e5e 100644 --- a/chromium/gpu/command_buffer/service/gpu_switches.cc +++ b/chromium/gpu/command_buffer/service/gpu_switches.cc @@ -40,17 +40,9 @@ const char kDisableGpuProgramCache[] = "disable-gpu-program-cache"; // Enforce GL minimums. const char kEnforceGLMinimums[] = "enforce-gl-minimums"; -// Force the use of a workaround for graphics hangs seen on certain -// Mac OS systems. Enabled by default (and can't be disabled) on known -// affected systems. -const char kForceGLFinishWorkaround[] = "force-glfinish-workaround"; - // Sets the total amount of memory that may be allocated for GPU resources const char kForceGpuMemAvailableMb[] = "force-gpu-mem-available-mb"; -// Force the synchronous copy path in compositing_iosurface_mac. -const char kForceSynchronousGLReadPixels[] = "force-synchronous-glreadpixels"; - // Pass a set of GpuDriverBugWorkaroundType ids, seperated by ','. const char kGpuDriverBugWorkarounds[] = "gpu-driver-bug-workarounds"; @@ -75,9 +67,7 @@ const char* kGpuSwitches[] = { kEnableGPUServiceLoggingGPU, kDisableGpuProgramCache, kEnforceGLMinimums, - kForceGLFinishWorkaround, kForceGpuMemAvailableMb, - kForceSynchronousGLReadPixels, kGpuDriverBugWorkarounds, kGpuProgramCacheSizeKb, kDisableGpuShaderDiskCache, diff --git a/chromium/gpu/command_buffer/service/gpu_switches.h b/chromium/gpu/command_buffer/service/gpu_switches.h index 7916d690142..d582b7ae267 100644 --- a/chromium/gpu/command_buffer/service/gpu_switches.h +++ b/chromium/gpu/command_buffer/service/gpu_switches.h @@ -21,9 +21,7 @@ GPU_EXPORT extern const char kEnableGPUDebugging[]; GPU_EXPORT extern const char kEnableGPUServiceLoggingGPU[]; GPU_EXPORT extern const char kDisableGpuProgramCache[]; GPU_EXPORT extern const char kEnforceGLMinimums[]; -GPU_EXPORT extern const char kForceGLFinishWorkaround[]; GPU_EXPORT extern const char kForceGpuMemAvailableMb[]; -GPU_EXPORT extern const char kForceSynchronousGLReadPixels[]; GPU_EXPORT extern const char kGpuDriverBugWorkarounds[]; GPU_EXPORT extern const char kGpuProgramCacheSizeKb[]; GPU_EXPORT extern const char kDisableGpuShaderDiskCache[]; diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.cc b/chromium/gpu/command_buffer/service/gpu_tracer.cc index 413dc68739f..2cd38e79ca4 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.cc +++ b/chromium/gpu/command_buffer/service/gpu_tracer.cc @@ -8,111 +8,62 @@ #include "base/bind.h" #include "base/debug/trace_event.h" -#include "base/memory/weak_ptr.h" #include "base/strings/string_util.h" -#include "base/threading/thread.h" #include "base/time/time.h" -#include "ui/gl/gl_bindings.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" namespace gpu { namespace gles2 { -namespace { - -class Outputter; static const unsigned int kProcessInterval = 16; -static Outputter* g_outputter_thread = NULL; +static TraceOutputter* g_outputter_thread = NULL; -class Outputter - : private base::Thread, - public base::RefCounted<Outputter> { - public: - static scoped_refptr<Outputter> Create(const std::string& name) { - if (!g_outputter_thread) { - g_outputter_thread = new Outputter(name); - g_outputter_thread->Start(); - g_outputter_thread->Stop(); - } - return g_outputter_thread; +scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { + if (!g_outputter_thread) { + g_outputter_thread = new TraceOutputter(name); } + return g_outputter_thread; +} - uint64 Id() { return thread_id(); } - - private: - friend class base::RefCounted<Outputter>; - - explicit Outputter(const std::string& name) : base::Thread(name.c_str()) {} - - virtual ~Outputter() { - g_outputter_thread = NULL; - } - - DISALLOW_COPY_AND_ASSIGN(Outputter); -}; - -class Trace : public base::RefCounted<Trace> { - public: - explicit Trace(const std::string& name) : name_(name) {} - - virtual void Start() = 0; - virtual void End() = 0; - - // True if the the results of this query are available. - virtual bool IsAvailable() = 0; - - virtual bool IsProcessable() { return true; } - virtual void Process() = 0; - - virtual const std::string& name() { - return name_; - } - - protected: - virtual ~Trace() {} - - private: - friend class base::RefCounted<Trace>; - - std::string name_; - - DISALLOW_COPY_AND_ASSIGN(Trace); -}; - -class GLARBTimerTrace : public Trace { - public: - GLARBTimerTrace(scoped_refptr<Outputter> outputter, const std::string& name, - int64 offset); - - // Implementation of Tracer - virtual void Start() OVERRIDE; - virtual void End() OVERRIDE; - virtual bool IsAvailable() OVERRIDE; - virtual void Process() OVERRIDE; - - private: - virtual ~GLARBTimerTrace(); - - void Output(); - - scoped_refptr<Outputter> outputter_; - - int64 offset_; - int64 start_time_; - int64 end_time_; - bool end_requested_; - - GLuint queries_[2]; +TraceOutputter::TraceOutputter(const std::string& name) + : named_thread_(name.c_str()), local_trace_id_(0) { + named_thread_.Start(); + named_thread_.Stop(); +} - DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace); -}; +TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } + +void TraceOutputter::Trace(const std::string& name, + int64 start_time, + int64 end_time) { + TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( + TRACE_DISABLED_BY_DEFAULT("gpu.device"), + name.c_str(), + local_trace_id_, + named_thread_.thread_id(), + start_time); + TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( + TRACE_DISABLED_BY_DEFAULT("gpu.device"), + name.c_str(), + local_trace_id_, + named_thread_.thread_id(), + end_time); + ++local_trace_id_; +} class NoopTrace : public Trace { public: explicit NoopTrace(const std::string& name) : Trace(name) {} // Implementation of Tracer - virtual void Start() OVERRIDE {} - virtual void End() OVERRIDE {} + virtual void Start() OVERRIDE { + TRACE_EVENT_COPY_ASYNC_BEGIN0( + TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); + } + virtual void End() OVERRIDE { + TRACE_EVENT_COPY_ASYNC_END0( + TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); + } virtual bool IsAvailable() OVERRIDE { return true; } virtual bool IsProcessable() OVERRIDE { return false; } virtual void Process() OVERRIDE {} @@ -123,37 +74,57 @@ class NoopTrace : public Trace { DISALLOW_COPY_AND_ASSIGN(NoopTrace); }; +struct TraceMarker { + TraceMarker(const std::string& name, GpuTracerSource source) + : name_(name), source_(source) {} + + std::string name_; + GpuTracerSource source_; + scoped_refptr<Trace> trace_; +}; + class GPUTracerImpl : public GPUTracer, public base::SupportsWeakPtr<GPUTracerImpl> { public: GPUTracerImpl() - : gpu_category_enabled_( - TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("gpu")), - process_posted_(false) { - } + : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( + TRACE_DISABLED_BY_DEFAULT("gpu.service"))), + gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( + TRACE_DISABLED_BY_DEFAULT("gpu.device"))), + gpu_executing_(false), + process_posted_(false) {} virtual ~GPUTracerImpl() {} // Implementation of gpu::gles2::GPUTracer - virtual bool Begin(const std::string& name) OVERRIDE; - virtual bool End() OVERRIDE; + virtual bool BeginDecoding() OVERRIDE; + virtual bool EndDecoding() OVERRIDE; + virtual bool Begin(const std::string& name, GpuTracerSource source) OVERRIDE; + virtual bool End(GpuTracerSource source) OVERRIDE; virtual const std::string& CurrentName() const OVERRIDE; + virtual bool IsTracing() OVERRIDE { + return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); + } + virtual void CalculateTimerOffset() {} // Process any completed traces. virtual void Process(); + virtual void ProcessTraces(); protected: // Create a new trace. virtual scoped_refptr<Trace> CreateTrace(const std::string& name); - const unsigned char* gpu_category_enabled_; + const unsigned char* gpu_trace_srv_category; + const unsigned char* gpu_trace_dev_category; - private: + protected: void IssueProcessTask(); - scoped_refptr<Trace> current_trace_; + std::vector<TraceMarker> markers_; std::deque<scoped_refptr<Trace> > traces_; + bool gpu_executing_; bool process_posted_; DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl); @@ -161,28 +132,36 @@ class GPUTracerImpl class GPUTracerARBTimerQuery : public GPUTracerImpl { public: - GPUTracerARBTimerQuery(); + explicit GPUTracerARBTimerQuery(gles2::GLES2Decoder* decoder); virtual ~GPUTracerARBTimerQuery(); // Implementation of GPUTracerImpl - virtual void Process() OVERRIDE; + virtual void ProcessTraces() OVERRIDE; - private: + protected: // Implementation of GPUTracerImpl. + virtual bool BeginDecoding() OVERRIDE; + virtual bool EndDecoding() OVERRIDE; virtual scoped_refptr<Trace> CreateTrace(const std::string& name) OVERRIDE; - - void CalculateTimerOffset(); + virtual void CalculateTimerOffset() OVERRIDE; scoped_refptr<Outputter> outputter_; + bool gpu_timing_synced_; int64 timer_offset_; - int64 last_offset_check_; + + gles2::GLES2Decoder* decoder_; DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery); }; +bool Trace::IsProcessable() { return true; } + +const std::string& Trace::name() { return name_; } + GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> outputter, - const std::string& name, int64 offset) + const std::string& name, + int64 offset) : Trace(name), outputter_(outputter), offset_(offset), @@ -192,16 +171,19 @@ GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> outputter, glGenQueries(2, queries_); } -GLARBTimerTrace::~GLARBTimerTrace() { -} +GLARBTimerTrace::~GLARBTimerTrace() { glDeleteQueries(2, queries_); } void GLARBTimerTrace::Start() { + TRACE_EVENT_COPY_ASYNC_BEGIN0( + TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); glQueryCounter(queries_[0], GL_TIMESTAMP); } void GLARBTimerTrace::End() { glQueryCounter(queries_[1], GL_TIMESTAMP); end_requested_ = true; + TRACE_EVENT_COPY_ASYNC_END0( + TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); } bool GLARBTimerTrace::IsAvailable() { @@ -216,63 +198,116 @@ bool GLARBTimerTrace::IsAvailable() { void GLARBTimerTrace::Process() { DCHECK(IsAvailable()); - GLint64 timestamp; + GLuint64 timestamp; // TODO(dsinclair): It's possible for the timer to wrap during the start/end. // We need to detect if the end is less then the start and correct for the // wrapping. - glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, ×tamp); + glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, ×tamp); start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; - glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, ×tamp); + glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, ×tamp); end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; glDeleteQueries(2, queries_); + outputter_->Trace(name(), start_time_, end_time_); +} + +bool GPUTracerImpl::BeginDecoding() { + if (gpu_executing_) + return false; - TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(), - this, outputter_->Id(), start_time_); - TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(), - this, outputter_->Id(), end_time_); + gpu_executing_ = true; + + if (IsTracing()) { + // Begin a Trace for all active markers + for (size_t i = 0; i < markers_.size(); i++) { + markers_[i].trace_ = CreateTrace(markers_[i].name_); + markers_[i].trace_->Start(); + } + } + return true; } -bool GPUTracerImpl::Begin(const std::string& name) { - // Make sure we are not nesting trace commands. - if (current_trace_.get()) +bool GPUTracerImpl::EndDecoding() { + if (!gpu_executing_) return false; - current_trace_ = CreateTrace(name); - current_trace_->Start(); + // End Trace for all active markers + if (IsTracing()) { + for (size_t i = 0; i < markers_.size(); i++) { + if (markers_[i].trace_) { + markers_[i].trace_->End(); + if (markers_[i].trace_->IsProcessable()) + traces_.push_back(markers_[i].trace_); + markers_[i].trace_ = 0; + } + } + IssueProcessTask(); + } + + gpu_executing_ = false; return true; } -bool GPUTracerImpl::End() { - if (!current_trace_.get()) +bool GPUTracerImpl::Begin(const std::string& name, GpuTracerSource source) { + if (!gpu_executing_) return false; - current_trace_->End(); - if (current_trace_->IsProcessable()) - traces_.push_back(current_trace_); - current_trace_ = NULL; + // Push new marker from given 'source' + markers_.push_back(TraceMarker(name, source)); - IssueProcessTask(); + // Create trace + if (IsTracing()) { + scoped_refptr<Trace> trace = CreateTrace(name); + trace->Start(); + markers_.back().trace_ = trace; + } return true; } +bool GPUTracerImpl::End(GpuTracerSource source) { + if (!gpu_executing_) + return false; + + // Pop last marker with matching 'source' + for (int i = markers_.size() - 1; i >= 0; i--) { + if (markers_[i].source_ == source) { + // End trace + if (IsTracing()) { + scoped_refptr<Trace> trace = markers_[i].trace_; + if (trace) { + trace->End(); + if (trace->IsProcessable()) + traces_.push_back(trace); + IssueProcessTask(); + } + } + + markers_.erase(markers_.begin() + i); + return true; + } + } + return false; +} + void GPUTracerImpl::Process() { process_posted_ = false; + ProcessTraces(); + IssueProcessTask(); +} +void GPUTracerImpl::ProcessTraces() { while (!traces_.empty() && traces_.front()->IsAvailable()) { traces_.front()->Process(); traces_.pop_front(); } - - IssueProcessTask(); } const std::string& GPUTracerImpl::CurrentName() const { - if (!current_trace_.get()) + if (markers_.empty()) return base::EmptyString(); - return current_trace_->name(); + return markers_.back().name_; } scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) { @@ -290,12 +325,9 @@ void GPUTracerImpl::IssueProcessTask() { base::TimeDelta::FromMilliseconds(kProcessInterval)); } -GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() - : GPUTracerImpl(), - timer_offset_(0), - last_offset_check_(0) { - CalculateTimerOffset(); - outputter_ = Outputter::Create("GL_ARB_timer_query"); +GPUTracerARBTimerQuery::GPUTracerARBTimerQuery(gles2::GLES2Decoder* decoder) + : timer_offset_(0), decoder_(decoder) { + outputter_ = TraceOutputter::Create("GL_ARB_timer_query"); } GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() { @@ -303,43 +335,82 @@ GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() { scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace( const std::string& name) { - if (*gpu_category_enabled_) + if (*gpu_trace_dev_category) return new GLARBTimerTrace(outputter_, name, timer_offset_); return GPUTracerImpl::CreateTrace(name); } -void GPUTracerARBTimerQuery::Process() { - GPUTracerImpl::Process(); +bool GPUTracerARBTimerQuery::BeginDecoding() { + if (*gpu_trace_dev_category) { + // Make sure timing is synced before tracing + if (!gpu_timing_synced_) { + CalculateTimerOffset(); + gpu_timing_synced_ = true; + } + } else { + // If GPU device category is off, invalidate timing sync + gpu_timing_synced_ = false; + } - if (*gpu_category_enabled_ && - (last_offset_check_ + base::Time::kMicrosecondsPerSecond) < - base::TimeTicks::NowFromSystemTraceTime().ToInternalValue()) - CalculateTimerOffset(); + return GPUTracerImpl::BeginDecoding(); +} + +bool GPUTracerARBTimerQuery::EndDecoding() { + bool ret = GPUTracerImpl::EndDecoding(); + + // NOTE(vmiura_: glFlush() here can help give better trace results, + // but it distorts the normal device behavior. + return ret; +} + +void GPUTracerARBTimerQuery::ProcessTraces() { + TRACE_EVENT0("gpu", "GPUTracerARBTimerQuery::ProcessTraces"); + + // Make owning decoder's GL context current + if (!decoder_->MakeCurrent()) { + // Skip subsequent GL calls if MakeCurrent fails + traces_.clear(); + return; + } + + while (!traces_.empty() && traces_.front()->IsAvailable()) { + traces_.front()->Process(); + traces_.pop_front(); + } + + // Clear pending traces if there were are any errors + GLenum err = glGetError(); + if (err != GL_NO_ERROR) + traces_.clear(); } void GPUTracerARBTimerQuery::CalculateTimerOffset() { - TRACE_EVENT0("gpu", "CalculateTimerOffset"); - // TODO(dsinclair): Change to glGetInteger64v. + TRACE_EVENT0("gpu", "GPUTracerARBTimerQuery::CalculateTimerOffset"); + + // NOTE(vmiura): It would be better to use glGetInteger64v, however + // it's not available everywhere. GLuint64 gl_now = 0; GLuint query; + glFinish(); glGenQueries(1, &query); - glQueryCounter(query, GL_TIMESTAMP); + glFinish(); glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); gl_now /= base::Time::kNanosecondsPerMicrosecond; timer_offset_ = system_now.ToInternalValue() - gl_now; glDeleteQueries(1, &query); - - last_offset_check_ = system_now.ToInternalValue(); } -} // namespace +GPUTracer::GPUTracer() {} + +GPUTracer::~GPUTracer() {} -scoped_ptr<GPUTracer> GPUTracer::Create() { - if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) - return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery()); +scoped_ptr<GPUTracer> GPUTracer::Create(gles2::GLES2Decoder* decoder) { + if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { + return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery(decoder)); + } return scoped_ptr<GPUTracer>(new GPUTracerImpl()); } diff --git a/chromium/gpu/command_buffer/service/gpu_tracer.h b/chromium/gpu/command_buffer/service/gpu_tracer.h index f64455c0671..7daea897db6 100644 --- a/chromium/gpu/command_buffer/service/gpu_tracer.h +++ b/chromium/gpu/command_buffer/service/gpu_tracer.h @@ -10,23 +10,43 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/thread.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/gpu_export.h" +#include "ui/gl/gl_bindings.h" namespace gpu { namespace gles2 { +// Id used to keep trace namespaces separate +enum GpuTracerSource { + kTraceGroupMarker = 0, + kTraceCHROMIUM = 1, + kTraceDecoder = 2, +}; + // Traces GPU Commands. class GPUTracer { public: - static scoped_ptr<GPUTracer> Create(); + static scoped_ptr<GPUTracer> Create(gles2::GLES2Decoder* decoder); + + GPUTracer(); + virtual ~GPUTracer(); + + // Scheduled processing in decoder begins. + virtual bool BeginDecoding() = 0; + + // Scheduled processing in decoder ends. + virtual bool EndDecoding() = 0; - GPUTracer() {} - virtual ~GPUTracer() {} + // Begin a trace marker. + virtual bool Begin(const std::string& name, GpuTracerSource source) = 0; - // Begin a trace. - virtual bool Begin(const std::string& name) = 0; + // End the last started trace marker. + virtual bool End(GpuTracerSource source) = 0; - // End the last started trace. - virtual bool End() = 0; + virtual bool IsTracing() = 0; // Retrieve the name of the current open trace. // Returns empty string if no current open trace. @@ -36,6 +56,90 @@ class GPUTracer { DISALLOW_COPY_AND_ASSIGN(GPUTracer); }; +class Outputter : public base::RefCounted<Outputter> { + public: + virtual void Trace(const std::string& name, + int64 start_time, + int64 end_time) = 0; + + protected: + virtual ~Outputter() {} + friend class base::RefCounted<Outputter>; +}; + +class TraceOutputter : public Outputter { + public: + static scoped_refptr<TraceOutputter> Create(const std::string& name); + virtual void Trace(const std::string& name, + int64 start_time, + int64 end_time) OVERRIDE; + + protected: + friend class base::RefCounted<Outputter>; + explicit TraceOutputter(const std::string& name); + virtual ~TraceOutputter(); + + base::Thread named_thread_; + uint64 local_trace_id_; + + DISALLOW_COPY_AND_ASSIGN(TraceOutputter); +}; + +class GPU_EXPORT Trace : public base::RefCounted<Trace> { + public: + explicit Trace(const std::string& name) : name_(name) {} + + virtual void Start() = 0; + virtual void End() = 0; + + // True if the the results of this query are available. + virtual bool IsAvailable() = 0; + + virtual bool IsProcessable(); + virtual void Process() = 0; + + virtual const std::string& name(); + + protected: + virtual ~Trace() {} + + private: + friend class base::RefCounted<Trace>; + + std::string name_; + + DISALLOW_COPY_AND_ASSIGN(Trace); +}; + +class GPU_EXPORT GLARBTimerTrace : public Trace { + public: + GLARBTimerTrace(scoped_refptr<Outputter> outputter, + const std::string& name, + int64 offset); + + // Implementation of Tracer + virtual void Start() OVERRIDE; + virtual void End() OVERRIDE; + virtual bool IsAvailable() OVERRIDE; + virtual void Process() OVERRIDE; + + private: + virtual ~GLARBTimerTrace(); + + void Output(); + + scoped_refptr<Outputter> outputter_; + + int64 offset_; + int64 start_time_; + int64 end_time_; + bool end_requested_; + + GLuint queries_[2]; + + DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace); +}; + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc b/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc new file mode 100644 index 00000000000..735498c87e5 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_tracer_unittest.cc @@ -0,0 +1,209 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <map> +#include <set> + +#include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/gpu_tracer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_mock.h" + +namespace gpu { +namespace gles2 { + +using ::testing::InvokeWithoutArgs; +using ::testing::Return; +using ::testing::ReturnRef; +using ::testing::ReturnPointee; +using ::testing::NotNull; +using ::testing::ElementsAreArray; +using ::testing::ElementsAre; +using ::testing::SetArrayArgument; +using ::testing::AtLeast; +using ::testing::SetArgPointee; +using ::testing::Pointee; +using ::testing::Unused; +using ::testing::Invoke; +using ::testing::_; + +class MockOutputter : public Outputter { + public: + MockOutputter() {} + MOCK_METHOD3(Trace, + void(const std::string& name, int64 start_time, int64 end_time)); + + protected: + ~MockOutputter() {} +}; + +class GlFakeQueries { + public: + GlFakeQueries() {} + + void Reset() { + current_time_ = 0; + next_query_id_ = 23; + alloced_queries_.clear(); + query_timestamp_.clear(); + } + + void SetCurrentGLTime(GLint64 current_time) { current_time_ = current_time; } + + void GenQueries(GLsizei n, GLuint* ids) { + for (GLsizei i = 0; i < n; i++) { + ids[i] = next_query_id_++; + alloced_queries_.insert(ids[i]); + } + } + + void DeleteQueries(GLsizei n, const GLuint* ids) { + for (GLsizei i = 0; i < n; i++) { + alloced_queries_.erase(ids[i]); + query_timestamp_.erase(ids[i]); + } + } + + void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) { + switch (pname) { + case GL_QUERY_RESULT_AVAILABLE: { + std::map<GLuint, GLint64>::iterator it = query_timestamp_.find(id); + if (it != query_timestamp_.end() && it->second <= current_time_) + *params = 1; + else + *params = 0; + break; + } + default: + ASSERT_TRUE(false); + } + } + + void QueryCounter(GLuint id, GLenum target) { + switch (target) { + case GL_TIMESTAMP: + ASSERT_TRUE(alloced_queries_.find(id) != alloced_queries_.end()); + query_timestamp_[id] = current_time_; + break; + default: + ASSERT_TRUE(false); + } + } + + void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) { + switch (pname) { + case GL_QUERY_RESULT: + ASSERT_TRUE(query_timestamp_.find(id) != query_timestamp_.end()); + *params = query_timestamp_.find(id)->second; + break; + default: + ASSERT_TRUE(false); + } + } + + protected: + GLint64 current_time_; + GLuint next_query_id_; + std::set<GLuint> alloced_queries_; + std::map<GLuint, GLint64> query_timestamp_; +}; + +class GpuTracerTest : public GpuServiceTest { + public: + GpuTracerTest() {} + + /////////////////////////////////////////////////////////////////////////// + + protected: + virtual void SetUp() { + GpuServiceTest::SetUp(); + gl_fake_queries_.Reset(); + } + + virtual void TearDown() { + gl_.reset(); + gl_fake_queries_.Reset(); + GpuServiceTest::TearDown(); + } + + void SetupTimerQueryMocks() { + // Delegate query APIs used by GLARBTimerTrace to a GlFakeQueries + EXPECT_CALL(*gl_, GenQueries(_, NotNull())).Times(AtLeast(1)).WillOnce( + Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueries)); + + EXPECT_CALL(*gl_, GetQueryObjectiv(_, GL_QUERY_RESULT_AVAILABLE, NotNull())) + .Times(AtLeast(2)) + .WillRepeatedly( + Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectiv)); + + EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP)) + .Times(AtLeast(2)) + .WillRepeatedly( + Invoke(&gl_fake_queries_, &GlFakeQueries::QueryCounter)); + + EXPECT_CALL(*gl_, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull())) + .Times(AtLeast(2)) + .WillRepeatedly( + Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectui64v)); + + EXPECT_CALL(*gl_, DeleteQueries(2, NotNull())) + .Times(AtLeast(1)) + .WillRepeatedly( + Invoke(&gl_fake_queries_, &GlFakeQueries::DeleteQueries)); + } + + GlFakeQueries gl_fake_queries_; +}; + +TEST_F(GpuTracerTest, GLARBTimerTrace) { + // Test basic timer query functionality + { + MockOutputter* outputter = new MockOutputter(); + scoped_refptr<Outputter> outputter_ref = outputter; + + SetupTimerQueryMocks(); + + // Expected results + const std::string trace_name("trace_test"); + const int64 offset_time = 3231; + const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond; + const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond; + const int64 expect_start_time = + (start_timestamp / base::Time::kNanosecondsPerMicrosecond) + + offset_time; + const int64 expect_end_time = + (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time; + + // Expected Outputter::Trace call + EXPECT_CALL(*outputter, + Trace(trace_name, expect_start_time, expect_end_time)); + + scoped_refptr<GLARBTimerTrace> trace = + new GLARBTimerTrace(outputter_ref, trace_name, offset_time); + + gl_fake_queries_.SetCurrentGLTime(start_timestamp); + trace->Start(); + + // Shouldn't be available before End() call + gl_fake_queries_.SetCurrentGLTime(end_timestamp); + EXPECT_FALSE(trace->IsAvailable()); + + trace->End(); + + // Shouldn't be available until the queries complete + gl_fake_queries_.SetCurrentGLTime(end_timestamp - + base::Time::kNanosecondsPerMicrosecond); + EXPECT_FALSE(trace->IsAvailable()); + + // Now it should be available + gl_fake_queries_.SetCurrentGLTime(end_timestamp); + EXPECT_TRUE(trace->IsAvailable()); + + // Proces should output expected Trace results to MockOutputter + trace->Process(); + } +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/image_manager.cc b/chromium/gpu/command_buffer/service/image_manager.cc index f39eba21c8a..a3ac4350c87 100644 --- a/chromium/gpu/command_buffer/service/image_manager.cc +++ b/chromium/gpu/command_buffer/service/image_manager.cc @@ -15,19 +15,19 @@ ImageManager::ImageManager() : release_after_use_(false) { ImageManager::~ImageManager() { } -bool ImageManager::RegisterGpuMemoryBuffer(int32 id, +void ImageManager::RegisterGpuMemoryBuffer(int32 id, gfx::GpuMemoryBufferHandle buffer, size_t width, size_t height, unsigned internalformat) { if (id <= 0) { DVLOG(0) << "Cannot register GPU memory buffer with non-positive ID."; - return false; + return; } if (LookupImage(id)) { DVLOG(0) << "GPU memory buffer ID already in use."; - return false; + return; } scoped_refptr<gfx::GLImage> gl_image = @@ -35,16 +35,15 @@ bool ImageManager::RegisterGpuMemoryBuffer(int32 id, gfx::Size(width, height), internalformat); if (!gl_image) - return false; + return; if (release_after_use_) gl_image->SetReleaseAfterUse(); AddImage(gl_image.get(), id); - return true; } -void ImageManager::DestroyGpuMemoryBuffer(int32 id) { +void ImageManager::UnregisterGpuMemoryBuffer(int32 id) { RemoveImage(id); } diff --git a/chromium/gpu/command_buffer/service/image_manager.h b/chromium/gpu/command_buffer/service/image_manager.h index 51e006d7836..95d836f232e 100644 --- a/chromium/gpu/command_buffer/service/image_manager.h +++ b/chromium/gpu/command_buffer/service/image_manager.h @@ -26,12 +26,12 @@ class GPU_EXPORT ImageManager ImageManager(); // Overridden from GpuMemoryBufferManagerInterface: - virtual bool RegisterGpuMemoryBuffer(int32 id, + virtual void RegisterGpuMemoryBuffer(int32 id, gfx::GpuMemoryBufferHandle buffer, size_t width, size_t height, unsigned internalformat) OVERRIDE; - virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE; + virtual void UnregisterGpuMemoryBuffer(int32 id) OVERRIDE; void AddImage(gfx::GLImage* gl_image, int32 service_id); void RemoveImage(int32 service_id); diff --git a/chromium/gpu/command_buffer/service/in_process_command_buffer.cc b/chromium/gpu/command_buffer/service/in_process_command_buffer.cc index af14778de27..b1e59a85d3f 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.cc @@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/in_process_command_buffer.h" #include <queue> +#include <set> #include <utility> #include <GLES2/gl2.h> @@ -21,13 +22,16 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop_proxy.h" #include "base/sequence_checker.h" +#include "base/synchronization/condition_variable.h" #include "base/threading/thread.h" +#include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/gpu_control_service.h" #include "gpu/command_buffer/service/gpu_scheduler.h" #include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" #include "ui/gfx/size.h" #include "ui/gl/gl_context.h" @@ -43,11 +47,6 @@ namespace gpu { namespace { -static base::LazyInstance<std::set<InProcessCommandBuffer*> > - g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER; - -static bool g_use_virtualized_gl_context = false; -static bool g_uses_explicit_scheduling = false; static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; template <typename T> @@ -60,14 +59,29 @@ static void RunTaskWithResult(base::Callback<T(void)> task, class GpuInProcessThread : public base::Thread, + public InProcessCommandBuffer::Service, public base::RefCountedThreadSafe<GpuInProcessThread> { public: GpuInProcessThread(); + virtual void AddRef() const OVERRIDE { + base::RefCountedThreadSafe<GpuInProcessThread>::AddRef(); + } + virtual void Release() const OVERRIDE { + base::RefCountedThreadSafe<GpuInProcessThread>::Release(); + } + + virtual void ScheduleTask(const base::Closure& task) OVERRIDE; + virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE; + virtual bool UseVirtualizedGLContexts() OVERRIDE { return false; } + virtual scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache() + OVERRIDE; + private: - friend class base::RefCountedThreadSafe<GpuInProcessThread>; virtual ~GpuInProcessThread(); + friend class base::RefCountedThreadSafe<GpuInProcessThread>; + scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_; DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread); }; @@ -79,195 +93,134 @@ GpuInProcessThread::~GpuInProcessThread() { Stop(); } -// Used with explicit scheduling when there is no dedicated GPU thread. -class GpuCommandQueue { - public: - GpuCommandQueue(); - ~GpuCommandQueue(); - - void QueueTask(const base::Closure& task); - void RunTasks(); - void SetScheduleCallback(const base::Closure& callback); - - private: - base::Lock tasks_lock_; - std::queue<base::Closure> tasks_; - base::Closure schedule_callback_; - - DISALLOW_COPY_AND_ASSIGN(GpuCommandQueue); -}; - -GpuCommandQueue::GpuCommandQueue() {} - -GpuCommandQueue::~GpuCommandQueue() { - base::AutoLock lock(tasks_lock_); - DCHECK(tasks_.empty()); +void GpuInProcessThread::ScheduleTask(const base::Closure& task) { + message_loop()->PostTask(FROM_HERE, task); } -void GpuCommandQueue::QueueTask(const base::Closure& task) { - { - base::AutoLock lock(tasks_lock_); - tasks_.push(task); - } - - DCHECK(!schedule_callback_.is_null()); - schedule_callback_.Run(); -} - -void GpuCommandQueue::RunTasks() { - size_t num_tasks; - { - base::AutoLock lock(tasks_lock_); - num_tasks = tasks_.size(); - } - - while (num_tasks) { - base::Closure task; - { - base::AutoLock lock(tasks_lock_); - task = tasks_.front(); - tasks_.pop(); - num_tasks = tasks_.size(); - } - - task.Run(); - } +void GpuInProcessThread::ScheduleIdleWork(const base::Closure& callback) { + message_loop()->PostDelayedTask( + FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5)); } -void GpuCommandQueue::SetScheduleCallback(const base::Closure& callback) { - DCHECK(schedule_callback_.is_null()); - schedule_callback_ = callback; +scoped_refptr<gles2::ShaderTranslatorCache> +GpuInProcessThread::shader_translator_cache() { + if (!shader_translator_cache_.get()) + shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache; + return shader_translator_cache_; } -static base::LazyInstance<GpuCommandQueue> g_gpu_queue = +base::LazyInstance<std::set<InProcessCommandBuffer*> > default_thread_clients_ = + LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<base::Lock> default_thread_clients_lock_ = LAZY_INSTANCE_INITIALIZER; -class SchedulerClientBase : public InProcessCommandBuffer::SchedulerClient { +class ScopedEvent { public: - explicit SchedulerClientBase(bool need_thread); - virtual ~SchedulerClientBase(); - - static bool HasClients(); - - protected: - scoped_refptr<GpuInProcessThread> thread_; + ScopedEvent(base::WaitableEvent* event) : event_(event) {} + ~ScopedEvent() { event_->Signal(); } private: - static base::LazyInstance<std::set<SchedulerClientBase*> > all_clients_; - static base::LazyInstance<base::Lock> all_clients_lock_; + base::WaitableEvent* event_; }; -base::LazyInstance<std::set<SchedulerClientBase*> > - SchedulerClientBase::all_clients_ = LAZY_INSTANCE_INITIALIZER; -base::LazyInstance<base::Lock> SchedulerClientBase::all_clients_lock_ = - LAZY_INSTANCE_INITIALIZER; - -SchedulerClientBase::SchedulerClientBase(bool need_thread) { - base::AutoLock lock(all_clients_lock_.Get()); - if (need_thread) { - if (!all_clients_.Get().empty()) { - SchedulerClientBase* other = *all_clients_.Get().begin(); - thread_ = other->thread_; - DCHECK(thread_.get()); - } else { - thread_ = new GpuInProcessThread; - } - } - all_clients_.Get().insert(this); -} - -SchedulerClientBase::~SchedulerClientBase() { - base::AutoLock lock(all_clients_lock_.Get()); - all_clients_.Get().erase(this); -} - -bool SchedulerClientBase::HasClients() { - base::AutoLock lock(all_clients_lock_.Get()); - return !all_clients_.Get().empty(); -} - -// A client that talks to the GPU thread -class ThreadClient : public SchedulerClientBase { +class SyncPointManager { public: - ThreadClient(); - virtual void QueueTask(const base::Closure& task) OVERRIDE; - virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE; + SyncPointManager(); + ~SyncPointManager(); + + uint32 GenerateSyncPoint(); + void RetireSyncPoint(uint32 sync_point); + + bool IsSyncPointPassed(uint32 sync_point); + void WaitSyncPoint(uint32 sync_point); + +private: + // This lock protects access to pending_sync_points_ and next_sync_point_ and + // is used with the ConditionVariable to signal when a sync point is retired. + base::Lock lock_; + std::set<uint32> pending_sync_points_; + uint32 next_sync_point_; + base::ConditionVariable cond_var_; }; -ThreadClient::ThreadClient() : SchedulerClientBase(true) { - DCHECK(thread_.get()); -} +SyncPointManager::SyncPointManager() : next_sync_point_(1), cond_var_(&lock_) {} -void ThreadClient::QueueTask(const base::Closure& task) { - thread_->message_loop()->PostTask(FROM_HERE, task); +SyncPointManager::~SyncPointManager() { + DCHECK_EQ(pending_sync_points_.size(), 0U); } -void ThreadClient::ScheduleIdleWork(const base::Closure& callback) { - thread_->message_loop()->PostDelayedTask( - FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5)); +uint32 SyncPointManager::GenerateSyncPoint() { + base::AutoLock lock(lock_); + uint32 sync_point = next_sync_point_++; + DCHECK_EQ(pending_sync_points_.count(sync_point), 0U); + pending_sync_points_.insert(sync_point); + return sync_point; } -// A client that talks to the GpuCommandQueue -class QueueClient : public SchedulerClientBase { - public: - QueueClient(); - virtual void QueueTask(const base::Closure& task) OVERRIDE; - virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE; -}; - -QueueClient::QueueClient() : SchedulerClientBase(false) { - DCHECK(!thread_.get()); +void SyncPointManager::RetireSyncPoint(uint32 sync_point) { + base::AutoLock lock(lock_); + DCHECK(pending_sync_points_.count(sync_point)); + pending_sync_points_.erase(sync_point); + cond_var_.Broadcast(); } -void QueueClient::QueueTask(const base::Closure& task) { - g_gpu_queue.Get().QueueTask(task); +bool SyncPointManager::IsSyncPointPassed(uint32 sync_point) { + base::AutoLock lock(lock_); + return pending_sync_points_.count(sync_point) == 0; } -void QueueClient::ScheduleIdleWork(const base::Closure& callback) { - // TODO(sievers): Should this do anything? +void SyncPointManager::WaitSyncPoint(uint32 sync_point) { + base::AutoLock lock(lock_); + while (pending_sync_points_.count(sync_point)) { + cond_var_.Wait(); + } } -static scoped_ptr<InProcessCommandBuffer::SchedulerClient> -CreateSchedulerClient() { - scoped_ptr<InProcessCommandBuffer::SchedulerClient> client; - if (g_uses_explicit_scheduling) - client.reset(new QueueClient); - else - client.reset(new ThreadClient); +base::LazyInstance<SyncPointManager> g_sync_point_manager = + LAZY_INSTANCE_INITIALIZER; - return client.Pass(); +bool WaitSyncPoint(uint32 sync_point) { + g_sync_point_manager.Get().WaitSyncPoint(sync_point); + return true; } -class ScopedEvent { - public: - ScopedEvent(base::WaitableEvent* event) : event_(event) {} - ~ScopedEvent() { event_->Signal(); } +} // anonyous namespace - private: - base::WaitableEvent* event_; -}; +InProcessCommandBuffer::Service::Service() {} -} // anonyous namespace +InProcessCommandBuffer::Service::~Service() {} -InProcessCommandBuffer::InProcessCommandBuffer() +scoped_refptr<InProcessCommandBuffer::Service> +InProcessCommandBuffer::GetDefaultService() { + base::AutoLock lock(default_thread_clients_lock_.Get()); + scoped_refptr<Service> service; + if (!default_thread_clients_.Get().empty()) { + InProcessCommandBuffer* other = *default_thread_clients_.Get().begin(); + service = other->service_; + DCHECK(service.get()); + } else { + service = new GpuInProcessThread; + } + return service; +} + +InProcessCommandBuffer::InProcessCommandBuffer( + const scoped_refptr<Service>& service) : context_lost_(false), - share_group_id_(0), last_put_offset_(-1), flush_event_(false, false), - queue_(CreateSchedulerClient()), - gpu_thread_weak_ptr_factory_(this) {} + service_(service.get() ? service : GetDefaultService()), + gpu_thread_weak_ptr_factory_(this) { + if (!service) { + base::AutoLock lock(default_thread_clients_lock_.Get()); + default_thread_clients_.Get().insert(this); + } +} InProcessCommandBuffer::~InProcessCommandBuffer() { Destroy(); -} - -bool InProcessCommandBuffer::IsContextLost() { - CheckSequencedThread(); - if (context_lost_ || !command_buffer_) { - return true; - } - CommandBuffer::State state = GetState(); - return error::IsError(state.error); + base::AutoLock lock(default_thread_clients_lock_.Get()); + default_thread_clients_.Get().erase(this); } void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) { @@ -308,17 +261,14 @@ bool InProcessCommandBuffer::GetBufferChanged(int32 transfer_buffer_id) { bool InProcessCommandBuffer::Initialize( scoped_refptr<gfx::GLSurface> surface, bool is_offscreen, - bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference, const base::Closure& context_lost_callback, - unsigned int share_group_id) { - - share_resources_ = share_resources; + InProcessCommandBuffer* share_group) { + DCHECK(!share_group || service_ == share_group->service_); context_lost_callback_ = WrapCallback(context_lost_callback); - share_group_id_ = share_group_id; if (surface) { // GPU thread must be the same as client thread due to GLSurface not being @@ -328,8 +278,13 @@ bool InProcessCommandBuffer::Initialize( } gpu::Capabilities capabilities; - InitializeOnGpuThreadParams params( - is_offscreen, window, size, attribs, gpu_preference, &capabilities); + InitializeOnGpuThreadParams params(is_offscreen, + window, + size, + attribs, + gpu_preference, + &capabilities, + share_group); base::Callback<bool(void)> init_task = base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread, @@ -342,8 +297,11 @@ bool InProcessCommandBuffer::Initialize( base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion)); completion.Wait(); - if (result) + if (result) { capabilities_ = capabilities; + capabilities_.map_image = + capabilities_.map_image && g_gpu_memory_buffer_factory; + } return result; } @@ -351,9 +309,6 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( const InitializeOnGpuThreadParams& params) { CheckSequencedThread(); gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr(); - // Use one share group for all contexts. - CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, - (new gfx::GLShareGroup)); DCHECK(params.size.width() >= 0 && params.size.height() >= 0); @@ -374,41 +329,24 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( return false; } - InProcessCommandBuffer* context_group = NULL; - - if (share_resources_ && !g_all_shared_contexts.Get().empty()) { - DCHECK(share_group_id_); - for (std::set<InProcessCommandBuffer*>::iterator it = - g_all_shared_contexts.Get().begin(); - it != g_all_shared_contexts.Get().end(); - ++it) { - if ((*it)->share_group_id_ == share_group_id_) { - context_group = *it; - DCHECK(context_group->share_resources_); - context_lost_ = context_group->IsContextLost(); - break; - } - } - if (!context_group) - share_group = new gfx::GLShareGroup; - } + gl_share_group_ = params.context_group + ? params.context_group->gl_share_group_.get() + : new gfx::GLShareGroup; - StreamTextureManager* stream_texture_manager = NULL; #if defined(OS_ANDROID) - stream_texture_manager = stream_texture_manager_ = - context_group ? context_group->stream_texture_manager_.get() - : new StreamTextureManagerInProcess; + stream_texture_manager_.reset(new StreamTextureManagerInProcess); #endif bool bind_generates_resource = false; decoder_.reset(gles2::GLES2Decoder::Create( - context_group ? context_group->decoder_->GetContextGroup() - : new gles2::ContextGroup(NULL, - NULL, - NULL, - stream_texture_manager, - NULL, - bind_generates_resource))); + params.context_group + ? params.context_group->decoder_->GetContextGroup() + : new gles2::ContextGroup(NULL, + NULL, + NULL, + service_->shader_translator_cache(), + NULL, + bind_generates_resource))); gpu_scheduler_.reset( new GpuScheduler(command_buffer.get(), decoder_.get(), decoder_.get())); @@ -431,16 +369,16 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( return false; } - if (g_use_virtualized_gl_context) { - context_ = share_group->GetSharedContext(); + if (service_->UseVirtualizedGLContexts()) { + context_ = gl_share_group_->GetSharedContext(); if (!context_.get()) { context_ = gfx::GLContext::CreateGLContext( - share_group.get(), surface_.get(), params.gpu_preference); - share_group->SetSharedContext(context_.get()); + gl_share_group_.get(), surface_.get(), params.gpu_preference); + gl_share_group_->SetSharedContext(context_.get()); } context_ = new GLContextVirtual( - share_group.get(), context_.get(), decoder_->AsWeakPtr()); + gl_share_group_.get(), context_.get(), decoder_->AsWeakPtr()); if (context_->Initialize(surface_.get(), params.gpu_preference)) { VLOG(1) << "Created virtual GL context."; } else { @@ -448,7 +386,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( } } else { context_ = gfx::GLContext::CreateGLContext( - share_group.get(), surface_.get(), params.gpu_preference); + gl_share_group_.get(), surface_.get(), params.gpu_preference); } if (!context_.get()) { @@ -475,24 +413,17 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( DestroyOnGpuThread(); return false; } + *params.capabilities = decoder_->GetCapabilities(); gpu_control_.reset( new GpuControlService(decoder_->GetContextGroup()->image_manager(), - g_gpu_memory_buffer_factory, - decoder_->GetContextGroup()->mailbox_manager(), - decoder_->GetQueryManager(), - decoder_->GetCapabilities())); - - *params.capabilities = gpu_control_->GetCapabilities(); + decoder_->GetQueryManager())); if (!params.is_offscreen) { decoder_->SetResizeCallback(base::Bind( &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_)); } - - if (share_resources_) { - g_all_shared_contexts.Pointer()->insert(this); - } + decoder_->SetWaitSyncPointCallback(base::Bind(&WaitSyncPoint)); return true; } @@ -521,8 +452,11 @@ bool InProcessCommandBuffer::DestroyOnGpuThread() { } context_ = NULL; surface_ = NULL; + gl_share_group_ = NULL; +#if defined(OS_ANDROID) + stream_texture_manager_.reset(); +#endif - g_all_shared_contexts.Pointer()->erase(this); return true; } @@ -539,14 +473,6 @@ void InProcessCommandBuffer::OnContextLost() { } context_lost_ = true; - if (share_resources_) { - for (std::set<InProcessCommandBuffer*>::iterator it = - g_all_shared_contexts.Get().begin(); - it != g_all_shared_contexts.Get().end(); - ++it) { - (*it)->context_lost_ = true; - } - } } CommandBuffer::State InProcessCommandBuffer::GetStateFast() { @@ -557,11 +483,6 @@ CommandBuffer::State InProcessCommandBuffer::GetStateFast() { return last_state_; } -CommandBuffer::State InProcessCommandBuffer::GetState() { - CheckSequencedThread(); - return GetStateFast(); -} - CommandBuffer::State InProcessCommandBuffer::GetLastState() { CheckSequencedThread(); return last_state_; @@ -581,7 +502,7 @@ void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) { { // Update state before signaling the flush event. base::AutoLock lock(state_after_last_flush_lock_); - state_after_last_flush_ = command_buffer_->GetState(); + state_after_last_flush_ = command_buffer_->GetLastState(); } DCHECK((!error::IsError(state_after_last_flush_.error) && !context_lost_) || (error::IsError(state_after_last_flush_.error) && context_lost_)); @@ -590,7 +511,7 @@ void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) { // pump idle work until the query is passed. if (put_offset == state_after_last_flush_.get_offset && gpu_scheduler_->HasMoreWork()) { - queue_->ScheduleIdleWork( + service_->ScheduleIdleWork( base::Bind(&InProcessCommandBuffer::ScheduleMoreIdleWork, gpu_thread_weak_ptr_)); } @@ -601,7 +522,7 @@ void InProcessCommandBuffer::ScheduleMoreIdleWork() { base::AutoLock lock(command_buffer_lock_); if (gpu_scheduler_->HasMoreWork()) { gpu_scheduler_->PerformIdleWork(); - queue_->ScheduleIdleWork( + service_->ScheduleIdleWork( base::Bind(&InProcessCommandBuffer::ScheduleMoreIdleWork, gpu_thread_weak_ptr_)); } @@ -622,21 +543,22 @@ void InProcessCommandBuffer::Flush(int32 put_offset) { QueueTask(task); } -CommandBuffer::State InProcessCommandBuffer::FlushSync(int32 put_offset, - int32 last_known_get) { +void InProcessCommandBuffer::WaitForTokenInRange(int32 start, int32 end) { + CheckSequencedThread(); + while (!InRange(start, end, GetLastToken()) && + last_state_.error == gpu::error::kNoError) + flush_event_.Wait(); +} + +void InProcessCommandBuffer::WaitForGetOffsetInRange(int32 start, int32 end) { CheckSequencedThread(); - if (put_offset == last_known_get || last_state_.error != gpu::error::kNoError) - return last_state_; - Flush(put_offset); GetStateFast(); - while (last_known_get == last_state_.get_offset && + while (!InRange(start, end, last_state_.get_offset) && last_state_.error == gpu::error::kNoError) { flush_event_.Wait(); GetStateFast(); } - - return last_state_; } void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) { @@ -651,12 +573,12 @@ void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) { } { base::AutoLock lock(state_after_last_flush_lock_); - state_after_last_flush_ = command_buffer_->GetState(); + state_after_last_flush_ = command_buffer_->GetLastState(); } } -gpu::Buffer InProcessCommandBuffer::CreateTransferBuffer(size_t size, - int32* id) { +scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer(size_t size, + int32* id) { CheckSequencedThread(); base::AutoLock lock(command_buffer_lock_); return command_buffer_->CreateTransferBuffer(size, id); @@ -664,16 +586,17 @@ gpu::Buffer InProcessCommandBuffer::CreateTransferBuffer(size_t size, void InProcessCommandBuffer::DestroyTransferBuffer(int32 id) { CheckSequencedThread(); - base::Closure task = base::Bind(&CommandBuffer::DestroyTransferBuffer, - base::Unretained(command_buffer_.get()), - id); + base::Closure task = + base::Bind(&InProcessCommandBuffer::DestroyTransferBufferOnGputhread, + base::Unretained(this), + id); QueueTask(task); } -gpu::Buffer InProcessCommandBuffer::GetTransferBuffer(int32 id) { - NOTREACHED(); - return gpu::Buffer(); +void InProcessCommandBuffer::DestroyTransferBufferOnGputhread(int32 id) { + base::AutoLock lock(command_buffer_lock_); + command_buffer_->DestroyTransferBuffer(id); } gpu::Capabilities InProcessCommandBuffer::GetCapabilities() { @@ -684,45 +607,96 @@ gfx::GpuMemoryBuffer* InProcessCommandBuffer::CreateGpuMemoryBuffer( size_t width, size_t height, unsigned internalformat, + unsigned usage, int32* id) { CheckSequencedThread(); - base::AutoLock lock(command_buffer_lock_); - return gpu_control_->CreateGpuMemoryBuffer(width, - height, - internalformat, - id); + + *id = -1; + linked_ptr<gfx::GpuMemoryBuffer> buffer = + make_linked_ptr(g_gpu_memory_buffer_factory->CreateGpuMemoryBuffer( + width, height, internalformat, usage)); + if (!buffer.get()) + return NULL; + + static int32 next_id = 1; + *id = next_id++; + + base::Closure task = base::Bind(&GpuControlService::RegisterGpuMemoryBuffer, + base::Unretained(gpu_control_.get()), + *id, + buffer->GetHandle(), + width, + height, + internalformat); + + QueueTask(task); + + gpu_memory_buffers_[*id] = buffer; + return buffer.get(); } void InProcessCommandBuffer::DestroyGpuMemoryBuffer(int32 id) { CheckSequencedThread(); - base::Closure task = base::Bind(&GpuControl::DestroyGpuMemoryBuffer, + GpuMemoryBufferMap::iterator it = gpu_memory_buffers_.find(id); + if (it != gpu_memory_buffers_.end()) + gpu_memory_buffers_.erase(it); + base::Closure task = base::Bind(&GpuControlService::UnregisterGpuMemoryBuffer, base::Unretained(gpu_control_.get()), id); QueueTask(task); } -bool InProcessCommandBuffer::GenerateMailboxNames( - unsigned num, std::vector<gpu::Mailbox>* names) { - CheckSequencedThread(); - base::AutoLock lock(command_buffer_lock_); - return gpu_control_->GenerateMailboxNames(num, names); -} - uint32 InProcessCommandBuffer::InsertSyncPoint() { - return 0; + uint32 sync_point = g_sync_point_manager.Get().GenerateSyncPoint(); + QueueTask(base::Bind(&InProcessCommandBuffer::RetireSyncPointOnGpuThread, + base::Unretained(this), + sync_point)); + return sync_point; +} + +void InProcessCommandBuffer::RetireSyncPointOnGpuThread(uint32 sync_point) { + gles2::MailboxManager* mailbox_manager = + decoder_->GetContextGroup()->mailbox_manager(); + if (mailbox_manager->UsesSync()) { + bool make_current_success = false; + { + base::AutoLock lock(command_buffer_lock_); + make_current_success = MakeCurrent(); + } + if (make_current_success) + mailbox_manager->PushTextureUpdates(); + } + g_sync_point_manager.Get().RetireSyncPoint(sync_point); } void InProcessCommandBuffer::SignalSyncPoint(unsigned sync_point, const base::Closure& callback) { CheckSequencedThread(); - QueueTask(WrapCallback(callback)); + QueueTask(base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread, + base::Unretained(this), + sync_point, + WrapCallback(callback))); +} + +void InProcessCommandBuffer::SignalSyncPointOnGpuThread( + unsigned sync_point, + const base::Closure& callback) { + if (g_sync_point_manager.Get().IsSyncPointPassed(sync_point)) { + callback.Run(); + } else { + service_->ScheduleIdleWork( + base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread, + gpu_thread_weak_ptr_, + sync_point, + callback)); + } } void InProcessCommandBuffer::SignalQuery(unsigned query, const base::Closure& callback) { CheckSequencedThread(); - QueueTask(base::Bind(&GpuControl::SignalQuery, + QueueTask(base::Bind(&GpuControlService::SignalQuery, base::Unretained(gpu_control_.get()), query, WrapCallback(callback))); @@ -730,14 +704,33 @@ void InProcessCommandBuffer::SignalQuery(unsigned query, void InProcessCommandBuffer::SetSurfaceVisible(bool visible) {} -void InProcessCommandBuffer::SendManagedMemoryStats( - const gpu::ManagedMemoryStats& stats) { -} - void InProcessCommandBuffer::Echo(const base::Closure& callback) { QueueTask(WrapCallback(callback)); } +uint32 InProcessCommandBuffer::CreateStreamTexture(uint32 texture_id) { + base::WaitableEvent completion(true, false); + uint32 stream_id = 0; + base::Callback<uint32(void)> task = + base::Bind(&InProcessCommandBuffer::CreateStreamTextureOnGpuThread, + base::Unretained(this), + texture_id); + QueueTask( + base::Bind(&RunTaskWithResult<uint32>, task, &stream_id, &completion)); + completion.Wait(); + return stream_id; +} + +uint32 InProcessCommandBuffer::CreateStreamTextureOnGpuThread( + uint32 client_texture_id) { +#if defined(OS_ANDROID) + return stream_texture_manager_->CreateStreamTexture( + client_texture_id, decoder_->GetContextGroup()->texture_manager()); +#else + return 0; +#endif +} + gpu::error::Error InProcessCommandBuffer::GetLastError() { CheckSequencedThread(); return last_state_.error; @@ -748,19 +741,6 @@ bool InProcessCommandBuffer::Initialize() { return false; } -void InProcessCommandBuffer::SetGetOffset(int32 get_offset) { NOTREACHED(); } - -void InProcessCommandBuffer::SetToken(int32 token) { NOTREACHED(); } - -void InProcessCommandBuffer::SetParseError(gpu::error::Error error) { - NOTREACHED(); -} - -void InProcessCommandBuffer::SetContextLostReason( - gpu::error::ContextLostReason reason) { - NOTREACHED(); -} - namespace { void PostCallback(const scoped_refptr<base::MessageLoopProxy>& loop, @@ -801,25 +781,6 @@ InProcessCommandBuffer::GetSurfaceTexture(uint32 stream_id) { #endif // static -void InProcessCommandBuffer::EnableVirtualizedContext() { - g_use_virtualized_gl_context = true; -} - -// static -void InProcessCommandBuffer::SetScheduleCallback( - const base::Closure& callback) { - DCHECK(!g_uses_explicit_scheduling); - DCHECK(!SchedulerClientBase::HasClients()); - g_uses_explicit_scheduling = true; - g_gpu_queue.Get().SetScheduleCallback(callback); -} - -// static -void InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread() { - g_gpu_queue.Get().RunTasks(); -} - -// static void InProcessCommandBuffer::SetGpuMemoryBufferFactory( GpuMemoryBufferFactory* factory) { g_gpu_memory_buffer_factory = factory; diff --git a/chromium/gpu/command_buffer/service/in_process_command_buffer.h b/chromium/gpu/command_buffer/service/in_process_command_buffer.h index b00f25be97e..f8986d81ab0 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.h +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.h @@ -5,17 +5,19 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_IN_PROCESS_COMMAND_BUFFER_H_ #define GPU_COMMAND_BUFFER_SERVICE_IN_PROCESS_COMMAND_BUFFER_H_ +#include <map> #include <vector> #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" +#include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" -#include "gpu/command_buffer/common/gpu_control.h" #include "gpu/gpu_export.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/native_widget_types.h" @@ -28,6 +30,7 @@ class SequenceChecker; namespace gfx { class GLContext; +class GLShareGroup; class GLSurface; class Size; } @@ -45,8 +48,11 @@ namespace gpu { namespace gles2 { class GLES2Decoder; +class ShaderTranslatorCache; } +class CommandBufferServiceBase; +class GpuControlService; class GpuMemoryBufferFactory; class GpuScheduler; class TransferBufferManagerInterface; @@ -58,21 +64,10 @@ class TransferBufferManagerInterface; class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, public GpuControl { public: - InProcessCommandBuffer(); + class Service; + explicit InProcessCommandBuffer(const scoped_refptr<Service>& service); virtual ~InProcessCommandBuffer(); - // Used to override the GPU thread with explicit scheduling. - // (By default an internal GPU thread will be spawned to handle all GL work - // and the two functions are unused.) - // The callback will be called from different client threads. After the - // callback is issued, the client is expected to eventually call - // ProcessGpuWorkOnCurrentThread(). The latter cannot be called from different - // threads. - // The callback needs to be set before any context is created. - static void SetScheduleCallback(const base::Closure& callback); - static void ProcessGpuWorkOnCurrentThread(); - - static void EnableVirtualizedContext(); static void SetGpuMemoryBufferFactory(GpuMemoryBufferFactory* factory); // If |surface| is not NULL, use it directly; in this case, the command @@ -80,64 +75,63 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, // a new GLSurface. bool Initialize(scoped_refptr<gfx::GLSurface> surface, bool is_offscreen, - bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference, const base::Closure& context_lost_callback, - unsigned int share_group_id); + InProcessCommandBuffer* share_group); void Destroy(); // CommandBuffer implementation: virtual bool Initialize() OVERRIDE; - virtual State GetState() OVERRIDE; virtual State GetLastState() OVERRIDE; virtual int32 GetLastToken() OVERRIDE; virtual void Flush(int32 put_offset) OVERRIDE; - virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE; + virtual void WaitForTokenInRange(int32 start, int32 end) OVERRIDE; + virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE; virtual void SetGetBuffer(int32 shm_id) OVERRIDE; - virtual void SetGetOffset(int32 get_offset) OVERRIDE; - virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE; + virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size, + int32* id) OVERRIDE; virtual void DestroyTransferBuffer(int32 id) OVERRIDE; - virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE; - virtual void SetToken(int32 token) OVERRIDE; - virtual void SetParseError(gpu::error::Error error) OVERRIDE; - virtual void SetContextLostReason( - gpu::error::ContextLostReason reason) OVERRIDE; virtual gpu::error::Error GetLastError() OVERRIDE; // GpuControl implementation: virtual gpu::Capabilities GetCapabilities() OVERRIDE; - virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( - size_t width, - size_t height, - unsigned internalformat, - int32* id) OVERRIDE; + virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer(size_t width, + size_t height, + unsigned internalformat, + unsigned usage, + int32* id) OVERRIDE; virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE; - virtual bool GenerateMailboxNames(unsigned num, - std::vector<gpu::Mailbox>* names) OVERRIDE; virtual uint32 InsertSyncPoint() OVERRIDE; virtual void SignalSyncPoint(uint32 sync_point, const base::Closure& callback) OVERRIDE; virtual void SignalQuery(uint32 query, const base::Closure& callback) OVERRIDE; virtual void SetSurfaceVisible(bool visible) OVERRIDE; - virtual void SendManagedMemoryStats(const gpu::ManagedMemoryStats& stats) - OVERRIDE; virtual void Echo(const base::Closure& callback) OVERRIDE; + virtual uint32 CreateStreamTexture(uint32 texture_id) OVERRIDE; // The serializer interface to the GPU service (i.e. thread). - class SchedulerClient { + class Service { public: - virtual ~SchedulerClient() {} + Service(); + virtual ~Service(); - // Queues a task to run as soon as possible. - virtual void QueueTask(const base::Closure& task) = 0; + virtual void AddRef() const = 0; + virtual void Release() const = 0; - // Schedules |callback| to run at an appropriate time for performing idle - // work. - virtual void ScheduleIdleWork(const base::Closure& task) = 0; + // Queues a task to run as soon as possible. + virtual void ScheduleTask(const base::Closure& task) = 0; + + // Schedules |callback| to run at an appropriate time for performing idle + // work. + virtual void ScheduleIdleWork(const base::Closure& task) = 0; + + virtual bool UseVirtualizedGLContexts() = 0; + virtual scoped_refptr<gles2::ShaderTranslatorCache> + shader_translator_cache() = 0; }; #if defined(OS_ANDROID) @@ -153,30 +147,37 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, const std::vector<int32>& attribs; gfx::GpuPreference gpu_preference; gpu::Capabilities* capabilities; // Ouptut. + InProcessCommandBuffer* context_group; InitializeOnGpuThreadParams(bool is_offscreen, gfx::AcceleratedWidget window, const gfx::Size& size, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference, - gpu::Capabilities* capabilities) + gpu::Capabilities* capabilities, + InProcessCommandBuffer* share_group) : is_offscreen(is_offscreen), window(window), size(size), attribs(attribs), gpu_preference(gpu_preference), - capabilities(capabilities) {} + capabilities(capabilities), + context_group(share_group) {} }; bool InitializeOnGpuThread(const InitializeOnGpuThreadParams& params); bool DestroyOnGpuThread(); void FlushOnGpuThread(int32 put_offset); + uint32 CreateStreamTextureOnGpuThread(uint32 client_texture_id); bool MakeCurrent(); - bool IsContextLost(); base::Closure WrapCallback(const base::Closure& callback); State GetStateFast(); - void QueueTask(const base::Closure& task) { queue_->QueueTask(task); } + void QueueTask(const base::Closure& task) { service_->ScheduleTask(task); } void CheckSequencedThread(); + void RetireSyncPointOnGpuThread(uint32 sync_point); + void SignalSyncPointOnGpuThread(uint32 sync_point, + const base::Closure& callback); + void DestroyTransferBufferOnGputhread(int32 id); // Callbacks: void OnContextLost(); @@ -185,34 +186,37 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, void PumpCommands(); void ScheduleMoreIdleWork(); + static scoped_refptr<Service> GetDefaultService(); + // Members accessed on the gpu thread (possibly with the exception of // creation): bool context_lost_; - bool share_resources_; scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<GpuScheduler> gpu_scheduler_; scoped_ptr<gles2::GLES2Decoder> decoder_; scoped_refptr<gfx::GLContext> context_; scoped_refptr<gfx::GLSurface> surface_; base::Closure context_lost_callback_; - unsigned int share_group_id_; // Members accessed on the client thread: State last_state_; int32 last_put_offset_; gpu::Capabilities capabilities_; + typedef std::map<int32, linked_ptr<gfx::GpuMemoryBuffer> > GpuMemoryBufferMap; + GpuMemoryBufferMap gpu_memory_buffers_; // Accessed on both threads: - scoped_ptr<CommandBuffer> command_buffer_; + scoped_ptr<CommandBufferServiceBase> command_buffer_; base::Lock command_buffer_lock_; base::WaitableEvent flush_event_; - scoped_ptr<SchedulerClient> queue_; + scoped_refptr<Service> service_; State state_after_last_flush_; base::Lock state_after_last_flush_lock_; - scoped_ptr<GpuControl> gpu_control_; + scoped_ptr<GpuControlService> gpu_control_; + scoped_refptr<gfx::GLShareGroup> gl_share_group_; #if defined(OS_ANDROID) - scoped_refptr<StreamTextureManagerInProcess> stream_texture_manager_; + scoped_ptr<StreamTextureManagerInProcess> stream_texture_manager_; #endif // Only used with explicit scheduling and the gpu thread is the same as diff --git a/chromium/gpu/command_buffer/service/mailbox_manager.cc b/chromium/gpu/command_buffer/service/mailbox_manager.cc index bb2f7262a2f..12a13fbac4c 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager.cc +++ b/chromium/gpu/command_buffer/service/mailbox_manager.cc @@ -6,26 +6,16 @@ #include <algorithm> -#include "base/rand_util.h" -#include "crypto/hmac.h" +#include "crypto/random.h" +#include "gpu/command_buffer/service/mailbox_synchronizer.h" #include "gpu/command_buffer/service/texture_manager.h" namespace gpu { namespace gles2 { -MailboxName::MailboxName() { - std::fill(key, key + sizeof(key), 0); - std::fill(signature, signature + sizeof(signature), 0); -} - MailboxManager::MailboxManager() - : hmac_(crypto::HMAC::SHA256), - mailbox_to_textures_(std::ptr_fun(&MailboxManager::TargetNameLess)) { - base::RandBytes(private_key_, sizeof(private_key_)); - bool success = hmac_.Init( - base::StringPiece(private_key_, sizeof(private_key_))); - DCHECK(success); - DCHECK(!IsMailboxNameValid(MailboxName())); + : mailbox_to_textures_(std::ptr_fun(&MailboxManager::TargetNameLess)), + sync_(MailboxSynchronizer::GetInstance()) { } MailboxManager::~MailboxManager() { @@ -33,42 +23,49 @@ MailboxManager::~MailboxManager() { DCHECK(textures_to_mailboxes_.empty()); } -void MailboxManager::GenerateMailboxName(MailboxName* name) { - base::RandBytes(name->key, sizeof(name->key)); - SignMailboxName(name); -} - Texture* MailboxManager::ConsumeTexture(unsigned target, - const MailboxName& name) { + const Mailbox& mailbox) { + TargetName target_name(target, mailbox); MailboxToTextureMap::iterator it = - mailbox_to_textures_.find(TargetName(target, name)); - if (it == mailbox_to_textures_.end()) - return NULL; + mailbox_to_textures_.find(target_name); + if (it != mailbox_to_textures_.end()) + return it->second->first; + + if (sync_) { + // See if it's visible in another mailbox manager, and if so make it visible + // here too. + Texture* texture = sync_->CreateTextureFromMailbox(target, mailbox); + if (texture) { + InsertTexture(target_name, texture); + DCHECK_EQ(0U, texture->refs_.size()); + } + return texture; + } - DCHECK(IsMailboxNameValid(name)); - return it->second->first; + return NULL; } -bool MailboxManager::ProduceTexture(unsigned target, - const MailboxName& name, +void MailboxManager::ProduceTexture(unsigned target, + const Mailbox& mailbox, Texture* texture) { - if (!IsMailboxNameValid(name)) - return false; - - texture->SetMailboxManager(this); - TargetName target_name(target, name); + TargetName target_name(target, mailbox); MailboxToTextureMap::iterator it = mailbox_to_textures_.find(target_name); if (it != mailbox_to_textures_.end()) { + if (it->second->first == texture) + return; TextureToMailboxMap::iterator texture_it = it->second; mailbox_to_textures_.erase(it); textures_to_mailboxes_.erase(texture_it); } + InsertTexture(target_name, texture); +} + +void MailboxManager::InsertTexture(TargetName target_name, Texture* texture) { + texture->SetMailboxManager(this); TextureToMailboxMap::iterator texture_it = textures_to_mailboxes_.insert(std::make_pair(texture, target_name)); mailbox_to_textures_.insert(std::make_pair(target_name, texture_it)); DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size()); - - return true; } void MailboxManager::TextureDeleted(Texture* texture) { @@ -82,27 +79,24 @@ void MailboxManager::TextureDeleted(Texture* texture) { } textures_to_mailboxes_.erase(range.first, range.second); DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size()); + + if (sync_) + sync_->TextureDeleted(texture); } -void MailboxManager::SignMailboxName(MailboxName* name) { - bool success = hmac_.Sign( - base::StringPiece(reinterpret_cast<char*>(name->key), sizeof(name->key)), - reinterpret_cast<unsigned char*>(name->signature), - sizeof(name->signature)); - DCHECK(success); +void MailboxManager::PushTextureUpdates() { + if (sync_) + sync_->PushTextureUpdates(this); } -bool MailboxManager::IsMailboxNameValid(const MailboxName& name) { - return hmac_.Verify( - base::StringPiece(reinterpret_cast<const char*>(name.key), - sizeof(name.key)), - base::StringPiece(reinterpret_cast<const char*>(name.signature), - sizeof(name.signature))); +void MailboxManager::PullTextureUpdates() { + if (sync_) + sync_->PullTextureUpdates(this); } -MailboxManager::TargetName::TargetName(unsigned target, const MailboxName& name) +MailboxManager::TargetName::TargetName(unsigned target, const Mailbox& mailbox) : target(target), - name(name) { + mailbox(mailbox) { } bool MailboxManager::TargetNameLess(const MailboxManager::TargetName& lhs, diff --git a/chromium/gpu/command_buffer/service/mailbox_manager.h b/chromium/gpu/command_buffer/service/mailbox_manager.h index c97302813a0..e1b36cb934e 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager.h +++ b/chromium/gpu/command_buffer/service/mailbox_manager.h @@ -10,68 +10,55 @@ #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" -#include "crypto/hmac.h" #include "gpu/command_buffer/common/constants.h" +#include "gpu/command_buffer/common/mailbox.h" #include "gpu/gpu_export.h" -// From gl2/gl2ext.h. -#ifndef GL_MAILBOX_SIZE_CHROMIUM -#define GL_MAILBOX_SIZE_CHROMIUM 64 -#endif - typedef signed char GLbyte; namespace gpu { namespace gles2 { +class MailboxSynchronizer; class Texture; class TextureManager; -// Identifies a mailbox where a texture definition can be stored for -// transferring textures between contexts that are not in the same context -// group. It is a random key signed with a hash of a private key. -struct GPU_EXPORT MailboxName { - MailboxName(); - GLbyte key[GL_MAILBOX_SIZE_CHROMIUM / 2]; - GLbyte signature[GL_MAILBOX_SIZE_CHROMIUM / 2]; -}; - // Manages resources scoped beyond the context or context group level. class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> { public: MailboxManager(); - // Generate a unique mailbox name signed with the manager's private key. - void GenerateMailboxName(MailboxName* name); - // Look up the texture definition from the named mailbox. - Texture* ConsumeTexture(unsigned target, const MailboxName& name); + Texture* ConsumeTexture(unsigned target, const Mailbox& mailbox); // Put the texture into the named mailbox. - bool ProduceTexture(unsigned target, - const MailboxName& name, + void ProduceTexture(unsigned target, + const Mailbox& mailbox, Texture* texture); + // Returns whether this manager synchronizes with other instances. + bool UsesSync() { return sync_ != NULL; } + + // Used with the MailboxSynchronizer to push/pull texture state to/from + // other manager instances. + void PushTextureUpdates(); + void PullTextureUpdates(); + // Destroy any mailbox that reference the given texture. void TextureDeleted(Texture* texture); - std::string private_key() { - return std::string(private_key_, sizeof(private_key_)); - } - private: friend class base::RefCounted<MailboxManager>; + friend class MailboxSynchronizer; ~MailboxManager(); - void SignMailboxName(MailboxName* name); - bool IsMailboxNameValid(const MailboxName& name); - struct TargetName { - TargetName(unsigned target, const MailboxName& name); + TargetName(unsigned target, const Mailbox& mailbox); unsigned target; - MailboxName name; + Mailbox mailbox; }; + void InsertTexture(TargetName target_name, Texture* texture); static bool TargetNameLess(const TargetName& lhs, const TargetName& rhs); @@ -80,17 +67,17 @@ class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> { // iterator in the MailboxToTextureMap to be able to manage changes to // the TextureToMailboxMap efficiently. typedef std::multimap<Texture*, TargetName> TextureToMailboxMap; - typedef std::map< - TargetName, - TextureToMailboxMap::iterator, - std::pointer_to_binary_function< - const TargetName&, const TargetName&, bool> > MailboxToTextureMap; - - char private_key_[GL_MAILBOX_SIZE_CHROMIUM / 2]; - crypto::HMAC hmac_; + typedef std::map<TargetName, + TextureToMailboxMap::iterator, + std::pointer_to_binary_function<const TargetName&, + const TargetName&, + bool> > MailboxToTextureMap; + MailboxToTextureMap mailbox_to_textures_; TextureToMailboxMap textures_to_mailboxes_; + MailboxSynchronizer* sync_; + DISALLOW_COPY_AND_ASSIGN(MailboxManager); }; } // namespage gles2 @@ -98,4 +85,3 @@ class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> { #endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_ - diff --git a/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc b/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc index 8864843571d..8e57faa96c0 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc @@ -4,20 +4,81 @@ #include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/mailbox_synchronizer.h" #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_context_stub.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" namespace gpu { namespace gles2 { -class MailboxManagerTest : public testing::Test { +using namespace ::testing; + +class MailboxManagerTest : public GpuServiceTest { public: - MailboxManagerTest() : manager_(new MailboxManager()) {} + MailboxManagerTest() : initialized_synchronizer_(false) {} virtual ~MailboxManagerTest() {} protected: + virtual void SetUp() { + GpuServiceTest::SetUp(); + feature_info_ = new FeatureInfo; + manager_ = new MailboxManager; + } + + virtual void SetUpWithSynchronizer() { + GpuServiceTest::SetUp(); + MailboxSynchronizer::Initialize(); + initialized_synchronizer_ = true; + feature_info_ = new FeatureInfo; + manager_ = new MailboxManager; + } + + virtual void TearDown() { + if (initialized_synchronizer_) + MailboxSynchronizer::Terminate(); + GpuServiceTest::TearDown(); + } + Texture* CreateTexture() { - return new Texture(0); + return new Texture(1); + } + + void SetTarget(Texture* texture, GLenum target, GLuint max_level) { + texture->SetTarget(NULL, target, max_level); + } + + void SetLevelInfo( + Texture* texture, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + bool cleared) { + texture->SetLevelInfo(NULL, + target, + level, + internal_format, + width, + height, + depth, + border, + format, + type, + cleared); + } + + GLenum SetParameter(Texture* texture, GLenum pname, GLint param) { + return texture->SetParameteri(feature_info_, pname, param); } void DestroyTexture(Texture* texture) { @@ -27,6 +88,9 @@ class MailboxManagerTest : public testing::Test { scoped_refptr<MailboxManager> manager_; private: + bool initialized_synchronizer_; + scoped_refptr<FeatureInfo> feature_info_; + DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest); }; @@ -34,9 +98,8 @@ class MailboxManagerTest : public testing::Test { TEST_F(MailboxManagerTest, Basic) { Texture* texture = CreateTexture(); - MailboxName name; - manager_->GenerateMailboxName(&name); - EXPECT_TRUE(manager_->ProduceTexture(0, name, texture)); + Mailbox name = Mailbox::Generate(); + manager_->ProduceTexture(0, name, texture); EXPECT_EQ(texture, manager_->ConsumeTexture(0, name)); // We can consume multiple times. @@ -50,34 +113,22 @@ TEST_F(MailboxManagerTest, Basic) { EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name)); } -// Should fail to produce or consume with an invalid mailbox. -TEST_F(MailboxManagerTest, InvalidName) { - Texture* texture = CreateTexture(); - MailboxName name; - memset(&name, 0, sizeof(name)); - EXPECT_FALSE(manager_->ProduceTexture(0, name, texture)); - EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name)); - DestroyTexture(texture); -} - // Tests behavior with multiple produce on the same texture. TEST_F(MailboxManagerTest, ProduceMultipleMailbox) { Texture* texture = CreateTexture(); - MailboxName name1; - manager_->GenerateMailboxName(&name1); + Mailbox name1 = Mailbox::Generate(); - EXPECT_TRUE(manager_->ProduceTexture(0, name1, texture)); + manager_->ProduceTexture(0, name1, texture); EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1)); // Can produce a second time with the same mailbox. - EXPECT_TRUE(manager_->ProduceTexture(0, name1, texture)); + manager_->ProduceTexture(0, name1, texture); EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1)); // Can produce again, with a different mailbox. - MailboxName name2; - manager_->GenerateMailboxName(&name2); - EXPECT_TRUE(manager_->ProduceTexture(0, name2, texture)); + Mailbox name2 = Mailbox::Generate(); + manager_->ProduceTexture(0, name2, texture); // Still available under all mailboxes. EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1)); @@ -95,14 +146,13 @@ TEST_F(MailboxManagerTest, ProduceMultipleTexture) { Texture* texture1 = CreateTexture(); Texture* texture2 = CreateTexture(); - MailboxName name; - manager_->GenerateMailboxName(&name); + Mailbox name = Mailbox::Generate(); - EXPECT_TRUE(manager_->ProduceTexture(0, name, texture1)); + manager_->ProduceTexture(0, name, texture1); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name)); // Can produce a second time with the same mailbox, but different texture. - EXPECT_TRUE(manager_->ProduceTexture(0, name, texture2)); + manager_->ProduceTexture(0, name, texture2); EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name)); // Destroying the texture that's under no mailbox shouldn't have an effect. @@ -117,19 +167,17 @@ TEST_F(MailboxManagerTest, ProduceMultipleTexture) { TEST_F(MailboxManagerTest, ProduceMultipleTextureMailbox) { Texture* texture1 = CreateTexture(); Texture* texture2 = CreateTexture(); - MailboxName name1; - manager_->GenerateMailboxName(&name1); - MailboxName name2; - manager_->GenerateMailboxName(&name2); + Mailbox name1 = Mailbox::Generate(); + Mailbox name2 = Mailbox::Generate(); // Put texture1 on name1 and name2. - EXPECT_TRUE(manager_->ProduceTexture(0, name1, texture1)); - EXPECT_TRUE(manager_->ProduceTexture(0, name2, texture1)); + manager_->ProduceTexture(0, name1, texture1); + manager_->ProduceTexture(0, name2, texture1); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1)); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name2)); // Put texture2 on name2. - EXPECT_TRUE(manager_->ProduceTexture(0, name2, texture2)); + manager_->ProduceTexture(0, name2, texture2); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1)); EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2)); @@ -142,5 +190,290 @@ TEST_F(MailboxManagerTest, ProduceMultipleTextureMailbox) { EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2)); } +const GLsizei kMaxTextureWidth = 64; +const GLsizei kMaxTextureHeight = 64; +const GLsizei kMaxTextureDepth = 1; + +class MailboxManagerSyncTest : public MailboxManagerTest { + public: + MailboxManagerSyncTest() {} + virtual ~MailboxManagerSyncTest() {} + + protected: + virtual void SetUp() { + MailboxManagerTest::SetUpWithSynchronizer(); + manager2_ = new MailboxManager; + context_ = new gfx::GLContextStub(); + surface_ = new gfx::GLSurfaceStub(); + context_->MakeCurrent(surface_); + } + + Texture* DefineTexture() { + Texture* texture = CreateTexture(); + const GLsizei levels_needed = TextureManager::ComputeMipMapCount( + GL_TEXTURE_2D, kMaxTextureWidth, kMaxTextureHeight, kMaxTextureDepth); + SetTarget(texture, GL_TEXTURE_2D, levels_needed); + SetLevelInfo(texture, + GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + SetParameter(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + return texture; + } + + void SetupUpdateTexParamExpectations(GLuint texture_id, + GLenum min, + GLenum mag, + GLenum wrap_s, + GLenum wrap_t) { + DCHECK(texture_id); + const GLuint kCurrentTexture = 0; + EXPECT_CALL(*gl_, GetIntegerv(GL_TEXTURE_BINDING_2D, _)) + .WillOnce(SetArgPointee<1>(kCurrentTexture)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, texture_id)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, Flush()) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kCurrentTexture)) + .Times(1) + .RetiresOnSaturation(); + } + + virtual void TearDown() { + context_->ReleaseCurrent(NULL); + MailboxManagerTest::TearDown(); + } + + scoped_refptr<MailboxManager> manager2_; + scoped_refptr<gfx::GLContext> context_; + scoped_refptr<gfx::GLSurface> surface_; + + private: + DISALLOW_COPY_AND_ASSIGN(MailboxManagerSyncTest); +}; + +TEST_F(MailboxManagerSyncTest, ProduceDestroy) { + Texture* texture = DefineTexture(); + Mailbox name = Mailbox::Generate(); + + InSequence sequence; + manager_->ProduceTexture(GL_TEXTURE_2D, name, texture); + EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + + DestroyTexture(texture); + EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); +} + +TEST_F(MailboxManagerSyncTest, ProduceSyncDestroy) { + InSequence sequence; + + Texture* texture = DefineTexture(); + Mailbox name = Mailbox::Generate(); + + manager_->ProduceTexture(GL_TEXTURE_2D, name, texture); + EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + + // Synchronize + manager_->PushTextureUpdates(); + manager2_->PullTextureUpdates(); + + DestroyTexture(texture); + EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); +} + +// Duplicates a texture into a second manager instance, and then +// makes sure a redefinition becomes visible there too. +TEST_F(MailboxManagerSyncTest, ProduceConsumeResize) { + const GLuint kNewTextureId = 1234; + InSequence sequence; + + Texture* texture = DefineTexture(); + Mailbox name = Mailbox::Generate(); + + manager_->ProduceTexture(GL_TEXTURE_2D, name, texture); + EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + + // Synchronize + manager_->PushTextureUpdates(); + manager2_->PullTextureUpdates(); + + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgPointee<1>(kNewTextureId)); + SetupUpdateTexParamExpectations( + kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name); + EXPECT_FALSE(new_texture == NULL); + EXPECT_NE(texture, new_texture); + EXPECT_EQ(kNewTextureId, new_texture->service_id()); + + // Resize original texture + SetLevelInfo(texture, + GL_TEXTURE_2D, + 0, + GL_RGBA, + 16, + 32, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + // Should have been orphaned + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Synchronize again + manager_->PushTextureUpdates(); + SetupUpdateTexParamExpectations( + kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + manager2_->PullTextureUpdates(); + GLsizei width, height; + new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height); + EXPECT_EQ(16, width); + EXPECT_EQ(32, height); + + // Should have gotten a new attachment + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) != NULL); + // Resize original texture again.... + SetLevelInfo(texture, + GL_TEXTURE_2D, + 0, + GL_RGBA, + 64, + 64, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + // ...and immediately delete the texture which should save the changes. + SetupUpdateTexParamExpectations( + kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + DestroyTexture(texture); + + // Should be still around since there is a ref from manager2 + EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); + + // The last change to the texture should be visible without a sync point (i.e. + // push). + manager2_->PullTextureUpdates(); + new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height); + EXPECT_EQ(64, width); + EXPECT_EQ(64, height); + + DestroyTexture(new_texture); + EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); +} + +// Makes sure changes are correctly published even when updates are +// pushed in both directions, i.e. makes sure we don't clobber a shared +// texture definition with an older version. +TEST_F(MailboxManagerSyncTest, ProduceConsumeBidirectional) { + const GLuint kNewTextureId1 = 1234; + const GLuint kNewTextureId2 = 4321; + + Texture* texture1 = DefineTexture(); + Mailbox name1 = Mailbox::Generate(); + Texture* texture2 = DefineTexture(); + Mailbox name2 = Mailbox::Generate(); + Texture* new_texture1 = NULL; + Texture* new_texture2 = NULL; + + manager_->ProduceTexture(GL_TEXTURE_2D, name1, texture1); + manager2_->ProduceTexture(GL_TEXTURE_2D, name2, texture2); + + // Make visible. + manager_->PushTextureUpdates(); + manager2_->PushTextureUpdates(); + + // Create textures in the other manager instances for texture1 and texture2, + // respectively to create a real sharing scenario. Otherwise, there would + // never be conflicting updates/pushes. + { + InSequence sequence; + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgPointee<1>(kNewTextureId1)); + SetupUpdateTexParamExpectations( + kNewTextureId1, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + new_texture1 = manager2_->ConsumeTexture(GL_TEXTURE_2D, name1); + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgPointee<1>(kNewTextureId2)); + SetupUpdateTexParamExpectations( + kNewTextureId2, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + new_texture2 = manager_->ConsumeTexture(GL_TEXTURE_2D, name2); + } + EXPECT_EQ(kNewTextureId1, new_texture1->service_id()); + EXPECT_EQ(kNewTextureId2, new_texture2->service_id()); + + // Make a change to texture1 + DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture1->min_filter()); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), + SetParameter(texture1, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + + // Make sure this does not clobber it with the previous version we pushed. + manager_->PullTextureUpdates(); + + // Make a change to texture2 + DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture2->mag_filter()); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), + SetParameter(texture2, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + + Mock::VerifyAndClearExpectations(gl_.get()); + + // Synchronize in both directions + manager_->PushTextureUpdates(); + manager2_->PushTextureUpdates(); + // manager1 should see the change to texture2 mag_filter being applied. + SetupUpdateTexParamExpectations( + new_texture2->service_id(), GL_LINEAR, GL_NEAREST, GL_REPEAT, GL_REPEAT); + manager_->PullTextureUpdates(); + // manager2 should see the change to texture1 min_filter being applied. + SetupUpdateTexParamExpectations( + new_texture1->service_id(), GL_NEAREST, GL_LINEAR, GL_REPEAT, GL_REPEAT); + manager2_->PullTextureUpdates(); + + DestroyTexture(texture1); + DestroyTexture(texture2); + DestroyTexture(new_texture1); + DestroyTexture(new_texture2); +} + +// TODO: different texture into same mailbox + +// TODO: same texture, multiple mailboxes + +// TODO: Produce incomplete texture + +// TODO: Texture::level_infos_[][].size() + +// TODO: unsupported targets and formats + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/mailbox_synchronizer.cc b/chromium/gpu/command_buffer/service/mailbox_synchronizer.cc new file mode 100644 index 00000000000..d25368ab096 --- /dev/null +++ b/chromium/gpu/command_buffer/service/mailbox_synchronizer.cc @@ -0,0 +1,226 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/mailbox_synchronizer.h" + +#include "base/bind.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/texture_manager.h" +#include "ui/gl/gl_implementation.h" + +namespace gpu { +namespace gles2 { + +namespace { + +MailboxSynchronizer* g_instance = NULL; + +} // anonymous namespace + +// static +bool MailboxSynchronizer::Initialize() { + DCHECK(!g_instance); + DCHECK(gfx::GetGLImplementation() != gfx::kGLImplementationNone) + << "GL bindings not initialized"; + switch (gfx::GetGLImplementation()) { + case gfx::kGLImplementationMockGL: + break; + case gfx::kGLImplementationEGLGLES2: +#if !defined(OS_MACOSX) + { + if (!gfx::g_driver_egl.ext.b_EGL_KHR_image_base || + !gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image || + !gfx::g_driver_gl.ext.b_GL_OES_EGL_image || + !gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { + LOG(WARNING) << "MailboxSync not supported due to missing EGL " + "image/fence support"; + return false; + } + } + break; +#endif + default: + NOTREACHED(); + return false; + } + g_instance = new MailboxSynchronizer; + return true; +} + +// static +void MailboxSynchronizer::Terminate() { + DCHECK(g_instance); + delete g_instance; + g_instance = NULL; +} + +// static +MailboxSynchronizer* MailboxSynchronizer::GetInstance() { + return g_instance; +} + +MailboxSynchronizer::TargetName::TargetName(unsigned target, + const Mailbox& mailbox) + : target(target), mailbox(mailbox) {} + +MailboxSynchronizer::TextureGroup::TextureGroup( + const TextureDefinition& definition) + : definition(definition) {} + +MailboxSynchronizer::TextureGroup::~TextureGroup() {} + +MailboxSynchronizer::TextureVersion::TextureVersion( + linked_ptr<TextureGroup> group) + : version(group->definition.version()), group(group) {} + +MailboxSynchronizer::TextureVersion::~TextureVersion() {} + +MailboxSynchronizer::MailboxSynchronizer() {} + +MailboxSynchronizer::~MailboxSynchronizer() { + DCHECK_EQ(0U, textures_.size()); +} + +void MailboxSynchronizer::ReassociateMailboxLocked( + const TargetName& target_name, + TextureGroup* group) { + lock_.AssertAcquired(); + for (TextureMap::iterator it = textures_.begin(); it != textures_.end(); + it++) { + std::set<TargetName>::iterator mb_it = + it->second.group->mailboxes.find(target_name); + if (it->second.group != group && + mb_it != it->second.group->mailboxes.end()) { + it->second.group->mailboxes.erase(mb_it); + } + } + group->mailboxes.insert(target_name); +} + +linked_ptr<MailboxSynchronizer::TextureGroup> +MailboxSynchronizer::GetGroupForMailboxLocked(const TargetName& target_name) { + lock_.AssertAcquired(); + for (TextureMap::iterator it = textures_.begin(); it != textures_.end(); + it++) { + std::set<TargetName>::const_iterator mb_it = + it->second.group->mailboxes.find(target_name); + if (mb_it != it->second.group->mailboxes.end()) + return it->second.group; + } + return make_linked_ptr<MailboxSynchronizer::TextureGroup>(NULL); +} + +Texture* MailboxSynchronizer::CreateTextureFromMailbox(unsigned target, + const Mailbox& mailbox) { + base::AutoLock lock(lock_); + TargetName target_name(target, mailbox); + linked_ptr<TextureGroup> group = GetGroupForMailboxLocked(target_name); + if (group.get()) { + Texture* new_texture = group->definition.CreateTexture(); + if (new_texture) + textures_.insert(std::make_pair(new_texture, TextureVersion(group))); + return new_texture; + } + + return NULL; +} + +void MailboxSynchronizer::TextureDeleted(Texture* texture) { + base::AutoLock lock(lock_); + TextureMap::iterator it = textures_.find(texture); + if (it != textures_.end()) { + // TODO: We could avoid the update if this was the last ref. + UpdateTextureLocked(it->first, it->second); + textures_.erase(it); + } +} + +void MailboxSynchronizer::PushTextureUpdates(MailboxManager* manager) { + base::AutoLock lock(lock_); + for (MailboxManager::MailboxToTextureMap::const_iterator texture_it = + manager->mailbox_to_textures_.begin(); + texture_it != manager->mailbox_to_textures_.end(); + texture_it++) { + TargetName target_name(texture_it->first.target, texture_it->first.mailbox); + Texture* texture = texture_it->second->first; + // TODO(sievers): crbug.com/352274 + // Should probably only fail if it already *has* mipmaps, while allowing + // incomplete textures here. Also reconsider how to fail otherwise. + bool needs_mips = texture->min_filter() != GL_NEAREST && + texture->min_filter() != GL_LINEAR; + if (target_name.target != GL_TEXTURE_2D || needs_mips) + continue; + + TextureMap::iterator it = textures_.find(texture); + if (it != textures_.end()) { + TextureVersion& texture_version = it->second; + TextureGroup* group = texture_version.group.get(); + std::set<TargetName>::const_iterator mb_it = + group->mailboxes.find(target_name); + if (mb_it == group->mailboxes.end()) { + // We previously did not associate this texture with the given mailbox. + // Unlink other texture groups from the mailbox. + ReassociateMailboxLocked(target_name, group); + } + UpdateTextureLocked(texture, texture_version); + + } else { + linked_ptr<TextureGroup> group = make_linked_ptr(new TextureGroup( + TextureDefinition(target_name.target, texture, 1, NULL))); + + // Unlink other textures from this mailbox in case the name is not new. + ReassociateMailboxLocked(target_name, group.get()); + textures_.insert(std::make_pair(texture, TextureVersion(group))); + } + } +} + +void MailboxSynchronizer::UpdateTextureLocked(Texture* texture, + TextureVersion& texture_version) { + lock_.AssertAcquired(); + gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0); + TextureGroup* group = texture_version.group.get(); + scoped_refptr<NativeImageBuffer> image_buffer = group->definition.image(); + + // Make sure we don't clobber with an older version + if (!group->definition.IsOlderThan(texture_version.version)) + return; + + // Also don't push redundant updates. Note that it would break the + // versioning. + if (group->definition.Matches(texture)) + return; + + if (gl_image && !image_buffer->IsClient(gl_image)) { + LOG(ERROR) << "MailboxSync: Incompatible attachment"; + return; + } + + group->definition = TextureDefinition(texture->target(), + texture, + ++texture_version.version, + gl_image ? image_buffer : NULL); +} + +void MailboxSynchronizer::PullTextureUpdates(MailboxManager* manager) { + base::AutoLock lock(lock_); + for (MailboxManager::MailboxToTextureMap::const_iterator texture_it = + manager->mailbox_to_textures_.begin(); + texture_it != manager->mailbox_to_textures_.end(); + texture_it++) { + Texture* texture = texture_it->second->first; + TextureMap::iterator it = textures_.find(texture); + if (it != textures_.end()) { + TextureDefinition& definition = it->second.group->definition; + if (it->second.version == definition.version() || + definition.IsOlderThan(it->second.version)) + continue; + it->second.version = definition.version(); + definition.UpdateTexture(texture); + } + } +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/mailbox_synchronizer.h b/chromium/gpu/command_buffer/service/mailbox_synchronizer.h new file mode 100644 index 00000000000..a845963bbbf --- /dev/null +++ b/chromium/gpu/command_buffer/service/mailbox_synchronizer.h @@ -0,0 +1,96 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_ + +#include "gpu/command_buffer/common/mailbox.h" + +#include <map> +#include <set> + +#include "base/memory/linked_ptr.h" +#include "base/synchronization/lock.h" +#include "gpu/command_buffer/service/texture_definition.h" +#include "gpu/gpu_export.h" + +namespace gpu { +namespace gles2 { + +class MailboxManager; +class Texture; + +// A thread-safe proxy that can be used to emulate texture sharing across +// share-groups. +class MailboxSynchronizer { + public: + ~MailboxSynchronizer(); + + GPU_EXPORT static bool Initialize(); + GPU_EXPORT static void Terminate(); + static MailboxSynchronizer* GetInstance(); + + // Create a texture from a globally visible mailbox. + Texture* CreateTextureFromMailbox(unsigned target, const Mailbox& mailbox); + + void PushTextureUpdates(MailboxManager* manager); + void PullTextureUpdates(MailboxManager* manager); + + void TextureDeleted(Texture* texture); + + private: + MailboxSynchronizer(); + + struct TargetName { + TargetName(unsigned target, const Mailbox& mailbox); + bool operator<(const TargetName& rhs) const { + return memcmp(this, &rhs, sizeof(rhs)) < 0; + } + bool operator!=(const TargetName& rhs) const { + return memcmp(this, &rhs, sizeof(rhs)) != 0; + } + bool operator==(const TargetName& rhs) const { + return !operator!=(rhs); + } + unsigned target; + Mailbox mailbox; + }; + + base::Lock lock_; + + struct TextureGroup { + explicit TextureGroup(const TextureDefinition& definition); + ~TextureGroup(); + + TextureDefinition definition; + std::set<TargetName> mailboxes; + private: + DISALLOW_COPY_AND_ASSIGN(TextureGroup); + }; + + struct TextureVersion { + explicit TextureVersion(linked_ptr<TextureGroup> group); + ~TextureVersion(); + + unsigned int version; + linked_ptr<TextureGroup> group; + }; + typedef std::map<Texture*, TextureVersion> TextureMap; + TextureMap textures_; + + linked_ptr<TextureGroup> GetGroupForMailboxLocked( + const TargetName& target_name); + void ReassociateMailboxLocked( + const TargetName& target_name, + TextureGroup* group); + void UpdateTextureLocked(Texture* texture, TextureVersion& texture_version); + + DISALLOW_COPY_AND_ASSIGN(MailboxSynchronizer); +}; + +} // namespage gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_ + diff --git a/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc b/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc index 6c6b099a20e..6973e67afe4 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc +++ b/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/shader_translator.h" #include "testing/gtest/include/gtest/gtest.h" @@ -65,7 +66,7 @@ class ProgramBinaryEmulator { const char* binary_; }; -class MemoryProgramCacheTest : public testing::Test { +class MemoryProgramCacheTest : public GpuServiceTest { public: static const size_t kCacheSizeBytes = 1024; static const GLuint kVertexShaderClientId = 90; @@ -92,8 +93,7 @@ class MemoryProgramCacheTest : public testing::Test { protected: virtual void SetUp() { - gl_.reset(new ::testing::StrictMock<gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); vertex_shader_ = shader_manager_.CreateShader(kVertexShaderClientId, kVertexShaderServiceId, @@ -137,11 +137,6 @@ class MemoryProgramCacheTest : public testing::Test { fragment_shader_->SetStatus(true, NULL, NULL); } - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); - } - void SetExpectationsForSaveLinkedProgram( const GLint program_id, ProgramBinaryEmulator* emulator) const { @@ -181,8 +176,6 @@ class MemoryProgramCacheTest : public testing::Test { .WillOnce(SetArgPointee<2>(GL_FALSE)); } - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock<gfx::MockGLInterface> > gl_; scoped_ptr<MemoryProgramCache> cache_; ShaderManager shader_manager_; Shader* vertex_shader_; @@ -481,7 +474,6 @@ TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentMap) { } TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) { - typedef ShaderTranslator::VariableMap VariableMap; const GLenum kFormat = 1; const int kProgramId = 10; const int kBinaryLength = 20; diff --git a/chromium/gpu/command_buffer/service/mocks.h b/chromium/gpu/command_buffer/service/mocks.h index 2a95db5f3c8..b64305149e7 100644 --- a/chromium/gpu/command_buffer/service/mocks.h +++ b/chromium/gpu/command_buffer/service/mocks.h @@ -93,7 +93,7 @@ class MockShaderTranslator : public ShaderTranslatorInterface { MOCK_CONST_METHOD0(varying_map, const VariableMap&()); MOCK_CONST_METHOD0(name_map, const NameMap&()); MOCK_CONST_METHOD0( - GetStringForOptionsThatWouldEffectCompilation, std::string()); + GetStringForOptionsThatWouldAffectCompilation, std::string()); }; class MockProgramCache : public ProgramCache { diff --git a/chromium/gpu/command_buffer/service/program_cache.cc b/chromium/gpu/command_buffer/service/program_cache.cc index 6599d4ad3d9..ad395c7f476 100644 --- a/chromium/gpu/command_buffer/service/program_cache.cc +++ b/chromium/gpu/command_buffer/service/program_cache.cc @@ -74,7 +74,7 @@ void ProgramCache::ComputeShaderHash( const ShaderTranslatorInterface* translator, char* result) const { std::string s(( - translator ? translator->GetStringForOptionsThatWouldEffectCompilation() : + translator ? translator->GetStringForOptionsThatWouldAffectCompilation() : std::string()) + str); base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(s.c_str()), s.length(), reinterpret_cast<unsigned char*>(result)); diff --git a/chromium/gpu/command_buffer/service/program_manager.cc b/chromium/gpu/command_buffer/service/program_manager.cc index d6e121a5da6..44169b8e197 100644 --- a/chromium/gpu/command_buffer/service/program_manager.cc +++ b/chromium/gpu/command_buffer/service/program_manager.cc @@ -125,16 +125,77 @@ Program::UniformInfo::UniformInfo() is_array(false) { } -Program::UniformInfo::UniformInfo( - GLsizei _size, - GLenum _type, - int _fake_location_base, - const std::string& _name) +Program::UniformInfo::UniformInfo(GLsizei _size, + GLenum _type, + int _fake_location_base, + const std::string& _name) : size(_size), type(_type), + accepts_api_type(0), fake_location_base(_fake_location_base), is_array(false), name(_name) { + switch (type) { + case GL_INT: + accepts_api_type = kUniform1i; + break; + case GL_INT_VEC2: + accepts_api_type = kUniform2i; + break; + case GL_INT_VEC3: + accepts_api_type = kUniform3i; + break; + case GL_INT_VEC4: + accepts_api_type = kUniform4i; + break; + + case GL_BOOL: + accepts_api_type = kUniform1i | kUniform1f; + break; + case GL_BOOL_VEC2: + accepts_api_type = kUniform2i | kUniform2f; + break; + case GL_BOOL_VEC3: + accepts_api_type = kUniform3i | kUniform3f; + break; + case GL_BOOL_VEC4: + accepts_api_type = kUniform4i | kUniform4f; + break; + + case GL_FLOAT: + accepts_api_type = kUniform1f; + break; + case GL_FLOAT_VEC2: + accepts_api_type = kUniform2f; + break; + case GL_FLOAT_VEC3: + accepts_api_type = kUniform3f; + break; + case GL_FLOAT_VEC4: + accepts_api_type = kUniform4f; + break; + + case GL_FLOAT_MAT2: + accepts_api_type = kUniformMatrix2f; + break; + case GL_FLOAT_MAT3: + accepts_api_type = kUniformMatrix3f; + break; + case GL_FLOAT_MAT4: + accepts_api_type = kUniformMatrix4f; + break; + + case GL_SAMPLER_2D: + case GL_SAMPLER_2D_RECT_ARB: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_3D_OES: + case GL_SAMPLER_EXTERNAL_OES: + accepts_api_type = kUniform1i; + break; + default: + NOTREACHED() << "Unhandled UniformInfo type " << type; + break; + } } Program::UniformInfo::~UniformInfo() {} @@ -179,7 +240,7 @@ std::string Program::ProcessLogInfo( std::string prior_log; std::string hashed_name; while (RE2::Consume(&input, - "(.*)(webgl_[0123456789abcdefABCDEF]+)", + "(.*?)(webgl_[0123456789abcdefABCDEF]+)", &prior_log, &hashed_name)) { output += prior_log; @@ -357,13 +418,13 @@ void Program::Update() { #if !defined(NDEBUG) if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUServiceLoggingGPU)) { - DLOG(INFO) << "----: attribs for service_id: " << service_id(); + DVLOG(1) << "----: attribs for service_id: " << service_id(); for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { const VertexAttrib& info = attrib_infos_[ii]; - DLOG(INFO) << ii << ": loc = " << info.location - << ", size = " << info.size - << ", type = " << GLES2Util::GetStringEnum(info.type) - << ", name = " << info.name; + DVLOG(1) << ii << ": loc = " << info.location + << ", size = " << info.size + << ", type = " << GLES2Util::GetStringEnum(info.type) + << ", name = " << info.name; } } #endif @@ -435,14 +496,14 @@ void Program::Update() { #if !defined(NDEBUG) if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUServiceLoggingGPU)) { - DLOG(INFO) << "----: uniforms for service_id: " << service_id(); + DVLOG(1) << "----: uniforms for service_id: " << service_id(); for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { const UniformInfo& info = uniform_infos_[ii]; if (info.IsValid()) { - DLOG(INFO) << ii << ": loc = " << info.element_locations[0] - << ", size = " << info.size - << ", type = " << GLES2Util::GetStringEnum(info.type) - << ", name = " << info.name; + DVLOG(1) << ii << ": loc = " << info.element_locations[0] + << ", size = " << info.size + << ", type = " << GLES2Util::GetStringEnum(info.type) + << ", name = " << info.name; } } } @@ -533,18 +594,24 @@ bool Program::Link(ShaderManager* manager, set_log_info("glBindAttribLocation() conflicts"); return false; } - if (DetectUniformsMismatch()) { - set_log_info("Uniforms with the same name but different type/precision"); + std::string conflicting_name; + if (DetectUniformsMismatch(&conflicting_name)) { + std::string info_log = "Uniforms with the same name but different " + "type/precision: " + conflicting_name; + set_log_info(ProcessLogInfo(info_log).c_str()); return false; } - if (DetectVaryingsMismatch()) { - set_log_info("Varyings with the same name but different type, " - "or statically used varyings in fragment shader are not " - "declared in vertex shader"); + if (DetectVaryingsMismatch(&conflicting_name)) { + std::string info_log = "Varyings with the same name but different type, " + "or statically used varyings in fragment shader are " + "not declared in vertex shader: " + conflicting_name; + set_log_info(ProcessLogInfo(info_log).c_str()); return false; } - if (DetectGlobalNameConflicts()) { - set_log_info("Name conflicts between an uniform and an attribute"); + if (DetectGlobalNameConflicts(&conflicting_name)) { + std::string info_log = "Name conflicts between an uniform and an " + "attribute: " + conflicting_name; + set_log_info(ProcessLogInfo(info_log).c_str()); return false; } if (!CheckVaryingsPacking(varyings_packing_option)) { @@ -1005,7 +1072,7 @@ bool Program::DetectAttribLocationBindingConflicts() const { return false; } -bool Program::DetectUniformsMismatch() const { +bool Program::DetectUniformsMismatch(std::string* conflicting_name) const { typedef std::map<std::string, UniformType> UniformMap; UniformMap uniform_map; for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { @@ -1024,6 +1091,7 @@ bool Program::DetectUniformsMismatch() const { // declared by other shader, then the type and precision must match. if (map_entry->second == type) continue; + *conflicting_name = name; return true; } } @@ -1031,7 +1099,7 @@ bool Program::DetectUniformsMismatch() const { return false; } -bool Program::DetectVaryingsMismatch() const { +bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const { DCHECK(attached_shaders_[0] && attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && attached_shaders_[1] && @@ -1051,20 +1119,24 @@ bool Program::DetectVaryingsMismatch() const { ShaderTranslator::VariableMap::const_iterator hit = vertex_varyings->find(name); if (hit == vertex_varyings->end()) { - if (iter->second.static_use) + if (iter->second.static_use) { + *conflicting_name = name; return true; + } continue; } if (hit->second.type != iter->second.type || - hit->second.size != iter->second.size) + hit->second.size != iter->second.size) { + *conflicting_name = name; return true; + } } return false; } -bool Program::DetectGlobalNameConflicts() const { +bool Program::DetectGlobalNameConflicts(std::string* conflicting_name) const { DCHECK(attached_shaders_[0] && attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && attached_shaders_[1] && @@ -1078,8 +1150,10 @@ bool Program::DetectGlobalNameConflicts() const { for (ShaderTranslator::VariableMap::const_iterator iter = attribs->begin(); iter != attribs->end(); ++iter) { for (int ii = 0; ii < 2; ++ii) { - if (uniforms[ii]->find(iter->first) != uniforms[ii]->end()) + if (uniforms[ii]->find(iter->first) != uniforms[ii]->end()) { + *conflicting_name = iter->first; return true; + } } } return false; diff --git a/chromium/gpu/command_buffer/service/program_manager.h b/chromium/gpu/command_buffer/service/program_manager.h index 50dd0ff1b80..c1bf3a44d4e 100644 --- a/chromium/gpu/command_buffer/service/program_manager.h +++ b/chromium/gpu/command_buffer/service/program_manager.h @@ -38,6 +38,20 @@ class GPU_EXPORT Program : public base::RefCounted<Program> { kCountAll }; + enum UniformApiType { + kUniform1i = 1 << 0, + kUniform2i = 1 << 1, + kUniform3i = 1 << 2, + kUniform4i = 1 << 3, + kUniform1f = 1 << 4, + kUniform2f = 1 << 5, + kUniform3f = 1 << 6, + kUniform4f = 1 << 7, + kUniformMatrix2f = 1 << 8, + kUniformMatrix3f = 1 << 9, + kUniformMatrix4f = 1 << 10, + }; + struct UniformInfo { UniformInfo(); UniformInfo( @@ -56,6 +70,7 @@ class GPU_EXPORT Program : public base::RefCounted<Program> { GLsizei size; GLenum type; + uint32 accepts_api_type; GLint fake_location_base; bool is_array; std::string name; @@ -192,15 +207,16 @@ class GPU_EXPORT Program : public base::RefCounted<Program> { // Detects if there are uniforms of the same name but different type // or precision in vertex/fragment shaders. - // Return true if such cases are detected. - bool DetectUniformsMismatch() const; + // Return true and set the first found conflicting hashed name to + // conflicting_name if such cases are detected. + bool DetectUniformsMismatch(std::string* conflicting_name) const; // Return true if a varying is statically used in fragment shader, but it // is not declared in vertex shader. - bool DetectVaryingsMismatch() const; + bool DetectVaryingsMismatch(std::string* conflicting_name) const; // Return true if an uniform and an attribute share the same name. - bool DetectGlobalNameConflicts() const; + bool DetectGlobalNameConflicts(std::string* conflicting_name) const; // Return false if varyings can't be packed into the max available // varying registers. diff --git a/chromium/gpu/command_buffer/service/program_manager_unittest.cc b/chromium/gpu/command_buffer/service/program_manager_unittest.cc index 0823d096452..326486108b1 100644 --- a/chromium/gpu/command_buffer/service/program_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/program_manager_unittest.cc @@ -13,13 +13,13 @@ #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/common_decoder.h" #include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mocks.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" -using ::gfx::MockGLInterface; using ::testing::_; using ::testing::DoAll; using ::testing::InSequence; @@ -30,7 +30,6 @@ using ::testing::ReturnRef; using ::testing::SetArrayArgument; using ::testing::SetArgumentPointee; using ::testing::StrEq; -using ::testing::StrictMock; namespace gpu { namespace gles2 { @@ -41,7 +40,7 @@ const uint32 kMaxVaryingVectors = 8; void ShaderCacheCb(const std::string& key, const std::string& shader) {} } // namespace anonymous -class ProgramManagerTest : public testing::Test { +class ProgramManagerTest : public GpuServiceTest { public: ProgramManagerTest() : manager_(NULL, kMaxVaryingVectors) { } virtual ~ProgramManagerTest() { @@ -49,18 +48,6 @@ class ProgramManagerTest : public testing::Test { } protected: - virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - } - - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); - } - - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; ProgramManager manager_; }; @@ -138,7 +125,7 @@ TEST_F(ProgramManagerTest, Program) { EXPECT_TRUE(program1->log_info() == NULL); } -class ProgramManagerWithShaderTest : public testing::Test { +class ProgramManagerWithShaderTest : public GpuServiceTest { public: ProgramManagerWithShaderTest() : manager_(NULL, kMaxVaryingVectors), program_(NULL) { @@ -228,8 +215,7 @@ class ProgramManagerWithShaderTest : public testing::Test { } VarInfo; virtual void SetUp() { - gl_.reset(new StrictMock<gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); SetupDefaultShaderExpectations(); @@ -272,10 +258,6 @@ class ProgramManagerWithShaderTest : public testing::Test { gl_.get(), uniforms, num_uniforms); } - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - } - // Return true if link status matches expected_link_status bool LinkAsExpected(Program* program, bool expected_link_status) { @@ -398,8 +380,6 @@ class ProgramManagerWithShaderTest : public testing::Test { static AttribInfo kAttribs[]; static UniformInfo kUniforms[]; - scoped_ptr<StrictMock<gfx::MockGLInterface> > gl_; - ProgramManager manager_; Program* program_; ShaderManager shader_manager_; @@ -1260,7 +1240,10 @@ TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) { EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); - EXPECT_TRUE(program->DetectUniformsMismatch()); + std::string conflicting_name; + + EXPECT_TRUE(program->DetectUniformsMismatch(&conflicting_name)); + EXPECT_EQ("a", conflicting_name); EXPECT_TRUE(LinkAsExpected(program, false)); } @@ -1274,7 +1257,10 @@ TEST_F(ProgramManagerWithShaderTest, VaryingTypeMismatch) { Program* program = SetupShaderVariableTest( &kVertexVarying, 1, &kFragmentVarying, 1); - EXPECT_TRUE(program->DetectVaryingsMismatch()); + std::string conflicting_name; + + EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name)); + EXPECT_EQ("a", conflicting_name); EXPECT_TRUE(LinkAsExpected(program, false)); } @@ -1288,7 +1274,10 @@ TEST_F(ProgramManagerWithShaderTest, VaryingArraySizeMismatch) { Program* program = SetupShaderVariableTest( &kVertexVarying, 1, &kFragmentVarying, 1); - EXPECT_TRUE(program->DetectVaryingsMismatch()); + std::string conflicting_name; + + EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name)); + EXPECT_EQ("a", conflicting_name); EXPECT_TRUE(LinkAsExpected(program, false)); } @@ -1302,7 +1291,10 @@ TEST_F(ProgramManagerWithShaderTest, VaryingPrecisionMismatch) { Program* program = SetupShaderVariableTest( &kVertexVarying, 1, &kFragmentVarying, 1); - EXPECT_FALSE(program->DetectVaryingsMismatch()); + std::string conflicting_name; + + EXPECT_FALSE(program->DetectVaryingsMismatch(&conflicting_name)); + EXPECT_TRUE(conflicting_name.empty()); EXPECT_TRUE(LinkAsExpected(program, true)); } @@ -1314,7 +1306,10 @@ TEST_F(ProgramManagerWithShaderTest, VaryingMissing) { Program* program = SetupShaderVariableTest( NULL, 0, &kFragmentVarying, 1); - EXPECT_TRUE(program->DetectVaryingsMismatch()); + std::string conflicting_name; + + EXPECT_TRUE(program->DetectVaryingsMismatch(&conflicting_name)); + EXPECT_EQ("a", conflicting_name); EXPECT_TRUE(LinkAsExpected(program, false)); } @@ -1327,7 +1322,10 @@ TEST_F(ProgramManagerWithShaderTest, InactiveVarying) { Program* program = SetupShaderVariableTest( NULL, 0, &kFragmentVarying, 1); - EXPECT_FALSE(program->DetectVaryingsMismatch()); + std::string conflicting_name; + + EXPECT_FALSE(program->DetectVaryingsMismatch(&conflicting_name)); + EXPECT_TRUE(conflicting_name.empty()); EXPECT_TRUE(LinkAsExpected(program, true)); } @@ -1342,7 +1340,10 @@ TEST_F(ProgramManagerWithShaderTest, AttribUniformNameConflict) { Program* program = SetupShaderVariableTest( &kVertexAttribute, 1, &kFragmentUniform, 1); - EXPECT_TRUE(program->DetectGlobalNameConflicts()); + std::string conflicting_name; + + EXPECT_TRUE(program->DetectGlobalNameConflicts(&conflicting_name)); + EXPECT_EQ("a", conflicting_name); EXPECT_TRUE(LinkAsExpected(program, false)); } @@ -1548,7 +1549,7 @@ TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) { program->GetUniformFakeLocation(kUniform3GoodName)); } -class ProgramManagerWithCacheTest : public testing::Test { +class ProgramManagerWithCacheTest : public GpuServiceTest { public: static const GLuint kClientProgramId = 1; static const GLuint kServiceProgramId = 10; @@ -1571,8 +1572,7 @@ class ProgramManagerWithCacheTest : public testing::Test { protected: virtual void SetUp() { - gl_.reset(new StrictMock<gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); vertex_shader_ = shader_manager_.CreateShader( kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); @@ -1591,10 +1591,6 @@ class ProgramManagerWithCacheTest : public testing::Test { program_->AttachShader(&shader_manager_, fragment_shader_); } - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - } - void SetShadersCompiled() { vertex_shader_->SetStatus(true, NULL, NULL); fragment_shader_->SetStatus(true, NULL, NULL); @@ -1736,8 +1732,6 @@ class ProgramManagerWithCacheTest : public testing::Test { .Times(1); } - scoped_ptr<StrictMock<gfx::MockGLInterface> > gl_; - scoped_ptr<MockProgramCache> cache_; ProgramManager manager_; diff --git a/chromium/gpu/command_buffer/service/query_manager.cc b/chromium/gpu/command_buffer/service/query_manager.cc index db508e0a7f7..ffb54cca514 100644 --- a/chromium/gpu/command_buffer/service/query_manager.cc +++ b/chromium/gpu/command_buffer/service/query_manager.cc @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/memory/shared_memory.h" +#include "base/numerics/safe_math.h" #include "base/synchronization/lock.h" #include "base/time/time.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" @@ -15,6 +16,7 @@ #include "gpu/command_buffer/service/error_state.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "ui/gl/gl_fence.h" namespace gpu { namespace gles2 { @@ -24,9 +26,8 @@ namespace { class AsyncPixelTransferCompletionObserverImpl : public AsyncPixelTransferCompletionObserver { public: - AsyncPixelTransferCompletionObserverImpl(uint32 submit_count) - : submit_count_(submit_count), - cancelled_(false) {} + AsyncPixelTransferCompletionObserverImpl(base::subtle::Atomic32 submit_count) + : submit_count_(submit_count), cancelled_(false) {} void Cancel() { base::AutoLock locked(lock_); @@ -36,23 +37,17 @@ class AsyncPixelTransferCompletionObserverImpl virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE { base::AutoLock locked(lock_); if (!cancelled_) { - DCHECK(mem_params.shared_memory); - DCHECK(mem_params.shared_memory->memory()); - void* data = static_cast<int8*>(mem_params.shared_memory->memory()) + - mem_params.shm_data_offset; + DCHECK(mem_params.buffer()); + void* data = mem_params.GetDataAddress(); QuerySync* sync = static_cast<QuerySync*>(data); - - // Need a MemoryBarrier here to ensure that upload completed before - // submit_count was written to sync->process_count. - base::subtle::MemoryBarrier(); - sync->process_count = submit_count_; + base::subtle::Release_Store(&sync->process_count, submit_count_); } } private: virtual ~AsyncPixelTransferCompletionObserverImpl() {} - uint32 submit_count_; + base::subtle::Atomic32 submit_count_; base::Lock lock_; bool cancelled_; @@ -68,7 +63,7 @@ class AsyncPixelTransfersCompletedQuery QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); virtual bool Begin() OVERRIDE; - virtual bool End(uint32 submit_count) OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; virtual bool Process() OVERRIDE; virtual void Destroy(bool have_context) OVERRIDE; @@ -87,19 +82,16 @@ bool AsyncPixelTransfersCompletedQuery::Begin() { return true; } -bool AsyncPixelTransfersCompletedQuery::End(uint32 submit_count) { - AsyncMemoryParams mem_params; +bool AsyncPixelTransfersCompletedQuery::End( + base::subtle::Atomic32 submit_count) { // Get the real shared memory since it might need to be duped to prevent // use-after-free of the memory. - Buffer buffer = manager()->decoder()->GetSharedMemoryBuffer(shm_id()); - if (!buffer.shared_memory) + scoped_refptr<Buffer> buffer = + manager()->decoder()->GetSharedMemoryBuffer(shm_id()); + if (!buffer) return false; - mem_params.shared_memory = buffer.shared_memory; - mem_params.shm_size = buffer.size; - mem_params.shm_data_offset = shm_offset(); - mem_params.shm_data_size = sizeof(QuerySync); - uint32 end = mem_params.shm_data_offset + mem_params.shm_data_size; - if (end > mem_params.shm_size || end < mem_params.shm_data_offset) + AsyncMemoryParams mem_params(buffer, shm_offset(), sizeof(QuerySync)); + if (!mem_params.GetDataAddress()) return false; observer_ = new AsyncPixelTransferCompletionObserverImpl(submit_count); @@ -122,7 +114,7 @@ bool AsyncPixelTransfersCompletedQuery::Process() { // Check if completion callback has been run. sync->process_count atomicity // is guaranteed as this is already used to notify client of a completed // query. - if (sync->process_count != submit_count()) + if (base::subtle::Acquire_Load(&sync->process_count) != submit_count()) return true; UnmarkAsPending(); @@ -148,7 +140,7 @@ class AllSamplesPassedQuery : public QueryManager::Query { QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset, GLuint service_id); virtual bool Begin() OVERRIDE; - virtual bool End(uint32 submit_count) OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; virtual bool Process() OVERRIDE; virtual void Destroy(bool have_context) OVERRIDE; @@ -172,7 +164,7 @@ bool AllSamplesPassedQuery::Begin() { return true; } -bool AllSamplesPassedQuery::End(uint32 submit_count) { +bool AllSamplesPassedQuery::End(base::subtle::Atomic32 submit_count) { EndQueryHelper(target()); return AddToPendingQueue(submit_count); } @@ -207,7 +199,7 @@ class CommandsIssuedQuery : public QueryManager::Query { QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); virtual bool Begin() OVERRIDE; - virtual bool End(uint32 submit_count) OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; virtual bool Process() OVERRIDE; virtual void Destroy(bool have_context) OVERRIDE; @@ -228,7 +220,7 @@ bool CommandsIssuedQuery::Begin() { return true; } -bool CommandsIssuedQuery::End(uint32 submit_count) { +bool CommandsIssuedQuery::End(base::subtle::Atomic32 submit_count) { base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_; MarkAsPending(submit_count); return MarkAsCompleted(elapsed.InMicroseconds()); @@ -254,7 +246,7 @@ class CommandLatencyQuery : public QueryManager::Query { QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); virtual bool Begin() OVERRIDE; - virtual bool End(uint32 submit_count) OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; virtual bool Process() OVERRIDE; virtual void Destroy(bool have_context) OVERRIDE; @@ -271,7 +263,7 @@ bool CommandLatencyQuery::Begin() { return true; } -bool CommandLatencyQuery::End(uint32 submit_count) { +bool CommandLatencyQuery::End(base::subtle::Atomic32 submit_count) { base::TimeDelta now = base::TimeTicks::HighResNow() - base::TimeTicks(); MarkAsPending(submit_count); return MarkAsCompleted(now.InMicroseconds()); @@ -300,25 +292,31 @@ class AsyncReadPixelsCompletedQuery QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); virtual bool Begin() OVERRIDE; - virtual bool End(uint32 submit_count) OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; virtual bool Process() OVERRIDE; virtual void Destroy(bool have_context) OVERRIDE; protected: void Complete(); virtual ~AsyncReadPixelsCompletedQuery(); + + private: + bool completed_; + bool complete_result_; }; AsyncReadPixelsCompletedQuery::AsyncReadPixelsCompletedQuery( QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) - : Query(manager, target, shm_id, shm_offset) { + : Query(manager, target, shm_id, shm_offset), + completed_(false), + complete_result_(false) { } bool AsyncReadPixelsCompletedQuery::Begin() { return true; } -bool AsyncReadPixelsCompletedQuery::End(uint32 submit_count) { +bool AsyncReadPixelsCompletedQuery::End(base::subtle::Atomic32 submit_count) { if (!AddToPendingQueue(submit_count)) { return false; } @@ -326,15 +324,16 @@ bool AsyncReadPixelsCompletedQuery::End(uint32 submit_count) { base::Bind(&AsyncReadPixelsCompletedQuery::Complete, AsWeakPtr())); - return true; + return Process(); } void AsyncReadPixelsCompletedQuery::Complete() { - MarkAsCompleted(1); + completed_ = true; + complete_result_ = MarkAsCompleted(1); } bool AsyncReadPixelsCompletedQuery::Process() { - return true; + return !completed_ || complete_result_; } void AsyncReadPixelsCompletedQuery::Destroy(bool /* have_context */) { @@ -353,7 +352,7 @@ class GetErrorQuery : public QueryManager::Query { QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); virtual bool Begin() OVERRIDE; - virtual bool End(uint32 submit_count) OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; virtual bool Process() OVERRIDE; virtual void Destroy(bool have_context) OVERRIDE; @@ -372,7 +371,7 @@ bool GetErrorQuery::Begin() { return true; } -bool GetErrorQuery::End(uint32 submit_count) { +bool GetErrorQuery::End(base::subtle::Atomic32 submit_count) { MarkAsPending(submit_count); return MarkAsCompleted(manager()->decoder()->GetErrorState()->GetGLError()); } @@ -391,6 +390,55 @@ void GetErrorQuery::Destroy(bool /* have_context */) { GetErrorQuery::~GetErrorQuery() { } +class CommandsCompletedQuery : public QueryManager::Query { + public: + CommandsCompletedQuery(QueryManager* manager, + GLenum target, + int32 shm_id, + uint32 shm_offset); + + // Overridden from QueryManager::Query: + virtual bool Begin() OVERRIDE; + virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE; + virtual bool Process() OVERRIDE; + virtual void Destroy(bool have_context) OVERRIDE; + + protected: + virtual ~CommandsCompletedQuery(); + + private: + scoped_ptr<gfx::GLFence> fence_; +}; + +CommandsCompletedQuery::CommandsCompletedQuery(QueryManager* manager, + GLenum target, + int32 shm_id, + uint32 shm_offset) + : Query(manager, target, shm_id, shm_offset) {} + +bool CommandsCompletedQuery::Begin() { return true; } + +bool CommandsCompletedQuery::End(base::subtle::Atomic32 submit_count) { + fence_.reset(gfx::GLFence::Create()); + DCHECK(fence_); + return AddToPendingQueue(submit_count); +} + +bool CommandsCompletedQuery::Process() { + if (fence_ && !fence_->HasCompleted()) + return true; + return MarkAsCompleted(0); +} + +void CommandsCompletedQuery::Destroy(bool have_context) { + if (have_context && !IsDeleted()) { + fence_.reset(); + MarkAsDeleted(); + } +} + +CommandsCompletedQuery::~CommandsCompletedQuery() {} + QueryManager::QueryManager( GLES2Decoder* decoder, FeatureInfo* feature_info) @@ -446,6 +494,9 @@ QueryManager::Query* QueryManager::CreateQuery( case GL_GET_ERROR_QUERY_CHROMIUM: query = new GetErrorQuery(this, target, shm_id, shm_offset); break; + case GL_COMMANDS_COMPLETED_CHROMIUM: + query = new CommandsCompletedQuery(this, target, shm_id, shm_offset); + break; default: { GLuint service_id = 0; glGenQueriesARB(1, &service_id); @@ -461,6 +512,18 @@ QueryManager::Query* QueryManager::CreateQuery( return query.get(); } +void QueryManager::GenQueries(GLsizei n, const GLuint* queries) { + DCHECK_GE(n, 0); + for (GLsizei i = 0; i < n; ++i) { + generated_query_ids_.insert(queries[i]); + } +} + +bool QueryManager::IsValidQuery(GLuint id) { + GeneratedQueryIds::iterator it = generated_query_ids_.find(id); + return it != generated_query_ids_.end(); +} + QueryManager::Query* QueryManager::GetQuery( GLuint client_id) { QueryMap::iterator it = queries_.find(client_id); @@ -475,6 +538,7 @@ void QueryManager::RemoveQuery(GLuint client_id) { query->MarkAsDeleted(); queries_.erase(it); } + generated_query_ids_.erase(client_id); } void QueryManager::StartTracking(QueryManager::Query* /* query */) { @@ -566,10 +630,7 @@ bool QueryManager::Query::MarkAsCompleted(uint64 result) { pending_ = false; sync->result = result; - // Need a MemoryBarrier here so that sync->result is written before - // sync->process_count. - base::subtle::MemoryBarrier(); - sync->process_count = submit_count_; + base::subtle::Release_Store(&sync->process_count, submit_count_); return true; } @@ -614,7 +675,8 @@ bool QueryManager::HavePendingTransferQueries() { return !pending_transfer_queries_.empty(); } -bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { +bool QueryManager::AddPendingQuery(Query* query, + base::subtle::Atomic32 submit_count) { DCHECK(query); DCHECK(!query->IsDeleted()); if (!RemovePendingQuery(query)) { @@ -625,7 +687,9 @@ bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { return true; } -bool QueryManager::AddPendingTransferQuery(Query* query, uint32 submit_count) { +bool QueryManager::AddPendingTransferQuery( + Query* query, + base::subtle::Atomic32 submit_count) { DCHECK(query); DCHECK(!query->IsDeleted()); if (!RemovePendingQuery(query)) { @@ -671,7 +735,7 @@ bool QueryManager::BeginQuery(Query* query) { return query->Begin(); } -bool QueryManager::EndQuery(Query* query, uint32 submit_count) { +bool QueryManager::EndQuery(Query* query, base::subtle::Atomic32 submit_count) { DCHECK(query); if (!RemovePendingQuery(query)) { return false; diff --git a/chromium/gpu/command_buffer/service/query_manager.h b/chromium/gpu/command_buffer/service/query_manager.h index d77982b897f..36d424cefb3 100644 --- a/chromium/gpu/command_buffer/service/query_manager.h +++ b/chromium/gpu/command_buffer/service/query_manager.h @@ -7,6 +7,7 @@ #include <deque> #include <vector> +#include "base/atomicops.h" #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/logging.h" @@ -61,7 +62,7 @@ class GPU_EXPORT QueryManager { virtual bool Begin() = 0; // Returns false if shared memory for sync is invalid. - virtual bool End(uint32 submit_count) = 0; + virtual bool End(base::subtle::Atomic32 submit_count) = 0; // Returns false if shared memory for sync is invalid. virtual bool Process() = 0; @@ -84,7 +85,7 @@ class GPU_EXPORT QueryManager { // Returns false if shared memory for sync is invalid. bool MarkAsCompleted(uint64 result); - void MarkAsPending(uint32 submit_count) { + void MarkAsPending(base::subtle::Atomic32 submit_count) { DCHECK(!pending_); pending_ = true; submit_count_ = submit_count; @@ -96,12 +97,12 @@ class GPU_EXPORT QueryManager { } // Returns false if shared memory for sync is invalid. - bool AddToPendingQueue(uint32 submit_count) { + bool AddToPendingQueue(base::subtle::Atomic32 submit_count) { return manager_->AddPendingQuery(this, submit_count); } // Returns false if shared memory for sync is invalid. - bool AddToPendingTransferQueue(uint32 submit_count) { + bool AddToPendingTransferQueue(base::subtle::Atomic32 submit_count) { return manager_->AddPendingTransferQuery(this, submit_count); } @@ -113,9 +114,7 @@ class GPU_EXPORT QueryManager { manager_->EndQueryHelper(target); } - uint32 submit_count() const { - return submit_count_; - } + base::subtle::Atomic32 submit_count() const { return submit_count_; } private: friend class QueryManager; @@ -135,7 +134,7 @@ class GPU_EXPORT QueryManager { uint32 shm_offset_; // Count to set process count do when completed. - uint32 submit_count_; + base::subtle::Atomic32 submit_count_; // True if in the queue. bool pending_; @@ -169,7 +168,7 @@ class GPU_EXPORT QueryManager { bool BeginQuery(Query* query); // Returns false if any query is pointing to invalid shared memory. - bool EndQuery(Query* query, uint32 submit_count); + bool EndQuery(Query* query, base::subtle::Atomic32 submit_count); // Processes pending queries. Returns false if any queries are pointing // to invalid shared memory. @@ -189,6 +188,9 @@ class GPU_EXPORT QueryManager { return decoder_; } + void GenQueries(GLsizei n, const GLuint* queries); + bool IsValidQuery(GLuint id); + private: void StartTracking(Query* query); void StopTracking(Query* query); @@ -200,11 +202,12 @@ class GPU_EXPORT QueryManager { // Adds to queue of queries waiting for completion. // Returns false if any query is pointing to invalid shared memory. - bool AddPendingQuery(Query* query, uint32 submit_count); + bool AddPendingQuery(Query* query, base::subtle::Atomic32 submit_count); // Adds to queue of transfer queries waiting for completion. // Returns false if any query is pointing to invalid shared memory. - bool AddPendingTransferQuery(Query* query, uint32 submit_count); + bool AddPendingTransferQuery(Query* query, + base::subtle::Atomic32 submit_count); // Removes a query from the queue of pending queries. // Returns false if any query is pointing to invalid shared memory. @@ -228,6 +231,9 @@ class GPU_EXPORT QueryManager { typedef base::hash_map<GLuint, scoped_refptr<Query> > QueryMap; QueryMap queries_; + typedef base::hash_set<GLuint> GeneratedQueryIds; + GeneratedQueryIds generated_query_ids_; + // Queries waiting for completion. typedef std::deque<scoped_refptr<Query> > QueryQueue; QueryQueue pending_queries_; diff --git a/chromium/gpu/command_buffer/service/query_manager_unittest.cc b/chromium/gpu/command_buffer/service/query_manager_unittest.cc index 0c0829346a6..9f0156f791a 100644 --- a/chromium/gpu/command_buffer/service/query_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/query_manager_unittest.cc @@ -6,9 +6,10 @@ #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/error_state_mock.h" +#include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" -#include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" @@ -21,7 +22,7 @@ using ::testing::SetArgumentPointee; namespace gpu { namespace gles2 { -class QueryManagerTest : public testing::Test { +class QueryManagerTest : public GpuServiceTest { public: static const int32 kSharedMemoryId = 401; static const size_t kSharedBufferSize = 2048; @@ -38,8 +39,7 @@ class QueryManagerTest : public testing::Test { protected: virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); engine_.reset(new MockCommandBufferEngine()); decoder_.reset(new MockGLES2Decoder()); decoder_->set_engine(engine_.get()); @@ -56,8 +56,7 @@ class QueryManagerTest : public testing::Test { manager_->Destroy(false); manager_.reset(); engine_.reset(); - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + GpuServiceTest::TearDown(); } QueryManager::Query* CreateQuery( @@ -69,8 +68,9 @@ class QueryManagerTest : public testing::Test { return manager_->CreateQuery(target, client_id, shm_id, shm_offset); } - void QueueQuery( - QueryManager::Query* query, GLuint service_id, uint32 submit_count) { + void QueueQuery(QueryManager::Query* query, + GLuint service_id, + base::subtle::Atomic32 submit_count) { EXPECT_CALL(*gl_, BeginQueryARB(query->target(), service_id)) .Times(1) .RetiresOnSaturation(); @@ -81,8 +81,6 @@ class QueryManagerTest : public testing::Test { EXPECT_TRUE(manager_->EndQuery(query, submit_count)); } - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_ptr<MockGLES2Decoder> decoder_; scoped_ptr<QueryManager> manager_; @@ -90,21 +88,24 @@ class QueryManagerTest : public testing::Test { class MockCommandBufferEngine : public CommandBufferEngine { public: MockCommandBufferEngine() { - data_.reset(new int8[kSharedBufferSize]); + scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + shared_memory->CreateAndMapAnonymous(kSharedBufferSize); + valid_buffer_ = + MakeBufferFromSharedMemory(shared_memory.Pass(), kSharedBufferSize); + data_ = static_cast<uint8*>(valid_buffer_->memory()); ClearSharedMemory(); - valid_buffer_.ptr = data_.get(); - valid_buffer_.size = kSharedBufferSize; } virtual ~MockCommandBufferEngine() { } - virtual gpu::Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE { + virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id) + OVERRIDE { return shm_id == kSharedMemoryId ? valid_buffer_ : invalid_buffer_; } void ClearSharedMemory() { - memset(data_.get(), kInitialMemoryValue, kSharedBufferSize); + memset(data_, kInitialMemoryValue, kSharedBufferSize); } virtual void set_token(int32 token) OVERRIDE { @@ -129,9 +130,9 @@ class QueryManagerTest : public testing::Test { } private: - scoped_ptr<int8[]> data_; - gpu::Buffer valid_buffer_; - gpu::Buffer invalid_buffer_; + uint8* data_; + scoped_refptr<gpu::Buffer> valid_buffer_; + scoped_refptr<gpu::Buffer> invalid_buffer_; }; scoped_ptr<MockCommandBufferEngine> engine_; @@ -214,7 +215,7 @@ TEST_F(QueryManagerTest, ProcessPendingQuery) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT; - const uint32 kSubmitCount = 123; + const base::subtle::Atomic32 kSubmitCount = 123; const GLuint kResult = 1; // Check nothing happens if there are no pending queries. @@ -245,7 +246,7 @@ TEST_F(QueryManagerTest, ProcessPendingQuery) { .RetiresOnSaturation(); EXPECT_TRUE(manager_->ProcessPendingQueries()); EXPECT_TRUE(query->pending()); - EXPECT_EQ(0u, sync->process_count); + EXPECT_EQ(0, sync->process_count); EXPECT_EQ(0u, sync->result); // Process with return available. @@ -277,9 +278,9 @@ TEST_F(QueryManagerTest, ProcessPendingQueries) { const GLuint kClient3Id = 3; const GLuint kService3Id = 13; const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT; - const uint32 kSubmitCount1 = 123; - const uint32 kSubmitCount2 = 123; - const uint32 kSubmitCount3 = 123; + const base::subtle::Atomic32 kSubmitCount1 = 123; + const base::subtle::Atomic32 kSubmitCount2 = 123; + const base::subtle::Atomic32 kSubmitCount3 = 123; const GLuint kResult1 = 1; const GLuint kResult2 = 1; const GLuint kResult3 = 1; @@ -355,7 +356,7 @@ TEST_F(QueryManagerTest, ProcessPendingQueries) { EXPECT_EQ(kSubmitCount2, sync2->process_count); EXPECT_EQ(kResult1, sync1->result); EXPECT_EQ(kResult2, sync2->result); - EXPECT_EQ(0u, sync3->process_count); + EXPECT_EQ(0, sync3->process_count); EXPECT_EQ(0u, sync3->result); EXPECT_TRUE(manager_->HavePendingQueries()); @@ -367,7 +368,7 @@ TEST_F(QueryManagerTest, ProcessPendingQueries) { .RetiresOnSaturation(); EXPECT_TRUE(manager_->ProcessPendingQueries()); EXPECT_TRUE(query3->pending()); - EXPECT_EQ(0u, sync3->process_count); + EXPECT_EQ(0, sync3->process_count); EXPECT_EQ(0u, sync3->result); EXPECT_TRUE(manager_->HavePendingQueries()); @@ -392,7 +393,7 @@ TEST_F(QueryManagerTest, ProcessPendingBadSharedMemoryId) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT; - const uint32 kSubmitCount = 123; + const base::subtle::Atomic32 kSubmitCount = 123; const GLuint kResult = 1; // Create Query. @@ -421,7 +422,7 @@ TEST_F(QueryManagerTest, ProcessPendingBadSharedMemoryOffset) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT; - const uint32 kSubmitCount = 123; + const base::subtle::Atomic32 kSubmitCount = 123; const GLuint kResult = 1; // Create Query. @@ -450,7 +451,7 @@ TEST_F(QueryManagerTest, ExitWithPendingQuery) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT; - const uint32 kSubmitCount = 123; + const base::subtle::Atomic32 kSubmitCount = 123; // Create Query. scoped_refptr<QueryManager::Query> query( @@ -468,7 +469,7 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery2) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; const GLenum kTarget = GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT; - const uint32 kSubmitCount = 123; + const base::subtle::Atomic32 kSubmitCount = 123; TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), @@ -502,7 +503,7 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT; - const uint32 kSubmitCount = 123; + const base::subtle::Atomic32 kSubmitCount = 123; TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), @@ -533,7 +534,7 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery) { TEST_F(QueryManagerTest, GetErrorQuery) { const GLuint kClient1Id = 1; const GLenum kTarget = GL_GET_ERROR_QUERY_CHROMIUM; - const uint32 kSubmitCount = 123; + const base::subtle::Atomic32 kSubmitCount = 123; TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), ""); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); diff --git a/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc index 87fde79bf09..ba0ebea8700 100644 --- a/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc @@ -6,6 +6,7 @@ #include <set> #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mocks.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_implementation.h" @@ -16,15 +17,14 @@ using ::testing::StrictMock; namespace gpu { namespace gles2 { -class RenderbufferManagerTestBase : public testing::Test { +class RenderbufferManagerTestBase : public GpuServiceTest { public: static const GLint kMaxSize = 128; static const GLint kMaxSamples = 4; protected: void SetUpBase(MemoryTracker* memory_tracker, bool depth24_supported) { - gl_.reset(new ::testing::StrictMock<gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); manager_.reset(new RenderbufferManager( memory_tracker, kMaxSize, kMaxSamples, depth24_supported)); } @@ -32,12 +32,9 @@ class RenderbufferManagerTestBase : public testing::Test { virtual void TearDown() { manager_->Destroy(true); manager_.reset(); - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + GpuServiceTest::TearDown(); } - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_ptr<RenderbufferManager> manager_; }; diff --git a/chromium/gpu/command_buffer/service/safe_shared_memory_pool.cc b/chromium/gpu/command_buffer/service/safe_shared_memory_pool.cc deleted file mode 100644 index 9ba5390d200..00000000000 --- a/chromium/gpu/command_buffer/service/safe_shared_memory_pool.cc +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/process/process_handle.h" -#include "build/build_config.h" - -using base::SharedMemory; -using base::SharedMemoryHandle; - -namespace gpu { - -ScopedSafeSharedMemory::ScopedSafeSharedMemory(SafeSharedMemoryPool* pool, - base::SharedMemory* memory, - size_t shm_size) { - DCHECK(pool); - DCHECK(memory); - DCHECK(memory->memory()); - pool_ = pool; - original_handle_ = memory->handle(); - safe_shared_memory_ = pool->AcquireSafeSharedMemory(memory, shm_size); - CHECK(safe_shared_memory_); -} - -ScopedSafeSharedMemory::~ScopedSafeSharedMemory() { - // Release the handle. The pool will delete the SharedMemory - // object when it is no longer referenced. - pool_->ReleaseSafeSharedMemory(original_handle_); -} - -base::SharedMemory* ScopedSafeSharedMemory::shared_memory() { - return safe_shared_memory_; -} - -SafeSharedMemoryPool::SafeSharedMemoryPool() - : handles_acquired_(0), - handles_consumed_(0), - address_space_consumed_(0), - max_handles_acquired_(0), - max_handles_consumed_(0), - max_address_space_consumed_(0) { -} - -SafeSharedMemoryPool::~SafeSharedMemoryPool() { -} - -base::SharedMemory* SafeSharedMemoryPool:: - AcquireSafeSharedMemory(base::SharedMemory* shared_memory, - size_t shm_size) { - DCHECK(shared_memory); - DCHECK(shared_memory->memory()); - base::AutoLock scoped_lock(lock_); - - // Adjust stats. - handles_acquired_++; - max_handles_acquired_ = std::max(max_handles_acquired_, - handles_acquired_); - - MemoryMap::iterator it = memory_.find(shared_memory->handle()); - // If we don't already have it, duplicated it. - if (it == memory_.end()) { - // Duplicate a new shared memory and track it. - TrackedMemory tracker; - tracker.safe_shared_memory = DuplicateSharedMemory(shared_memory, shm_size); - tracker.reference_count = 1; - tracker.shm_size = shm_size; - memory_[shared_memory->handle()] = tracker; - - // Adjust stats. - handles_consumed_++; - address_space_consumed_ += shm_size; - max_handles_consumed_ = std::max(max_handles_consumed_, - handles_consumed_); - max_address_space_consumed_ = std::max(max_address_space_consumed_, - address_space_consumed_); - return tracker.safe_shared_memory; - } - - // Otherwise, add a reference and return the existing one. - DCHECK(it->second.reference_count); - DCHECK(it->second.safe_shared_memory); - DCHECK(it->second.safe_shared_memory->memory()); - it->second.reference_count++; - return it->second.safe_shared_memory; -} - -void SafeSharedMemoryPool:: - ReleaseSafeSharedMemory(const base::SharedMemoryHandle& handle) { - base::AutoLock scoped_lock(lock_); - - // Adjust stats. - DCHECK_GT(handles_acquired_, 0); - handles_acquired_--; - - MemoryMap::iterator it = memory_.find(handle); - CHECK(it != memory_.end()); - CHECK(it->second.reference_count); - CHECK(it->second.safe_shared_memory); - if (--it->second.reference_count == 0) { - // Adjust stats. - DCHECK_GT(handles_consumed_, 0); - handles_consumed_--; - DCHECK_LE(it->second.shm_size, address_space_consumed_); - address_space_consumed_ -= it->second.shm_size; - // Delete the safe memory and remove it. - delete it->second.safe_shared_memory; - memory_.erase(it); - } -} - -SharedMemory* SafeSharedMemoryPool::DuplicateSharedMemory( - SharedMemory* shared_memory, size_t size) { - // Duplicate the handle. - SharedMemoryHandle duped_shared_memory_handle; - if (!shared_memory->ShareToProcess( - base::GetCurrentProcessHandle(), - &duped_shared_memory_handle)) { - PLOG(ERROR) << "Failed SharedMemory::ShareToProcess"; - LOG(ERROR) << "Total handles acquired " << handles_acquired_; - LOG(ERROR) << "Total handles open " << handles_consumed_; - LOG(ERROR) << "Total address space " << address_space_consumed_; - LOG(ERROR) << "Max handles acquired " << max_handles_acquired_; - LOG(ERROR) << "Max handles open " << max_handles_consumed_; - LOG(ERROR) << "Max address space " << max_address_space_consumed_; - CHECK(false); // Diagnosing a crash. - return NULL; - } - scoped_ptr<SharedMemory> duped_shared_memory( - new SharedMemory(duped_shared_memory_handle, false)); - // Map the shared memory into this process. This validates the size. - if (!duped_shared_memory->Map(size)) { - PLOG(ERROR) << "Failed SharedMemory::Map(" << size << ")"; - LOG(ERROR) << "Total handles acquired " << handles_acquired_; - LOG(ERROR) << "Total handles open " << handles_consumed_; - LOG(ERROR) << "Total address space " << address_space_consumed_; - LOG(ERROR) << "Max handles acquired " << max_handles_acquired_; - LOG(ERROR) << "Max handles open " << max_handles_consumed_; - LOG(ERROR) << "Max address space " << max_address_space_consumed_; - CHECK(false); // Diagnosing a crash. - return NULL; - } - return duped_shared_memory.release(); -} - -} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/safe_shared_memory_pool.h b/chromium/gpu/command_buffer/service/safe_shared_memory_pool.h deleted file mode 100644 index fed17ff3726..00000000000 --- a/chromium/gpu/command_buffer/service/safe_shared_memory_pool.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_ -#define GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/memory/shared_memory.h" -#include "base/synchronization/lock.h" -#include "build/build_config.h" - -namespace gpu { -class SafeSharedMemoryPool; - -// These classes exist to help protect against deletion of shared -// memory that is being used on a worker thread. It's mainly a -// security measure to prevent use-after-free in the browser, due -// to a misbehaving client. That said, this should be removed -// in favor of higher-level reference counting of an appropriate -// opaque 'memory blob' data-structure. - -class ScopedSafeSharedMemory { - public: - base::SharedMemory* shared_memory(); - ScopedSafeSharedMemory(SafeSharedMemoryPool* pool, - base::SharedMemory* memory, - size_t shm_size); - ~ScopedSafeSharedMemory(); - private: - base::SharedMemory* safe_shared_memory_; - base::SharedMemoryHandle original_handle_; - SafeSharedMemoryPool* pool_; - - DISALLOW_COPY_AND_ASSIGN(ScopedSafeSharedMemory); -}; - -class SafeSharedMemoryPool { - public: - SafeSharedMemoryPool(); - virtual ~SafeSharedMemoryPool(); - - private: - friend class ScopedSafeSharedMemory; - - // Acquires and release shared memory. The acquired shared memory - // is guaranteed to live until it is released. - base::SharedMemory* AcquireSafeSharedMemory(base::SharedMemory*, size_t size); - void ReleaseSafeSharedMemory(const base::SharedMemoryHandle&); - - // Utility function to duplicate shared memory. - base::SharedMemory* DuplicateSharedMemory(base::SharedMemory*, size_t size); - - // Track all SharedMemory's that we have already duplicated. - struct TrackedMemory { - base::SharedMemory* safe_shared_memory; - size_t shm_size; - int reference_count; - }; - - typedef std::map<base::SharedMemoryHandle, TrackedMemory> MemoryMap; - MemoryMap memory_; - - // Track usage to diagnose crashes. - int handles_acquired_; - int handles_consumed_; - size_t address_space_consumed_; - int max_handles_acquired_; - int max_handles_consumed_; - size_t max_address_space_consumed_; - - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(SafeSharedMemoryPool); -}; - -} // namespace gfx - -#endif // GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_ - diff --git a/chromium/gpu/command_buffer/service/shader_manager_unittest.cc b/chromium/gpu/command_buffer/service/shader_manager_unittest.cc index d86aca48bcf..b5b7b383984 100644 --- a/chromium/gpu/command_buffer/service/shader_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/shader_manager_unittest.cc @@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/shader_manager.h" #include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mocks.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" @@ -15,7 +16,7 @@ using ::testing::ReturnRef; namespace gpu { namespace gles2 { -class ShaderManagerTest : public testing::Test { +class ShaderManagerTest : public GpuServiceTest { public: ShaderManagerTest() { } @@ -25,18 +26,6 @@ class ShaderManagerTest : public testing::Test { } protected: - virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - } - - virtual void TearDown() { - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); - } - - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; ShaderManager manager_; }; diff --git a/chromium/gpu/command_buffer/service/shader_translator.cc b/chromium/gpu/command_buffer/service/shader_translator.cc index 37e2dc64d33..3964c2db16b 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.cc +++ b/chromium/gpu/command_buffer/service/shader_translator.cc @@ -9,6 +9,7 @@ #include "base/at_exit.h" #include "base/debug/trace_event.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" @@ -16,21 +17,21 @@ namespace { using gpu::gles2::ShaderTranslator; -void FinalizeShaderTranslator(void* /* dummy */) { - TRACE_EVENT0("gpu", "ShFinalize"); - ShFinalize(); -} - -bool InitializeShaderTranslator() { - static bool initialized = false; - if (!initialized) { +class ShaderTranslatorInitializer { + public: + ShaderTranslatorInitializer() { TRACE_EVENT0("gpu", "ShInitialize"); CHECK(ShInitialize()); - base::AtExitManager::RegisterCallback(&FinalizeShaderTranslator, NULL); - initialized = true; } - return initialized; -} + + ~ShaderTranslatorInitializer() { + TRACE_EVENT0("gpu", "ShFinalize"); + ShFinalize(); + } +}; + +base::LazyInstance<ShaderTranslatorInitializer> g_translator_initializer = + LAZY_INSTANCE_INITIALIZER; #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108 typedef int ANGLEGetInfoType; @@ -133,8 +134,7 @@ bool ShaderTranslator::Init( DCHECK(shader_spec == SH_GLES2_SPEC || shader_spec == SH_WEBGL_SPEC); DCHECK(resources != NULL); - if (!InitializeShaderTranslator()) - return false; + g_translator_initializer.Get(); ShShaderOutput shader_output = (glsl_implementation_type == kGlslES ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT); @@ -152,11 +152,9 @@ bool ShaderTranslator::Init( int ShaderTranslator::GetCompileOptions() const { int compile_options = - SH_OBJECT_CODE | SH_VARIABLES | - SH_MAP_LONG_VARIABLE_NAMES | SH_ENFORCE_PACKING_RESTRICTIONS | - SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH; - - compile_options |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS; + SH_OBJECT_CODE | SH_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS | + SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH | + SH_CLAMP_INDIRECT_ARRAY_BOUNDS; compile_options |= driver_bug_workarounds_; @@ -203,9 +201,29 @@ bool ShaderTranslator::Translate(const char* shader) { return success; } -std::string ShaderTranslator::GetStringForOptionsThatWouldEffectCompilation() +std::string ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation() const { +#if ANGLE_SH_VERSION >= 124 + DCHECK(compiler_ != NULL); + + ANGLEGetInfoType resource_len = 0; + ShGetInfo(compiler_, SH_RESOURCES_STRING_LENGTH, &resource_len); + DCHECK(resource_len > 1); + scoped_ptr<char[]> resource_str(new char[resource_len]); + + ShGetBuiltInResourcesString(compiler_, resource_len, resource_str.get()); + + return std::string(":CompileOptions:" + + base::IntToString(GetCompileOptions())) + + std::string(resource_str.get()); +#else +#if ANGLE_SH_VERSION >= 123 + const size_t kNumIntFields = 21; +#elif ANGLE_SH_VERSION >= 122 + const size_t kNumIntFields = 20; +#else const size_t kNumIntFields = 16; +#endif const size_t kNumEnumFields = 1; const size_t kNumFunctionPointerFields = 1; struct MustMatchShBuiltInResource { @@ -256,7 +274,24 @@ std::string ShaderTranslator::GetStringForOptionsThatWouldEffectCompilation() ":MaxCallStackDepth:" + base::IntToString(compiler_options_.MaxCallStackDepth) + ":EXT_frag_depth:" + +#if ANGLE_SH_VERSION >= 122 + base::IntToString(compiler_options_.EXT_frag_depth) + +#if ANGLE_SH_VERSION >= 123 + ":EXT_shader_texture_lod:" + + base::IntToString(compiler_options_.EXT_shader_texture_lod) + +#endif + ":MaxVertexOutputVectors:" + + base::IntToString(compiler_options_.MaxVertexOutputVectors) + + ":MaxFragmentInputVectors:" + + base::IntToString(compiler_options_.MaxFragmentInputVectors) + + ":MinProgramTexelOffset:" + + base::IntToString(compiler_options_.MinProgramTexelOffset) + + ":MaxProgramTexelOffset:" + + base::IntToString(compiler_options_.MaxProgramTexelOffset)); +#else // ANGLE_SH_VERSION < 122 base::IntToString(compiler_options_.EXT_frag_depth)); +#endif +#endif } const char* ShaderTranslator::translated_shader() const { diff --git a/chromium/gpu/command_buffer/service/shader_translator.h b/chromium/gpu/command_buffer/service/shader_translator.h index b9bacf155e6..d993967da9b 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.h +++ b/chromium/gpu/command_buffer/service/shader_translator.h @@ -89,8 +89,8 @@ class ShaderTranslatorInterface { virtual const NameMap& name_map() const = 0; // Return a string that is unique for a specfic set of options that would - // possibly effect compilation. - virtual std::string GetStringForOptionsThatWouldEffectCompilation() const = 0; + // possibly affect compilation. + virtual std::string GetStringForOptionsThatWouldAffectCompilation() const = 0; protected: virtual ~ShaderTranslatorInterface() {} @@ -135,7 +135,7 @@ class GPU_EXPORT ShaderTranslator virtual const VariableMap& varying_map() const OVERRIDE; virtual const NameMap& name_map() const OVERRIDE; - virtual std::string GetStringForOptionsThatWouldEffectCompilation() const + virtual std::string GetStringForOptionsThatWouldAffectCompilation() const OVERRIDE; void AddDestructionObserver(DestructionObserver* observer); diff --git a/chromium/gpu/command_buffer/service/shader_translator_cache.cc b/chromium/gpu/command_buffer/service/shader_translator_cache.cc index 9626a0e25ef..f204186c7e7 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_cache.cc +++ b/chromium/gpu/command_buffer/service/shader_translator_cache.cc @@ -7,14 +7,11 @@ namespace gpu { namespace gles2 { -ShaderTranslatorCache* ShaderTranslatorCache::GetInstance() { - return Singleton<ShaderTranslatorCache>::get(); -} - ShaderTranslatorCache::ShaderTranslatorCache() { } ShaderTranslatorCache::~ShaderTranslatorCache() { + DCHECK(cache_.empty()); } void ShaderTranslatorCache::OnDestruct(ShaderTranslator* translator) { diff --git a/chromium/gpu/command_buffer/service/shader_translator_cache.h b/chromium/gpu/command_buffer/service/shader_translator_cache.h index 8439d533987..32b7f5f84a1 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_cache.h +++ b/chromium/gpu/command_buffer/service/shader_translator_cache.h @@ -10,22 +10,23 @@ #include <map> #include "base/memory/ref_counted.h" -#include "base/memory/singleton.h" #include "gpu/command_buffer/service/shader_translator.h" #include "third_party/angle/include/GLSLANG/ShaderLang.h" namespace gpu { namespace gles2 { -// This singleton and the cache that it implements is NOT thread safe. -// We're relying on the fact that the all GLES2DecoderImpl's are used -// on one thread. +// This class is not thread safe and can only be created and destroyed +// on a single thread. But it is safe to use two independent instances on two +// threads without synchronization. // // TODO(backer): Investigate using glReleaseShaderCompiler as an alternative to // to this cache. -class ShaderTranslatorCache : public ShaderTranslator::DestructionObserver { +class GPU_EXPORT ShaderTranslatorCache + : public base::RefCounted<ShaderTranslatorCache>, + public NON_EXPORTED_BASE(ShaderTranslator::DestructionObserver) { public: - static ShaderTranslatorCache* GetInstance(); + ShaderTranslatorCache(); // ShaderTranslator::DestructionObserver implementation virtual void OnDestruct(ShaderTranslator* translator) OVERRIDE; @@ -39,11 +40,9 @@ class ShaderTranslatorCache : public ShaderTranslator::DestructionObserver { ShCompileOptions driver_bug_workarounds); private: - ShaderTranslatorCache(); + friend class base::RefCounted<ShaderTranslatorCache>; virtual ~ShaderTranslatorCache(); - friend struct DefaultSingletonTraits<ShaderTranslatorCache>; - // Parameters passed into ShaderTranslator::Init struct ShaderTranslatorInitParams { ShShaderType shader_type; diff --git a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc index 1b53c2b768b..233b412024c 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc +++ b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc @@ -19,9 +19,10 @@ class ShaderTranslatorTest : public testing::Test { protected: virtual void SetUp() { ShBuiltInResources resources; + ShInitBuiltInResources(&resources); resources.MaxExpressionComplexity = 32; resources.MaxCallStackDepth = 32; - ShInitBuiltInResources(&resources); + vertex_translator_ = new ShaderTranslator(); fragment_translator_ = new ShaderTranslator(); @@ -244,13 +245,13 @@ TEST_F(ShaderTranslatorTest, OptionsString) { SH_EMULATE_BUILT_IN_FUNCTIONS)); std::string options_1( - translator_1->GetStringForOptionsThatWouldEffectCompilation()); + translator_1->GetStringForOptionsThatWouldAffectCompilation()); std::string options_2( - translator_1->GetStringForOptionsThatWouldEffectCompilation()); + translator_1->GetStringForOptionsThatWouldAffectCompilation()); std::string options_3( - translator_2->GetStringForOptionsThatWouldEffectCompilation()); + translator_2->GetStringForOptionsThatWouldAffectCompilation()); std::string options_4( - translator_3->GetStringForOptionsThatWouldEffectCompilation()); + translator_3->GetStringForOptionsThatWouldAffectCompilation()); EXPECT_EQ(options_1, options_2); EXPECT_NE(options_1, options_3); diff --git a/chromium/gpu/command_buffer/service/stream_texture.h b/chromium/gpu/command_buffer/service/stream_texture.h deleted file mode 100644 index bcddc82dd82..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_H_ -#define GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_H_ - -#include "base/basictypes.h" -#include "ui/gfx/size.h" - -namespace gpu { - -class StreamTexture { - public: - StreamTexture() { - } - - virtual ~StreamTexture() { - } - - virtual void Update() = 0; - - // Get the size of the StreamTexture. - virtual gfx::Size GetSize() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(StreamTexture); -}; - -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_H_ diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager.h b/chromium/gpu/command_buffer/service/stream_texture_manager.h deleted file mode 100644 index 51119fad528..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture_manager.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_H_ -#define GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_H_ - -#include "base/basictypes.h" - -namespace gpu { - -class StreamTexture; - -// Interface used by the cmd decoder to create and lookup stream textures. -class StreamTextureManager { - public: - StreamTextureManager() { - } - - virtual ~StreamTextureManager() { - } - - // Returns an identifier for the object, or NULL if not successful. - virtual uint32 CreateStreamTexture(uint32 service_id, uint32 client_id) = 0; - - virtual void DestroyStreamTexture(uint32 service_id) = 0; - - virtual StreamTexture* LookupStreamTexture(uint32 service_id) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(StreamTextureManager); -}; - -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_H_ diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc index 2fd55358b4a..a8ece57ebcd 100644 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc +++ b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc @@ -5,41 +5,76 @@ #include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" #include "base/bind.h" +#include "base/callback.h" +#include "gpu/command_buffer/service/texture_manager.h" #include "ui/gfx/size.h" #include "ui/gl/android/surface_texture.h" #include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_image.h" namespace gpu { -StreamTextureManagerInProcess::StreamTextureImpl::StreamTextureImpl( - uint32 service_id, - uint32 stream_id) - : surface_texture_(new gfx::SurfaceTexture(service_id)), - stream_id_(stream_id) {} +namespace { -StreamTextureManagerInProcess::StreamTextureImpl::~StreamTextureImpl() {} +// Simply wraps a SurfaceTexture reference as a GLImage. +class GLImageImpl : public gfx::GLImage { + public: + GLImageImpl(const scoped_refptr<gfx::SurfaceTexture>& surface_texture, + const base::Closure& release_callback); -void StreamTextureManagerInProcess::StreamTextureImpl::Update() { - GLint texture_id = 0; - glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id); + // implement gfx::GLImage + virtual void Destroy() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual bool BindTexImage(unsigned target) OVERRIDE; + virtual void ReleaseTexImage(unsigned target) OVERRIDE; + virtual void WillUseTexImage() OVERRIDE; + virtual void DidUseTexImage() OVERRIDE {} + virtual void WillModifyTexImage() OVERRIDE {} + virtual void DidModifyTexImage() OVERRIDE {} + + private: + virtual ~GLImageImpl(); + + scoped_refptr<gfx::SurfaceTexture> surface_texture_; + base::Closure release_callback_; + + DISALLOW_COPY_AND_ASSIGN(GLImageImpl); +}; + +GLImageImpl::GLImageImpl( + const scoped_refptr<gfx::SurfaceTexture>& surface_texture, + const base::Closure& release_callback) + : surface_texture_(surface_texture), release_callback_(release_callback) {} + +GLImageImpl::~GLImageImpl() { + release_callback_.Run(); +} + +void GLImageImpl::Destroy() { + NOTREACHED(); +} + +void GLImageImpl::WillUseTexImage() { surface_texture_->UpdateTexImage(); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id); } -gfx::Size StreamTextureManagerInProcess::StreamTextureImpl::GetSize() { - return size_; +bool GLImageImpl::BindTexImage(unsigned target) { + NOTREACHED(); + return false; } -void StreamTextureManagerInProcess::StreamTextureImpl::SetSize(gfx::Size size) { - size_ = size; +void GLImageImpl::ReleaseTexImage(unsigned target) { + NOTREACHED(); } -scoped_refptr<gfx::SurfaceTexture> -StreamTextureManagerInProcess::StreamTextureImpl::GetSurfaceTexture() { - return surface_texture_; +gfx::Size GLImageImpl::GetSize() { + return gfx::Size(); } -StreamTextureManagerInProcess::StreamTextureManagerInProcess() : next_id_(1) {} +} // anonymous namespace + +StreamTextureManagerInProcess::StreamTextureManagerInProcess() + : next_id_(1), weak_factory_(this) {} StreamTextureManagerInProcess::~StreamTextureManagerInProcess() { if (!textures_.empty()) { @@ -48,13 +83,47 @@ StreamTextureManagerInProcess::~StreamTextureManagerInProcess() { } } -GLuint StreamTextureManagerInProcess::CreateStreamTexture(uint32 service_id, - uint32 client_id) { - base::AutoLock lock(map_lock_); +GLuint StreamTextureManagerInProcess::CreateStreamTexture( + uint32 client_texture_id, + gles2::TextureManager* texture_manager) { + CalledOnValidThread(); + + gles2::TextureRef* texture = texture_manager->GetTexture(client_texture_id); + + if (!texture || (texture->texture()->target() && + texture->texture()->target() != GL_TEXTURE_EXTERNAL_OES)) { + return 0; + } + + scoped_refptr<gfx::SurfaceTexture> surface_texture( + gfx::SurfaceTexture::Create(texture->service_id())); + uint32 stream_id = next_id_++; - linked_ptr<StreamTextureImpl> texture( - new StreamTextureImpl(service_id, stream_id)); - textures_[service_id] = texture; + base::Closure release_callback = + base::Bind(&StreamTextureManagerInProcess::OnReleaseStreamTexture, + weak_factory_.GetWeakPtr(), stream_id); + scoped_refptr<gfx::GLImage> gl_image(new GLImageImpl(surface_texture, + release_callback)); + + gfx::Size size = gl_image->GetSize(); + texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES); + texture_manager->SetLevelInfo(texture, + GL_TEXTURE_EXTERNAL_OES, + 0, + GL_RGBA, + size.width(), + size.height(), + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image); + + { + base::AutoLock lock(map_lock_); + textures_[stream_id] = surface_texture; + } if (next_id_ == 0) next_id_++; @@ -62,29 +131,19 @@ GLuint StreamTextureManagerInProcess::CreateStreamTexture(uint32 service_id, return stream_id; } -void StreamTextureManagerInProcess::DestroyStreamTexture(uint32 service_id) { +void StreamTextureManagerInProcess::OnReleaseStreamTexture(uint32 stream_id) { + CalledOnValidThread(); base::AutoLock lock(map_lock_); - textures_.erase(service_id); -} - -gpu::StreamTexture* StreamTextureManagerInProcess::LookupStreamTexture( - uint32 service_id) { - base::AutoLock lock(map_lock_); - TextureMap::const_iterator it = textures_.find(service_id); - if (it != textures_.end()) - return it->second.get(); - - return NULL; + textures_.erase(stream_id); } +// This can get called from any thread. scoped_refptr<gfx::SurfaceTexture> StreamTextureManagerInProcess::GetSurfaceTexture(uint32 stream_id) { base::AutoLock lock(map_lock_); - for (TextureMap::iterator it = textures_.begin(); it != textures_.end(); - it++) { - if (it->second->stream_id() == stream_id) - return it->second->GetSurfaceTexture(); - } + TextureMap::const_iterator it = textures_.find(stream_id); + if (it != textures_.end()) + return it->second; return NULL; } diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h index 6753c139989..8b507b058fc 100644 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h +++ b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h @@ -7,66 +7,41 @@ #include <map> -#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" -#include "gpu/command_buffer/service/stream_texture.h" -#include "gpu/command_buffer/service/stream_texture_manager.h" +#include "base/threading/non_thread_safe.h" namespace gfx { -class Size; class SurfaceTexture; } namespace gpu { -class StreamTextureManagerInProcess - : public gpu::StreamTextureManager, - public base::RefCountedThreadSafe<StreamTextureManagerInProcess> { +namespace gles2 { +class TextureManager; +} + +class StreamTextureManagerInProcess : public base::NonThreadSafe { public: StreamTextureManagerInProcess(); + ~StreamTextureManagerInProcess(); - // implement gpu::StreamTextureManager: - virtual uint32 CreateStreamTexture(uint32 service_id, - uint32 client_id) OVERRIDE; - virtual void DestroyStreamTexture(uint32 service_id) OVERRIDE; - virtual gpu::StreamTexture* LookupStreamTexture(uint32 service_id) OVERRIDE; + uint32 CreateStreamTexture(uint32 client_texture_id, + gles2::TextureManager* texture_manager); + // This method can be called from any thread. scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(uint32 stream_id); private: - class StreamTextureImpl : public gpu::StreamTexture { - public: - StreamTextureImpl(uint32 service_id, uint32 stream_id); - virtual ~StreamTextureImpl(); - - // implement gpu::StreamTexture - virtual void Update() OVERRIDE; - virtual gfx::Size GetSize() OVERRIDE; - - void SetSize(gfx::Size size); - - scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(); - uint32 stream_id() { return stream_id_; } - - private: - scoped_refptr<gfx::SurfaceTexture> surface_texture_; - uint32 stream_id_; - gfx::Size size_; + void OnReleaseStreamTexture(uint32 stream_id); - DISALLOW_COPY_AND_ASSIGN(StreamTextureImpl); - }; - - friend class base::RefCountedThreadSafe<StreamTextureManagerInProcess>; - virtual ~StreamTextureManagerInProcess(); - - typedef std::map<uint32, linked_ptr<StreamTextureImpl> > TextureMap; + typedef std::map<uint32, scoped_refptr<gfx::SurfaceTexture> > TextureMap; TextureMap textures_; - - uint32 next_id_; - base::Lock map_lock_; + uint32 next_id_; + base::WeakPtrFactory<StreamTextureManagerInProcess> weak_factory_; DISALLOW_COPY_AND_ASSIGN(StreamTextureManagerInProcess); }; diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager_mock.cc b/chromium/gpu/command_buffer/service/stream_texture_manager_mock.cc deleted file mode 100644 index 75268b86205..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_mock.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/service/stream_texture_manager_mock.h" - -namespace gpu { - -MockStreamTextureManager::MockStreamTextureManager() { -} - -MockStreamTextureManager::~MockStreamTextureManager() { -} - -} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager_mock.h b/chromium/gpu/command_buffer/service/stream_texture_manager_mock.h deleted file mode 100644 index 4b744f21b1e..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_mock.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_MOCK_H_ -#define GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_MOCK_H_ - -#include "base/basictypes.h" -#include "gpu/command_buffer/service/stream_texture_manager.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace gpu { - -class StreamTexture; - -class MockStreamTextureManager : public StreamTextureManager { - public: - MockStreamTextureManager(); - virtual ~MockStreamTextureManager(); - - MOCK_METHOD2(CreateStreamTexture, - uint32(uint32 service_id, uint32 client_id)); - MOCK_METHOD1(DestroyStreamTexture, void(uint32 service_id)); - MOCK_METHOD1(LookupStreamTexture, StreamTexture*(uint32 service_id)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockStreamTextureManager); -}; - -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_MOCK_H_ diff --git a/chromium/gpu/command_buffer/service/stream_texture_mock.cc b/chromium/gpu/command_buffer/service/stream_texture_mock.cc deleted file mode 100644 index 742a4f71ec0..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture_mock.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/service/stream_texture_mock.h" - -namespace gpu { - -MockStreamTexture::MockStreamTexture() { -} - -MockStreamTexture::~MockStreamTexture() { -} - -} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/stream_texture_mock.h b/chromium/gpu/command_buffer/service/stream_texture_mock.h deleted file mode 100644 index cd951d22618..00000000000 --- a/chromium/gpu/command_buffer/service/stream_texture_mock.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MOCK_H_ -#define GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MOCK_H_ - -#include "base/memory/ref_counted.h" -#include "gpu/command_buffer/service/stream_texture.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace gpu { - -class MockStreamTexture : public StreamTexture { - public: - MockStreamTexture(); - virtual ~MockStreamTexture(); - - MOCK_METHOD0(Update, void()); - MOCK_METHOD0(GetSize, gfx::Size(void)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockStreamTexture); -}; - -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MOCK_H_ diff --git a/chromium/gpu/command_buffer/service/test_helper.cc b/chromium/gpu/command_buffer/service/test_helper.cc index 92c5ec456ef..c589be4326a 100644 --- a/chromium/gpu/command_buffer/service/test_helper.cc +++ b/chromium/gpu/command_buffer/service/test_helper.cc @@ -9,7 +9,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" -#include "gpu/command_buffer/common/types.h" #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/gl_utils.h" @@ -61,7 +60,9 @@ const GLint TestHelper::kMaxVertexUniformComponents; #endif void TestHelper::SetupTextureInitializationExpectations( - ::gfx::MockGLInterface* gl, GLenum target) { + ::gfx::MockGLInterface* gl, + GLenum target, + bool use_default_textures) { InSequence sequence; bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); @@ -98,7 +99,7 @@ void TestHelper::SetupTextureInitializationExpectations( NOTREACHED(); } - int array_size = 2; + int array_size = use_default_textures ? 2 : 1; EXPECT_CALL(*gl, GenTextures(array_size, _)) .WillOnce(SetArrayArgument<1>(texture_ids, @@ -139,11 +140,14 @@ void TestHelper::SetupTextureInitializationExpectations( void TestHelper::SetupTextureManagerInitExpectations( ::gfx::MockGLInterface* gl, - const char* extensions) { + const char* extensions, + bool use_default_textures) { InSequence sequence; - SetupTextureInitializationExpectations(gl, GL_TEXTURE_2D); - SetupTextureInitializationExpectations(gl, GL_TEXTURE_CUBE_MAP); + SetupTextureInitializationExpectations( + gl, GL_TEXTURE_2D, use_default_textures); + SetupTextureInitializationExpectations( + gl, GL_TEXTURE_CUBE_MAP, use_default_textures); bool ext_image_external = false; bool arb_texture_rectangle = false; @@ -160,15 +164,22 @@ void TestHelper::SetupTextureManagerInitExpectations( } if (ext_image_external) { - SetupTextureInitializationExpectations(gl, GL_TEXTURE_EXTERNAL_OES); + SetupTextureInitializationExpectations( + gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); } if (arb_texture_rectangle) { - SetupTextureInitializationExpectations(gl, GL_TEXTURE_RECTANGLE_ARB); + SetupTextureInitializationExpectations( + gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); } } void TestHelper::SetupTextureDestructionExpectations( - ::gfx::MockGLInterface* gl, GLenum target) { + ::gfx::MockGLInterface* gl, + GLenum target, + bool use_default_textures) { + if (!use_default_textures) + return; + GLuint texture_id = 0; switch (target) { case GL_TEXTURE_2D: @@ -194,9 +205,11 @@ void TestHelper::SetupTextureDestructionExpectations( void TestHelper::SetupTextureManagerDestructionExpectations( ::gfx::MockGLInterface* gl, - const char* extensions) { - SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D); - SetupTextureDestructionExpectations(gl, GL_TEXTURE_CUBE_MAP); + const char* extensions, + bool use_default_textures) { + SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D, use_default_textures); + SetupTextureDestructionExpectations( + gl, GL_TEXTURE_CUBE_MAP, use_default_textures); bool ext_image_external = false; bool arb_texture_rectangle = false; @@ -213,10 +226,12 @@ void TestHelper::SetupTextureManagerDestructionExpectations( } if (ext_image_external) { - SetupTextureDestructionExpectations(gl, GL_TEXTURE_EXTERNAL_OES); + SetupTextureDestructionExpectations( + gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); } if (arb_texture_rectangle) { - SetupTextureDestructionExpectations(gl, GL_TEXTURE_RECTANGLE_ARB); + SetupTextureDestructionExpectations( + gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); } EXPECT_CALL(*gl, DeleteTextures(4, _)) @@ -225,18 +240,23 @@ void TestHelper::SetupTextureManagerDestructionExpectations( } void TestHelper::SetupContextGroupInitExpectations( - ::gfx::MockGLInterface* gl, - const DisallowedFeatures& disallowed_features, - const char* extensions) { + ::gfx::MockGLInterface* gl, + const DisallowedFeatures& disallowed_features, + const char* extensions, + const char* gl_version, + bool bind_generates_resource) { InSequence sequence; - SetupFeatureInfoInitExpectations(gl, extensions); + SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", gl_version); + + std::string l_version(StringToLowerASCII(std::string(gl_version))); + bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _)) .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize)) .RetiresOnSaturation(); if (strstr(extensions, "GL_EXT_framebuffer_multisample") || - strstr(extensions, "GL_EXT_multisampled_render_to_texture")) { + strstr(extensions, "GL_EXT_multisampled_render_to_texture") || is_es3) { EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _)) .WillOnce(SetArgumentPointee<1>(kMaxSamples)) .RetiresOnSaturation(); @@ -273,7 +293,8 @@ void TestHelper::SetupContextGroupInitExpectations( .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) .RetiresOnSaturation(); - SetupTextureManagerInitExpectations(gl, extensions); + bool use_default_textures = bind_generates_resource; + SetupTextureManagerInitExpectations(gl, extensions, use_default_textures); } void TestHelper::SetupFeatureInfoInitExpectations( @@ -297,6 +318,78 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( EXPECT_CALL(*gl, GetString(GL_VERSION)) .WillOnce(Return(reinterpret_cast<const uint8*>(gl_version))) .RetiresOnSaturation(); + + std::string l_version(StringToLowerASCII(std::string(gl_version))); + bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); + + if (strstr(extensions, "GL_ARB_texture_float") || + (is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) { + static const GLuint gl_ids[] = {101, 102}; + const GLsizei width = 16; + EXPECT_CALL(*gl, GetIntegerv(GL_FRAMEBUFFER_BINDING, _)) + .WillOnce(SetArgumentPointee<1>(gl_ids[0])) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_TEXTURE_BINDING_2D, _)) + .WillOnce(SetArgumentPointee<1>(gl_ids[0])) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GenTextures(1, _)) + .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GenFramebuffersEXT(1, _)) + .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[1])) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, + GL_RGBA, GL_FLOAT, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[1])) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, FramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl_ids[1], 0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, + GL_RGB, GL_FLOAT, _)) + .Times(1) + .RetiresOnSaturation(); + if (is_es3) { + EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)) + .RetiresOnSaturation(); + } else { + EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + } + EXPECT_CALL(*gl, DeleteFramebuffersEXT(1, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, DeleteTextures(1, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[0])) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[0])) + .Times(1) + .RetiresOnSaturation(); +#if DCHECK_IS_ON + EXPECT_CALL(*gl, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); +#endif + } } void TestHelper::SetupExpectationsForClearingUniforms( @@ -524,7 +617,7 @@ void TestHelper::DoBufferData( manager->DoBufferData(error_state, buffer, size, usage, data); } -void TestHelper::SetTexParameterWithExpectations( +void TestHelper::SetTexParameteriWithExpectations( ::gfx::MockGLInterface* gl, MockErrorState* error_state, TextureManager* manager, TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) { @@ -540,11 +633,11 @@ void TestHelper::SetTexParameterWithExpectations( .Times(1) .RetiresOnSaturation(); } else { - EXPECT_CALL(*error_state, SetGLErrorInvalidParam(_, _, error, _, _, _)) + EXPECT_CALL(*error_state, SetGLErrorInvalidParami(_, _, error, _, _, _)) .Times(1) .RetiresOnSaturation(); } - manager->SetParameter("", error_state, texture_ref, pname, value); + manager->SetParameteri("", error_state, texture_ref, pname, value); } ScopedGLImplementationSetter::ScopedGLImplementationSetter( diff --git a/chromium/gpu/command_buffer/service/test_helper.h b/chromium/gpu/command_buffer/service/test_helper.h index a619073878f..d0ae758aae7 100644 --- a/chromium/gpu/command_buffer/service/test_helper.h +++ b/chromium/gpu/command_buffer/service/test_helper.h @@ -65,7 +65,9 @@ class TestHelper { static void SetupContextGroupInitExpectations( ::gfx::MockGLInterface* gl, const DisallowedFeatures& disallowed_features, - const char* extensions); + const char* extensions, + const char* gl_version, + bool bind_generates_resource); static void SetupFeatureInfoInitExpectations( ::gfx::MockGLInterface* gl, const char* extensions); static void SetupFeatureInfoInitExpectationsWithGLVersion( @@ -73,10 +75,13 @@ class TestHelper { const char* extensions, const char* gl_renderer, const char* gl_version); - static void SetupTextureManagerInitExpectations( - ::gfx::MockGLInterface* gl, const char* extensions); + static void SetupTextureManagerInitExpectations(::gfx::MockGLInterface* gl, + const char* extensions, + bool use_default_textures); static void SetupTextureManagerDestructionExpectations( - ::gfx::MockGLInterface* gl, const char* extensions); + ::gfx::MockGLInterface* gl, + const char* extensions, + bool use_default_textures); static void SetupExpectationsForClearingUniforms( ::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms); @@ -97,16 +102,18 @@ class TestHelper { BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data, GLenum error); - static void SetTexParameterWithExpectations( + static void SetTexParameteriWithExpectations( ::gfx::MockGLInterface* gl, MockErrorState* error_state, TextureManager* manager, TextureRef* texture_ref, GLenum pname, GLint value, GLenum error); private: - static void SetupTextureInitializationExpectations( - ::gfx::MockGLInterface* gl, GLenum target); - static void SetupTextureDestructionExpectations( - ::gfx::MockGLInterface* gl, GLenum target); + static void SetupTextureInitializationExpectations(::gfx::MockGLInterface* gl, + GLenum target, + bool use_default_textures); + static void SetupTextureDestructionExpectations(::gfx::MockGLInterface* gl, + GLenum target, + bool use_default_textures); }; // This object temporaritly Sets what gfx::GetGLImplementation returns. During diff --git a/chromium/gpu/command_buffer/service/texture_definition.cc b/chromium/gpu/command_buffer/service/texture_definition.cc new file mode 100644 index 00000000000..3703f14b511 --- /dev/null +++ b/chromium/gpu/command_buffer/service/texture_definition.cc @@ -0,0 +1,456 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/texture_definition.h" + +#include "gpu/command_buffer/service/texture_manager.h" +#include "ui/gl/gl_image.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/scoped_binders.h" + +#if !defined(OS_MACOSX) +#include "ui/gl/gl_surface_egl.h" +#endif + +namespace gpu { +namespace gles2 { + +namespace { + +class GLImageSync : public gfx::GLImage { + public: + explicit GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer, + const gfx::Size& size); + + // Implement GLImage. + virtual void Destroy() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual bool BindTexImage(unsigned target) OVERRIDE; + virtual void ReleaseTexImage(unsigned target) OVERRIDE; + virtual void WillUseTexImage() OVERRIDE; + virtual void WillModifyTexImage() OVERRIDE; + virtual void DidModifyTexImage() OVERRIDE; + + virtual void DidUseTexImage() OVERRIDE; + virtual void SetReleaseAfterUse() OVERRIDE; + + protected: + virtual ~GLImageSync(); + + private: + scoped_refptr<NativeImageBuffer> buffer_; + gfx::Size size_; + + DISALLOW_COPY_AND_ASSIGN(GLImageSync); +}; + +GLImageSync::GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer, + const gfx::Size& size) + : buffer_(buffer), size_(size) { + if (buffer) + buffer->AddClient(this); +} + +GLImageSync::~GLImageSync() { + if (buffer_) + buffer_->RemoveClient(this); +} + +void GLImageSync::Destroy() {} + +gfx::Size GLImageSync::GetSize() { + return size_; +} + +bool GLImageSync::BindTexImage(unsigned target) { + NOTREACHED(); + return false; +} + +void GLImageSync::ReleaseTexImage(unsigned target) { + NOTREACHED(); +} + +void GLImageSync::WillUseTexImage() { + if (buffer_) + buffer_->WillRead(this); +} + +void GLImageSync::DidUseTexImage() { + if (buffer_) + buffer_->DidRead(this); +} + +void GLImageSync::WillModifyTexImage() { + if (buffer_) + buffer_->WillWrite(this); +} + +void GLImageSync::DidModifyTexImage() { + if (buffer_) + buffer_->DidWrite(this); +} + +void GLImageSync::SetReleaseAfterUse() { + NOTREACHED(); +} + +#if !defined(OS_MACOSX) +class NativeImageBufferEGL : public NativeImageBuffer { + public: + static scoped_refptr<NativeImageBufferEGL> Create(GLuint texture_id); + + private: + NativeImageBufferEGL(scoped_ptr<gfx::GLFence> write_fence, + EGLDisplay display, + EGLImageKHR image); + virtual ~NativeImageBufferEGL(); + virtual void BindToTexture(GLenum target) OVERRIDE; + + EGLDisplay egl_display_; + EGLImageKHR egl_image_; + + DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL); +}; + +scoped_refptr<NativeImageBufferEGL> NativeImageBufferEGL::Create( + GLuint texture_id) { + EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); + EGLContext egl_context = eglGetCurrentContext(); + + DCHECK_NE(EGL_NO_CONTEXT, egl_context); + DCHECK_NE(EGL_NO_DISPLAY, egl_display); + DCHECK(glIsTexture(texture_id)); + + DCHECK(gfx::g_driver_egl.ext.b_EGL_KHR_image_base && + gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image && + gfx::g_driver_gl.ext.b_GL_OES_EGL_image && + gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync); + + const EGLint egl_attrib_list[] = { + EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; + EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id); + EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO + + EGLImageKHR egl_image = eglCreateImageKHR( + egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list); + + if (egl_image == EGL_NO_IMAGE_KHR) + return NULL; + + return new NativeImageBufferEGL( + make_scoped_ptr(gfx::GLFence::Create()), egl_display, egl_image); +} + +NativeImageBufferEGL::NativeImageBufferEGL(scoped_ptr<gfx::GLFence> write_fence, + EGLDisplay display, + EGLImageKHR image) + : NativeImageBuffer(write_fence.Pass()), + egl_display_(display), + egl_image_(image) { + DCHECK(egl_display_ != EGL_NO_DISPLAY); + DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); +} + +NativeImageBufferEGL::~NativeImageBufferEGL() { + if (egl_image_ != EGL_NO_IMAGE_KHR) + eglDestroyImageKHR(egl_display_, egl_image_); +} + +void NativeImageBufferEGL::BindToTexture(GLenum target) { + DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); + glEGLImageTargetTexture2DOES(target, egl_image_); + DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError()); + DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); +} +#endif + +class NativeImageBufferStub : public NativeImageBuffer { + public: + NativeImageBufferStub() : NativeImageBuffer(scoped_ptr<gfx::GLFence>()) {} + + private: + virtual ~NativeImageBufferStub() {} + virtual void BindToTexture(GLenum target) OVERRIDE {} + + DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub); +}; + +} // anonymous namespace + +// static +scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) { + switch (gfx::GetGLImplementation()) { +#if !defined(OS_MACOSX) + case gfx::kGLImplementationEGLGLES2: + return NativeImageBufferEGL::Create(texture_id); +#endif + case gfx::kGLImplementationMockGL: + return new NativeImageBufferStub; + default: + NOTREACHED(); + return NULL; + } +} + +NativeImageBuffer::ClientInfo::ClientInfo(gfx::GLImage* client) + : client(client), needs_wait_before_read(true) {} + +NativeImageBuffer::ClientInfo::~ClientInfo() {} + +NativeImageBuffer::NativeImageBuffer(scoped_ptr<gfx::GLFence> write_fence) + : write_fence_(write_fence.Pass()), write_client_(NULL) { +} + +NativeImageBuffer::~NativeImageBuffer() { + DCHECK(client_infos_.empty()); +} + +void NativeImageBuffer::AddClient(gfx::GLImage* client) { + base::AutoLock lock(lock_); + client_infos_.push_back(ClientInfo(client)); +} + +void NativeImageBuffer::RemoveClient(gfx::GLImage* client) { + base::AutoLock lock(lock_); + if (write_client_ == client) + write_client_ = NULL; + for (std::list<ClientInfo>::iterator it = client_infos_.begin(); + it != client_infos_.end(); + it++) { + if (it->client == client) { + client_infos_.erase(it); + return; + } + } + NOTREACHED(); +} + +bool NativeImageBuffer::IsClient(gfx::GLImage* client) { + base::AutoLock lock(lock_); + for (std::list<ClientInfo>::iterator it = client_infos_.begin(); + it != client_infos_.end(); + it++) { + if (it->client == client) + return true; + } + return false; +} + +void NativeImageBuffer::WillRead(gfx::GLImage* client) { + base::AutoLock lock(lock_); + if (!write_fence_.get() || write_client_ == client) + return; + + for (std::list<ClientInfo>::iterator it = client_infos_.begin(); + it != client_infos_.end(); + it++) { + if (it->client == client) { + if (it->needs_wait_before_read) { + it->needs_wait_before_read = false; + write_fence_->ServerWait(); + } + return; + } + } + NOTREACHED(); +} + +void NativeImageBuffer::WillWrite(gfx::GLImage* client) { + base::AutoLock lock(lock_); + if (write_client_ != client) + write_fence_->ServerWait(); + + for (std::list<ClientInfo>::iterator it = client_infos_.begin(); + it != client_infos_.end(); + it++) { + if (it->read_fence.get() && it->client != client) + it->read_fence->ServerWait(); + } +} + +void NativeImageBuffer::DidRead(gfx::GLImage* client) { + base::AutoLock lock(lock_); + for (std::list<ClientInfo>::iterator it = client_infos_.begin(); + it != client_infos_.end(); + it++) { + if (it->client == client) { + it->read_fence = make_linked_ptr(gfx::GLFence::Create()); + return; + } + } + NOTREACHED(); +} + +void NativeImageBuffer::DidWrite(gfx::GLImage* client) { + base::AutoLock lock(lock_); + // Sharing semantics require the client to flush in order to make changes + // visible to other clients. + write_fence_.reset(gfx::GLFence::CreateWithoutFlush()); + write_client_ = client; + for (std::list<ClientInfo>::iterator it = client_infos_.begin(); + it != client_infos_.end(); + it++) { + it->needs_wait_before_read = true; + } +} + +TextureDefinition::LevelInfo::LevelInfo(GLenum target, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + bool cleared) + : target(target), + internal_format(internal_format), + width(width), + height(height), + depth(depth), + border(border), + format(format), + type(type), + cleared(cleared) {} + +TextureDefinition::LevelInfo::~LevelInfo() {} + +TextureDefinition::TextureDefinition( + GLenum target, + Texture* texture, + unsigned int version, + const scoped_refptr<NativeImageBuffer>& image_buffer) + : version_(version), + target_(target), + image_buffer_(image_buffer ? image_buffer : NativeImageBuffer::Create( + texture->service_id())), + min_filter_(texture->min_filter()), + mag_filter_(texture->mag_filter()), + wrap_s_(texture->wrap_s()), + wrap_t_(texture->wrap_t()), + usage_(texture->usage()), + immutable_(texture->IsImmutable()) { + + // TODO + DCHECK(!texture->level_infos_.empty()); + DCHECK(!texture->level_infos_[0].empty()); + DCHECK(!texture->NeedsMips()); + DCHECK(texture->level_infos_[0][0].width); + DCHECK(texture->level_infos_[0][0].height); + + scoped_refptr<gfx::GLImage> gl_image( + new GLImageSync(image_buffer_, + gfx::Size(texture->level_infos_[0][0].width, + texture->level_infos_[0][0].height))); + texture->SetLevelImage(NULL, target, 0, gl_image); + + // TODO: all levels + level_infos_.clear(); + const Texture::LevelInfo& level = texture->level_infos_[0][0]; + LevelInfo info(level.target, + level.internal_format, + level.width, + level.height, + level.depth, + level.border, + level.format, + level.type, + level.cleared); + std::vector<LevelInfo> infos; + infos.push_back(info); + level_infos_.push_back(infos); +} + +TextureDefinition::~TextureDefinition() { +} + +Texture* TextureDefinition::CreateTexture() const { + if (!image_buffer_) + return NULL; + + GLuint texture_id; + glGenTextures(1, &texture_id); + + Texture* texture(new Texture(texture_id)); + UpdateTexture(texture); + + return texture; +} + +void TextureDefinition::UpdateTexture(Texture* texture) const { + gfx::ScopedTextureBinder texture_binder(target_, texture->service_id()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_); + if (image_buffer_) + image_buffer_->BindToTexture(target_); + // We have to make sure the changes are visible to other clients in this share + // group. As far as the clients are concerned, the mailbox semantics only + // demand a single flush from the client after changes are first made, + // and it is not visible to them when another share group boundary is crossed. + // We could probably track this and be a bit smarter about when to flush + // though. + glFlush(); + + texture->level_infos_.resize(1); + for (size_t i = 0; i < level_infos_.size(); i++) { + const LevelInfo& base_info = level_infos_[i][0]; + const size_t levels_needed = TextureManager::ComputeMipMapCount( + base_info.target, base_info.width, base_info.height, base_info.depth); + DCHECK(level_infos_.size() <= levels_needed); + texture->level_infos_[0].resize(levels_needed); + for (size_t n = 0; n < level_infos_.size(); n++) { + const LevelInfo& info = level_infos_[i][n]; + texture->SetLevelInfo(NULL, + info.target, + i, + info.internal_format, + info.width, + info.height, + info.depth, + info.border, + info.format, + info.type, + info.cleared); + } + } + if (image_buffer_) { + texture->SetLevelImage( + NULL, + target_, + 0, + new GLImageSync( + image_buffer_, + gfx::Size(level_infos_[0][0].width, level_infos_[0][0].height))); + } + + texture->target_ = target_; + texture->SetImmutable(immutable_); + texture->min_filter_ = min_filter_; + texture->mag_filter_ = mag_filter_; + texture->wrap_s_ = wrap_s_; + texture->wrap_t_ = wrap_t_; + texture->usage_ = usage_; +} + +bool TextureDefinition::Matches(const Texture* texture) const { + DCHECK(target_ == texture->target()); + if (texture->min_filter_ != min_filter_ || + texture->mag_filter_ != mag_filter_ || + texture->wrap_s_ != wrap_s_ || + texture->wrap_t_ != wrap_t_) { + return false; + } + + // All structural changes should have orphaned the texture. + if (image_buffer_ && !texture->GetLevelImage(texture->target(), 0)) + return false; + + return true; +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/texture_definition.h b/chromium/gpu/command_buffer/service/texture_definition.h new file mode 100644 index 00000000000..7708902fab4 --- /dev/null +++ b/chromium/gpu/command_buffer/service/texture_definition.h @@ -0,0 +1,127 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ +#define GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ + +#include <list> +#include <vector> + +#include "base/callback.h" +#include "base/memory/linked_ptr.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "gpu/command_buffer/service/gl_utils.h" +#include "ui/gl/gl_fence.h" + +namespace gfx { +class GLFence; +class GLImage; +} + +namespace gpu { +namespace gles2 { + +class Texture; + +class NativeImageBuffer : public base::RefCountedThreadSafe<NativeImageBuffer> { + public: + static scoped_refptr<NativeImageBuffer> Create(GLuint texture_id); + virtual void BindToTexture(GLenum target) = 0; + + void AddClient(gfx::GLImage* client); + void RemoveClient(gfx::GLImage* client); + bool IsClient(gfx::GLImage* client); + + void WillRead(gfx::GLImage* client); + void WillWrite(gfx::GLImage* client); + void DidRead(gfx::GLImage* client); + void DidWrite(gfx::GLImage* client); + + protected: + friend class base::RefCountedThreadSafe<NativeImageBuffer>; + explicit NativeImageBuffer(scoped_ptr<gfx::GLFence> write_fence); + virtual ~NativeImageBuffer(); + + base::Lock lock_; + + struct ClientInfo { + ClientInfo(gfx::GLImage* client); + ~ClientInfo(); + + gfx::GLImage* client; + bool needs_wait_before_read; + linked_ptr<gfx::GLFence> read_fence; + }; + std::list<ClientInfo> client_infos_; + scoped_ptr<gfx::GLFence> write_fence_; + gfx::GLImage* write_client_; + + DISALLOW_COPY_AND_ASSIGN(NativeImageBuffer); +}; + +// An immutable description that can be used to create a texture that shares +// the underlying image buffer(s). +class TextureDefinition { + public: + TextureDefinition(GLenum target, + Texture* texture, + unsigned int version, + const scoped_refptr<NativeImageBuffer>& image); + virtual ~TextureDefinition(); + + Texture* CreateTexture() const; + void UpdateTexture(Texture* texture) const; + + unsigned int version() const { return version_; } + bool IsOlderThan(unsigned int version) const { + return (version - version_) < 0x80000000; + } + bool Matches(const Texture* texture) const; + + scoped_refptr<NativeImageBuffer> image() { return image_buffer_; } + + private: + struct LevelInfo { + LevelInfo(GLenum target, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + bool cleared); + ~LevelInfo(); + + GLenum target; + GLenum internal_format; + GLsizei width; + GLsizei height; + GLsizei depth; + GLint border; + GLenum format; + GLenum type; + bool cleared; + }; + + typedef std::vector<std::vector<LevelInfo> > LevelInfos; + + unsigned int version_; + GLenum target_; + scoped_refptr<NativeImageBuffer> image_buffer_; + GLenum min_filter_; + GLenum mag_filter_; + GLenum wrap_s_; + GLenum wrap_t_; + GLenum usage_; + bool immutable_; + LevelInfos level_infos_; +}; + +} // namespage gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ diff --git a/chromium/gpu/command_buffer/service/texture_manager.cc b/chromium/gpu/command_buffer/service/texture_manager.cc index 64ead827edd..76863c62a5e 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.cc +++ b/chromium/gpu/command_buffer/service/texture_manager.cc @@ -13,7 +13,6 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" -#include "gpu/command_buffer/service/stream_texture_manager.h" namespace gpu { namespace gles2 { @@ -67,9 +66,8 @@ TextureManager::DestructionObserver::DestructionObserver() {} TextureManager::DestructionObserver::~DestructionObserver() {} TextureManager::~TextureManager() { - FOR_EACH_OBSERVER(DestructionObserver, - destruction_observers_, - OnTextureManagerDestroying(this)); + for (unsigned int i = 0; i < destruction_observers_.size(); i++) + destruction_observers_[i]->OnTextureManagerDestroying(this); DCHECK(textures_.empty()); @@ -117,11 +115,11 @@ Texture::Texture(GLuint service_id) npot_(false), has_been_bound_(false), framebuffer_attachment_count_(0), - stream_texture_(false), immutable_(false), has_images_(false), estimated_size_(0), - can_render_condition_(CAN_RENDER_ALWAYS) { + can_render_condition_(CAN_RENDER_ALWAYS), + texture_max_anisotropy_initialized_(false) { } Texture::~Texture() { @@ -401,6 +399,13 @@ void Texture::UpdateCleared() { } } } + + // If texture is uncleared and is attached to a framebuffer, + // that framebuffer must be marked possibly incomplete. + if (!cleared && IsAttachedToFramebuffer()) { + IncAllFramebufferStateChangeCount(); + } + UpdateSafeToRenderFrom(cleared); } @@ -519,7 +524,6 @@ bool Texture::ValidForTexture( GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type) const { size_t face_index = GLTargetToFaceIndex(target); if (level >= 0 && face_index < level_infos_.size() && @@ -533,7 +537,6 @@ bool Texture::ValidForTexture( yoffset >= 0 && right <= info.width && top <= info.height && - format == info.internal_format && type == info.type; } return false; @@ -573,7 +576,7 @@ bool Texture::GetLevelType( return false; } -GLenum Texture::SetParameter( +GLenum Texture::SetParameteri( const FeatureInfo* feature_info, GLenum pname, GLint param) { DCHECK(feature_info); @@ -641,6 +644,31 @@ GLenum Texture::SetParameter( return GL_NO_ERROR; } +GLenum Texture::SetParameterf( + const FeatureInfo* feature_info, GLenum pname, GLfloat param) { + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_POOL_CHROMIUM: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_USAGE_ANGLE: + { + GLint iparam = static_cast<GLint>(param); + return SetParameteri(feature_info, pname, iparam); + } + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (param < 1.f) { + return GL_INVALID_VALUE; + } + break; + default: + NOTREACHED(); + return GL_INVALID_ENUM; + } + return GL_NO_ERROR; +} + void Texture::Update(const FeatureInfo* feature_info) { // Update npot status. // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others @@ -759,6 +787,14 @@ bool Texture::IsLevelCleared(GLenum target, GLint level) const { return info.cleared; } +void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) { + if (texture_max_anisotropy_initialized_) + return; + texture_max_anisotropy_initialized_ = true; + GLfloat params[] = { 1.0f }; + glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params); +} + bool Texture::ClearLevel( GLES2Decoder* decoder, GLenum target, GLint level) { DCHECK(decoder); @@ -784,8 +820,8 @@ bool Texture::ClearLevel( // but only the decoder knows all the state (like unpack_alignment_) that's // needed to be able to call GL correctly. bool cleared = decoder->ClearLevel( - service_id_, target_, info.target, info.level, info.format, info.type, - info.width, info.height, immutable_); + service_id_, target_, info.target, info.level, info.internal_format, + info.format, info.type, info.width, info.height, immutable_); UpdateMipCleared(&info, cleared); return info.cleared; } @@ -810,6 +846,11 @@ void Texture::SetLevelImage( } gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const { + if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES && + target != GL_TEXTURE_RECTANGLE_ARB) { + return NULL; + } + size_t face_index = GLTargetToFaceIndex(target); if (level >= 0 && face_index < level_infos_.size() && static_cast<size_t>(level) < level_infos_[face_index].size()) { @@ -821,6 +862,17 @@ gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const { return 0; } +void Texture::OnWillModifyPixels() { + gfx::GLImage* image = GetLevelImage(target(), 0); + if (image) + image->WillModifyTexImage(); +} + +void Texture::OnDidModifyPixels() { + gfx::GLImage* image = GetLevelImage(target(), 0); + if (image) + image->DidModifyTexImage(); +} TextureRef::TextureRef(TextureManager* manager, GLuint client_id, @@ -828,7 +880,7 @@ TextureRef::TextureRef(TextureManager* manager, : manager_(manager), texture_(texture), client_id_(client_id), - is_stream_texture_owner_(false) { + num_observers_(0) { DCHECK(manager_); DCHECK(texture_); texture_->AddTextureRef(this); @@ -850,14 +902,14 @@ TextureRef::~TextureRef() { TextureManager::TextureManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info, GLint max_texture_size, - GLint max_cube_map_texture_size) - : memory_tracker_managed_(new MemoryTypeTracker(memory_tracker, - MemoryTracker::kManaged)), + GLint max_cube_map_texture_size, + bool use_default_textures) + : memory_tracker_managed_( + new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)), memory_tracker_unmanaged_( new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)), feature_info_(feature_info), framebuffer_manager_(NULL), - stream_texture_manager_(NULL), max_texture_size_(max_texture_size), max_cube_map_texture_size_(max_cube_map_texture_size), max_levels_(ComputeMipMapCount(GL_TEXTURE_2D, @@ -868,6 +920,7 @@ TextureManager::TextureManager(MemoryTracker* memory_tracker, max_cube_map_texture_size, max_cube_map_texture_size, max_cube_map_texture_size)), + use_default_textures_(use_default_textures), num_unrenderable_textures_(0), num_unsafe_textures_(0), num_uncleared_mips_(0), @@ -915,8 +968,9 @@ scoped_refptr<TextureRef> // Make default textures and texture for replacing non-renderable textures. GLuint ids[2]; - glGenTextures(arraysize(ids), ids); - for (unsigned long ii = 0; ii < arraysize(ids); ++ii) { + const unsigned long num_ids = use_default_textures_ ? 2 : 1; + glGenTextures(num_ids, ids); + for (unsigned long ii = 0; ii < num_ids; ++ii) { glBindTexture(target, ids[ii]); if (needs_initialization) { if (needs_faces) { @@ -932,48 +986,50 @@ scoped_refptr<TextureRef> } glBindTexture(target, 0); - scoped_refptr<TextureRef> default_texture( - TextureRef::Create(this, 0, ids[1])); - SetTarget(default_texture.get(), target); - if (needs_faces) { - for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { - SetLevelInfo(default_texture.get(), - GLES2Util::IndexToGLFaceTarget(ii), - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); - } - } else { - if (needs_initialization) { - SetLevelInfo(default_texture.get(), - GL_TEXTURE_2D, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + scoped_refptr<TextureRef> default_texture; + if (use_default_textures_) { + default_texture = TextureRef::Create(this, 0, ids[1]); + SetTarget(default_texture.get(), target); + if (needs_faces) { + for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { + SetLevelInfo(default_texture.get(), + GLES2Util::IndexToGLFaceTarget(ii), + 0, + GL_RGBA, + 1, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + } } else { - SetLevelInfo(default_texture.get(), - GL_TEXTURE_EXTERNAL_OES, - 0, - GL_RGBA, - 1, - 1, - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); + if (needs_initialization) { + SetLevelInfo(default_texture.get(), + GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + } else { + SetLevelInfo(default_texture.get(), + GL_TEXTURE_EXTERNAL_OES, + 0, + GL_RGBA, + 1, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + } } } @@ -1006,19 +1062,6 @@ void TextureManager::SetTarget(TextureRef* ref, GLenum target) { ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target)); } -void TextureManager::SetStreamTexture(TextureRef* ref, bool stream_texture) { - DCHECK(ref); - // Only the owner can mark as non-stream texture. - DCHECK_EQ(stream_texture, !ref->is_stream_texture_owner_); - ref->texture()->SetStreamTexture(stream_texture); - ref->set_is_stream_texture_owner(stream_texture); -} - -bool TextureManager::IsStreamTextureOwner(TextureRef* ref) { - DCHECK(ref); - return ref->is_stream_texture_owner(); -} - void TextureManager::SetLevelCleared(TextureRef* ref, GLenum target, GLint level, @@ -1091,20 +1134,20 @@ TextureRef* TextureManager::Consume( return ref.get(); } -void TextureManager::SetParameter( +void TextureManager::SetParameteri( const char* function_name, ErrorState* error_state, TextureRef* ref, GLenum pname, GLint param) { DCHECK(error_state); DCHECK(ref); Texture* texture = ref->texture(); - GLenum result = texture->SetParameter(feature_info_.get(), pname, param); + GLenum result = texture->SetParameteri(feature_info_.get(), pname, param); if (result != GL_NO_ERROR) { if (result == GL_INVALID_ENUM) { ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( error_state, function_name, param, "param"); } else { - ERRORSTATE_SET_GL_ERROR_INVALID_PARAM( - error_state, result, function_name, pname, static_cast<GLint>(param)); + ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI( + error_state, result, function_name, pname, param); } } else { // Texture tracking pools exist only for the command decoder, so @@ -1115,6 +1158,30 @@ void TextureManager::SetParameter( } } +void TextureManager::SetParameterf( + const char* function_name, ErrorState* error_state, + TextureRef* ref, GLenum pname, GLfloat param) { + DCHECK(error_state); + DCHECK(ref); + Texture* texture = ref->texture(); + GLenum result = texture->SetParameterf(feature_info_.get(), pname, param); + if (result != GL_NO_ERROR) { + if (result == GL_INVALID_ENUM) { + ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( + error_state, function_name, param, "param"); + } else { + ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF( + error_state, result, function_name, pname, param); + } + } else { + // Texture tracking pools exist only for the command decoder, so + // do not pass them on to the native GL implementation. + if (pname != GL_TEXTURE_POOL_CHROMIUM) { + glTexParameterf(texture->target(), pname, param); + } + } +} + bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) { DCHECK(ref); Texture* texture = ref->texture(); @@ -1162,15 +1229,14 @@ void TextureManager::StartTracking(TextureRef* ref) { } void TextureManager::StopTracking(TextureRef* ref) { - FOR_EACH_OBSERVER(DestructionObserver, - destruction_observers_, - OnTextureRefDestroying(ref)); + if (ref->num_observers()) { + for (unsigned int i = 0; i < destruction_observers_.size(); i++) { + destruction_observers_[i]->OnTextureRefDestroying(ref); + } + DCHECK_EQ(ref->num_observers(), 0); + } Texture* texture = ref->texture(); - if (ref->is_stream_texture_owner_ && stream_texture_manager_) { - DCHECK(texture->IsStreamTexture()); - stream_texture_manager_->DestroyStreamTexture(texture->service_id()); - } --texture_count_; if (texture->HasImages()) { @@ -1280,20 +1346,10 @@ void TextureManager::IncFramebufferStateChangeCount() { framebuffer_manager_->IncFramebufferStateChangeCount(); } -bool TextureManager::ValidateTextureParameters( - ErrorState* error_state, const char* function_name, - GLenum target, GLenum format, GLenum type, GLint level) { +bool TextureManager::ValidateFormatAndTypeCombination( + ErrorState* error_state, const char* function_name, GLenum format, + GLenum type) { if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) { - ERRORSTATE_SET_GL_ERROR( - error_state, GL_INVALID_OPERATION, function_name, - (std::string("invalid type ") + - GLES2Util::GetStringEnum(type) + " for format " + - GLES2Util::GetStringEnum(format)).c_str()); - return false; - } - - uint32 channels = GLES2Util::GetChannelsForFormat(format); - if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) { ERRORSTATE_SET_GL_ERROR( error_state, GL_INVALID_OPERATION, function_name, (std::string("invalid type ") + @@ -1304,6 +1360,40 @@ bool TextureManager::ValidateTextureParameters( return true; } +bool TextureManager::ValidateTextureParameters( + ErrorState* error_state, const char* function_name, + GLenum format, GLenum type, GLenum internal_format, GLint level) { + const Validators* validators = feature_info_->validators(); + if (!validators->texture_format.IsValid(format)) { + ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( + error_state, function_name, format, "format"); + return false; + } + if (!validators->pixel_type.IsValid(type)) { + ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( + error_state, function_name, type, "type"); + return false; + } + if (format != internal_format && + !((internal_format == GL_RGBA32F && format == GL_RGBA) || + (internal_format == GL_RGB32F && format == GL_RGB))) { + ERRORSTATE_SET_GL_ERROR( + error_state, GL_INVALID_OPERATION, function_name, + "format != internalformat"); + return false; + } + uint32 channels = GLES2Util::GetChannelsForFormat(format); + if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) { + ERRORSTATE_SET_GL_ERROR( + error_state, GL_INVALID_OPERATION, function_name, + (std::string("invalid format ") + GLES2Util::GetStringEnum(format) + + " for level != 0").c_str()); + return false; + } + return ValidateFormatAndTypeCombination(error_state, function_name, + format, type); +} + // Gets the texture id for a given target. TextureRef* TextureManager::GetTextureInfoForTarget( ContextState* state, GLenum target) { @@ -1357,31 +1447,15 @@ bool TextureManager::ValidateTexImage2D( error_state, function_name, args.target, "target"); return false; } - if (!validators->texture_format.IsValid(args.internal_format)) { + if (!validators->texture_internal_format.IsValid(args.internal_format)) { ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( error_state, function_name, args.internal_format, - "internal_format"); - return false; - } - if (!validators->texture_format.IsValid(args.format)) { - ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( - error_state, function_name, args.format, "format"); - return false; - } - if (!validators->pixel_type.IsValid(args.type)) { - ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( - error_state, function_name, args.type, "type"); - return false; - } - if (args.format != args.internal_format) { - ERRORSTATE_SET_GL_ERROR( - error_state, GL_INVALID_OPERATION, function_name, - "format != internalFormat"); + "internalformat"); return false; } if (!ValidateTextureParameters( - error_state, function_name, args.target, args.format, args.type, - args.level)) { + error_state, function_name, args.format, args.type, + args.internal_format, args.level)) { return false; } if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) || @@ -1417,7 +1491,7 @@ bool TextureManager::ValidateTexImage2D( // They both use the same MemoryTracker, and this call just re-routes // to it. if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) { - ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, "glTexImage2D", + ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name, "out of memory"); return false; } diff --git a/chromium/gpu/command_buffer/service/texture_manager.h b/chromium/gpu/command_buffer/service/texture_manager.h index bd9e3dab410..6b3a32ebf39 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.h +++ b/chromium/gpu/command_buffer/service/texture_manager.h @@ -13,7 +13,6 @@ #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/memory/ref_counted.h" -#include "base/observer_list.h" #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/memory_tracking.h" @@ -21,9 +20,6 @@ #include "ui/gl/gl_image.h" namespace gpu { - -class StreamTextureManager; - namespace gles2 { class GLES2Decoder; @@ -77,7 +73,7 @@ class GPU_EXPORT Texture { } bool CanRenderTo() const { - return !stream_texture_ && target_ != GL_TEXTURE_EXTERNAL_OES; + return target_ != GL_TEXTURE_EXTERNAL_OES; } // The service side OpenGL id of the texture. @@ -119,7 +115,7 @@ class GPU_EXPORT Texture { } // Returns true of the given dimensions are inside the dimensions of the - // level and if the format and type match the level. + // level and if the type matches the level. bool ValidForTexture( GLint target, GLint level, @@ -127,7 +123,6 @@ class GPU_EXPORT Texture { GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type) const; bool IsValid() const { @@ -147,10 +142,6 @@ class GPU_EXPORT Texture { --framebuffer_attachment_count_; } - bool IsStreamTexture() const { - return stream_texture_; - } - void SetImmutable(bool immutable) { immutable_ = immutable; } @@ -167,9 +158,16 @@ class GPU_EXPORT Texture { return estimated_size() > 0; } + // Initialize TEXTURE_MAX_ANISOTROPY to 1 if we haven't done so yet. + void InitTextureMaxAnisotropyIfNeeded(GLenum target); + + void OnWillModifyPixels(); + void OnDidModifyPixels(); + private: friend class MailboxManager; friend class MailboxManagerTest; + friend class TextureDefinition; friend class TextureManager; friend class TextureRef; friend class TextureTestHelper; @@ -242,11 +240,6 @@ class GPU_EXPORT Texture { return npot_; } - void SetStreamTexture(bool stream_texture) { - stream_texture_ = stream_texture; - UpdateCanRenderCondition(); - } - // Marks a particular level as cleared or uncleared. void SetLevelCleared(GLenum target, GLint level, bool cleared); @@ -262,10 +255,12 @@ class GPU_EXPORT Texture { bool ClearLevel(GLES2Decoder* decoder, GLenum target, GLint level); // Sets a texture parameter. - // TODO(gman): Expand to SetParameteri,f,iv,fv + // TODO(gman): Expand to SetParameteriv,fv // Returns GL_NO_ERROR on success. Otherwise the error to generate. - GLenum SetParameter( + GLenum SetParameteri( const FeatureInfo* feature_info, GLenum pname, GLint param); + GLenum SetParameterf( + const FeatureInfo* feature_info, GLenum pname, GLfloat param); // Makes each of the mip levels as though they were generated. bool MarkMipmapsGenerated(const FeatureInfo* feature_info); @@ -379,9 +374,6 @@ class GPU_EXPORT Texture { // The number of framebuffers this texture is attached to. int framebuffer_attachment_count_; - // Whether this is a special streaming texture. - bool stream_texture_; - // Whether the texture is immutable and no further changes to the format // or dimensions of the texture object can be made. bool immutable_; @@ -395,6 +387,9 @@ class GPU_EXPORT Texture { // Cache of the computed CanRenderCondition flag. CanRenderCondition can_render_condition_; + // Whether we have initialized TEXTURE_MAX_ANISOTROPY to 1. + bool texture_max_anisotropy_initialized_; + DISALLOW_COPY_AND_ASSIGN(Texture); }; @@ -402,23 +397,21 @@ class GPU_EXPORT Texture { // with a client id, though it can outlive the client id if it's still bound to // a FBO or another context when destroyed. // Multiple TextureRef can point to the same texture with cross-context sharing. -// -// Note: for stream textures, the TextureRef that created the stream texture is -// set as the "owner" of the stream texture, i.e. it will call -// DestroyStreamTexture on destruction. This is because the StreamTextureManager -// isn't generally shared between ContextGroups, so ownership can't be at the -// Texture level. We also can't have multiple StreamTexture on the same service -// id, so there can be only one owner. class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { public: TextureRef(TextureManager* manager, GLuint client_id, Texture* texture); static scoped_refptr<TextureRef> Create(TextureManager* manager, GLuint client_id, GLuint service_id); + + void AddObserver() { num_observers_++; } + void RemoveObserver() { num_observers_--; } + const Texture* texture() const { return texture_; } Texture* texture() { return texture_; } GLuint client_id() const { return client_id_; } GLuint service_id() const { return texture_->service_id(); } + GLint num_observers() const { return num_observers_; } private: friend class base::RefCounted<TextureRef>; @@ -429,15 +422,11 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { const TextureManager* manager() const { return manager_; } TextureManager* manager() { return manager_; } void reset_client_id() { client_id_ = 0; } - void set_is_stream_texture_owner(bool owner) { - is_stream_texture_owner_ = owner; - } - bool is_stream_texture_owner() const { return is_stream_texture_owner_; } TextureManager* manager_; Texture* texture_; GLuint client_id_; - bool is_stream_texture_owner_; + GLint num_observers_; DISALLOW_COPY_AND_ASSIGN(TextureRef); }; @@ -497,17 +486,14 @@ class GPU_EXPORT TextureManager { TextureManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info, GLsizei max_texture_size, - GLsizei max_cube_map_texture_size); + GLsizei max_cube_map_texture_size, + bool use_default_textures); ~TextureManager(); void set_framebuffer_manager(FramebufferManager* manager) { framebuffer_manager_ = manager; } - void set_stream_texture_manager(StreamTextureManager* manager) { - stream_texture_manager_ = manager; - } - // Init the texture manager. bool Initialize(); @@ -567,13 +553,6 @@ class GPU_EXPORT TextureManager { TextureRef* ref, GLenum target); - // Marks a texture as a stream texture, and the ref as the stream texture - // owner. - void SetStreamTexture(TextureRef* ref, bool stream_texture); - - // Whether the TextureRef is the stream texture owner. - bool IsStreamTextureOwner(TextureRef* ref); - // Set the info for a particular level in a TexureInfo. void SetLevelInfo( TextureRef* ref, @@ -609,10 +588,13 @@ class GPU_EXPORT TextureManager { // Sets a texture parameter of a Texture // Returns GL_NO_ERROR on success. Otherwise the error to generate. - // TODO(gman): Expand to SetParameteri,f,iv,fv - void SetParameter( + // TODO(gman): Expand to SetParameteriv,fv + void SetParameteri( const char* function_name, ErrorState* error_state, TextureRef* ref, GLenum pname, GLint param); + void SetParameterf( + const char* function_name, ErrorState* error_state, + TextureRef* ref, GLenum pname, GLfloat param); // Makes each of the mip levels as though they were generated. // Returns false if that's not allowed for the given texture. @@ -705,11 +687,18 @@ class GPU_EXPORT TextureManager { std::string* signature) const; void AddObserver(DestructionObserver* observer) { - destruction_observers_.AddObserver(observer); + destruction_observers_.push_back(observer); } void RemoveObserver(DestructionObserver* observer) { - destruction_observers_.RemoveObserver(observer); + for (unsigned int i = 0; i < destruction_observers_.size(); i++) { + if (destruction_observers_[i] == observer) { + std::swap(destruction_observers_[i], destruction_observers_.back()); + destruction_observers_.pop_back(); + return; + } + } + NOTREACHED(); } struct DoTextImage2DArguments { @@ -745,9 +734,15 @@ class GPU_EXPORT TextureManager { TextureRef* GetTextureInfoForTargetUnlessDefault( ContextState* state, GLenum target); + bool ValidateFormatAndTypeCombination( + ErrorState* error_state, const char* function_name, + GLenum format, GLenum type); + + // Note that internal_format is only checked in relation to the format + // parameter, so that this function may be used to validate texSubImage2D. bool ValidateTextureParameters( ErrorState* error_state, const char* function_name, - GLenum target, GLenum format, GLenum type, GLint level); + GLenum format, GLenum type, GLenum internal_format, GLint level); private: friend class Texture; @@ -782,7 +777,6 @@ class GPU_EXPORT TextureManager { scoped_refptr<FeatureInfo> feature_info_; FramebufferManager* framebuffer_manager_; - StreamTextureManager* stream_texture_manager_; // Info for each texture in the system. typedef base::hash_map<GLuint, scoped_refptr<TextureRef> > TextureMap; @@ -793,6 +787,8 @@ class GPU_EXPORT TextureManager { GLint max_levels_; GLint max_cube_map_levels_; + const bool use_default_textures_; + int num_unrenderable_textures_; int num_unsafe_textures_; int num_uncleared_mips_; @@ -812,7 +808,7 @@ class GPU_EXPORT TextureManager { // The default textures for each target (texture name = 0) scoped_refptr<TextureRef> default_textures_[kNumDefaultTextures]; - ObserverList<DestructionObserver> destruction_observers_; + std::vector<DestructionObserver*> destruction_observers_; DISALLOW_COPY_AND_ASSIGN(TextureManager); }; diff --git a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc index 312adfddbf3..2335191a0e9 100644 --- a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc @@ -9,6 +9,7 @@ #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/mocks.h" @@ -39,7 +40,7 @@ class TextureTestHelper { } }; -class TextureManagerTest : public testing::Test { +class TextureManagerTest : public GpuServiceTest { public: static const GLint kMaxTextureSize = 16; static const GLint kMaxCubeMapTextureSize = 8; @@ -47,23 +48,23 @@ class TextureManagerTest : public testing::Test { static const GLint kMax2dLevels = 5; static const GLint kMaxCubeMapLevels = 4; static const GLint kMaxExternalLevels = 1; + static const bool kUseDefaultTextures = false; - TextureManagerTest() - : feature_info_(new FeatureInfo()) { - } + TextureManagerTest() : feature_info_(new FeatureInfo()) {} virtual ~TextureManagerTest() { } protected: virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - - manager_.reset(new TextureManager( - NULL, feature_info_.get(), - kMaxTextureSize, kMaxCubeMapTextureSize)); - TestHelper::SetupTextureManagerInitExpectations(gl_.get(), ""); + GpuServiceTest::SetUp(); + manager_.reset(new TextureManager(NULL, + feature_info_.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures)); + TestHelper::SetupTextureManagerInitExpectations( + gl_.get(), "", kUseDefaultTextures); manager_->Initialize(); error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>()); } @@ -71,19 +72,16 @@ class TextureManagerTest : public testing::Test { virtual void TearDown() { manager_->Destroy(false); manager_.reset(); - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + GpuServiceTest::TearDown(); } void SetParameter( TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) { - TestHelper::SetTexParameterWithExpectations( + TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), manager_.get(), texture_ref, pname, value, error); } - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<FeatureInfo> feature_info_; scoped_ptr<TextureManager> manager_; scoped_ptr<MockErrorState> error_state_; @@ -162,11 +160,54 @@ TEST_F(TextureManagerTest, SetParameter) { SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0, GL_INVALID_VALUE); } +TEST_F(TextureManagerTest, UseDefaultTexturesTrue) { + bool use_default_textures = true; + scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); + + TestHelper::SetupTextureManagerInitExpectations( + gl_.get(), "GL_ANGLE_texture_usage", use_default_textures); + TextureManager manager(NULL, + feature_info_.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + use_default_textures); + manager.Initialize(); + + EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D) != NULL); + EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP) != NULL); + + // TODO(vmiura): Test GL_TEXTURE_EXTERNAL_OES & GL_TEXTURE_RECTANGLE_ARB. + + manager.Destroy(false); +} + +TEST_F(TextureManagerTest, UseDefaultTexturesFalse) { + bool use_default_textures = false; + TestHelper::SetupTextureManagerInitExpectations( + gl_.get(), "GL_ANGLE_texture_usage", use_default_textures); + TextureManager manager(NULL, + feature_info_.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + use_default_textures); + manager.Initialize(); + + EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D) == NULL); + EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP) == NULL); + + // TODO(vmiura): Test GL_TEXTURE_EXTERNAL_OES & GL_TEXTURE_RECTANGLE_ARB. + + manager.Destroy(false); +} + TEST_F(TextureManagerTest, TextureUsageExt) { - TestHelper::SetupTextureManagerInitExpectations(gl_.get(), - "GL_ANGLE_texture_usage"); - TextureManager manager( - NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupTextureManagerInitExpectations( + gl_.get(), "GL_ANGLE_texture_usage", kUseDefaultTextures); + TextureManager manager(NULL, + feature_info_.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.Initialize(); const GLuint kClient1Id = 1; const GLuint kService1Id = 11; @@ -175,7 +216,7 @@ TEST_F(TextureManagerTest, TextureUsageExt) { // Check texture got created. TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); - TestHelper::SetTexParameterWithExpectations( + TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE,GL_NO_ERROR); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_ATTACHMENT_ANGLE), @@ -186,9 +227,13 @@ TEST_F(TextureManagerTest, TextureUsageExt) { TEST_F(TextureManagerTest, Destroy) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; - TestHelper::SetupTextureManagerInitExpectations(gl_.get(), ""); - TextureManager manager( - NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupTextureManagerInitExpectations( + gl_.get(), "", kUseDefaultTextures); + TextureManager manager(NULL, + feature_info_.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.Initialize(); // Check we can create texture. manager.CreateTexture(kClient1Id, kService1Id); @@ -198,7 +243,8 @@ TEST_F(TextureManagerTest, Destroy) { EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService1Id))) .Times(1) .RetiresOnSaturation(); - TestHelper::SetupTextureManagerDestructionExpectations(gl_.get(), ""); + TestHelper::SetupTextureManagerDestructionExpectations( + gl_.get(), "", kUseDefaultTextures); manager.Destroy(true); // Check that resources got freed. texture = manager.GetTexture(kClient1Id); @@ -319,8 +365,11 @@ TEST_F(TextureManagerTest, ValidForTargetNPOT) { gl_.get(), "GL_OES_texture_npot"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); // Check NPOT width on level 0 EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1)); // Check NPOT height on level 0 @@ -332,7 +381,7 @@ TEST_F(TextureManagerTest, ValidForTargetNPOT) { manager.Destroy(false); } -class TextureTestBase : public testing::Test { +class TextureTestBase : public GpuServiceTest { public: static const GLint kMaxTextureSize = 16; static const GLint kMaxCubeMapTextureSize = 8; @@ -340,6 +389,7 @@ class TextureTestBase : public testing::Test { static const GLint kMaxCubeMapLevels = 4; static const GLuint kClient1Id = 1; static const GLuint kService1Id = 11; + static const bool kUseDefaultTextures = false; TextureTestBase() : feature_info_(new FeatureInfo()) { @@ -350,18 +400,18 @@ class TextureTestBase : public testing::Test { protected: void SetUpBase(MemoryTracker* memory_tracker, std::string extensions) { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - + GpuServiceTest::SetUp(); if (!extensions.empty()) { TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions.c_str()); feature_info_->Initialize(); } - manager_.reset(new TextureManager( - memory_tracker, feature_info_.get(), - kMaxTextureSize, kMaxCubeMapTextureSize)); + manager_.reset(new TextureManager(memory_tracker, + feature_info_.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures)); decoder_.reset(new ::testing::StrictMock<gles2::MockGLES2Decoder>()); error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>()); manager_->CreateTexture(kClient1Id, kService1Id); @@ -384,21 +434,18 @@ class TextureTestBase : public testing::Test { } manager_->Destroy(false); manager_.reset(); - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + GpuServiceTest::TearDown(); } void SetParameter( TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) { - TestHelper::SetTexParameterWithExpectations( + TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), manager_.get(), texture_ref, pname, value, error); } scoped_ptr<MockGLES2Decoder> decoder_; scoped_ptr<MockErrorState> error_state_; - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<FeatureInfo> feature_info_; scoped_ptr<TextureManager> manager_; scoped_refptr<TextureRef> texture_ref_; @@ -795,8 +842,11 @@ TEST_F(TextureTest, NPOT2DNPOTOK) { gl_.get(), "GL_OES_texture_npot"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); @@ -1042,43 +1092,40 @@ TEST_F(TextureTest, ValidForTexture) { Texture* texture = texture_ref_->texture(); EXPECT_FALSE(texture->ValidForTexture( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + 1, 0, 0, 4, 5, GL_UNSIGNED_BYTE)); // Check bad level. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_UNSIGNED_BYTE)); // Check bad xoffset. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_UNSIGNED_BYTE)); // Check bad xoffset + width > width. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_UNSIGNED_BYTE)); // Check bad yoffset. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_UNSIGNED_BYTE)); // Check bad yoffset + height > height. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_UNSIGNED_BYTE)); // Check bad width. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_UNSIGNED_BYTE)); // Check bad height. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_RGBA, GL_UNSIGNED_BYTE)); - // Check bad format. - EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGB, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_UNSIGNED_BYTE)); // Check bad type. EXPECT_FALSE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4)); + GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_UNSIGNED_SHORT_4_4_4_4)); // Check valid full size EXPECT_TRUE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_UNSIGNED_BYTE)); // Check valid particial size. EXPECT_TRUE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_UNSIGNED_BYTE)); manager_->RemoveTexture(kClient1Id); EXPECT_TRUE(texture->ValidForTexture( - GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_UNSIGNED_BYTE)); } TEST_F(TextureTest, FloatNotLinear) { @@ -1086,8 +1133,11 @@ TEST_F(TextureTest, FloatNotLinear) { gl_.get(), "GL_OES_texture_float"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); @@ -1097,11 +1147,11 @@ TEST_F(TextureTest, FloatNotLinear) { manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); - TestHelper::SetTexParameterWithExpectations( + TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); - TestHelper::SetTexParameterWithExpectations( + TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); @@ -1113,8 +1163,11 @@ TEST_F(TextureTest, FloatLinear) { gl_.get(), "GL_OES_texture_float GL_OES_texture_float_linear"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); @@ -1132,8 +1185,11 @@ TEST_F(TextureTest, HalfFloatNotLinear) { gl_.get(), "GL_OES_texture_half_float"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); @@ -1143,11 +1199,11 @@ TEST_F(TextureTest, HalfFloatNotLinear) { manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, true); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); - TestHelper::SetTexParameterWithExpectations( + TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); - TestHelper::SetTexParameterWithExpectations( + TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); @@ -1159,8 +1215,11 @@ TEST_F(TextureTest, HalfFloatLinear) { gl_.get(), "GL_OES_texture_half_float GL_OES_texture_half_float_linear"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); @@ -1178,8 +1237,11 @@ TEST_F(TextureTest, EGLImageExternal) { gl_.get(), "GL_OES_EGL_image_external"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); @@ -1195,8 +1257,11 @@ TEST_F(TextureTest, DepthTexture) { gl_.get(), "GL_ANGLE_depth_texture"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); feature_info->Initialize(); - TextureManager manager( - NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(NULL, + feature_info.get(), + kMaxTextureSize, + kMaxCubeMapTextureSize, + kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); @@ -1428,7 +1493,7 @@ TEST_F(TextureTest, SafeUnsafe) { } TEST_F(TextureTest, ClearTexture) { - EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) + EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), @@ -1805,7 +1870,8 @@ TEST_F(TextureTest, AddToSignature) { EXPECT_EQ(11u, string_set.size()); } -class ProduceConsumeTextureTest : public TextureTest { +class ProduceConsumeTextureTest : public TextureTest, + public ::testing::WithParamInterface<GLenum> { public: virtual void SetUp() { TextureTest::SetUpBase(NULL, "GL_OES_EGL_image_external"); @@ -1994,7 +2060,7 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsumeClearRectangle) { // See if we can clear the previously uncleared level now. EXPECT_EQ(level0, GetLevelInfo(restored_texture.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); - EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) + EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); EXPECT_TRUE(manager_->ClearTextureLevel( decoder_.get(), restored_texture.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); @@ -2020,25 +2086,43 @@ TEST_F(ProduceConsumeTextureTest, ProduceConsumeExternal) { GetLevelInfo(restored_texture.get(), GL_TEXTURE_EXTERNAL_OES, 0)); } -TEST_F(ProduceConsumeTextureTest, ProduceConsumeStreamTexture) { - manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES); +TEST_P(ProduceConsumeTextureTest, ProduceConsumeTextureWithImage) { + GLenum target = GetParam(); + manager_->SetTarget(texture_ref_.get(), target); Texture* texture = texture_ref_->texture(); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target()); - manager_->SetStreamTexture(texture_ref_.get(), true); + EXPECT_EQ(static_cast<GLenum>(target), texture->target()); + scoped_refptr<gfx::GLImage> image(gfx::GLImage::CreateGLImage(0)); + manager_->SetLevelInfo(texture_ref_.get(), + target, + 0, + GL_RGBA, + 0, + 0, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + manager_->SetLevelImage(texture_ref_.get(), target, 0, image); GLuint service_id = texture->service_id(); Texture* produced_texture = Produce(texture_ref_.get()); - EXPECT_TRUE(texture->IsStreamTexture()); GLuint client_id = texture2_->client_id(); manager_->RemoveTexture(client_id); Consume(client_id, produced_texture); scoped_refptr<TextureRef> restored_texture = manager_->GetTexture(client_id); EXPECT_EQ(produced_texture, restored_texture->texture()); - EXPECT_TRUE(restored_texture->texture()->IsStreamTexture()); - EXPECT_TRUE(restored_texture->texture()->IsImmutable()); EXPECT_EQ(service_id, restored_texture->service_id()); + EXPECT_EQ(image.get(), restored_texture->texture()->GetLevelImage(target, 0)); } +static const GLenum kTextureTargets[] = {GL_TEXTURE_2D, GL_TEXTURE_EXTERNAL_OES, + GL_TEXTURE_RECTANGLE_ARB, }; + +INSTANTIATE_TEST_CASE_P(Target, + ProduceConsumeTextureTest, + ::testing::ValuesIn(kTextureTargets)); + TEST_F(ProduceConsumeTextureTest, ProduceConsumeCube) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_CUBE_MAP); Texture* texture = texture_ref_->texture(); @@ -2108,34 +2192,36 @@ class CountingMemoryTracker : public MemoryTracker { DISALLOW_COPY_AND_ASSIGN(CountingMemoryTracker); }; -class SharedTextureTest : public testing::Test { +class SharedTextureTest : public GpuServiceTest { public: - SharedTextureTest() - : feature_info_(new FeatureInfo()) { - } + static const bool kUseDefaultTextures = false; + + SharedTextureTest() : feature_info_(new FeatureInfo()) {} virtual ~SharedTextureTest() { } virtual void SetUp() { - gl_.reset(new ::gfx::MockGLInterface()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - + GpuServiceTest::SetUp(); memory_tracker1_ = new CountingMemoryTracker; texture_manager1_.reset( new TextureManager(memory_tracker1_.get(), feature_info_.get(), TextureManagerTest::kMaxTextureSize, - TextureManagerTest::kMaxCubeMapTextureSize)); + TextureManagerTest::kMaxCubeMapTextureSize, + kUseDefaultTextures)); memory_tracker2_ = new CountingMemoryTracker; texture_manager2_.reset( new TextureManager(memory_tracker2_.get(), feature_info_.get(), TextureManagerTest::kMaxTextureSize, - TextureManagerTest::kMaxCubeMapTextureSize)); - TestHelper::SetupTextureManagerInitExpectations(gl_.get(), ""); + TextureManagerTest::kMaxCubeMapTextureSize, + kUseDefaultTextures)); + TestHelper::SetupTextureManagerInitExpectations( + gl_.get(), "", kUseDefaultTextures); texture_manager1_->Initialize(); - TestHelper::SetupTextureManagerInitExpectations(gl_.get(), ""); + TestHelper::SetupTextureManagerInitExpectations( + gl_.get(), "", kUseDefaultTextures); texture_manager2_->Initialize(); } @@ -2144,12 +2230,10 @@ class SharedTextureTest : public testing::Test { texture_manager2_.reset(); texture_manager1_->Destroy(false); texture_manager1_.reset(); - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + GpuServiceTest::TearDown(); } protected: - scoped_ptr< ::gfx::MockGLInterface > gl_; scoped_refptr<FeatureInfo> feature_info_; scoped_refptr<CountingMemoryTracker> memory_tracker1_; scoped_ptr<TextureManager> texture_manager1_; diff --git a/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc b/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc index 76443a1f250..4404a9eb6c4 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager.cc @@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/debug/trace_event.h" #include "base/process/process_handle.h" +#include "gpu/command_buffer/common/cmd_buffer_common.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" using ::base::SharedMemory; @@ -26,9 +27,8 @@ TransferBufferManager::TransferBufferManager() TransferBufferManager::~TransferBufferManager() { while (!registered_buffers_.empty()) { BufferMap::iterator it = registered_buffers_.begin(); - DCHECK(shared_memory_bytes_allocated_ >= it->second.size); - shared_memory_bytes_allocated_ -= it->second.size; - delete it->second.shared_memory; + DCHECK(shared_memory_bytes_allocated_ >= it->second->size()); + shared_memory_bytes_allocated_ -= it->second->size(); registered_buffers_.erase(it); } DCHECK(!shared_memory_bytes_allocated_); @@ -40,8 +40,7 @@ bool TransferBufferManager::Initialize() { bool TransferBufferManager::RegisterTransferBuffer( int32 id, - base::SharedMemory* shared_memory, - size_t size) { + scoped_ptr<BufferBacking> buffer_backing) { if (id <= 0) { DVLOG(0) << "Cannot register transfer buffer with non-positive ID."; return false; @@ -53,29 +52,14 @@ bool TransferBufferManager::RegisterTransferBuffer( return false; } - // Duplicate the handle. - base::SharedMemoryHandle duped_shared_memory_handle; - if (!shared_memory->ShareToProcess(base::GetCurrentProcessHandle(), - &duped_shared_memory_handle)) { - DVLOG(0) << "Failed to duplicate shared memory handle."; - return false; - } - scoped_ptr<SharedMemory> duped_shared_memory( - new SharedMemory(duped_shared_memory_handle, false)); - - // Map the shared memory into this process. This validates the size. - if (!duped_shared_memory->Map(size)) { - DVLOG(0) << "Failed to map shared memory."; - return false; - } + // Register the shared memory with the ID. + scoped_refptr<Buffer> buffer(new gpu::Buffer(buffer_backing.Pass())); - // If it could be mapped register the shared memory with the ID. - Buffer buffer; - buffer.ptr = duped_shared_memory->memory(); - buffer.size = size; - buffer.shared_memory = duped_shared_memory.release(); + // Check buffer alignment is sane. + DCHECK(!(reinterpret_cast<uintptr_t>(buffer->memory()) & + (kCommandBufferEntrySize - 1))); - shared_memory_bytes_allocated_ += size; + shared_memory_bytes_allocated_ += buffer->size(); TRACE_COUNTER_ID1( "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_); @@ -91,22 +75,21 @@ void TransferBufferManager::DestroyTransferBuffer(int32 id) { return; } - DCHECK(shared_memory_bytes_allocated_ >= it->second.size); - shared_memory_bytes_allocated_ -= it->second.size; + DCHECK(shared_memory_bytes_allocated_ >= it->second->size()); + shared_memory_bytes_allocated_ -= it->second->size(); TRACE_COUNTER_ID1( "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_); - delete it->second.shared_memory; registered_buffers_.erase(it); } -Buffer TransferBufferManager::GetTransferBuffer(int32 id) { +scoped_refptr<Buffer> TransferBufferManager::GetTransferBuffer(int32 id) { if (id == 0) - return Buffer(); + return NULL; BufferMap::iterator it = registered_buffers_.find(id); if (it == registered_buffers_.end()) - return Buffer(); + return NULL; return it->second; } diff --git a/chromium/gpu/command_buffer/service/transfer_buffer_manager.h b/chromium/gpu/command_buffer/service/transfer_buffer_manager.h index 5e1a7464824..d8bb3bb4fd4 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager.h +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager.h @@ -21,11 +21,9 @@ class GPU_EXPORT TransferBufferManagerInterface { virtual ~TransferBufferManagerInterface(); virtual bool RegisterTransferBuffer(int32 id, - base::SharedMemory* shared_memory, - size_t size) = 0; + scoped_ptr<BufferBacking> buffer) = 0; virtual void DestroyTransferBuffer(int32 id) = 0; - virtual Buffer GetTransferBuffer(int32 id) = 0; - + virtual scoped_refptr<Buffer> GetTransferBuffer(int32 id) = 0; }; class GPU_EXPORT TransferBufferManager @@ -35,15 +33,15 @@ class GPU_EXPORT TransferBufferManager bool Initialize(); virtual bool RegisterTransferBuffer(int32 id, - base::SharedMemory* shared_memory, - size_t size) OVERRIDE; + scoped_ptr<BufferBacking> buffer_backing) + OVERRIDE; virtual void DestroyTransferBuffer(int32 id) OVERRIDE; - virtual Buffer GetTransferBuffer(int32 id) OVERRIDE; + virtual scoped_refptr<Buffer> GetTransferBuffer(int32 id) OVERRIDE; private: virtual ~TransferBufferManager(); - typedef base::hash_map<int32, Buffer> BufferMap; + typedef base::hash_map<int32, scoped_refptr<Buffer> > BufferMap; BufferMap registered_buffers_; size_t shared_memory_bytes_allocated_; diff --git a/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc index 68c5c2ec21c..4af09368cb0 100644 --- a/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc @@ -17,83 +17,81 @@ const static size_t kBufferSize = 1024; class TransferBufferManagerTest : public testing::Test { protected: virtual void SetUp() { - for (size_t i = 0; i < arraysize(buffers_); ++i) { - buffers_[i].CreateAnonymous(kBufferSize); - buffers_[i].Map(kBufferSize); - } - TransferBufferManager* manager = new TransferBufferManager(); transfer_buffer_manager_.reset(manager); ASSERT_TRUE(manager->Initialize()); } - base::SharedMemory buffers_[3]; scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; }; TEST_F(TransferBufferManagerTest, ZeroHandleMapsToNull) { - EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(0).ptr); + EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(0)); } TEST_F(TransferBufferManagerTest, NegativeHandleMapsToNull) { - EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(-1).ptr); + EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(-1)); } TEST_F(TransferBufferManagerTest, OutOfRangeHandleMapsToNull) { - EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(1).ptr); + EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(1)); } TEST_F(TransferBufferManagerTest, CanRegisterTransferBuffer) { - EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1, - &buffers_[0], - kBufferSize)); - Buffer registered = transfer_buffer_manager_->GetTransferBuffer(1); - - // Distinct memory range and shared memory handle from that originally - // registered. - EXPECT_NE(static_cast<void*>(NULL), registered.ptr); - EXPECT_NE(buffers_[0].memory(), registered.ptr); - EXPECT_EQ(kBufferSize, registered.size); - EXPECT_NE(&buffers_[0], registered.shared_memory); - - // But maps to the same physical memory. - *static_cast<int*>(registered.ptr) = 7; - *static_cast<int*>(buffers_[0].memory()) = 8; - EXPECT_EQ(8, *static_cast<int*>(registered.ptr)); + scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + shm->CreateAndMapAnonymous(kBufferSize); + base::SharedMemory* shm_raw_pointer = shm.get(); + scoped_ptr<SharedMemoryBufferBacking> backing( + new SharedMemoryBufferBacking(shm.Pass(), kBufferSize)); + SharedMemoryBufferBacking* backing_raw_ptr = backing.get(); + + EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer( + 1, backing.PassAs<BufferBacking>())); + scoped_refptr<Buffer> registered = + transfer_buffer_manager_->GetTransferBuffer(1); + + // Shared-memory ownership is transfered. It should be the same memory. + EXPECT_EQ(backing_raw_ptr, registered->backing()); + EXPECT_EQ(shm_raw_pointer, backing_raw_ptr->shared_memory()); } +class FakeBufferBacking : public BufferBacking { + public: + virtual void* GetMemory() const OVERRIDE { + return reinterpret_cast<void*>(0xBADF00D0); + } + virtual size_t GetSize() const OVERRIDE { return 42; } + static scoped_ptr<BufferBacking> Make() { + return scoped_ptr<BufferBacking>(new FakeBufferBacking); + } +}; + TEST_F(TransferBufferManagerTest, CanDestroyTransferBuffer) { - EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1, - &buffers_[0], - kBufferSize)); + EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer( + 1, scoped_ptr<BufferBacking>(new FakeBufferBacking))); transfer_buffer_manager_->DestroyTransferBuffer(1); - Buffer registered = transfer_buffer_manager_->GetTransferBuffer(1); + scoped_refptr<Buffer> registered = + transfer_buffer_manager_->GetTransferBuffer(1); - EXPECT_EQ(static_cast<void*>(NULL), registered.ptr); - EXPECT_EQ(0U, registered.size); - EXPECT_EQ(static_cast<base::SharedMemory*>(NULL), registered.shared_memory); + scoped_refptr<Buffer> null_buffer; + EXPECT_EQ(null_buffer, registered); } TEST_F(TransferBufferManagerTest, CannotRegregisterTransferBufferId) { - EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1, - &buffers_[0], - kBufferSize)); - EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(1, - &buffers_[0], - kBufferSize)); - EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(1, - &buffers_[1], - kBufferSize)); + EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer( + 1, FakeBufferBacking::Make())); + EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer( + 1, FakeBufferBacking::Make())); + EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer( + 1, FakeBufferBacking::Make())); } TEST_F(TransferBufferManagerTest, CanReuseTransferBufferIdAfterDestroying) { - EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1, - &buffers_[0], - kBufferSize)); + EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer( + 1, FakeBufferBacking::Make())); transfer_buffer_manager_->DestroyTransferBuffer(1); - EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1, - &buffers_[1], - kBufferSize)); + EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer( + 1, FakeBufferBacking::Make())); } TEST_F(TransferBufferManagerTest, DestroyUnusedTransferBufferIdDoesNotCrash) { @@ -101,15 +99,15 @@ TEST_F(TransferBufferManagerTest, DestroyUnusedTransferBufferIdDoesNotCrash) { } TEST_F(TransferBufferManagerTest, CannotRegisterNullTransferBuffer) { - EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(0, - &buffers_[0], - kBufferSize)); + EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer( + 0, FakeBufferBacking::Make())); } TEST_F(TransferBufferManagerTest, CannotRegisterNegativeTransferBufferId) { - EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(-1, - &buffers_[0], - kBufferSize)); + scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + shm->CreateAndMapAnonymous(kBufferSize); + EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer( + -1, FakeBufferBacking::Make())); } } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/vertex_array_manager.cc b/chromium/gpu/command_buffer/service/vertex_array_manager.cc index 974751941ce..1560c043c25 100644 --- a/chromium/gpu/command_buffer/service/vertex_array_manager.cc +++ b/chromium/gpu/command_buffer/service/vertex_array_manager.cc @@ -28,14 +28,22 @@ void VertexArrayManager::Destroy(bool have_context) { vertex_attrib_managers_.clear(); } -void VertexArrayManager::CreateVertexAttribManager( - GLuint client_id, GLuint service_id, uint32 num_vertex_attribs) { +scoped_refptr<VertexAttribManager> +VertexArrayManager::CreateVertexAttribManager(GLuint client_id, + GLuint service_id, + uint32 num_vertex_attribs, + bool client_visible) { scoped_refptr<VertexAttribManager> vertex_attrib_manager( new VertexAttribManager(this, service_id, num_vertex_attribs)); - std::pair<VertexAttribManagerMap::iterator, bool> result = - vertex_attrib_managers_.insert( - std::make_pair(client_id, vertex_attrib_manager)); - DCHECK(result.second); + + if (client_visible) { + std::pair<VertexAttribManagerMap::iterator, bool> result = + vertex_attrib_managers_.insert( + std::make_pair(client_id, vertex_attrib_manager)); + DCHECK(result.second); + } + + return vertex_attrib_manager; } VertexAttribManager* VertexArrayManager::GetVertexAttribManager( diff --git a/chromium/gpu/command_buffer/service/vertex_array_manager.h b/chromium/gpu/command_buffer/service/vertex_array_manager.h index 4fc567c7b79..97ecc1a5353 100644 --- a/chromium/gpu/command_buffer/service/vertex_array_manager.h +++ b/chromium/gpu/command_buffer/service/vertex_array_manager.h @@ -28,9 +28,13 @@ class GPU_EXPORT VertexArrayManager { // Must call before destruction. void Destroy(bool have_context); - // Creates a VertexArrayInfo for the given vertex array. - void CreateVertexAttribManager(GLuint client_id, GLuint service_id, - uint32 num_vertex_attribs); + // Creates a VertexAttribManager and if client_visible, + // maps it to the client_id. + scoped_refptr<VertexAttribManager> CreateVertexAttribManager( + GLuint client_id, + GLuint service_id, + uint32 num_vertex_attribs, + bool client_visible); // Gets the vertex attrib manager for the given vertex array. VertexAttribManager* GetVertexAttribManager(GLuint client_id); diff --git a/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc b/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc index 50ce07752a4..aa2df355f70 100644 --- a/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/vertex_array_manager_unittest.cc @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" @@ -17,7 +18,7 @@ using ::testing::_; namespace gpu { namespace gles2 { -class VertexArrayManagerTest : public testing::Test { +class VertexArrayManagerTest : public GpuServiceTest { public: static const uint32 kNumVertexAttribs = 8; @@ -29,21 +30,16 @@ class VertexArrayManagerTest : public testing::Test { protected: virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); - - manager_ = new VertexArrayManager(); + GpuServiceTest::SetUp(); + manager_.reset(new VertexArrayManager()); } virtual void TearDown() { - delete manager_; - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); + manager_.reset(); + GpuServiceTest::TearDown(); } - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; - VertexArrayManager* manager_; + scoped_ptr<VertexArrayManager> manager_; }; // GCC requires these declarations, but MSVC requires they not be present @@ -58,7 +54,7 @@ TEST_F(VertexArrayManagerTest, Basic) { // Check we can create manager_->CreateVertexAttribManager( - kClient1Id, kService1Id, kNumVertexAttribs); + kClient1Id, kService1Id, kNumVertexAttribs, true); // Check creation success VertexAttribManager* info1 = manager_->GetVertexAttribManager(kClient1Id); ASSERT_TRUE(info1 != NULL); @@ -84,7 +80,8 @@ TEST_F(VertexArrayManagerTest, Destroy) { const GLuint kService1Id = 11; VertexArrayManager manager; // Check we can create - manager.CreateVertexAttribManager(kClient1Id, kService1Id, kNumVertexAttribs); + manager.CreateVertexAttribManager( + kClient1Id, kService1Id, kNumVertexAttribs, true); // Check creation success VertexAttribManager* info1 = manager.GetVertexAttribManager(kClient1Id); ASSERT_TRUE(info1 != NULL); diff --git a/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc b/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc index 23e592cf5f5..5bf40403756 100644 --- a/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc +++ b/chromium/gpu/command_buffer/service/vertex_attrib_manager.cc @@ -6,7 +6,6 @@ #include <list> -#include "base/command_line.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" @@ -122,14 +121,12 @@ VertexAttribManager::~VertexAttribManager() { void VertexAttribManager::Initialize( uint32 max_vertex_attribs, bool init_attribs) { vertex_attribs_.resize(max_vertex_attribs); - bool disable_workarounds = CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGpuDriverBugWorkarounds); for (uint32 vv = 0; vv < vertex_attribs_.size(); ++vv) { vertex_attribs_[vv].set_index(vv); vertex_attribs_[vv].SetList(&disabled_vertex_attribs_); - if (!disable_workarounds && init_attribs) { + if (init_attribs) { glVertexAttrib4f(vv, 0.0f, 0.0f, 0.0f, 1.0f); } } diff --git a/chromium/gpu/command_buffer/service/vertex_attrib_manager.h b/chromium/gpu/command_buffer/service/vertex_attrib_manager.h index 2eff3ccfe30..8ee858738a3 100644 --- a/chromium/gpu/command_buffer/service/vertex_attrib_manager.h +++ b/chromium/gpu/command_buffer/service/vertex_attrib_manager.h @@ -171,7 +171,7 @@ class GPU_EXPORT VertexAttribManager : VertexAttribManager(); - void Initialize(uint32 num_vertex_attribs, bool init_attribs = true); + void Initialize(uint32 num_vertex_attribs, bool init_attribs); bool Enable(GLuint index, bool enable); diff --git a/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc b/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc index 28a051c97b2..e7fd6905474 100644 --- a/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc @@ -8,6 +8,7 @@ #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" @@ -18,7 +19,7 @@ using ::testing::_; namespace gpu { namespace gles2 { -class VertexAttribManagerTest : public testing::Test { +class VertexAttribManagerTest : public GpuServiceTest { public: static const uint32 kNumVertexAttribs = 8; @@ -30,8 +31,7 @@ class VertexAttribManagerTest : public testing::Test { protected: virtual void SetUp() { - gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); - ::gfx::GLInterface::SetGLInterface(gl_.get()); + GpuServiceTest::SetUp(); for (uint32 ii = 0; ii < kNumVertexAttribs; ++ii) { EXPECT_CALL(*gl_, VertexAttrib4f(ii, 0.0f, 0.0f, 0.0f, 1.0f)) @@ -40,17 +40,9 @@ class VertexAttribManagerTest : public testing::Test { } manager_ = new VertexAttribManager(); - manager_->Initialize(kNumVertexAttribs); + manager_->Initialize(kNumVertexAttribs, true); } - virtual void TearDown() { - manager_ = NULL; - ::gfx::GLInterface::SetGLInterface(NULL); - gl_.reset(); - } - - // Use StrictMock to make 100% sure we know how GL will be called. - scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<VertexAttribManager> manager_; }; |