diff options
author | Andras Becsi <andras.becsi@digia.com> | 2013-12-11 21:33:03 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@digia.com> | 2013-12-13 12:34:07 +0100 |
commit | f2a33ff9cbc6d19943f1c7fbddd1f23d23975577 (patch) | |
tree | 0586a32aa390ade8557dfd6b4897f43a07449578 /chromium/gpu | |
parent | 5362912cdb5eea702b68ebe23702468d17c3017a (diff) | |
download | qtwebengine-chromium-f2a33ff9cbc6d19943f1c7fbddd1f23d23975577.tar.gz |
Update Chromium to branch 1650 (31.0.1650.63)
Change-Id: I57d8c832eaec1eb2364e0a8e7352a6dd354db99f
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'chromium/gpu')
111 files changed, 3353 insertions, 1354 deletions
diff --git a/chromium/gpu/GLES2/gl2extchromium.h b/chromium/gpu/GLES2/gl2extchromium.h index 433242c66fd..bd4d4325693 100644 --- a/chromium/gpu/GLES2/gl2extchromium.h +++ b/chromium/gpu/GLES2/gl2extchromium.h @@ -336,11 +336,11 @@ typedef void (GL_APIENTRYP PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC) ( #ifndef GL_CHROMIUM_async_pixel_transfers #define GL_CHROMIUM_async_pixel_transfers 1 -#ifndef GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM -#define GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM 0x84F5 +#ifndef GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM +#define GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM 0x84F5 #endif -#ifndef GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM -#define GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM 0x84F6 +#ifndef GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM +#define GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM 0x84F6 #endif #endif /* GL_CHROMIUM_async_pixel_transfers */ diff --git a/chromium/gpu/OWNERS b/chromium/gpu/OWNERS index 0c5f595fb6a..1cf4e0238a9 100644 --- a/chromium/gpu/OWNERS +++ b/chromium/gpu/OWNERS @@ -1,2 +1,3 @@ piman@chromium.org apatrick@chromium.org +sievers@chromium.org diff --git a/chromium/gpu/command_buffer/OWNERS b/chromium/gpu/command_buffer/OWNERS new file mode 100644 index 00000000000..7ef33ed2f58 --- /dev/null +++ b/chromium/gpu/command_buffer/OWNERS @@ -0,0 +1,5 @@ +piman@chromium.org +apatrick@chromium.org +jbauman@chromium.org +bajones@chromium.org +zmo@chromium.org
\ No newline at end of file diff --git a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py index 6555da26090..f4c7e5b7367 100755 --- a/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/chromium/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -62,13 +62,15 @@ _GL_TYPES = { _CAPABILITY_FLAGS = [ {'name': 'blend'}, {'name': 'cull_face'}, - {'name': 'depth_test', 'state_flag': 'clear_state_dirty_'}, + {'name': 'depth_test', 'state_flag': 'framebuffer_state_.clear_state_dirty'}, {'name': 'dither', 'default': True}, {'name': 'polygon_offset_fill'}, {'name': 'sample_alpha_to_coverage'}, {'name': 'sample_coverage'}, - {'name': 'scissor_test', 'state_flag': 'clear_state_dirty_'}, - {'name': 'stencil_test', 'state_flag': 'clear_state_dirty_'}, + {'name': 'scissor_test', + 'state_flag': 'framebuffer_state_.clear_state_dirty'}, + {'name': 'stencil_test', + 'state_flag': 'framebuffer_state_.clear_state_dirty'}, ] _STATES = { @@ -101,7 +103,7 @@ _STATES = { {'name': 'color_mask_blue', 'type': 'GLboolean', 'default': 'true'}, {'name': 'color_mask_alpha', 'type': 'GLboolean', 'default': 'true'}, ], - 'state_flag': 'clear_state_dirty_', + 'state_flag': 'framebuffer_state_.clear_state_dirty', }, 'ClearStencil': { 'type': 'Normal', @@ -242,7 +244,7 @@ _STATES = { 'StencilMask': { 'type': 'FrontBack', 'func': 'StencilMaskSeparate', - 'state_flag': 'clear_state_dirty_', + 'state_flag': 'framebuffer_state_.clear_state_dirty', 'states': [ { 'name': 'stencil_front_writemask', @@ -400,7 +402,7 @@ _STATES = { 'states': [ {'name': 'depth_mask', 'type': 'GLboolean', 'default': 'true'}, ], - 'state_flag': 'clear_state_dirty_', + 'state_flag': 'framebuffer_state_.clear_state_dirty', }, 'Scissor': { 'type': 'Normal', @@ -825,8 +827,8 @@ _ENUM_LISTS = { 'GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT', 'GL_COMMANDS_ISSUED_CHROMIUM', 'GL_LATENCY_QUERY_CHROMIUM', - 'GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM', - 'GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM', + 'GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM', + 'GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM', ], }, 'RenderBufferParameter': { diff --git a/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc b/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc index 86b69f06d20..51f4f944e1e 100644 --- a/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc +++ b/chromium/gpu/command_buffer/client/buffer_tracker_unittest.cc @@ -51,7 +51,8 @@ class BufferTrackerTest : public testing::Test { command_buffer_.reset(new MockClientCommandBufferImpl()); helper_.reset(new GLES2CmdHelper(command_buffer_.get())); helper_->Initialize(kCommandBufferSizeBytes); - mapped_memory_.reset(new MappedMemoryManager(helper_.get())); + mapped_memory_.reset(new MappedMemoryManager( + helper_.get(), MappedMemoryManager::kNoLimit)); buffer_tracker_.reset(new BufferTracker(mapped_memory_.get())); } diff --git a/chromium/gpu/command_buffer/client/client_test_helper.cc b/chromium/gpu/command_buffer/client/client_test_helper.cc index cccfa3b96ef..31a91b20d6c 100644 --- a/chromium/gpu/command_buffer/client/client_test_helper.cc +++ b/chromium/gpu/command_buffer/client/client_test_helper.cc @@ -151,6 +151,12 @@ void MockClientCommandBufferMockFlush::DelegateToFake() { this, &MockCommandBufferBase::FlushHelper)); } +MockClientGpuControl::MockClientGpuControl() { +} + +MockClientGpuControl::~MockClientGpuControl() { +} + } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/client_test_helper.h b/chromium/gpu/command_buffer/client/client_test_helper.h index 70107046660..e9d6c365fae 100644 --- a/chromium/gpu/command_buffer/client/client_test_helper.h +++ b/chromium/gpu/command_buffer/client/client_test_helper.h @@ -11,6 +11,7 @@ #include "gpu/command_buffer/common/cmd_buffer_common.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/compiler_specific.h" +#include "gpu/command_buffer/common/gpu_control.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -81,6 +82,22 @@ class MockClientCommandBufferMockFlush : public MockClientCommandBuffer { void DelegateToFake(); }; +class MockClientGpuControl : public GpuControl { + public: + MockClientGpuControl(); + virtual ~MockClientGpuControl(); + + MOCK_METHOD4(CreateGpuMemoryBuffer, + gfx::GpuMemoryBuffer*(size_t width, + size_t height, + unsigned internalformat, + int32* id)); + MOCK_METHOD1(DestroyGpuMemoryBuffer, void(int32 id)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockClientGpuControl); +}; + } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_CLIENT_TEST_HELPER_H_ diff --git a/chromium/gpu/command_buffer/client/fenced_allocator.cc b/chromium/gpu/command_buffer/client/fenced_allocator.cc index 6eb9ab3a148..02e891f665d 100644 --- a/chromium/gpu/command_buffer/client/fenced_allocator.cc +++ b/chromium/gpu/command_buffer/client/fenced_allocator.cc @@ -5,7 +5,9 @@ // This file contains the implementation of the FencedAllocator class. #include "gpu/command_buffer/client/fenced_allocator.h" + #include <algorithm> + #include "gpu/command_buffer/client/cmd_buffer_helper.h" namespace gpu { @@ -33,7 +35,8 @@ const FencedAllocator::Offset FencedAllocator::kInvalidOffset; FencedAllocator::FencedAllocator(unsigned int size, CommandBufferHelper *helper) - : helper_(helper) { + : helper_(helper), + bytes_in_use_(0) { Block block = { FREE, 0, RoundDown(size), kUnusedToken }; blocks_.push_back(block); } @@ -90,7 +93,12 @@ FencedAllocator::Offset FencedAllocator::Alloc(unsigned int size) { void FencedAllocator::Free(FencedAllocator::Offset offset) { BlockIndex index = GetBlockByOffset(offset); GPU_DCHECK_NE(blocks_[index].state, FREE); - blocks_[index].state = FREE; + Block &block = blocks_[index]; + + if (block.state == IN_USE) + bytes_in_use_ -= block.size; + + block.state = FREE; CollapseFreeBlock(index); } @@ -99,6 +107,8 @@ void FencedAllocator::FreePendingToken( FencedAllocator::Offset offset, int32 token) { BlockIndex index = GetBlockByOffset(offset); Block &block = blocks_[index]; + if (block.state == IN_USE) + bytes_in_use_ -= block.size; block.state = FREE_PENDING_TOKEN; block.token = token; } @@ -153,6 +163,8 @@ bool FencedAllocator::CheckConsistency() { return true; } +// Returns false if all blocks are actually FREE, in which +// case they would be coalesced into one block, true otherwise. bool FencedAllocator::InUse() { return blocks_.size() != 1 || blocks_[0].state != FREE; } @@ -211,6 +223,7 @@ FencedAllocator::Offset FencedAllocator::AllocInBlock(BlockIndex index, GPU_DCHECK_GE(block.size, size); GPU_DCHECK_EQ(block.state, FREE); Offset offset = block.offset; + bytes_in_use_ += size; if (block.size == size) { block.state = IN_USE; return offset; diff --git a/chromium/gpu/command_buffer/client/fenced_allocator.h b/chromium/gpu/command_buffer/client/fenced_allocator.h index 90288d9fb8f..71e6178e832 100644 --- a/chromium/gpu/command_buffer/client/fenced_allocator.h +++ b/chromium/gpu/command_buffer/client/fenced_allocator.h @@ -83,6 +83,9 @@ class GPU_EXPORT FencedAllocator { // True if any memory is allocated. bool InUse(); + // Return bytes of memory that is IN_USE + size_t bytes_in_use() const { return bytes_in_use_; } + private: // Status of a block of memory, for book-keeping. enum State { @@ -134,6 +137,7 @@ class GPU_EXPORT FencedAllocator { CommandBufferHelper *helper_; Container blocks_; + size_t bytes_in_use_; DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator); }; @@ -243,6 +247,8 @@ class FencedAllocatorWrapper { FencedAllocator &allocator() { return allocator_; } + size_t bytes_in_use() const { return allocator_.bytes_in_use(); } + private: FencedAllocator allocator_; void* base_; diff --git a/chromium/gpu/command_buffer/client/gl_in_process_context.cc b/chromium/gpu/command_buffer/client/gl_in_process_context.cc index cdbfc9f47c3..cf0c8a79ec6 100644 --- a/chromium/gpu/command_buffer/client/gl_in_process_context.cc +++ b/chromium/gpu/command_buffer/client/gl_in_process_context.cc @@ -23,8 +23,6 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" -#include "gpu/command_buffer/client/image_factory.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/constants.h" @@ -32,6 +30,10 @@ #include "ui/gfx/size.h" #include "ui/gl/gl_image.h" +#if defined(OS_ANDROID) +#include "ui/gl/android/surface_texture.h" +#endif + namespace gpu { namespace { @@ -43,11 +45,8 @@ const size_t kStartTransferBufferSize = 4 * 1024 * 1024; const size_t kMinTransferBufferSize = 1 * 256 * 1024; const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; -static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; - class GLInProcessContextImpl : public GLInProcessContext, - public gles2::ImageFactory, public base::SupportsWeakPtr<GLInProcessContextImpl> { public: explicit GLInProcessContextImpl(); @@ -58,7 +57,6 @@ class GLInProcessContextImpl bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, - const char* allowed_extensions, const GLInProcessContextAttribs& attribs, gfx::GpuPreference gpu_preference); @@ -70,11 +68,10 @@ class GLInProcessContextImpl OVERRIDE; virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE; - // ImageFactory implementation: - virtual scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( - int width, int height, GLenum internalformat, - unsigned* image_id) OVERRIDE; - virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE; +#if defined(OS_ANDROID) + virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture( + uint32 stream_id) OVERRIDE; +#endif private: void Destroy(); @@ -108,24 +105,6 @@ size_t SharedContextCount() { return g_all_shared_contexts.Get().size(); } -scoped_ptr<gfx::GpuMemoryBuffer> GLInProcessContextImpl::CreateGpuMemoryBuffer( - int width, int height, GLenum internalformat, unsigned int* image_id) { - scoped_ptr<gfx::GpuMemoryBuffer> buffer( - g_gpu_memory_buffer_factory->CreateGpuMemoryBuffer(width, - height, - internalformat)); - if (!buffer) - return scoped_ptr<gfx::GpuMemoryBuffer>(); - - *image_id = command_buffer_->CreateImageForGpuMemoryBuffer( - buffer->GetHandle(), gfx::Size(width, height)); - return buffer.Pass(); -} - -void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) { - command_buffer_->RemoveImage(image_id); -} - GLInProcessContextImpl::GLInProcessContextImpl() : share_group_id_(0), context_lost_(false) {} @@ -173,7 +152,6 @@ bool GLInProcessContextImpl::Initialize( bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, - const char* allowed_extensions, const GLInProcessContextAttribs& attribs, gfx::GpuPreference gpu_preference) { DCHECK(size.width() >= 0 && size.height() >= 0); @@ -253,7 +231,6 @@ bool GLInProcessContextImpl::Initialize( share_resources, window, size, - allowed_extensions, attrib_vector, gpu_preference, wrapped_callback, @@ -279,7 +256,7 @@ bool GLInProcessContextImpl::Initialize( share_group, transfer_buffer_.get(), false, - this)); + command_buffer_.get())); if (share_resources) { g_all_shared_contexts.Get().insert(this); @@ -289,7 +266,8 @@ bool GLInProcessContextImpl::Initialize( if (!gles2_implementation_->Initialize( kStartTransferBufferSize, kMinTransferBufferSize, - kMaxTransferBufferSize)) { + kMaxTransferBufferSize, + gles2::GLES2Implementation::kNoLimit)) { return false; } @@ -361,6 +339,13 @@ void GLInProcessContextImpl::SignalQuery( } } +#if defined(OS_ANDROID) +scoped_refptr<gfx::SurfaceTexture> +GLInProcessContextImpl::GetSurfaceTexture(uint32 stream_id) { + return command_buffer_->GetSurfaceTexture(stream_id); +} +#endif + } // anonymous namespace GLInProcessContextAttribs::GLInProcessContextAttribs() @@ -379,7 +364,6 @@ GLInProcessContext* GLInProcessContext::CreateContext( gfx::AcceleratedWidget window, const gfx::Size& size, bool share_resources, - const char* allowed_extensions, const GLInProcessContextAttribs& attribs, gfx::GpuPreference gpu_preference) { scoped_ptr<GLInProcessContextImpl> context( @@ -390,7 +374,6 @@ GLInProcessContext* GLInProcessContext::CreateContext( share_resources, window, size, - allowed_extensions, attribs, gpu_preference)) return NULL; @@ -402,7 +385,6 @@ GLInProcessContext* GLInProcessContext::CreateContext( GLInProcessContext* GLInProcessContext::CreateWithSurface( scoped_refptr<gfx::GLSurface> surface, bool share_resources, - const char* allowed_extensions, const GLInProcessContextAttribs& attribs, gfx::GpuPreference gpu_preference) { scoped_ptr<GLInProcessContextImpl> context( @@ -413,7 +395,6 @@ GLInProcessContext* GLInProcessContext::CreateWithSurface( share_resources, gfx::kNullAcceleratedWidget, surface->GetSize(), - allowed_extensions, attribs, gpu_preference)) return NULL; @@ -421,11 +402,4 @@ GLInProcessContext* GLInProcessContext::CreateWithSurface( return context.release(); } -// static -void GLInProcessContext::SetGpuMemoryBufferFactory( - GpuMemoryBufferFactory* factory) { - DCHECK_EQ(0u, SharedContextCount()); - g_gpu_memory_buffer_factory = factory; -} - } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/gl_in_process_context.h b/chromium/gpu/command_buffer/client/gl_in_process_context.h index 09f8140ee0e..1be0d9da92b 100644 --- a/chromium/gpu/command_buffer/client/gl_in_process_context.h +++ b/chromium/gpu/command_buffer/client/gl_in_process_context.h @@ -16,14 +16,18 @@ namespace gfx { class Size; } +#if defined(OS_ANDROID) +namespace gfx { +class SurfaceTexture; +} +#endif + namespace gpu { namespace gles2 { class GLES2Implementation; } -class GpuMemoryBufferFactory; - // The default uninitialized value is -1. struct GLES2_IMPL_EXPORT GLInProcessContextAttribs { GLInProcessContextAttribs(); @@ -42,9 +46,6 @@ class GLES2_IMPL_EXPORT GLInProcessContext { public: virtual ~GLInProcessContext() {} - // Must be called before any GLInProcessContext instances are created. - static void SetGpuMemoryBufferFactory(GpuMemoryBufferFactory* factory); - // Create a GLInProcessContext, if |is_offscreen| is true, renders to an // offscreen context. |attrib_list| must be NULL or a NONE-terminated list // of attribute/value pairs. @@ -53,7 +54,6 @@ class GLES2_IMPL_EXPORT GLInProcessContext { gfx::AcceleratedWidget window, const gfx::Size& size, bool share_resources, - const char* allowed_extensions, const GLInProcessContextAttribs& attribs, gfx::GpuPreference gpu_preference); @@ -64,7 +64,6 @@ class GLES2_IMPL_EXPORT GLInProcessContext { static GLInProcessContext* CreateWithSurface( scoped_refptr<gfx::GLSurface> surface, bool share_resources, - const char* allowed_extensions, const GLInProcessContextAttribs& attribs, gfx::GpuPreference gpu_preference); @@ -78,6 +77,11 @@ class GLES2_IMPL_EXPORT GLInProcessContext { // Allows direct access to the GLES2 implementation so a GLInProcessContext // can be used without making it current. virtual gles2::GLES2Implementation* GetImplementation() = 0; + +#if defined(OS_ANDROID) + virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture( + uint32 stream_id) = 0; +#endif }; } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.cc b/chromium/gpu/command_buffer/client/gles2_implementation.cc index 9285b6d82ef..0bee1ed5c4d 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation.cc @@ -17,7 +17,6 @@ #include <GLES2/gl2extchromium.h> #include "gpu/command_buffer/client/buffer_tracker.h" #include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h" -#include "gpu/command_buffer/client/mapped_memory.h" #include "gpu/command_buffer/client/program_info_manager.h" #include "gpu/command_buffer/client/query_tracker.h" #include "gpu/command_buffer/client/transfer_buffer.h" @@ -86,7 +85,7 @@ GLES2Implementation::GLES2Implementation( ShareGroup* share_group, TransferBufferInterface* transfer_buffer, bool bind_generates_resource, - ImageFactory* image_factory) + GpuControl* gpu_control) : helper_(helper), transfer_buffer_(transfer_buffer), angle_pack_reverse_row_order_status_(kUnknownExtensionStatus), @@ -111,7 +110,7 @@ GLES2Implementation::GLES2Implementation( use_count_(0), current_query_(NULL), error_message_callback_(NULL), - image_factory_(image_factory) { + gpu_control_(gpu_control) { GPU_DCHECK(helper); GPU_DCHECK(transfer_buffer); @@ -133,7 +132,8 @@ GLES2Implementation::GLES2Implementation( bool GLES2Implementation::Initialize( unsigned int starting_transfer_buffer_size, unsigned int min_transfer_buffer_size, - unsigned int max_transfer_buffer_size) { + unsigned int max_transfer_buffer_size, + unsigned int mapped_memory_limit) { GPU_DCHECK_GE(starting_transfer_buffer_size, min_transfer_buffer_size); GPU_DCHECK_LE(starting_transfer_buffer_size, max_transfer_buffer_size); GPU_DCHECK_GE(min_transfer_buffer_size, kStartingOffset); @@ -148,8 +148,14 @@ bool GLES2Implementation::Initialize( return false; } - mapped_memory_.reset(new MappedMemoryManager(helper_)); - SetSharedMemoryChunkSizeMultiple(1024 * 1024 * 2); + mapped_memory_.reset(new MappedMemoryManager(helper_, mapped_memory_limit)); + + unsigned chunk_size = 2 * 1024 * 1024; + if (mapped_memory_limit != kNoLimit) { + // Use smaller chunks if the client is very memory conscientious. + chunk_size = std::min(mapped_memory_limit / 4, chunk_size); + } + mapped_memory_->set_chunk_size_multiple(chunk_size); if (!QueryAndCacheStaticState()) return false; @@ -165,7 +171,7 @@ bool GLES2Implementation::Initialize( query_tracker_.reset(new QueryTracker(mapped_memory_.get())); buffer_tracker_.reset(new BufferTracker(mapped_memory_.get())); - gpu_memory_buffer_tracker_.reset(new GpuMemoryBufferTracker(image_factory_)); + gpu_memory_buffer_tracker_.reset(new GpuMemoryBufferTracker(gpu_control_)); #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) GetIdHandler(id_namespaces::kBuffers)->MakeIds( @@ -289,11 +295,6 @@ uint32 GLES2Implementation::GetResultShmOffset() { return transfer_buffer_->GetResultOffset(); } -void GLES2Implementation::SetSharedMemoryChunkSizeMultiple( - unsigned int multiple) { - mapped_memory_->set_chunk_size_multiple(multiple); -} - void GLES2Implementation::FreeUnusedSharedMemory() { mapped_memory_->FreeUnused(); } @@ -2089,7 +2090,7 @@ const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { "GL_CHROMIUM_map_sub " "GL_CHROMIUM_shallow_flush " "GL_EXT_unpack_subimage"; - if (image_factory_ != NULL) { + if (gpu_control_ != NULL) { // The first space character is intentional. str += " GL_CHROMIUM_map_image"; } diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.h b/chromium/gpu/command_buffer/client/gles2_implementation.h index c2bf49f41fc..9f8a7a2516a 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.h +++ b/chromium/gpu/command_buffer/client/gles2_implementation.h @@ -20,7 +20,7 @@ #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h" -#include "gpu/command_buffer/client/image_factory.h" +#include "gpu/command_buffer/client/mapped_memory.h" #include "gpu/command_buffer/client/query_tracker.h" #include "gpu/command_buffer/client/ref_counted.h" #include "gpu/command_buffer/client/ring_buffer.h" @@ -98,7 +98,7 @@ struct GLUniformDefinitionCHROMIUM; namespace gpu { -class MappedMemoryManager; +class GpuControl; class ScopedTransferBufferPtr; class TransferBufferInterface; @@ -115,6 +115,9 @@ class VertexArrayObjectManager; // shared memory and synchronization issues. class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface { public: + enum MappedMemoryLimit { + kNoLimit = MappedMemoryManager::kNoLimit, + }; class ErrorMessageCallback { public: virtual ~ErrorMessageCallback() { } @@ -177,14 +180,15 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface { ShareGroup* share_group, TransferBufferInterface* transfer_buffer, bool bind_generates_resource, - ImageFactory* image_factory); + GpuControl* gpu_control); virtual ~GLES2Implementation(); bool Initialize( unsigned int starting_transfer_buffer_size, unsigned int min_transfer_buffer_size, - unsigned int max_transfer_buffer_size); + unsigned int max_transfer_buffer_size, + unsigned int mapped_memory_limit); // The GLES2CmdHelper being used by this GLES2Implementation. You can use // this to issue cmds at a lower level for certain kinds of optimization. @@ -215,7 +219,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface { GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); - void SetSharedMemoryChunkSizeMultiple(unsigned int multiple); void FreeUnusedSharedMemory(); void FreeEverything(); @@ -668,7 +671,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface { scoped_ptr<std::string> current_trace_name_; - ImageFactory* image_factory_; + GpuControl* gpu_control_; DISALLOW_COPY_AND_ASSIGN(GLES2Implementation); }; diff --git a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc index e58907c8b27..84fa749fde5 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -366,6 +366,8 @@ class GLES2ImplementationTest : public testing::Test { helper_.reset(new GLES2CmdHelper(command_buffer())); helper_->Initialize(kCommandBufferSizeBytes); + gpu_control_.reset(new StrictMock<MockClientGpuControl>()); + GLES2Implementation::GLStaticState state; GLES2Implementation::GLStaticState::IntState& int_state = state.int_state; int_state.max_combined_texture_image_units = kMaxCombinedTextureImageUnits; @@ -401,11 +403,12 @@ class GLES2ImplementationTest : public testing::Test { NULL, transfer_buffer_.get(), bind_generates_resource, - NULL)); + gpu_control_.get())); ASSERT_TRUE(gl_->Initialize( kTransferBufferSize, kTransferBufferSize, - kTransferBufferSize)); + kTransferBufferSize, + GLES2Implementation::kNoLimit)); } EXPECT_CALL(*command_buffer(), OnFlush()) @@ -473,6 +476,7 @@ class GLES2ImplementationTest : public testing::Test { Sequence sequence_; scoped_ptr<MockClientCommandBuffer> command_buffer_; + scoped_ptr<MockClientGpuControl> gpu_control_; scoped_ptr<GLES2CmdHelper> helper_; scoped_ptr<MockTransferBuffer> transfer_buffer_; scoped_ptr<GLES2Implementation> gl_; @@ -2476,7 +2480,8 @@ TEST_F(GLES2ImplementationTest, GetString) { "GL_CHROMIUM_flipy " "GL_CHROMIUM_map_sub " "GL_CHROMIUM_shallow_flush " - "GL_EXT_unpack_subimage"; + "GL_EXT_unpack_subimage " + "GL_CHROMIUM_map_image"; const char kBad = 0x12; struct Cmds { cmd::SetBucketSize set_bucket_size1; diff --git a/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc b/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc index c1c9b4d63c7..a957cc4b8dc 100644 --- a/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc +++ b/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc @@ -6,15 +6,13 @@ #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/command_buffer/client/image_factory.h" -#include "ui/gfx/gpu_memory_buffer.h" +#include "gpu/command_buffer/common/gpu_control.h" namespace gpu { namespace gles2 { -GpuMemoryBufferTracker::GpuMemoryBufferTracker(ImageFactory* factory) - : buffers_(), - factory_(factory) { +GpuMemoryBufferTracker::GpuMemoryBufferTracker(GpuControl* gpu_control) + : gpu_control_(gpu_control) { } GpuMemoryBufferTracker::~GpuMemoryBufferTracker() { @@ -23,37 +21,33 @@ GpuMemoryBufferTracker::~GpuMemoryBufferTracker() { } } -GLuint GpuMemoryBufferTracker::CreateBuffer( - GLsizei width, GLsizei height, GLenum internalformat) { - GLuint image_id = 0; - DCHECK(factory_); - scoped_ptr<gfx::GpuMemoryBuffer> buffer = - factory_->CreateGpuMemoryBuffer(width, height, internalformat, &image_id); - - if (buffer.get() == NULL) +int32 GpuMemoryBufferTracker::CreateBuffer( + size_t width, size_t height, int32 internalformat) { + int32 image_id = 0; + DCHECK(gpu_control_); + gfx::GpuMemoryBuffer* buffer = gpu_control_->CreateGpuMemoryBuffer( + width, height, internalformat, &image_id); + if (!buffer) return 0; std::pair<BufferMap::iterator, bool> result = - buffers_.insert(std::make_pair(image_id, buffer.release())); + buffers_.insert(std::make_pair(image_id, buffer)); GPU_DCHECK(result.second); return image_id; } -gfx::GpuMemoryBuffer* GpuMemoryBufferTracker::GetBuffer(GLuint image_id) { +gfx::GpuMemoryBuffer* GpuMemoryBufferTracker::GetBuffer(int32 image_id) { BufferMap::iterator it = buffers_.find(image_id); return (it != buffers_.end()) ? it->second : NULL; } -void GpuMemoryBufferTracker::RemoveBuffer(GLuint image_id) { +void GpuMemoryBufferTracker::RemoveBuffer(int32 image_id) { BufferMap::iterator buffer_it = buffers_.find(image_id); - if (buffer_it != buffers_.end()) { - gfx::GpuMemoryBuffer* buffer = buffer_it->second; + if (buffer_it != buffers_.end()) buffers_.erase(buffer_it); - delete buffer; - } - DCHECK(factory_); - factory_->DeleteGpuMemoryBuffer(image_id); + DCHECK(gpu_control_); + gpu_control_->DestroyGpuMemoryBuffer(image_id); } } // namespace gles2 diff --git a/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.h b/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.h index 1192b1714f0..0b07dd0a148 100644 --- a/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.h +++ b/chromium/gpu/command_buffer/client/gpu_memory_buffer_tracker.h @@ -5,8 +5,6 @@ #ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_ #define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_ -#include <GLES2/gl2.h> - #include "base/basictypes.h" #include "gles2_impl_export.h" #include "gpu/command_buffer/client/hash_tables.h" @@ -16,25 +14,24 @@ class GpuMemoryBuffer; } namespace gpu { +class GpuControl; + namespace gles2 { -class ImageFactory; // Tracks GPU memory buffer objects on the client side. class GLES2_IMPL_EXPORT GpuMemoryBufferTracker { public: - // Ownership of |factory| remains with caller. - explicit GpuMemoryBufferTracker(ImageFactory* factory); + explicit GpuMemoryBufferTracker(GpuControl* gpu_control); virtual ~GpuMemoryBufferTracker(); - GLuint CreateBuffer( - GLsizei width, GLsizei height, GLenum internalformat); - gfx::GpuMemoryBuffer* GetBuffer(GLuint image_id); - void RemoveBuffer(GLuint image_id); + int32 CreateBuffer(size_t width, size_t height, int32 internalformat); + gfx::GpuMemoryBuffer* GetBuffer(int32 image_id); + void RemoveBuffer(int32 image_id); private: - typedef gpu::hash_map<GLuint, gfx::GpuMemoryBuffer*> BufferMap; + typedef gpu::hash_map<int32, gfx::GpuMemoryBuffer*> BufferMap; BufferMap buffers_; - ImageFactory* factory_; + GpuControl* gpu_control_; DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferTracker); }; diff --git a/chromium/gpu/command_buffer/client/image_factory.h b/chromium/gpu/command_buffer/client/image_factory.h deleted file mode 100644 index 449c8a4b74b..00000000000 --- a/chromium/gpu/command_buffer/client/image_factory.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 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_CLIENT_IMAGE_FACTORY_H_ -#define GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_ - -#include <GLES2/gl2.h> - -#include "base/memory/scoped_ptr.h" -#include "gles2_impl_export.h" - -namespace gfx { -class GpuMemoryBuffer; -} - -namespace gpu { -namespace gles2 { - -class GLES2_IMPL_EXPORT ImageFactory { - - public: - virtual ~ImageFactory() {} - - // Create a GpuMemoryBuffer and makes it available to the - // service side by inserting it to the ImageManager. - virtual scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( - int width, int height, GLenum internalformat, unsigned* image_id) = 0; - virtual void DeleteGpuMemoryBuffer(unsigned image_id) = 0; -}; - -} // namespace gles2 -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_ diff --git a/chromium/gpu/command_buffer/client/mapped_memory.cc b/chromium/gpu/command_buffer/client/mapped_memory.cc index 82829d48ec1..c367e696c50 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory.cc +++ b/chromium/gpu/command_buffer/client/mapped_memory.cc @@ -7,6 +7,7 @@ #include <algorithm> #include <functional> +#include "base/debug/trace_event.h" #include "gpu/command_buffer/client/cmd_buffer_helper.h" namespace gpu { @@ -18,9 +19,12 @@ MemoryChunk::MemoryChunk( allocator_(shm.size, helper, shm.ptr) { } -MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper) +MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper, + size_t unused_memory_reclaim_limit) : chunk_size_multiple_(1), - helper_(helper) { + helper_(helper), + allocated_memory_(0), + max_free_bytes_(unused_memory_reclaim_limit) { } MappedMemoryManager::~MappedMemoryManager() { @@ -36,16 +40,38 @@ void* MappedMemoryManager::Alloc( unsigned int size, int32* shm_id, unsigned int* shm_offset) { GPU_DCHECK(shm_id); GPU_DCHECK(shm_offset); - // See if any of the chucks can satisfy this request. - for (size_t ii = 0; ii < chunks_.size(); ++ii) { - MemoryChunk* chunk = chunks_[ii]; - chunk->FreeUnused(); - if (chunk->GetLargestFreeSizeWithoutWaiting() >= size) { - void* mem = chunk->Alloc(size); - GPU_DCHECK(mem); - *shm_id = chunk->shm_id(); - *shm_offset = chunk->GetOffset(mem); - return mem; + if (size <= allocated_memory_) { + size_t total_bytes_in_use = 0; + // See if any of the chunks can satisfy this request. + for (size_t ii = 0; ii < chunks_.size(); ++ii) { + MemoryChunk* chunk = chunks_[ii]; + chunk->FreeUnused(); + total_bytes_in_use += chunk->bytes_in_use(); + if (chunk->GetLargestFreeSizeWithoutWaiting() >= size) { + void* mem = chunk->Alloc(size); + GPU_DCHECK(mem); + *shm_id = chunk->shm_id(); + *shm_offset = chunk->GetOffset(mem); + return mem; + } + } + + // If there is a memory limit being enforced and total free + // memory (allocated_memory_ - total_bytes_in_use) is larger than + // the limit try waiting. + if (max_free_bytes_ != kNoLimit && + (allocated_memory_ - total_bytes_in_use) >= max_free_bytes_) { + TRACE_EVENT0("gpu", "MappedMemoryManager::Alloc::wait"); + for (size_t ii = 0; ii < chunks_.size(); ++ii) { + MemoryChunk* chunk = chunks_[ii]; + if (chunk->GetLargestFreeSizeWithWaiting() >= size) { + void* mem = chunk->Alloc(size); + GPU_DCHECK(mem); + *shm_id = chunk->shm_id(); + *shm_offset = chunk->GetOffset(mem); + return mem; + } + } } } @@ -59,6 +85,7 @@ void* MappedMemoryManager::Alloc( if (id < 0) return NULL; MemoryChunk* mc = new MemoryChunk(id, shm, helper_); + allocated_memory_ += mc->GetSize(); chunks_.push_back(mc); void* mem = mc->Alloc(size); GPU_DCHECK(mem); @@ -97,6 +124,7 @@ void MappedMemoryManager::FreeUnused() { chunk->FreeUnused(); if (!chunk->InUse()) { cmd_buf->DestroyTransferBuffer(chunk->shm_id()); + allocated_memory_ -= chunk->GetSize(); iter = chunks_.erase(iter); } else { ++iter; @@ -105,6 +133,3 @@ void MappedMemoryManager::FreeUnused() { } } // namespace gpu - - - diff --git a/chromium/gpu/command_buffer/client/mapped_memory.h b/chromium/gpu/command_buffer/client/mapped_memory.h index ec70c430de5..db73ca7a609 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory.h +++ b/chromium/gpu/command_buffer/client/mapped_memory.h @@ -79,7 +79,7 @@ class GPU_EXPORT MemoryChunk { allocator_.FreePendingToken(pointer, token); } - // Frees any blocks who's tokens have passed. + // Frees any blocks whose tokens have passed. void FreeUnused() { allocator_.FreeUnused(); } @@ -90,11 +90,15 @@ class GPU_EXPORT MemoryChunk { pointer < reinterpret_cast<const int8*>(shm_.ptr) + shm_.size; } - // Returns true of any memory in this chuck is in use. + // Returns true of any memory in this chunk is in use. bool InUse() { return allocator_.InUse(); } + size_t bytes_in_use() const { + return allocator_.bytes_in_use(); + } + private: int32 shm_id_; gpu::Buffer shm_; @@ -103,10 +107,17 @@ class GPU_EXPORT MemoryChunk { DISALLOW_COPY_AND_ASSIGN(MemoryChunk); }; -// Manages MemoryChucks. +// Manages MemoryChunks. class GPU_EXPORT MappedMemoryManager { public: - explicit MappedMemoryManager(CommandBufferHelper* helper); + enum MemoryLimit { + kNoLimit = 0, + }; + + // |unused_memory_reclaim_limit|: When exceeded this causes pending memory + // to be reclaimed before allocating more memory. + MappedMemoryManager(CommandBufferHelper* helper, + size_t unused_memory_reclaim_limit); ~MappedMemoryManager(); @@ -146,10 +157,15 @@ class GPU_EXPORT MappedMemoryManager { void FreeUnused(); // Used for testing - size_t num_chunks() { + size_t num_chunks() const { return chunks_.size(); } + // Used for testing + size_t allocated_memory() const { + return allocated_memory_; + } + private: typedef ScopedVector<MemoryChunk> MemoryChunkVector; @@ -157,6 +173,8 @@ class GPU_EXPORT MappedMemoryManager { unsigned int chunk_size_multiple_; CommandBufferHelper* helper_; MemoryChunkVector chunks_; + size_t allocated_memory_; + size_t max_free_bytes_; DISALLOW_COPY_AND_ASSIGN(MappedMemoryManager); }; diff --git a/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc b/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc index 99e6e8d3ec2..90d1ce7666b 100644 --- a/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc +++ b/chromium/gpu/command_buffer/client/mapped_memory_unittest.cc @@ -149,7 +149,8 @@ class MappedMemoryManagerTest : public MappedMemoryTestBase { protected: virtual void SetUp() { MappedMemoryTestBase::SetUp(); - manager_.reset(new MappedMemoryManager(helper_.get())); + manager_.reset(new MappedMemoryManager( + helper_.get(), MappedMemoryManager::kNoLimit)); } virtual void TearDown() { @@ -306,4 +307,81 @@ TEST_F(MappedMemoryManagerTest, ChunkSizeMultiple) { EXPECT_EQ(0u, offset3); } +TEST_F(MappedMemoryManagerTest, UnusedMemoryLimit) { + const unsigned int kChunkSize = 2048; + // Reset the manager with a memory limit. + manager_.reset(new MappedMemoryManager(helper_.get(), kChunkSize)); + manager_->set_chunk_size_multiple(kChunkSize); + + // Allocate one chunk worth of memory. + int32 id1 = -1; + unsigned int offset1 = 0xFFFFFFFFU; + void* mem1 = manager_->Alloc(kChunkSize, &id1, &offset1); + ASSERT_TRUE(mem1); + EXPECT_NE(-1, id1); + EXPECT_EQ(0u, offset1); + + // Allocate half a chunk worth of memory again. + // The same chunk will be used. + int32 id2 = -1; + unsigned int offset2 = 0xFFFFFFFFU; + void* mem2 = manager_->Alloc(kChunkSize, &id2, &offset2); + ASSERT_TRUE(mem2); + EXPECT_NE(-1, id2); + EXPECT_EQ(0u, offset2); + + // Expect two chunks to be allocated, exceeding the limit, + // since all memory is in use. + EXPECT_EQ(2 * kChunkSize, manager_->allocated_memory()); +} + +TEST_F(MappedMemoryManagerTest, MemoryLimitWithReuse) { + const unsigned int kSize = 1024; + // Reset the manager with a memory limit. + manager_.reset(new MappedMemoryManager(helper_.get(), kSize)); + const unsigned int kChunkSize = 2 * 1024; + manager_->set_chunk_size_multiple(kChunkSize); + + // Allocate half a chunk worth of memory. + int32 id1 = -1; + unsigned int offset1 = 0xFFFFFFFFU; + void* mem1 = manager_->Alloc(kSize, &id1, &offset1); + ASSERT_TRUE(mem1); + EXPECT_NE(-1, id1); + EXPECT_EQ(0u, offset1); + + // Allocate half a chunk worth of memory again. + // The same chunk will be used. + int32 id2 = -1; + unsigned int offset2 = 0xFFFFFFFFU; + void* mem2 = manager_->Alloc(kSize, &id2, &offset2); + ASSERT_TRUE(mem2); + EXPECT_NE(-1, id2); + EXPECT_EQ(kSize, offset2); + + // Free one successful allocation, pending fence. + int32 token = helper_.get()->InsertToken(); + manager_->FreePendingToken(mem2, token); + + // The way we hooked up the helper and engine, it won't process commands + // until it has to wait for something. Which means the token shouldn't have + // passed yet at this point. + EXPECT_GT(token, GetToken()); + + // Since we didn't call helper_.finish() the token did not pass. + // We won't be able to claim the free memory without waiting and + // as we've already met the memory limit we'll have to wait + // on the token. + int32 id3 = -1; + unsigned int offset3 = 0xFFFFFFFFU; + void* mem3 = manager_->Alloc(kSize, &id3, &offset3); + ASSERT_TRUE(mem3); + EXPECT_NE(-1, id3); + // It will reuse the space from the second allocation just freed. + EXPECT_EQ(kSize, offset3); + + // Expect one chunk to be allocated + EXPECT_EQ(1 * kChunkSize, manager_->allocated_memory()); +} + } // namespace gpu diff --git a/chromium/gpu/command_buffer/client/query_tracker.cc b/chromium/gpu/command_buffer/client/query_tracker.cc index 35732bf4a83..307b615c6fd 100644 --- a/chromium/gpu/command_buffer/client/query_tracker.cc +++ b/chromium/gpu/command_buffer/client/query_tracker.cc @@ -112,8 +112,8 @@ void QueryTracker::Query::Begin(GLES2Implementation* gl) { // tell service about id, shared memory and count gl->helper()->BeginQueryEXT(target(), id(), shm_id(), shm_offset()); break; - case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM: - case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: default: // tell service about id, shared memory and count gl->helper()->BeginQueryEXT(target(), id(), shm_id(), shm_offset()); @@ -162,8 +162,8 @@ bool QueryTracker::Query::CheckResultsAvailable( result_ = std::min(info_.sync->result - client_begin_time_us_, static_cast<uint64>(0xFFFFFFFFL)); break; - case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM: - case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: default: result_ = info_.sync->result; break; diff --git a/chromium/gpu/command_buffer/client/query_tracker_unittest.cc b/chromium/gpu/command_buffer/client/query_tracker_unittest.cc index 2dad335c7e7..800c479ec85 100644 --- a/chromium/gpu/command_buffer/client/query_tracker_unittest.cc +++ b/chromium/gpu/command_buffer/client/query_tracker_unittest.cc @@ -28,7 +28,8 @@ class QuerySyncManagerTest : public testing::Test { command_buffer_.reset(new MockClientCommandBuffer()); helper_.reset(new GLES2CmdHelper(command_buffer_.get())); helper_->Initialize(kCommandBufferSizeBytes); - mapped_memory_.reset(new MappedMemoryManager(helper_.get())); + mapped_memory_.reset(new MappedMemoryManager( + helper_.get(), MappedMemoryManager::kNoLimit)); sync_manager_.reset(new QuerySyncManager(mapped_memory_.get())); } @@ -81,7 +82,8 @@ class QueryTrackerTest : public testing::Test { command_buffer_.reset(new MockClientCommandBuffer()); helper_.reset(new GLES2CmdHelper(command_buffer_.get())); helper_->Initialize(kCommandBufferSizeBytes); - mapped_memory_.reset(new MappedMemoryManager(helper_.get())); + mapped_memory_.reset(new MappedMemoryManager( + helper_.get(), MappedMemoryManager::kNoLimit)); query_tracker_.reset(new QueryTracker(mapped_memory_.get())); } diff --git a/chromium/gpu/command_buffer/command_buffer_untrusted.gyp b/chromium/gpu/command_buffer/command_buffer_untrusted.gyp index 8f27a0b0569..0667fd859cf 100644 --- a/chromium/gpu/command_buffer/command_buffer_untrusted.gyp +++ b/chromium/gpu/command_buffer/command_buffer_untrusted.gyp @@ -21,7 +21,7 @@ 'nacl_untrusted_build': 1, 'nlib_target': 'libgles2_utils_untrusted.a', 'build_glibc': 0, - 'build_newlib': 1, + 'build_newlib': 0, 'build_irt': 1, }, 'dependencies': [ diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_format.h b/chromium/gpu/command_buffer/common/gles2_cmd_format.h index 37c7a53d970..76bb3fe1d4d 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_format.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_format.h @@ -56,7 +56,6 @@ enum IdNamespaces { kTextures, kQueries, kVertexArrays, - kImages, kNumIdNamespaces }; diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc b/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc index 25eafcd8a26..301ef4a1a11 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -715,7 +715,29 @@ bool GLES2Util::ParseUniformName( return true; } -ContextCreationAttribParser::ContextCreationAttribParser() +namespace { + +// From <EGL/egl.h>. +const int32 kAlphaSize = 0x3021; // EGL_ALPHA_SIZE +const int32 kBlueSize = 0x3022; // EGL_BLUE_SIZE +const int32 kGreenSize = 0x3023; // EGL_GREEN_SIZE +const int32 kRedSize = 0x3024; // EGL_RED_SIZE +const int32 kDepthSize = 0x3025; // EGL_DEPTH_SIZE +const int32 kStencilSize = 0x3026; // EGL_STENCIL_SIZE +const int32 kSamples = 0x3031; // EGL_SAMPLES +const int32 kSampleBuffers = 0x3032; // EGL_SAMPLE_BUFFERS +const int32 kNone = 0x3038; // EGL_NONE +const int32 kSwapBehavior = 0x3093; // EGL_SWAP_BEHAVIOR +const int32 kBufferPreserved = 0x3094; // EGL_BUFFER_PRESERVED +const int32 kBufferDestroyed = 0x3095; // EGL_BUFFER_DESTROYED + +// Chromium only. +const int32 kShareResources = 0x10000; +const int32 kBindGeneratesResource = 0x10001; + +} // namespace + +ContextCreationAttribHelper::ContextCreationAttribHelper() : alpha_size_(-1), blue_size_(-1), green_size_(-1), @@ -729,28 +751,53 @@ ContextCreationAttribParser::ContextCreationAttribParser() bind_generates_resource_(true) { } -bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) { - // From <EGL/egl.h>. - const int32 EGL_ALPHA_SIZE = 0x3021; - const int32 EGL_BLUE_SIZE = 0x3022; - const int32 EGL_GREEN_SIZE = 0x3023; - const int32 EGL_RED_SIZE = 0x3024; - const int32 EGL_DEPTH_SIZE = 0x3025; - const int32 EGL_STENCIL_SIZE = 0x3026; - const int32 EGL_SAMPLES = 0x3031; - const int32 EGL_SAMPLE_BUFFERS = 0x3032; - const int32 EGL_NONE = 0x3038; - const int32 EGL_SWAP_BEHAVIOR = 0x3093; - const int32 EGL_BUFFER_PRESERVED = 0x3094; - - // Chromium only. - const int32 SHARE_RESOURCES = 0x10000; - const int32 BIND_GENERATES_RESOURCES = 0x10001; +void ContextCreationAttribHelper::Serialize(std::vector<int32>* attribs) { + if (alpha_size_ != -1) { + attribs->push_back(kAlphaSize); + attribs->push_back(alpha_size_); + } + if (blue_size_ != -1) { + attribs->push_back(kBlueSize); + attribs->push_back(blue_size_); + } + if (green_size_ != -1) { + attribs->push_back(kGreenSize); + attribs->push_back(green_size_); + } + if (red_size_ != -1) { + attribs->push_back(kRedSize); + attribs->push_back(red_size_); + } + if (depth_size_ != -1) { + attribs->push_back(kDepthSize); + attribs->push_back(depth_size_); + } + if (stencil_size_ != -1) { + attribs->push_back(kStencilSize); + attribs->push_back(stencil_size_); + } + if (samples_ != -1) { + attribs->push_back(kSamples); + attribs->push_back(samples_); + } + if (sample_buffers_ != -1) { + attribs->push_back(kSampleBuffers); + attribs->push_back(sample_buffers_); + } + attribs->push_back(kSwapBehavior); + attribs->push_back(buffer_preserved_ ? kBufferPreserved : kBufferDestroyed); + attribs->push_back(kShareResources); + attribs->push_back(share_resources_ ? 1 : 0); + attribs->push_back(kBindGeneratesResource); + attribs->push_back(bind_generates_resource_ ? 1 : 0); + attribs->push_back(kNone); +} +bool ContextCreationAttribHelper::Parse(const std::vector<int32>& attribs) { for (size_t i = 0; i < attribs.size(); i += 2) { const int32 attrib = attribs[i]; if (i + 1 >= attribs.size()) { - if (attrib == EGL_NONE) { + if (attrib == kNone) { return true; } @@ -761,40 +808,40 @@ bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) { const int32 value = attribs[i+1]; switch (attrib) { - case EGL_ALPHA_SIZE: + case kAlphaSize: alpha_size_ = value; break; - case EGL_BLUE_SIZE: + case kBlueSize: blue_size_ = value; break; - case EGL_GREEN_SIZE: + case kGreenSize: green_size_ = value; break; - case EGL_RED_SIZE: + case kRedSize: red_size_ = value; break; - case EGL_DEPTH_SIZE: + case kDepthSize: depth_size_ = value; break; - case EGL_STENCIL_SIZE: + case kStencilSize: stencil_size_ = value; break; - case EGL_SAMPLES: + case kSamples: samples_ = value; break; - case EGL_SAMPLE_BUFFERS: + case kSampleBuffers: sample_buffers_ = value; break; - case EGL_SWAP_BEHAVIOR: - buffer_preserved_ = value == EGL_BUFFER_PRESERVED; + case kSwapBehavior: + buffer_preserved_ = value == kBufferPreserved; break; - case SHARE_RESOURCES: + case kShareResources: share_resources_ = value != 0; break; - case BIND_GENERATES_RESOURCES: + case kBindGeneratesResource: bind_generates_resource_ = value != 0; break; - case EGL_NONE: + case kNone: // Terminate list, even if more attributes. return true; default: diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils.h b/chromium/gpu/command_buffer/common/gles2_cmd_utils.h index 4bc4b1b7fcc..b8619e61d37 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils.h @@ -174,9 +174,11 @@ class GLES2_UTILS_EXPORT GLES2Util { int num_shader_binary_formats_; }; -class GLES2_UTILS_EXPORT ContextCreationAttribParser { +class GLES2_UTILS_EXPORT ContextCreationAttribHelper { public: - ContextCreationAttribParser(); + ContextCreationAttribHelper(); + + void Serialize(std::vector<int32>* attribs); bool Parse(const std::vector<int32>& attribs); // -1 if invalid or unspecified. diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 573aee9d756..aa24ccd77ea 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -225,10 +225,10 @@ static const GLES2Util::EnumToString enum_to_string_table[] = { { 0x90F1, "GL_MULTIVIEW_EXT", }, { 0x90F0, "GL_COLOR_ATTACHMENT_EXT", }, { 0x803C, "GL_ALPHA8_OES", }, - { 0x84F5, "GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM", }, + { 0x84F5, "GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM", }, { 0x882A, "GL_DRAW_BUFFER5_NV", }, { 0x80AA, "GL_SAMPLE_COVERAGE_VALUE", }, - { 0x84F6, "GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM", }, + { 0x84F6, "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM", }, { 0x80AB, "GL_SAMPLE_COVERAGE_INVERT", }, { 0x8FC4, "GL_SHADER_BINARY_VIV", }, { 0x882B, "GL_DRAW_BUFFER6_NV", }, @@ -1078,10 +1078,10 @@ std::string GLES2Util::GetStringQueryTarget(uint32 value) { "GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT" }, { GL_COMMANDS_ISSUED_CHROMIUM, "GL_COMMANDS_ISSUED_CHROMIUM" }, { GL_LATENCY_QUERY_CHROMIUM, "GL_LATENCY_QUERY_CHROMIUM" }, - { GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM, - "GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM" }, - { GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM, - "GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM" }, + { GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, + "GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM" }, + { GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, + "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM" }, }; return GLES2Util::GetQualifiedEnumString( string_table, arraysize(string_table), value); diff --git a/chromium/gpu/command_buffer/common/gpu_control.h b/chromium/gpu/command_buffer/common/gpu_control.h new file mode 100644 index 00000000000..5534ca78967 --- /dev/null +++ b/chromium/gpu/command_buffer/common/gpu_control.h @@ -0,0 +1,39 @@ +// Copyright 2013 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_COMMON_GPU_CONTROL_H_ +#define GPU_COMMAND_BUFFER_COMMON_GPU_CONTROL_H_ + +#include "gpu/gpu_export.h" + +namespace gfx { +class GpuMemoryBuffer; +} + +namespace gpu { + +// Common interface for GpuControl implementations. +class GPU_EXPORT GpuControl { + public: + GpuControl() {} + virtual ~GpuControl() {} + + // Create a gpu memory buffer of the given dimensions and format. Returns + // its ID or -1 on error. + virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( + size_t width, + size_t height, + unsigned internalformat, + int32* id) = 0; + + // Destroy a gpu memory buffer. The ID must be positive. + virtual void DestroyGpuMemoryBuffer(int32 id) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(GpuControl); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_COMMON_GPU_CONTROL_H_ 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 8de7d58a07a..5aaabf4ea8a 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 @@ -4,6 +4,7 @@ #include "gpu/command_buffer/service/async_pixel_transfer_manager.h" +#include "base/android/sys_utils.h" #include "base/debug/trace_event.h" #include "gpu/command_buffer/service/async_pixel_transfer_manager_egl.h" #include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h" @@ -38,6 +39,8 @@ bool IsImagination() { // - The heap size is large enough. // TODO(kaanb|epenner): Remove the IsImagination() check pending the // resolution of crbug.com/249147 +// TODO(kaanb|epenner): Remove the IsLowEndDevice() check pending the +// resolution of crbug.com/271929 AsyncPixelTransferManager* AsyncPixelTransferManager::Create( gfx::GLContext* context) { TRACE_EVENT0("gpu", "AsyncPixelTransferManager::Create"); @@ -50,7 +53,8 @@ AsyncPixelTransferManager* AsyncPixelTransferManager::Create( context->HasExtension("EGL_KHR_gl_texture_2D_image") && context->HasExtension("GL_OES_EGL_image") && !IsBroadcom() && - !IsImagination()) { + !IsImagination() && + !base::android::SysUtils::IsLowEndDevice()) { return new AsyncPixelTransferManagerEGL; } LOG(INFO) << "Async pixel transfers not supported"; 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 64e1f32c76b..7e0d515e49c 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 @@ -170,7 +170,8 @@ class TransferStateInternal "width", define_params_.width, "height", define_params_.height); DCHECK(texture_id_); - DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); + if (EGL_NO_IMAGE_KHR == egl_image_) + return; glBindTexture(GL_TEXTURE_2D, texture_id_); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); @@ -203,7 +204,8 @@ class TransferStateInternal egl_buffer, egl_attrib_list); - DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); + DLOG_IF(ERROR, EGL_NO_IMAGE_KHR == egl_image_) + << "eglCreateImageKHR failed"; } void CreateEglImageOnUploadThread() { @@ -259,7 +261,10 @@ class TransferStateInternal tex_params.height); DCHECK(!thread_texture_id_); DCHECK_EQ(0, tex_params.level); - DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); + if (EGL_NO_IMAGE_KHR != egl_image_) { + MarkAsCompleted(); + return; + } void* data = AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); diff --git a/chromium/gpu/command_buffer/service/buffer_manager.cc b/chromium/gpu/command_buffer/service/buffer_manager.cc index f9cec7ace9a..7b1c90dfbb3 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager.cc +++ b/chromium/gpu/command_buffer/service/buffer_manager.cc @@ -74,13 +74,13 @@ void BufferManager::StopTracking(Buffer* buffer) { Buffer::Buffer(BufferManager* manager, GLuint service_id) : manager_(manager), + size_(0), deleted_(false), + shadowed_(false), + is_client_side_array_(false), service_id_(service_id), target_(0), - size_(0), - usage_(GL_STATIC_DRAW), - shadowed_(false), - is_client_side_array_(false) { + usage_(GL_STATIC_DRAW) { manager_->StartTracking(this); } diff --git a/chromium/gpu/command_buffer/service/buffer_manager.h b/chromium/gpu/command_buffer/service/buffer_manager.h index 8ddf334d42f..cc23f01604b 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager.h +++ b/chromium/gpu/command_buffer/service/buffer_manager.h @@ -135,9 +135,23 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { // The manager that owns this Buffer. BufferManager* manager_; + // A copy of the data in the buffer. This data is only kept if the target + // is backed_ = true. + scoped_ptr<int8[]> shadow_; + + // Size of buffer. + GLsizeiptr size_; + // True if deleted. bool deleted_; + // Whether or not the data is shadowed. + bool shadowed_; + + // Whether or not this Buffer is not uploaded to the GPU but just + // sitting in local memory. + bool is_client_side_array_; + // Service side buffer id. GLuint service_id_; @@ -146,23 +160,9 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { // Once set a buffer can not be used for something else. GLenum target_; - // Size of buffer. - GLsizeiptr size_; - // Usage of buffer. GLenum usage_; - // Whether or not the data is shadowed. - bool shadowed_; - - // Whether or not this Buffer is not uploaded to the GPU but just - // sitting in local memory. - bool is_client_side_array_; - - // A copy of the data in the buffer. This data is only kept if the target - // is backed_ = true. - scoped_ptr<int8[]> shadow_; - // A map of ranges to the highest value in that range of a certain type. typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap; RangeToMaxValueMap range_set_; diff --git a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc index f6fb8386d03..444c3935bf5 100644 --- a/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/buffer_manager_unittest.cc @@ -27,7 +27,7 @@ class BufferManagerTestBase : public testing::Test { ::gfx::GLInterface::SetGLInterface(gl_.get()); if (feature_info) { TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions); - feature_info->Initialize(NULL); + feature_info->Initialize(); } error_state_.reset(new MockErrorState()); manager_.reset(new BufferManager(memory_tracker, feature_info)); diff --git a/chromium/gpu/command_buffer/service/context_group.cc b/chromium/gpu/command_buffer/service/context_group.cc index 0cf991a7f45..0cb6e51aa23 100644 --- a/chromium/gpu/command_buffer/service/context_group.cc +++ b/chromium/gpu/command_buffer/service/context_group.cc @@ -67,7 +67,6 @@ ContextGroup::ContextGroup( id_namespaces_[id_namespaces::kTextures].reset(new IdAllocator); id_namespaces_[id_namespaces::kQueries].reset(new IdAllocator); id_namespaces_[id_namespaces::kVertexArrays].reset(new IdAllocator); - id_namespaces_[id_namespaces::kImages].reset(new IdAllocator); } static void GetIntegerv(GLenum pname, uint32* var) { @@ -78,15 +77,14 @@ static void GetIntegerv(GLenum pname, uint32* var) { bool ContextGroup::Initialize( GLES2Decoder* decoder, - const DisallowedFeatures& disallowed_features, - const char* allowed_features) { + const DisallowedFeatures& disallowed_features) { // If we've already initialized the group just add the context. if (HaveContexts()) { decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder)); return true; } - if (!feature_info_->Initialize(disallowed_features, allowed_features)) { + if (!feature_info_->Initialize(disallowed_features)) { LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo " << "initialization failed."; return false; @@ -122,14 +120,16 @@ bool ContextGroup::Initialize( draw_buffer_ = GL_BACK; } + const bool depth24_supported = feature_info_->feature_flags().oes_depth24; + buffer_manager_.reset( new BufferManager(memory_tracker_.get(), feature_info_.get())); framebuffer_manager_.reset( new FramebufferManager(max_draw_buffers_, max_color_attachments_)); renderbuffer_manager_.reset(new RenderbufferManager( - memory_tracker_.get(), max_renderbuffer_size, max_samples)); + memory_tracker_.get(), max_renderbuffer_size, max_samples, + depth24_supported)); shader_manager_.reset(new ShaderManager()); - program_manager_.reset(new ProgramManager(program_cache_)); // Lookup GL things we need to know. const GLint kGLES2RequiredMinimumVertexAttribs = 8u; @@ -236,6 +236,9 @@ bool ContextGroup::Initialize( max_vertex_uniform_vectors_); } + program_manager_.reset(new ProgramManager( + program_cache_, max_varying_vectors_)); + if (!texture_manager_->Initialize()) { LOG(ERROR) << "Context::Group::Initialize failed because texture manager " << "failed to initialize."; diff --git a/chromium/gpu/command_buffer/service/context_group.h b/chromium/gpu/command_buffer/service/context_group.h index 13d031a707e..dd236ffa793 100644 --- a/chromium/gpu/command_buffer/service/context_group.h +++ b/chromium/gpu/command_buffer/service/context_group.h @@ -54,8 +54,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { // call to destroy if it succeeds. bool Initialize( GLES2Decoder* decoder, - const DisallowedFeatures& disallowed_features, - const char* allowed_features); + const DisallowedFeatures& disallowed_features); // Destroys all the resources when called for the last context in the group. // It should only be called by GLES2Decoder. diff --git a/chromium/gpu/command_buffer/service/context_group_unittest.cc b/chromium/gpu/command_buffer/service/context_group_unittest.cc index c80f6190a8e..59bc796405c 100644 --- a/chromium/gpu/command_buffer/service/context_group_unittest.cc +++ b/chromium/gpu/command_buffer/service/context_group_unittest.cc @@ -72,7 +72,7 @@ TEST_F(ContextGroupTest, Basic) { TEST_F(ContextGroupTest, InitializeNoExtensions) { TestHelper::SetupContextGroupInitExpectations(gl_.get(), DisallowedFeatures(), ""); - group_->Initialize(decoder_.get(), DisallowedFeatures(), ""); + group_->Initialize(decoder_.get(), DisallowedFeatures()); EXPECT_EQ(static_cast<uint32>(TestHelper::kNumVertexAttribs), group_->max_vertex_attribs()); EXPECT_EQ(static_cast<uint32>(TestHelper::kNumTextureUnits), @@ -107,8 +107,8 @@ TEST_F(ContextGroupTest, MultipleContexts) { scoped_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder()); TestHelper::SetupContextGroupInitExpectations(gl_.get(), DisallowedFeatures(), ""); - group_->Initialize(decoder_.get(), DisallowedFeatures(), ""); - group_->Initialize(decoder2_.get(), DisallowedFeatures(), ""); + group_->Initialize(decoder_.get(), DisallowedFeatures()); + group_->Initialize(decoder2_.get(), DisallowedFeatures()); EXPECT_TRUE(group_->buffer_manager() != NULL); EXPECT_TRUE(group_->framebuffer_manager() != NULL); diff --git a/chromium/gpu/command_buffer/service/disk_cache_proto.proto b/chromium/gpu/command_buffer/service/disk_cache_proto.proto index c165443e9fd..5a55943fba3 100644 --- a/chromium/gpu/command_buffer/service/disk_cache_proto.proto +++ b/chromium/gpu/command_buffer/service/disk_cache_proto.proto @@ -5,12 +5,15 @@ message ShaderInfoProto { optional int32 size = 2; optional string name = 3; optional string key = 4; + optional int32 precision = 5; + optional int32 static_use = 6; } message ShaderProto { optional bytes sha = 1; repeated ShaderInfoProto attribs = 2; repeated ShaderInfoProto uniforms = 3; + repeated ShaderInfoProto varyings = 4; } message GpuProgramProto { diff --git a/chromium/gpu/command_buffer/service/feature_info.cc b/chromium/gpu/command_buffer/service/feature_info.cc index 41c6a1b03a3..cddf0a5c963 100644 --- a/chromium/gpu/command_buffer/service/feature_info.cc +++ b/chromium/gpu/command_buffer/service/feature_info.cc @@ -104,6 +104,7 @@ FeatureInfo::FeatureFlags::FeatureFlags() use_img_for_multisampled_render_to_texture(false), oes_standard_derivatives(false), oes_egl_image_external(false), + oes_depth24(false), npot_ok(false), enable_texture_float_linear(false), enable_texture_half_float_linear(false), @@ -120,7 +121,8 @@ FeatureInfo::FeatureFlags::FeatureFlags() enable_samplers(false), ext_draw_buffers(false), ext_frag_depth(false), - use_async_readpixels(false) { + use_async_readpixels(false), + map_buffer_range(false) { } FeatureInfo::Workarounds::Workarounds() : @@ -132,6 +134,22 @@ FeatureInfo::Workarounds::Workarounds() : } FeatureInfo::FeatureInfo() { + InitializeBasicState(*CommandLine::ForCurrentProcess()); +} + +FeatureInfo::FeatureInfo(const CommandLine& command_line) { + InitializeBasicState(command_line); +} + +void FeatureInfo::InitializeBasicState(const CommandLine& command_line) { + if (command_line.HasSwitch(switches::kGpuDriverBugWorkarounds)) { + std::string types = command_line.GetSwitchValueASCII( + switches::kGpuDriverBugWorkarounds); + StringToWorkarounds(types, &workarounds_); + } + feature_flags_.enable_shader_name_hashing = + !command_line.HasSwitch(switches::kDisableShaderNameHashing); + static const GLenum kAlphaTypes[] = { GL_UNSIGNED_BYTE, }; @@ -167,33 +185,23 @@ FeatureInfo::FeatureInfo() { } } -bool FeatureInfo::Initialize(const char* allowed_features) { +bool FeatureInfo::Initialize() { disallowed_features_ = DisallowedFeatures(); - AddFeatures(*CommandLine::ForCurrentProcess()); + InitializeFeatures(); return true; } -bool FeatureInfo::Initialize(const DisallowedFeatures& disallowed_features, - const char* allowed_features) { +bool FeatureInfo::Initialize(const DisallowedFeatures& disallowed_features) { disallowed_features_ = disallowed_features; - AddFeatures(*CommandLine::ForCurrentProcess()); + InitializeFeatures(); return true; } -void FeatureInfo::AddFeatures(const CommandLine& command_line) { +void FeatureInfo::InitializeFeatures() { // Figure out what extensions to turn on. StringSet extensions( reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); - if (command_line.HasSwitch(switches::kGpuDriverBugWorkarounds)) { - std::string types = command_line.GetSwitchValueASCII( - switches::kGpuDriverBugWorkarounds); - StringToWorkarounds(types, &workarounds_); - } - - feature_flags_.enable_shader_name_hashing = - !command_line.HasSwitch(switches::kDisableShaderNameHashing); - bool npot_ok = false; AddExtensionString("GL_ANGLE_translated_shader_source"); @@ -490,6 +498,7 @@ void FeatureInfo::AddFeatures(const CommandLine& command_line) { if (extensions.Contains("GL_OES_depth24") || gfx::HasDesktopGLFeatures()) { AddExtensionString("GL_OES_depth24"); + feature_flags_.oes_depth24 = true; validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24); } @@ -644,16 +653,6 @@ void FeatureInfo::AddFeatures(const CommandLine& command_line) { feature_flags_.ext_frag_depth = true; } - bool ui_gl_fence_works = - extensions.Contains("GL_NV_fence") || - extensions.Contains("GL_ARB_sync"); - - if (ui_gl_fence_works && - extensions.Contains("GL_ARB_pixel_buffer_object") && - !workarounds_.disable_async_readpixels) { - feature_flags_.use_async_readpixels = true; - } - if (!disallowed_features_.swap_buffer_complete_callback) AddExtensionString("GL_CHROMIUM_swapbuffers_complete_callback"); @@ -664,11 +663,35 @@ void FeatureInfo::AddFeatures(const CommandLine& command_line) { is_es3 = (lstr.substr(0, 12) == "opengl es 3."); } + bool ui_gl_fence_works = extensions.Contains("GL_NV_fence") || + extensions.Contains("GL_ARB_sync") || + extensions.Contains("EGL_KHR_fence_sync"); + + feature_flags_.map_buffer_range = + is_es3 || extensions.Contains("GL_ARB_map_buffer_range"); + + // Really it's part of core OpenGL 2.1 and up, but let's assume the + // extension is still advertised. + bool has_pixel_buffers = + is_es3 || extensions.Contains("GL_ARB_pixel_buffer_object"); + + // We will use either glMapBuffer() or glMapBufferRange() for async readbacks. + if (has_pixel_buffers && ui_gl_fence_works && + !workarounds_.disable_async_readpixels) { + feature_flags_.use_async_readpixels = true; + } + if (is_es3 || extensions.Contains("GL_ARB_sampler_objects")) { feature_flags_.enable_samplers = true; // TODO(dsinclair): Add AddExtensionString("GL_CHROMIUM_sampler_objects") // when available. } + + if ((is_es3 || extensions.Contains("GL_EXT_discard_framebuffer")) && + !workarounds_.disable_ext_discard_framebuffer) { + // DiscardFramebufferEXT is automatically bound to InvalidateFramebuffer. + AddExtensionString("GL_EXT_discard_framebuffer"); + } } void FeatureInfo::AddExtensionString(const std::string& str) { diff --git a/chromium/gpu/command_buffer/service/feature_info.h b/chromium/gpu/command_buffer/service/feature_info.h index a9ccf64c009..7d5041f26b2 100644 --- a/chromium/gpu/command_buffer/service/feature_info.h +++ b/chromium/gpu/command_buffer/service/feature_info.h @@ -32,6 +32,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool use_img_for_multisampled_render_to_texture; bool oes_standard_derivatives; bool oes_egl_image_external; + bool oes_depth24; bool npot_ok; bool enable_texture_float_linear; bool enable_texture_half_float_linear; @@ -49,6 +50,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool ext_draw_buffers; bool ext_frag_depth; bool use_async_readpixels; + bool map_buffer_range; }; struct Workarounds { @@ -63,16 +65,15 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { GLint max_cube_map_texture_size; }; + // Constructor with workarounds taken from the current process's CommandLine FeatureInfo(); - // If allowed features = NULL or "*", all features are allowed. Otherwise - // only features that match the strings in allowed_features are allowed. - bool Initialize(const char* allowed_features); - bool Initialize(const DisallowedFeatures& disallowed_features, - const char* allowed_features); + // Constructor with workarounds taken from |command_line| + FeatureInfo(const CommandLine& command_line); - // Turns on certain features if they can be turned on. - void AddFeatures(const CommandLine& command_line); + // Initializes the feature information. Needs a current GL context. + bool Initialize(); + bool Initialize(const DisallowedFeatures& disallowed_features); const Validators* validators() const { return &validators_; @@ -105,6 +106,8 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { ~FeatureInfo(); void AddExtensionString(const std::string& str); + void InitializeBasicState(const 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 0dc1685e08d..97cc76b50e0 100644 --- a/chromium/gpu/command_buffer/service/feature_info_unittest.cc +++ b/chromium/gpu/command_buffer/service/feature_info_unittest.cc @@ -45,13 +45,30 @@ class FeatureInfoTest : public testing::Test { const char* extensions, const char* version) { TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( gl_.get(), extensions, version); + info_ = new FeatureInfo(); + info_->Initialize(); + } + + void SetupWithCommandLine(const CommandLine& command_line) { + info_ = new FeatureInfo(command_line); + } + + void SetupInitExpectationsWithCommandLine( + const char* extensions, const CommandLine& command_line) { + TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( + gl_.get(), extensions, ""); + info_ = new FeatureInfo(command_line); + info_->Initialize(); + } + + void SetupWithoutInit() { + info_ = new FeatureInfo(); } protected: virtual void SetUp() { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); - info_ = new FeatureInfo(); } virtual void TearDown() { @@ -75,6 +92,7 @@ struct FormatInfo { } // anonymous namespace. TEST_F(FeatureInfoTest, Basic) { + SetupWithoutInit(); // Test it starts off uninitialized. EXPECT_FALSE(info_->feature_flags().chromium_framebuffer_multisample); EXPECT_FALSE(info_->feature_flags().multisampled_render_to_texture); @@ -96,6 +114,8 @@ TEST_F(FeatureInfoTest, Basic) { EXPECT_FALSE(info_->feature_flags( ).use_arb_occlusion_query_for_occlusion_query_boolean); EXPECT_FALSE(info_->feature_flags().native_vertex_array_object); + EXPECT_FALSE(info_->feature_flags().map_buffer_range); + EXPECT_FALSE(info_->feature_flags().use_async_readpixels); #define GPU_OP(type, name) EXPECT_FALSE(info_->workarounds().name); GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) @@ -197,7 +217,6 @@ TEST_F(FeatureInfoTest, Basic) { TEST_F(FeatureInfoTest, InitializeNoExtensions) { SetupInitExpectations(""); - info_->Initialize(NULL); // Check default extensions are there EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_resource_safe")); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_strict_attribs")); @@ -270,21 +289,18 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) { TEST_F(FeatureInfoTest, InitializeNPOTExtensionGLES) { SetupInitExpectations("GL_OES_texture_npot"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_texture_npot")); EXPECT_TRUE(info_->feature_flags().npot_ok); } TEST_F(FeatureInfoTest, InitializeNPOTExtensionGL) { SetupInitExpectations("GL_ARB_texture_non_power_of_two"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_texture_npot")); EXPECT_TRUE(info_->feature_flags().npot_ok); } TEST_F(FeatureInfoTest, InitializeDXTExtensionGLES2) { SetupInitExpectations("GL_EXT_texture_compression_dxt1"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_compression_dxt1")); EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( @@ -299,7 +315,6 @@ TEST_F(FeatureInfoTest, InitializeDXTExtensionGLES2) { TEST_F(FeatureInfoTest, InitializeDXTExtensionGL) { SetupInitExpectations("GL_EXT_texture_compression_s3tc"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_compression_dxt1")); EXPECT_THAT(info_->extensions(), @@ -318,7 +333,6 @@ TEST_F(FeatureInfoTest, InitializeDXTExtensionGL) { TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GLES2) { SetupInitExpectations("GL_EXT_texture_format_BGRA8888"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_format_BGRA8888")); EXPECT_TRUE(info_->validators()->texture_format.IsValid( @@ -331,7 +345,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GLES2) { TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { SetupInitExpectations("GL_EXT_bgra"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_format_BGRA8888")); EXPECT_THAT(info_->extensions(), @@ -348,7 +361,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888Apple) { SetupInitExpectations("GL_APPLE_texture_format_BGRA8888"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_format_BGRA8888")); EXPECT_TRUE(info_->validators()->texture_format.IsValid( @@ -361,7 +373,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888Apple) { TEST_F(FeatureInfoTest, InitializeEXT_read_format_bgra) { SetupInitExpectations("GL_EXT_read_format_bgra"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_read_format_bgra")); EXPECT_FALSE(info_->validators()->texture_format.IsValid( @@ -374,7 +385,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_read_format_bgra) { TEST_F(FeatureInfoTest, InitializeOES_texture_floatGLES2) { SetupInitExpectations("GL_OES_texture_float"); - info_->Initialize(NULL); EXPECT_FALSE(info_->feature_flags().enable_texture_float_linear); EXPECT_FALSE(info_->feature_flags().enable_texture_half_float_linear); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_texture_float")); @@ -409,7 +419,6 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_floatGLES2) { TEST_F(FeatureInfoTest, InitializeOES_texture_float_linearGLES2) { SetupInitExpectations("GL_OES_texture_float GL_OES_texture_float_linear"); - info_->Initialize(NULL); EXPECT_TRUE(info_->feature_flags().enable_texture_float_linear); EXPECT_FALSE(info_->feature_flags().enable_texture_half_float_linear); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_texture_float")); @@ -443,7 +452,6 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_float_linearGLES2) { TEST_F(FeatureInfoTest, InitializeOES_texture_half_floatGLES2) { SetupInitExpectations("GL_OES_texture_half_float"); - info_->Initialize(NULL); EXPECT_FALSE(info_->feature_flags().enable_texture_float_linear); EXPECT_FALSE(info_->feature_flags().enable_texture_half_float_linear); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_OES_texture_float"))); @@ -479,7 +487,6 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_half_floatGLES2) { TEST_F(FeatureInfoTest, InitializeOES_texture_half_float_linearGLES2) { SetupInitExpectations( "GL_OES_texture_half_float GL_OES_texture_half_float_linear"); - info_->Initialize(NULL); EXPECT_FALSE(info_->feature_flags().enable_texture_float_linear); EXPECT_TRUE(info_->feature_flags().enable_texture_half_float_linear); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_OES_texture_float"))); @@ -514,7 +521,6 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_half_float_linearGLES2) { TEST_F(FeatureInfoTest, InitializeEXT_framebuffer_multisample) { SetupInitExpectations("GL_EXT_framebuffer_multisample"); - info_->Initialize(NULL); EXPECT_TRUE(info_->feature_flags().chromium_framebuffer_multisample); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_framebuffer_multisample")); @@ -532,7 +538,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_framebuffer_multisample) { TEST_F(FeatureInfoTest, InitializeEXT_multisampled_render_to_texture) { SetupInitExpectations("GL_EXT_multisampled_render_to_texture"); - info_->Initialize(NULL); EXPECT_TRUE(info_->feature_flags( ).multisampled_render_to_texture); EXPECT_FALSE(info_->feature_flags( @@ -549,7 +554,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_multisampled_render_to_texture) { TEST_F(FeatureInfoTest, InitializeIMG_multisampled_render_to_texture) { SetupInitExpectations("GL_IMG_multisampled_render_to_texture"); - info_->Initialize(NULL); EXPECT_TRUE(info_->feature_flags( ).use_img_for_multisampled_render_to_texture); EXPECT_TRUE(info_->feature_flags( @@ -566,7 +570,6 @@ TEST_F(FeatureInfoTest, InitializeIMG_multisampled_render_to_texture) { TEST_F(FeatureInfoTest, InitializeEXT_texture_filter_anisotropic) { SetupInitExpectations("GL_EXT_texture_filter_anisotropic"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_texture_filter_anisotropic")); EXPECT_TRUE(info_->validators()->texture_parameter.IsValid( @@ -577,7 +580,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_texture_filter_anisotropic) { TEST_F(FeatureInfoTest, InitializeEXT_ARB_depth_texture) { SetupInitExpectations("GL_ARB_depth_texture"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_GOOGLE_depth_texture")); EXPECT_THAT(info_->extensions(), @@ -598,7 +600,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_ARB_depth_texture) { TEST_F(FeatureInfoTest, InitializeOES_ARB_depth_texture) { SetupInitExpectations("GL_OES_depth_texture"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_GOOGLE_depth_texture")); EXPECT_THAT(info_->extensions(), @@ -619,7 +620,6 @@ TEST_F(FeatureInfoTest, InitializeOES_ARB_depth_texture) { TEST_F(FeatureInfoTest, InitializeANGLE_depth_texture) { SetupInitExpectations("GL_ANGLE_depth_texture"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_GOOGLE_depth_texture")); EXPECT_THAT(info_->extensions(), @@ -648,7 +648,6 @@ TEST_F(FeatureInfoTest, InitializeANGLE_depth_texture) { TEST_F(FeatureInfoTest, InitializeEXT_packed_depth_stencil) { SetupInitExpectations("GL_EXT_packed_depth_stencil"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_packed_depth_stencil")); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid( @@ -662,7 +661,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_packed_depth_stencil) { TEST_F(FeatureInfoTest, InitializeOES_packed_depth_stencil) { SetupInitExpectations("GL_OES_packed_depth_stencil"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_packed_depth_stencil")); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid( @@ -677,7 +675,6 @@ TEST_F(FeatureInfoTest, InitializeOES_packed_depth_stencil) { TEST_F(FeatureInfoTest, InitializeOES_packed_depth_stencil_and_GL_ARB_depth_texture) { SetupInitExpectations("GL_OES_packed_depth_stencil GL_ARB_depth_texture"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_packed_depth_stencil")); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid( @@ -698,7 +695,6 @@ TEST_F(FeatureInfoTest, TEST_F(FeatureInfoTest, InitializeOES_depth24) { SetupInitExpectations("GL_OES_depth24"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_depth24")); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid( GL_DEPTH_COMPONENT24)); @@ -706,7 +702,6 @@ TEST_F(FeatureInfoTest, InitializeOES_depth24) { TEST_F(FeatureInfoTest, InitializeOES_standard_derivatives) { SetupInitExpectations("GL_OES_standard_derivatives"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_standard_derivatives")); EXPECT_TRUE(info_->feature_flags().oes_standard_derivatives); EXPECT_TRUE(info_->validators()->hint_target.IsValid( @@ -717,7 +712,6 @@ TEST_F(FeatureInfoTest, InitializeOES_standard_derivatives) { TEST_F(FeatureInfoTest, InitializeOES_rgb8_rgba8) { SetupInitExpectations("GL_OES_rgb8_rgba8"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_rgb8_rgba8")); EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid( @@ -728,7 +722,6 @@ TEST_F(FeatureInfoTest, InitializeOES_rgb8_rgba8) { TEST_F(FeatureInfoTest, InitializeOES_EGL_image_external) { SetupInitExpectations("GL_OES_EGL_image_external"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_EGL_image_external")); EXPECT_TRUE(info_->feature_flags().oes_egl_image_external); @@ -744,7 +737,6 @@ TEST_F(FeatureInfoTest, InitializeOES_EGL_image_external) { TEST_F(FeatureInfoTest, InitializeOES_compressed_ETC1_RGB8_texture) { SetupInitExpectations("GL_OES_compressed_ETC1_RGB8_texture"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_compressed_ETC1_RGB8_texture")); EXPECT_TRUE(info_->validators()->compressed_texture_format.IsValid( @@ -755,7 +747,6 @@ TEST_F(FeatureInfoTest, InitializeOES_compressed_ETC1_RGB8_texture) { TEST_F(FeatureInfoTest, InitializeCHROMIUM_stream_texture) { SetupInitExpectations("GL_CHROMIUM_stream_texture"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_stream_texture")); EXPECT_TRUE(info_->feature_flags().chromium_stream_texture); @@ -763,7 +754,6 @@ TEST_F(FeatureInfoTest, InitializeCHROMIUM_stream_texture) { TEST_F(FeatureInfoTest, InitializeEXT_occlusion_query_boolean) { SetupInitExpectations("GL_EXT_occlusion_query_boolean"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_occlusion_query_boolean")); EXPECT_TRUE(info_->feature_flags().occlusion_query_boolean); @@ -775,7 +765,6 @@ TEST_F(FeatureInfoTest, InitializeEXT_occlusion_query_boolean) { TEST_F(FeatureInfoTest, InitializeARB_occlusion_query) { SetupInitExpectations("GL_ARB_occlusion_query"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_occlusion_query_boolean")); EXPECT_TRUE(info_->feature_flags().occlusion_query_boolean); @@ -787,7 +776,6 @@ TEST_F(FeatureInfoTest, InitializeARB_occlusion_query) { TEST_F(FeatureInfoTest, InitializeARB_occlusion_query2) { SetupInitExpectations("GL_ARB_occlusion_query2 GL_ARB_occlusion_query2"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_occlusion_query_boolean")); EXPECT_TRUE(info_->feature_flags().occlusion_query_boolean); @@ -799,7 +787,6 @@ TEST_F(FeatureInfoTest, InitializeARB_occlusion_query2) { TEST_F(FeatureInfoTest, InitializeOES_vertex_array_object) { SetupInitExpectations("GL_OES_vertex_array_object"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_vertex_array_object")); EXPECT_TRUE(info_->feature_flags().native_vertex_array_object); @@ -807,7 +794,6 @@ TEST_F(FeatureInfoTest, InitializeOES_vertex_array_object) { TEST_F(FeatureInfoTest, InitializeARB_vertex_array_object) { SetupInitExpectations("GL_ARB_vertex_array_object"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_vertex_array_object")); EXPECT_TRUE(info_->feature_flags().native_vertex_array_object); @@ -815,7 +801,6 @@ TEST_F(FeatureInfoTest, InitializeARB_vertex_array_object) { TEST_F(FeatureInfoTest, InitializeAPPLE_vertex_array_object) { SetupInitExpectations("GL_APPLE_vertex_array_object"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_vertex_array_object")); EXPECT_TRUE(info_->feature_flags().native_vertex_array_object); @@ -823,7 +808,6 @@ TEST_F(FeatureInfoTest, InitializeAPPLE_vertex_array_object) { TEST_F(FeatureInfoTest, InitializeNo_vertex_array_object) { SetupInitExpectations(""); - info_->Initialize(NULL); // Even if the native extensions are not available the implementation // may still emulate the GL_OES_vertex_array_object functionality. In this // scenario native_vertex_array_object must be false. @@ -834,71 +818,69 @@ TEST_F(FeatureInfoTest, InitializeNo_vertex_array_object) { TEST_F(FeatureInfoTest, InitializeOES_element_index_uint) { SetupInitExpectations("GL_OES_element_index_uint"); - info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_OES_element_index_uint")); EXPECT_TRUE(info_->validators()->index_type.IsValid(GL_UNSIGNED_INT)); } TEST_F(FeatureInfoTest, InitializeVAOsWithClientSideArrays) { - SetupInitExpectations("GL_OES_vertex_array_object"); CommandLine command_line(0, NULL); command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS)); - info_->AddFeatures(command_line); + SetupInitExpectationsWithCommandLine("GL_OES_vertex_array_object", + command_line); EXPECT_TRUE(info_->workarounds().use_client_side_arrays_for_stream_buffers); EXPECT_FALSE(info_->feature_flags().native_vertex_array_object); } TEST_F(FeatureInfoTest, InitializeEXT_frag_depth) { SetupInitExpectations("GL_EXT_frag_depth"); - info_->Initialize(NULL); EXPECT_TRUE(info_->feature_flags().ext_frag_depth); EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_frag_depth")); } TEST_F(FeatureInfoTest, InitializeSamplersWithARBSamplerObjects) { SetupInitExpectationsWithGLVersion("GL_ARB_sampler_objects", "OpenGL 3.0"); - info_->Initialize(NULL); EXPECT_TRUE(info_->feature_flags().enable_samplers); } -TEST_F(FeatureInfoTest, InitializeSamplersWithES3) { +TEST_F(FeatureInfoTest, InitializeWithES3) { SetupInitExpectationsWithGLVersion("", "OpenGL ES 3.0"); - info_->Initialize(NULL); EXPECT_TRUE(info_->feature_flags().enable_samplers); + EXPECT_TRUE(info_->feature_flags().map_buffer_range); + EXPECT_FALSE(info_->feature_flags().use_async_readpixels); } TEST_F(FeatureInfoTest, InitializeWithoutSamplers) { SetupInitExpectationsWithGLVersion("", "OpenGL GL 3.0"); - info_->Initialize(NULL); EXPECT_FALSE(info_->feature_flags().enable_samplers); } +TEST_F(FeatureInfoTest, InitializeWithES3AndFences) { + SetupInitExpectationsWithGLVersion("EGL_KHR_fence_sync", "OpenGL ES 3.0"); + EXPECT_TRUE(info_->feature_flags().use_async_readpixels); +} + TEST_F(FeatureInfoTest, ParseDriverBugWorkaroundsSingle) { - SetupInitExpectations(""); CommandLine command_line(0, NULL); command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::EXIT_ON_CONTEXT_LOST)); - EXPECT_FALSE(info_->workarounds().exit_on_context_lost); - info_->AddFeatures(command_line); + // Workarounds should get parsed without the need for a context. + SetupWithCommandLine(command_line); EXPECT_TRUE(info_->workarounds().exit_on_context_lost); } TEST_F(FeatureInfoTest, ParseDriverBugWorkaroundsMultiple) { - SetupInitExpectations(""); CommandLine command_line(0, NULL); command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::EXIT_ON_CONTEXT_LOST) + "," + base::IntToString(gpu::MAX_CUBE_MAP_TEXTURE_SIZE_LIMIT_1024) + "," + base::IntToString(gpu::MAX_TEXTURE_SIZE_LIMIT_4096)); - EXPECT_FALSE(info_->workarounds().exit_on_context_lost); - EXPECT_EQ(0, info_->workarounds().max_cube_map_texture_size); - EXPECT_EQ(0, info_->workarounds().max_texture_size); - info_->AddFeatures(command_line); + // Workarounds should get parsed without the need for a context. + SetupWithCommandLine(command_line); EXPECT_TRUE(info_->workarounds().exit_on_context_lost); EXPECT_EQ(1024, info_->workarounds().max_cube_map_texture_size); EXPECT_EQ(4096, info_->workarounds().max_texture_size); diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.cc b/chromium/gpu/command_buffer/service/framebuffer_manager.cc index b468262ecef..b4c6b090f0f 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.cc @@ -203,6 +203,13 @@ class TextureAttachment uint32 need = GLES2Util::GetChannelsNeededForAttachmentType( attachment_type, max_color_attachments); uint32 have = GLES2Util::GetChannelsForFormat(internal_format); + + // Workaround for NVIDIA drivers that incorrectly expose these formats as + // renderable: + if (internal_format == GL_LUMINANCE || internal_format == GL_ALPHA || + internal_format == GL_LUMINANCE_ALPHA) { + return false; + } return (need & have) != 0; } diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager.h b/chromium/gpu/command_buffer/service/framebuffer_manager.h index 176e3e2db99..aa1111813e1 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager.h +++ b/chromium/gpu/command_buffer/service/framebuffer_manager.h @@ -180,6 +180,15 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { DISALLOW_COPY_AND_ASSIGN(Framebuffer); }; +struct DecoderFramebufferState { + DecoderFramebufferState(): + clear_state_dirty(true) {} + + // State saved for clearing so we can clear render buffers and then + // restore to these values. + bool clear_state_dirty; +}; + // This class keeps track of the frambebuffers and their attached renderbuffers // so we can correctly clear them. class GPU_EXPORT FramebufferManager { diff --git a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc index a2c8aebcc46..079325807d4 100644 --- a/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -15,19 +15,24 @@ using ::testing::Return; namespace gpu { namespace gles2 { +namespace { -class FramebufferManagerTest : public testing::Test { - static const GLint kMaxTextureSize = 64; - static const GLint kMaxCubemapSize = 64; - static const GLint kMaxRenderbufferSize = 64; - static const GLint kMaxSamples = 4; +const GLint kMaxTextureSize = 64; +const GLint kMaxCubemapSize = 64; +const GLint kMaxRenderbufferSize = 64; +const GLint kMaxSamples = 4; +const bool kDepth24Supported = false; + +} // namespace +class FramebufferManagerTest : public testing::Test { public: FramebufferManagerTest() : manager_(1, 1), texture_manager_( NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize), - renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples) { + renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples, + kDepth24Supported) { } virtual ~FramebufferManagerTest() { @@ -54,13 +59,6 @@ class FramebufferManagerTest : public testing::Test { RenderbufferManager renderbuffer_manager_; }; -// GCC requires these declarations, but MSVC requires they not be present -#ifndef COMPILER_MSVC -const GLint FramebufferManagerTest::kMaxTextureSize; -const GLint FramebufferManagerTest::kMaxCubemapSize; -const GLint FramebufferManagerTest::kMaxRenderbufferSize; -#endif - TEST_F(FramebufferManagerTest, Basic) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; @@ -110,16 +108,12 @@ class FramebufferInfoTest : public testing::Test { static const GLuint kClient1Id = 1; static const GLuint kService1Id = 11; - static const GLint kMaxTextureSize = 64; - static const GLint kMaxCubemapSize = 64; - static const GLint kMaxRenderbufferSize = 64; - static const GLint kMaxSamples = 4; - FramebufferInfoTest() : manager_(1, 1), texture_manager_( NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize), - renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples) { + renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples, + kDepth24Supported) { } virtual ~FramebufferInfoTest() { manager_.Destroy(false); @@ -155,9 +149,6 @@ class FramebufferInfoTest : public testing::Test { #ifndef COMPILER_MSVC const GLuint FramebufferInfoTest::kClient1Id; const GLuint FramebufferInfoTest::kService1Id; -const GLint FramebufferInfoTest::kMaxTextureSize; -const GLint FramebufferInfoTest::kMaxCubemapSize; -const GLint FramebufferInfoTest::kMaxRenderbufferSize; #endif TEST_F(FramebufferInfoTest, Basic) { diff --git a/chromium/gpu/command_buffer/service/gl_context_virtual.cc b/chromium/gpu/command_buffer/service/gl_context_virtual.cc index e7a4c043bf7..a29e540981b 100644 --- a/chromium/gpu/command_buffer/service/gl_context_virtual.cc +++ b/chromium/gpu/command_buffer/service/gl_context_virtual.cc @@ -71,8 +71,7 @@ void GLContextVirtual::ReleaseCurrent(gfx::GLSurface* surface) { bool GLContextVirtual::IsCurrent(gfx::GLSurface* surface) { // If it's a real surface it needs to be current. if (surface && - !surface->IsOffscreen() && - !surface->GetBackingFrameBufferObject()) + !surface->IsOffscreen()) return shared_context_->IsCurrent(surface); // Otherwise, only insure the context itself is current. diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc index 44f76744b69..120359ceae8 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -42,6 +42,7 @@ #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" +#include "gpu/command_buffer/service/gpu_state_tracer.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/image_manager.h" @@ -68,6 +69,10 @@ #include "ui/gl/io_surface_support_mac.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); @@ -349,18 +354,6 @@ class ScopedResolvedFrameBufferBinder { DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder); }; -// This class records texture upload time when in scope. -class ScopedTextureUploadTimer { - public: - explicit ScopedTextureUploadTimer(GLES2DecoderImpl* decoder); - ~ScopedTextureUploadTimer(); - - private: - GLES2DecoderImpl* decoder_; - base::TimeTicks begin_time_; - DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer); -}; - // Encapsulates an OpenGL texture. class BackTexture { public: @@ -549,7 +542,6 @@ class GLES2DecoderImpl : public GLES2Decoder { bool offscreen, const gfx::Size& size, const DisallowedFeatures& disallowed_features, - const char* allowed_extensions, const std::vector<int32>& attribs) OVERRIDE; virtual void Destroy(bool have_context) OVERRIDE; virtual void SetSurface( @@ -651,7 +643,6 @@ class GLES2DecoderImpl : public GLES2Decoder { friend class ScopedFrameBufferBinder; friend class ScopedGLErrorSuppressor; friend class ScopedResolvedFrameBufferBinder; - friend class ScopedTextureUploadTimer; friend class BackTexture; friend class BackRenderbuffer; friend class BackFramebuffer; @@ -813,33 +804,6 @@ class GLES2DecoderImpl : public GLES2Decoder { GLsizei width, GLsizei height); - // Validation for TexImage2D commands. - bool ValidateTexImage2D( - const char* function_name, - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels, - uint32 pixels_size); - - // Wrapper for TexImage2D commands. - void DoTexImage2D( - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels, - uint32 pixels_size); - // Validation for TexSubImage2D. bool ValidateTexSubImage2D( error::Error* error, @@ -1327,6 +1291,12 @@ class GLES2DecoderImpl : public GLES2Decoder { GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + // Verifies that the currently bound multisample renderbuffer is valid + // Very slow! Only done on platforms with driver bugs that return invalid + // buffers under memory pressure + bool VerifyMultisampleRenderbufferIntegrity( + GLuint renderbuffer, GLenum format); + // Wrapper for glReleaseShaderCompiler. void DoReleaseShaderCompiler() { } @@ -1403,8 +1373,8 @@ class GLES2DecoderImpl : public GLES2Decoder { void RestoreStateForAttrib(GLuint attrib); // If texture is a stream texture, this will update the stream to the newest - // buffer. - void UpdateStreamTextureIfNeeded(Texture* texture); + // buffer and bind the texture implicitly. + void UpdateStreamTextureIfNeeded(Texture* texture, GLuint texture_unit_index); // Returns false if unrenderable textures were replaced. bool PrepareTexturesForRender(); @@ -1427,46 +1397,6 @@ class GLES2DecoderImpl : public GLES2Decoder { bool instanced, GLenum mode, GLsizei count, GLenum type, int32 offset, GLsizei primcount); - // Gets the texture id for a given target. - TextureRef* GetTextureInfoForTarget(GLenum target) { - TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; - TextureRef* texture = NULL; - switch (target) { - case GL_TEXTURE_2D: - texture = unit.bound_texture_2d.get(); - break; - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - texture = unit.bound_texture_cube_map.get(); - break; - case GL_TEXTURE_EXTERNAL_OES: - texture = unit.bound_texture_external_oes.get(); - break; - case GL_TEXTURE_RECTANGLE_ARB: - texture = unit.bound_texture_rectangle_arb.get(); - break; - default: - NOTREACHED(); - return NULL; - } - return texture; - } - - TextureRef* GetTextureInfoForTargetUnlessDefault( - GLenum target) { - TextureRef* texture = GetTextureInfoForTarget(target); - if (!texture) - return NULL; - if (texture == texture_manager()->GetDefaultTextureInfo(target)) - return NULL; - return texture; - } - GLenum GetBindTargetForSamplerType(GLenum type) { DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB); @@ -1642,10 +1572,6 @@ class GLES2DecoderImpl : public GLES2Decoder { // The size of fiixed attrib buffer. GLsizei fixed_attrib_buffer_size_; - // state saved for clearing so we can clear render buffers and then - // restore to these values. - bool clear_state_dirty_; - // The offscreen frame buffer that the client renders to. With EGL, the // depth and stencil buffers are separate. With regular GL there is a single // packed depth stencil buffer in offscreen_target_depth_render_buffer_. @@ -1692,8 +1618,6 @@ class GLES2DecoderImpl : public GLES2Decoder { // Backbuffer attachments that are currently undefined. uint32 backbuffer_needs_clear_bits_; - bool teximage2d_faster_than_texsubimage2d_; - // The current decoder error. error::Error current_decoder_error_; @@ -1707,10 +1631,6 @@ class GLES2DecoderImpl : public GLES2Decoder { const Validators* validators_; scoped_refptr<FeatureInfo> feature_info_; - // This indicates all the following texSubImage2D calls that are part of the - // failed texImage2D call should be ignored. - bool tex_image_2d_failed_; - int frame_number_; bool has_robustness_extension_; @@ -1744,14 +1664,22 @@ class GLES2DecoderImpl : public GLES2Decoder { GLsizei viewport_max_height_; // Command buffer stats. - int texture_upload_count_; - base::TimeDelta total_texture_upload_time_; base::TimeDelta total_processing_commands_time_; + // States related to each manager. + DecoderTextureState texture_state_; + DecoderFramebufferState framebuffer_state_; + scoped_ptr<GPUTracer> gpu_tracer_; + scoped_ptr<GPUStateTracer> gpu_state_tracer_; std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_; + // Used to validate multisample renderbuffers if needed + GLuint validation_texture_; + GLuint validation_fbo_multisample_; + GLuint validation_fbo_; + DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); }; @@ -1881,17 +1809,6 @@ ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() { } } -ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl* decoder) - : decoder_(decoder), - begin_time_(base::TimeTicks::HighResNow()) { -} - -ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { - decoder_->texture_upload_count_++; - decoder_->total_texture_upload_time_ += - base::TimeTicks::HighResNow() - begin_time_; -} - BackTexture::BackTexture(GLES2DecoderImpl* decoder) : decoder_(decoder), memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged), @@ -2024,8 +1941,8 @@ bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format, ScopedRenderBufferBinder binder(decoder_, id_); uint32 estimated_size = 0; - if (!RenderbufferManager::ComputeEstimatedRenderbufferSize( - size.width(), size.height(), samples, format, &estimated_size)) { + if (!decoder_->renderbuffer_manager()->ComputeEstimatedRenderbufferSize( + size.width(), size.height(), samples, format, &estimated_size)) { return false; } @@ -2156,7 +2073,6 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) attrib_0_size_(0), fixed_attrib_buffer_id_(0), fixed_attrib_buffer_size_(0), - clear_state_dirty_(true), offscreen_target_color_format_(0), offscreen_target_depth_format_(0), offscreen_target_stencil_format_(0), @@ -2167,12 +2083,10 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) back_buffer_has_depth_(false), back_buffer_has_stencil_(false), backbuffer_needs_clear_bits_(0), - teximage2d_faster_than_texsubimage2d_(true), current_decoder_error_(error::kNoError), use_shader_translator_(true), validators_(group_->feature_info()->validators()), feature_info_(group_->feature_info()), - tex_image_2d_failed_(false), frame_number_(0), has_robustness_extension_(false), reset_status_(GL_NO_ERROR), @@ -2186,7 +2100,9 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) switches::kEnableGPUServiceLoggingGPU)), viewport_max_width_(0), viewport_max_height_(0), - texture_upload_count_(0) { + validation_texture_(0), + validation_fbo_multisample_(0), + validation_fbo_(0) { DCHECK(group); attrib_0_value_.v[0] = 0.0f; @@ -2207,7 +2123,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) // TODO(gman): Consider setting this based on GPU and/or driver. if (IsAngle()) { - teximage2d_faster_than_texsubimage2d_ = false; + texture_state_.teximage2d_faster_than_texsubimage2d = false; } } @@ -2220,7 +2136,6 @@ bool GLES2DecoderImpl::Initialize( bool offscreen, const gfx::Size& size, const DisallowedFeatures& disallowed_features, - const char* allowed_extensions, const std::vector<int32>& attribs) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize"); DCHECK(context->IsCurrent(surface.get())); @@ -2228,6 +2143,7 @@ bool GLES2DecoderImpl::Initialize( set_initialized(); gpu_tracer_ = GPUTracer::Create(); + gpu_state_tracer_ = GPUStateTracer::Create(&state_); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUDebugging)) { @@ -2248,7 +2164,7 @@ bool GLES2DecoderImpl::Initialize( context_ = context; surface_ = surface; - if (!group_->Initialize(this, disallowed_features, allowed_extensions)) { + if (!group_->Initialize(this, disallowed_features)) { LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group " << "failed to initialize."; group_ = NULL; // Must not destroy ContextGroup if it is not initialized. @@ -2310,7 +2226,7 @@ bool GLES2DecoderImpl::Initialize( glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR(); - ContextCreationAttribParser attrib_parser; + ContextCreationAttribHelper attrib_parser; if (!attrib_parser.Parse(attribs)) return false; @@ -2582,6 +2498,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { resources.OES_standard_derivatives = derivatives_explicitly_enabled_; resources.EXT_frag_depth = frag_depth_explicitly_enabled_; resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_; + if (!draw_buffers_explicitly_enabled_) + resources.MaxDrawBuffers = 1; } else { resources.OES_standard_derivatives = features().oes_standard_derivatives ? 1 : 0; @@ -2608,15 +2526,17 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { ShaderTranslatorInterface::GlslImplementationType implementation_type = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ? ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl; - ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior = - workarounds().needs_glsl_built_in_function_emulation ? - ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated : - ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal; + int driver_bug_workarounds = 0; + if (workarounds().needs_glsl_built_in_function_emulation) + driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS; + if (workarounds().init_gl_position_in_vertex_shader) + driver_bug_workarounds |= SH_INIT_GL_POSITION; ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance(); vertex_translator_ = cache->GetTranslator( SH_VERTEX_SHADER, shader_spec, &resources, - implementation_type, function_behavior); + implementation_type, + static_cast<ShCompileOptions>(driver_bug_workarounds)); if (!vertex_translator_.get()) { LOG(ERROR) << "Could not initialize vertex shader translator."; Destroy(true); @@ -2625,7 +2545,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { fragment_translator_ = cache->GetTranslator( SH_FRAGMENT_SHADER, shader_spec, &resources, - implementation_type, function_behavior); + implementation_type, + static_cast<ShCompileOptions>(driver_bug_workarounds)); if (!fragment_translator_.get()) { LOG(ERROR) << "Could not initialize fragment shader translator."; Destroy(true); @@ -2717,7 +2638,7 @@ void GLES2DecoderImpl::DeleteFramebuffersHelper( if (framebuffer && !framebuffer->IsDeleted()) { if (framebuffer == state_.bound_draw_framebuffer.get()) { state_.bound_draw_framebuffer = NULL; - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; GLenum target = supports_separate_framebuffer_binds ? GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER; glBindFramebufferEXT(target, GetBackbufferServiceId()); @@ -2761,7 +2682,7 @@ void GLES2DecoderImpl::DeleteRenderbuffersHelper( ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer); } } - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; RemoveRenderbuffer(client_ids[ii]); } } @@ -2776,7 +2697,7 @@ void GLES2DecoderImpl::DeleteTexturesHelper( if (texture_ref) { Texture* texture = texture_ref->texture(); if (texture->IsAttachedToFramebuffer()) { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } // Unbind texture_ref from texture_ref units. for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) { @@ -2823,6 +2744,9 @@ bool GLES2DecoderImpl::MakeCurrent() { if (workarounds().exit_on_context_lost) { LOG(ERROR) << "Exiting GPU process because some drivers cannot reset" << " a D3D device in the Chrome GPU process sandbox."; +#if defined(OS_WIN) + base::win::SetShouldCrashOnProcessDetach(false); +#endif exit(0); } @@ -2835,7 +2759,7 @@ bool GLES2DecoderImpl::MakeCurrent() { if (workarounds().unbind_fbo_on_context_switch) RestoreFramebufferBindings(); - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; return true; } @@ -2879,7 +2803,7 @@ static void RebindCurrentFramebuffer( } void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; if (!features().chromium_framebuffer_multisample) { RebindCurrentFramebuffer( @@ -3075,7 +2999,8 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() { offscreen_saved_color_texture_info_.get(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); glBindTexture(target, texture_ref ? texture_ref->service_id() : 0); } @@ -3127,12 +3052,12 @@ bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id, } uint32 GLES2DecoderImpl::GetTextureUploadCount() { - return texture_upload_count_ + + return texture_state_.texture_upload_count + async_pixel_transfer_manager_->GetTextureUploadCount(); } base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() { - return total_texture_upload_time_ + + return texture_state_.total_texture_upload_time + async_pixel_transfer_manager_->GetTotalTextureUploadTime(); } @@ -3185,6 +3110,12 @@ void GLES2DecoderImpl::Destroy(bool have_context) { glDeleteBuffersARB(1, &fixed_attrib_buffer_id_); } + if (validation_texture_) { + glDeleteTextures(1, &validation_texture_); + glDeleteFramebuffersEXT(1, &validation_fbo_multisample_); + glDeleteFramebuffersEXT(1, &validation_fbo_); + } + if (offscreen_target_frame_buffer_.get()) offscreen_target_frame_buffer_->Destroy(); if (offscreen_target_color_texture_.get()) @@ -3678,7 +3609,7 @@ bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() { } void GLES2DecoderImpl::ApplyDirtyState() { - if (clear_state_dirty_) { + if (framebuffer_state_.clear_state_dirty) { glColorMask( state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue, state_.color_mask_alpha && @@ -3696,7 +3627,7 @@ void GLES2DecoderImpl::ApplyDirtyState() { 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); - clear_state_dirty_ = false; + framebuffer_state_.clear_state_dirty = false; } } @@ -3804,7 +3735,7 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { state_.bound_read_framebuffer = framebuffer; } - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; // If we are rendering to the backbuffer get the FBO id for any simulated // backbuffer. @@ -3969,7 +3900,32 @@ void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, } } - glDiscardFramebufferEXT(target, numAttachments, attachments); + // If the default framebuffer is bound but we are still rendering to an + // FBO, translate attachment names that refer to default framebuffer + // channels to corresponding framebuffer attachments. + scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]); + for (GLsizei i = 0; i < numAttachments; ++i) { + GLenum attachment = attachments[i]; + if (!framebuffer && GetBackbufferServiceId()) { + switch (attachment) { + case GL_COLOR_EXT: + attachment = GL_COLOR_ATTACHMENT0; + break; + case GL_DEPTH_EXT: + attachment = GL_DEPTH_ATTACHMENT; + break; + case GL_STENCIL_EXT: + attachment = GL_STENCIL_ATTACHMENT; + break; + default: + NOTREACHED(); + return; + } + } + translated_attachments[i] = attachment; + } + + glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get()); } void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { @@ -3982,7 +3938,8 @@ void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { } void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) { - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref || !texture_manager()->CanGenerateMipmaps(texture_ref)) { LOCAL_SET_GL_ERROR( @@ -4758,7 +4715,7 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer( framebuffer->AttachRenderbuffer(attachment, renderbuffer); } if (framebuffer == state_.bound_draw_framebuffer.get()) { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } OnFboChanged(); } @@ -4842,7 +4799,7 @@ void GLES2DecoderImpl::ClearUnclearedAttachments( } void GLES2DecoderImpl::RestoreClearState() { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; glClearColor( state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue, state_.color_clear_alpha); @@ -4942,7 +4899,7 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon( samples); } if (framebuffer == state_.bound_draw_framebuffer.get()) { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } OnFboChanged(); } @@ -5065,8 +5022,8 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( } uint32 estimated_size = 0; - if (!RenderbufferManager::ComputeEstimatedRenderbufferSize( - width, height, samples, internalformat, &estimated_size)) { + if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize( + width, height, samples, internalformat, &estimated_size)) { LOCAL_SET_GL_ERROR( GL_OUT_OF_MEMORY, "glRenderbufferStorageMultsample", "dimensions too large"); @@ -5080,8 +5037,9 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( return; } - GLenum impl_format = RenderbufferManager:: - InternalRenderbufferFormatToImplFormat(internalformat); + GLenum impl_format = + renderbuffer_manager()->InternalRenderbufferFormatToImplFormat( + internalformat); LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample"); if (IsAngle()) { glRenderbufferStorageMultisampleANGLE( @@ -5095,6 +5053,17 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( } GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample"); if (error == GL_NO_ERROR) { + + if (workarounds().validate_multisample_buffer_allocation) { + if (!VerifyMultisampleRenderbufferIntegrity( + renderbuffer->service_id(), impl_format)) { + LOCAL_SET_GL_ERROR( + GL_OUT_OF_MEMORY, + "glRenderbufferStorageMultisample", "out of memory"); + return; + } + } + // TODO(gman): If renderbuffers tracked which framebuffers they were // attached to we could just mark those framebuffers as not complete. framebuffer_manager()->IncFramebufferStateChangeCount(); @@ -5103,6 +5072,106 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( } } +// This function validates the allocation of a multisampled renderbuffer +// by clearing it to a key color, blitting the contents to a texture, and +// reading back the color to ensure it matches the key. +bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity( + GLuint renderbuffer, GLenum format) { + + // Only validate color buffers. + // These formats have been selected because they are very common or are known + // to be used by the WebGL backbuffer. If problems are observed with other + // color formats they can be added here. + switch(format) { + case GL_RGB: + case GL_RGB8: + case GL_RGBA: + case GL_RGBA8: + break; + default: + return true; + } + + GLint draw_framebuffer, read_framebuffer; + + // Cache framebuffer and texture bindings. + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer); + + if (!validation_texture_) { + GLint bound_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture); + + // Create additional resources needed for the verification. + glGenTextures(1, &validation_texture_); + glGenFramebuffersEXT(1, &validation_fbo_multisample_); + glGenFramebuffersEXT(1, &validation_fbo_); + + // Texture only needs to be 1x1. + glBindTexture(GL_TEXTURE_2D, validation_texture_); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, + GL_UNSIGNED_BYTE, NULL); + + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, validation_texture_, 0); + + glBindTexture(GL_TEXTURE_2D, bound_texture); + } + + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, renderbuffer); + + // Cache current state and reset it to the values we require. + GLboolean scissor_enabled = false; + glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled); + if (scissor_enabled) + glDisable(GL_SCISSOR_TEST); + + GLboolean color_mask[4] = {true, true, true, true}; + glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); + glColorMask(true, true, true, true); + + GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color); + glClearColor(1.0f, 0.0f, 1.0f, 1.0f); + + // Clear the buffer to the desired key color. + glClear(GL_COLOR_BUFFER_BIT); + + // Blit from the multisample buffer to a standard texture. + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_); + + glBlitFramebufferEXT(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + // Read a pixel from the buffer. + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_); + + unsigned char pixel[3] = {0, 0, 0}; + glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel); + + // Detach the renderbuffer. + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, 0); + + // Restore cached state. + if (scissor_enabled) + glEnable(GL_SCISSOR_TEST); + + glColorMask(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); + + // Return true if the pixel matched the desired key color. + return (pixel[0] == 0xFF && + pixel[1] == 0x00 && + pixel[2] == 0xFF); +} + void GLES2DecoderImpl::DoRenderbufferStorage( GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { Renderbuffer* renderbuffer = @@ -5122,8 +5191,8 @@ void GLES2DecoderImpl::DoRenderbufferStorage( } uint32 estimated_size = 0; - if (!RenderbufferManager::ComputeEstimatedRenderbufferSize( - width, height, 1, internalformat, &estimated_size)) { + if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize( + width, height, 1, internalformat, &estimated_size)) { LOCAL_SET_GL_ERROR( GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large"); return; @@ -5137,9 +5206,11 @@ void GLES2DecoderImpl::DoRenderbufferStorage( LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage"); glRenderbufferStorageEXT( - target, RenderbufferManager:: - InternalRenderbufferFormatToImplFormat(internalformat), - width, height); + target, + renderbuffer_manager()->InternalRenderbufferFormatToImplFormat( + internalformat), + width, + height); GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage"); if (error == GL_NO_ERROR) { // TODO(gman): If tetxures tracked which framebuffers they were attached to @@ -5181,7 +5252,8 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) { void GLES2DecoderImpl::DoTexParameterf( GLenum target, GLenum pname, GLfloat param) { - TextureRef* texture = GetTextureInfoForTarget(target); + TextureRef* texture = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture"); return; @@ -5194,7 +5266,8 @@ void GLES2DecoderImpl::DoTexParameterf( void GLES2DecoderImpl::DoTexParameteri( GLenum target, GLenum pname, GLint param) { - TextureRef* texture = GetTextureInfoForTarget(target); + TextureRef* texture = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture"); return; @@ -5206,7 +5279,8 @@ void GLES2DecoderImpl::DoTexParameteri( void GLES2DecoderImpl::DoTexParameterfv( GLenum target, GLenum pname, const GLfloat* params) { - TextureRef* texture = GetTextureInfoForTarget(target); + TextureRef* texture = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture"); return; @@ -5219,7 +5293,8 @@ void GLES2DecoderImpl::DoTexParameterfv( void GLES2DecoderImpl::DoTexParameteriv( GLenum target, GLenum pname, const GLint* params) { - TextureRef* texture = GetTextureInfoForTarget(target); + TextureRef* texture = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, "glTexParameteriv", "unknown texture"); @@ -5650,13 +5725,16 @@ void GLES2DecoderImpl::PerformanceWarning( std::string("PERFORMANCE WARNING: ") + msg); } -void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture) { +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) + if (stream_tex) { + glActiveTexture(GL_TEXTURE0 + texture_unit_index); stream_tex->Update(); + } } } @@ -5682,7 +5760,7 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() { TextureRef* texture = texture_unit.GetInfoForSamplerType(uniform_info->type).get(); if (texture) - UpdateStreamTextureIfNeeded(texture->texture()); + UpdateStreamTextureIfNeeded(texture->texture(), texture_unit_index); if (have_unrenderable_textures && (!texture || !texture_manager()->CanRender(texture))) { textures_set = true; @@ -6813,7 +6891,13 @@ void GLES2DecoderImpl::FinishReadPixels( if (buffer != 0) { glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer); - void* data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); + void* data; + if (features().map_buffer_range) { + data = glMapBufferRange( + GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT); + } else { + data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); + } memcpy(pixels, data, pixels_size); // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't // have to restore the state. @@ -7067,6 +7151,15 @@ error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM( "glPostSubBufferCHROMIUM", "command not supported by surface"); return error::kNoError; } + bool is_tracing; + TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"), + &is_tracing); + if (is_tracing) { + bool is_offscreen = !!offscreen_target_frame_buffer_.get(); + ScopedFrameBufferBinder binder(this, GetBackbufferServiceId()); + gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer( + is_offscreen ? offscreen_size_ : surface_->GetSize()); + } if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) { return error::kNoError; } else { @@ -7226,8 +7319,7 @@ error::Error GLES2DecoderImpl::HandleGetString( LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name"); return error::kNoError; } - const char* gl_str = reinterpret_cast<const char*>(glGetString(name)); - const char* str = NULL; + const char* str = reinterpret_cast<const char*>(glGetString(name)); std::string extensions; switch (name) { case GL_VERSION: @@ -7237,10 +7329,11 @@ error::Error GLES2DecoderImpl::HandleGetString( str = "OpenGL ES GLSL ES 1.0 Chromium"; break; case GL_RENDERER: - str = "Chromium"; - break; case GL_VENDOR: - str = "Chromium"; + // Return the unmasked VENDOR/RENDERER string for WebGL contexts. + // They are used by WEBGL_debug_renderer_info. + if (!force_webgl_glsl_validation_) + str = "Chromium"; break; case GL_EXTENSIONS: { @@ -7279,7 +7372,6 @@ error::Error GLES2DecoderImpl::HandleGetString( } break; default: - str = gl_str; break; } Bucket* bucket = CreateBucket(c.bucket_id); @@ -7420,7 +7512,8 @@ bool GLES2DecoderImpl::ClearLevel( } y += tile_height; } - TextureRef* texture = GetTextureInfoForTarget(bind_target); + TextureRef* texture = texture_manager()->GetTextureInfoForTarget( + &state_, bind_target); glBindTexture(bind_target, texture ? texture->service_id() : 0); return true; } @@ -7595,7 +7688,8 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( "glCompressedTexImage2D", "dimensions out of range"); return error::kNoError; } - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, @@ -7624,7 +7718,7 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( } if (texture->IsAttachedToFramebuffer()) { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } scoped_ptr<int8[]> zero; @@ -7759,176 +7853,16 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket( return error::kNoError; } -bool GLES2DecoderImpl::ValidateTextureParameters( - const char* function_name, - GLenum target, GLenum format, GLenum type, GLint level) { - if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) { - LOCAL_SET_GL_ERROR( - 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) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, function_name, - (std::string("invalid type ") + - GLES2Util::GetStringEnum(type) + " for format " + - GLES2Util::GetStringEnum(format)).c_str()); - return false; - } - return true; -} - -bool GLES2DecoderImpl::ValidateTexImage2D( - const char* function_name, - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels, - uint32 pixels_size) { - if (!validators_->texture_target.IsValid(target)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target"); - return false; - } - if (!validators_->texture_format.IsValid(internal_format)) { - LOCAL_SET_GL_ERROR_INVALID_ENUM( - function_name, internal_format, "internal_format"); - 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; - } - if (format != internal_format) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, function_name, "format != internalFormat"); - return false; - } - if (!ValidateTextureParameters(function_name, target, format, type, level)) { - return false; - } - if (!texture_manager()->ValidForTarget(target, level, width, height, 1) || - border != 0) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, function_name, "dimensions out of range"); - return false; - } - if ((GLES2Util::GetChannelsForFormat(format) & - (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, - function_name, "can not supply data for depth or stencil textures"); - return false; - } - TextureRef* texture_ref = GetTextureInfoForTarget(target); - if (!texture_ref) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, function_name, "unknown texture for target"); - return false; - } - if (texture_ref->texture()->IsImmutable()) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, function_name, "texture is immutable"); - return false; - } - return true; -} - -void GLES2DecoderImpl::DoTexImage2D( - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels, - uint32 pixels_size) { - if (!ValidateTexImage2D("glTexImage2D", target, level, internal_format, - width, height, border, format, type, pixels, pixels_size)) { - return; - } - - if (!EnsureGPUMemoryAvailable(pixels_size)) { - LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory"); - return; - } - - TextureRef* texture_ref = GetTextureInfoForTarget(target); - Texture* texture = texture_ref->texture(); - GLsizei tex_width = 0; - GLsizei tex_height = 0; - GLenum tex_type = 0; - GLenum tex_format = 0; - bool level_is_same = - texture->GetLevelSize(target, level, &tex_width, &tex_height) && - texture->GetLevelType(target, level, &tex_type, &tex_format) && - width == tex_width && height == tex_height && - type == tex_type && format == tex_format; - - if (level_is_same && !pixels) { - // Just set the level texture but mark the texture as uncleared. - texture_manager()->SetLevelInfo( - texture_ref, - target, level, internal_format, width, height, 1, border, format, type, - false); - tex_image_2d_failed_ = false; - return; - } - - if (texture->IsAttachedToFramebuffer()) { - clear_state_dirty_ = true; - } - - if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) { - { - ScopedTextureUploadTimer timer(this); - glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels); - } - texture_manager()->SetLevelCleared(texture_ref, target, level, true); - tex_image_2d_failed_ = false; - return; - } - - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexImage2D"); - { - ScopedTextureUploadTimer timer(this); - glTexImage2D( - target, level, internal_format, width, height, border, format, type, - pixels); - } - GLenum error = LOCAL_PEEK_GL_ERROR("glTexImage2D"); - if (error == GL_NO_ERROR) { - texture_manager()->SetLevelInfo( - texture_ref, - target, level, internal_format, width, height, 1, border, format, type, - pixels != NULL); - tex_image_2d_failed_ = false; - } - return; -} - error::Error GLES2DecoderImpl::HandleTexImage2D( uint32 immediate_data_size, const cmds::TexImage2D& c) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D"); - tex_image_2d_failed_ = true; + // 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); GLint level = static_cast<GLint>(c.level); - GLint internal_format = static_cast<GLint>(c.internalformat); + // TODO(kloveless): Change TexImage2D 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); GLint border = static_cast<GLint>(c.border); @@ -7951,9 +7885,11 @@ error::Error GLES2DecoderImpl::HandleTexImage2D( } } - DoTexImage2D( - target, level, internal_format, width, height, border, format, type, - pixels, pixels_size); + TextureManager::DoTextImage2DArguments args = { + target, level, internal_format, width, height, border, format, type, + pixels, pixels_size}; + texture_manager()->ValidateAndDoTexImage2D( + &texture_state_, &state_, &framebuffer_state_, args); return error::kNoError; } @@ -7961,7 +7897,9 @@ error::Error GLES2DecoderImpl::HandleTexImage2DImmediate( uint32 immediate_data_size, const cmds::TexImage2DImmediate& c) { GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); - GLint internal_format = static_cast<GLint>(c.internalformat); + // TODO(kloveless): Change TexImage2DImmediate 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); GLint border = static_cast<GLint>(c.border); @@ -7978,9 +7916,12 @@ error::Error GLES2DecoderImpl::HandleTexImage2DImmediate( if (!pixels) { return error::kOutOfBounds; } - DoTexImage2D( - target, level, internal_format, width, height, border, format, type, - pixels, size); + + TextureManager::DoTextImage2DArguments args = { + target, level, internal_format, width, height, border, format, type, + pixels, size}; + texture_manager()->ValidateAndDoTexImage2D( + &texture_state_, &state_, &framebuffer_state_, args); return error::kNoError; } @@ -7994,7 +7935,8 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D( GLenum format, GLsizei image_size, const void * data) { - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -8067,7 +8009,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D( GLsizei height, GLint border) { DCHECK(!ShouldDeferReads()); - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -8085,8 +8028,9 @@ void GLES2DecoderImpl::DoCopyTexImage2D( GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range"); return; } - if (!ValidateTextureParameters( - "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) { + if (!texture_manager()->ValidateTextureParameters( + state_.GetErrorState(), "glCopyTexImage2D", target, internal_format, + GL_UNSIGNED_BYTE, level)) { return; } @@ -8131,7 +8075,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D( gfx::Size size = GetBoundReadFrameBufferSize(); if (texture->IsAttachedToFramebuffer()) { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } // Clip to size to source dimensions @@ -8186,7 +8130,8 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( GLsizei width, GLsizei height) { DCHECK(!ShouldDeferReads()); - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -8312,7 +8257,8 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D( LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type"); return false; } - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -8379,7 +8325,8 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( xoffset, yoffset, width, height, format, type, data)) { return error; } - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); Texture* texture = texture_ref->texture(); GLsizei tex_width = 0; GLsizei tex_height = 0; @@ -8393,20 +8340,21 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big"); return error::kNoError; } - ScopedTextureUploadTimer timer(this); + ScopedTextureUploadTimer timer(&texture_state_); glTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, data); return error::kNoError; } - if (teximage2d_faster_than_texsubimage2d_ && !texture->IsImmutable()) { - ScopedTextureUploadTimer timer(this); + if (texture_state_.teximage2d_faster_than_texsubimage2d && + !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. glTexImage2D( target, level, format, width, height, 0, format, type, data); } else { - ScopedTextureUploadTimer timer(this); + ScopedTextureUploadTimer timer(&texture_state_); glTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, data); } @@ -8418,7 +8366,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D( uint32 immediate_data_size, const cmds::TexSubImage2D& c) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D"); GLboolean internal = static_cast<GLboolean>(c.internal); - if (internal == GL_TRUE && tex_image_2d_failed_) + if (internal == GL_TRUE && texture_state_.tex_image_2d_failed) return error::kNoError; GLenum target = static_cast<GLenum>(c.target); @@ -8444,7 +8392,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D( error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate( uint32 immediate_data_size, const cmds::TexSubImage2DImmediate& c) { GLboolean internal = static_cast<GLboolean>(c.internal); - if (internal == GL_TRUE && tex_image_2d_failed_) + if (internal == GL_TRUE && texture_state_.tex_image_2d_failed) return error::kNoError; GLenum target = static_cast<GLenum>(c.target); @@ -8803,6 +8751,15 @@ void GLES2DecoderImpl::DoSwapBuffers() { TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers", "offscreen", is_offscreen, "frame", this_frame_number); + bool is_tracing; + TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"), + &is_tracing); + if (is_tracing) { + ScopedFrameBufferBinder binder(this, GetBackbufferServiceId()); + gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer( + is_offscreen ? offscreen_size_ : surface_->GetSize()); + } + // If offscreen then don't actually SwapBuffers to the display. Just copy // the rendered frame to another frame buffer. if (is_offscreen) { @@ -8946,7 +8903,7 @@ error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM( const cmds::GetRequestableExtensionsCHROMIUM& c) { Bucket* bucket = CreateBucket(c.bucket_id); scoped_refptr<FeatureInfo> info(new FeatureInfo()); - info->Initialize(disallowed_features_, NULL); + info->Initialize(disallowed_features_); bucket->SetFromString(info->extensions().c_str()); return error::kNoError; } @@ -9251,8 +9208,8 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT( switch (target) { case GL_COMMANDS_ISSUED_CHROMIUM: case GL_LATENCY_QUERY_CHROMIUM: - case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM: - case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: case GL_GET_ERROR_QUERY_CHROMIUM: break; default: @@ -9564,7 +9521,8 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( // Default target might be conceptually valid, but disallow it to avoid // accidents. - TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target); + TextureRef* texture_ref = + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -9878,7 +9836,8 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range"); return; } - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -9887,7 +9846,7 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( } Texture* texture = texture_ref->texture(); if (texture->IsAttachedToFramebuffer()) { - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } if (texture->IsImmutable()) { LOCAL_SET_GL_ERROR( @@ -9959,7 +9918,8 @@ void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target, "context", logger_.GetLogPrefix(), "mailbox[0]", static_cast<unsigned char>(mailbox[0])); - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -9993,7 +9953,7 @@ void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target, "mailbox[0]", static_cast<unsigned char>(mailbox[0])); scoped_refptr<TextureRef> texture_ref = - GetTextureInfoForTargetUnlessDefault(target); + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); if (!texture_ref.get()) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glConsumeTextureCHROMIUM", @@ -10084,7 +10044,8 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM( // Default target might be conceptually valid, but disallow it to avoid // accidents. - TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target); + TextureRef* texture_ref = + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -10131,7 +10092,8 @@ void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM( // Default target might be conceptually valid, but disallow it to avoid // accidents. - TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target); + TextureRef* texture_ref = + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, @@ -10272,7 +10234,9 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM"); GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); - GLint internal_format = static_cast<GLint>(c.internalformat); + // 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); GLint border = static_cast<GLint>(c.border); @@ -10298,15 +10262,17 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( } } + TextureManager::DoTextImage2DArguments args = { + target, level, internal_format, width, height, border, format, type, + pixels, pixels_size}; + TextureRef* texture_ref; // All the normal glTexSubImage2D validation. - if (!ValidateTexImage2D( - "glAsyncTexImage2DCHROMIUM", target, level, internal_format, - width, height, border, format, type, pixels, pixels_size)) { + if (!texture_manager()->ValidateTexImage2D( + &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) { return error::kNoError; } // Extra async validation. - TextureRef* texture_ref = GetTextureInfoForTarget(target); Texture* texture = texture_ref->texture(); if (!ValidateAsyncTransfer( "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels)) @@ -10393,7 +10359,8 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( } // Extra async validation. - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); Texture* texture = texture_ref->texture(); if (!ValidateAsyncTransfer( "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels)) @@ -10461,7 +10428,8 @@ error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM( GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target"); return error::kNoError; } - TextureRef* texture_ref = GetTextureInfoForTarget(target); + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h index 57445c79867..e518702bccc 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -103,9 +103,6 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, // bound, offscreen contexts render to an internal buffer, onscreen ones // to the surface. // size: the size if the GL context is offscreen. - // allowed_extensions: A string in the same format as - // glGetString(GL_EXTENSIONS) that lists the extensions this context - // should allow. Passing NULL or "*" means allow all extensions. // Returns: // true if successful. virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface, @@ -113,7 +110,6 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, bool offscreen, const gfx::Size& size, const DisallowedFeatures& disallowed_features, - const char* allowed_extensions, const std::vector<int32>& attribs) = 0; // Destroys the graphics context. 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 a992e343446..393c90292c8 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -319,7 +319,7 @@ error::Error GLES2DecoderImpl::HandleColorMask( state_.color_mask_green = green; state_.color_mask_blue = blue; state_.color_mask_alpha = alpha; - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } return error::kNoError; } @@ -678,7 +678,7 @@ error::Error GLES2DecoderImpl::HandleDepthMask( GLboolean flag = static_cast<GLboolean>(c.flag); if (state_.depth_mask != flag) { state_.depth_mask = flag; - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } return error::kNoError; } @@ -1698,7 +1698,7 @@ error::Error GLES2DecoderImpl::HandleStencilMask( state_.stencil_back_writemask != mask) { state_.stencil_front_writemask = mask; state_.stencil_back_writemask = mask; - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } return error::kNoError; } @@ -1725,7 +1725,7 @@ error::Error GLES2DecoderImpl::HandleStencilMaskSeparate( if (face == GL_BACK || face == GL_FRONT_AND_BACK) { state_.stencil_back_writemask = mask; } - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } return error::kNoError; } @@ -3332,7 +3332,7 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { case GL_DEPTH_TEST: if (state_.enable_flags.depth_test != enabled) { state_.enable_flags.depth_test = enabled; - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } return false; case GL_DITHER: @@ -3350,13 +3350,13 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { case GL_SCISSOR_TEST: if (state_.enable_flags.scissor_test != enabled) { state_.enable_flags.scissor_test = enabled; - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } return false; case GL_STENCIL_TEST: if (state_.enable_flags.stencil_test != enabled) { state_.enable_flags.stencil_test = enabled; - clear_state_dirty_ = true; + framebuffer_state_.clear_state_dirty = true; } return false; default: 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 e6c497faca6..e993a5e6982 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -34,13 +34,12 @@ class MockGLES2Decoder : public GLES2Decoder { MockGLES2Decoder(); virtual ~MockGLES2Decoder(); - MOCK_METHOD7(Initialize, + MOCK_METHOD6(Initialize, bool(const scoped_refptr<gfx::GLSurface>& surface, const scoped_refptr<gfx::GLContext>& context, bool offscreen, const gfx::Size& size, const DisallowedFeatures& disallowed_features, - const char* allowed_extensions, const std::vector<int32>& attribs)); MOCK_METHOD1(Destroy, void(bool have_context)); MOCK_METHOD1(SetSurface, void(const scoped_refptr<gfx::GLSurface>& surface)); 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 906eb88f8f6..14acb4061cf 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -5759,6 +5759,9 @@ TEST_F(GLES2DecoderManualInitTest, DrawStreamTextureCHROMIUM) { 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(); 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 e2e3551c9f2..3ce452028f5 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 @@ -119,7 +119,7 @@ void GLES2DecoderTestBase::InitDecoder( // will initialize itself. mock_decoder_.reset(new MockGLES2Decoder()); EXPECT_TRUE( - group_->Initialize(mock_decoder_.get(), DisallowedFeatures(), NULL)); + group_->Initialize(mock_decoder_.get(), DisallowedFeatures())); AddExpectationsForVertexAttribManager(); @@ -267,9 +267,12 @@ void GLES2DecoderTestBase::InitDecoder( decoder_.reset(GLES2Decoder::Create(group_.get())); decoder_->GetLogger()->set_log_synthesized_gl_errors(false); - decoder_->Initialize( - surface_, context_, false, surface_->GetSize(), DisallowedFeatures(), - NULL, attribs); + decoder_->Initialize(surface_, + context_, + false, + surface_->GetSize(), + DisallowedFeatures(), + attribs); decoder_->MakeCurrent(); decoder_->set_engine(engine_.get()); 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 b8194d9589e..8975d202a6b 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 @@ -299,8 +299,8 @@ static const GLenum valid_query_target_table[] = { GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, GL_COMMANDS_ISSUED_CHROMIUM, GL_LATENCY_QUERY_CHROMIUM, - GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM, - GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM, + GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, + GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, }; static const GLenum valid_read_pixel_format_table[] = { diff --git a/chromium/gpu/command_buffer/service/gpu_control_service.cc b/chromium/gpu/command_buffer/service/gpu_control_service.cc new file mode 100644 index 00000000000..d368ff92149 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_control_service.cc @@ -0,0 +1,74 @@ +// Copyright 2013 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_control_service.h" + +#include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" +#include "gpu/command_buffer/service/gpu_memory_buffer_manager.h" + +namespace gpu { + +GpuControlService::GpuControlService( + GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager, + GpuMemoryBufferFactory* gpu_memory_buffer_factory) + : gpu_memory_buffer_manager_(gpu_memory_buffer_manager), + gpu_memory_buffer_factory_(gpu_memory_buffer_factory) { +} + +GpuControlService::~GpuControlService() { +} + +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); +} + +bool 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); +} + +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gpu_control_service.h b/chromium/gpu/command_buffer/service/gpu_control_service.h new file mode 100644 index 00000000000..a12fee46532 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_control_service.h @@ -0,0 +1,51 @@ +// Copyright 2013 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_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 "ui/gfx/gpu_memory_buffer.h" + +namespace gpu { +class GpuMemoryBufferFactory; +class GpuMemoryBufferManagerInterface; + +class GPU_EXPORT GpuControlService : public GpuControl { + public: + GpuControlService(GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager, + GpuMemoryBufferFactory* gpu_memory_buffer_factory); + virtual ~GpuControlService(); + + // Overridden from GpuControl: + virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( + size_t width, + size_t height, + unsigned internalformat, + int32* id) OVERRIDE; + virtual void DestroyGpuMemoryBuffer(int32 id) 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, + gfx::GpuMemoryBufferHandle buffer, + size_t width, + size_t height, + unsigned internalformat); + + private: + GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager_; + GpuMemoryBufferFactory* gpu_memory_buffer_factory_; + typedef std::map<int32, linked_ptr<gfx::GpuMemoryBuffer> > GpuMemoryBufferMap; + GpuMemoryBufferMap gpu_memory_buffers_; + + DISALLOW_COPY_AND_ASSIGN(GpuControlService); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_CONTROL_SERVICE_H_ diff --git a/chromium/gpu/command_buffer/service/gpu_memory_buffer_manager.h b/chromium/gpu/command_buffer/service/gpu_memory_buffer_manager.h new file mode 100644 index 00000000000..fb44ede7ed5 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_memory_buffer_manager.h @@ -0,0 +1,28 @@ +// Copyright 2013 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_MEMORY_BUFFER_MANAGER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GPU_MEMORY_BUFFER_MANAGER_H_ + +#include "base/basictypes.h" +#include "gpu/gpu_export.h" +#include "ui/gfx/gpu_memory_buffer.h" + +namespace gpu { + +class GPU_EXPORT GpuMemoryBufferManagerInterface { + public: + virtual ~GpuMemoryBufferManagerInterface() {} + + virtual bool RegisterGpuMemoryBuffer(int32 id, + gfx::GpuMemoryBufferHandle buffer, + size_t width, + size_t height, + unsigned internalformat) = 0; + virtual void DestroyGpuMemoryBuffer(int32 id) = 0; +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_MEMORY_BUFFER_MANAGER_H_ diff --git a/chromium/gpu/command_buffer/service/gpu_state_tracer.cc b/chromium/gpu/command_buffer/service/gpu_state_tracer.cc new file mode 100644 index 00000000000..dea05b3879b --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_state_tracer.cc @@ -0,0 +1,131 @@ +// Copyright 2013 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_state_tracer.h" + +#include "base/base64.h" +#include "base/debug/trace_event.h" +#include "context_state.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gl/gl_bindings.h" + +namespace gpu { +namespace gles2 { +namespace { + +const int kBytesPerPixel = 4; + +class Snapshot : public base::debug::ConvertableToTraceFormat { + public: + static scoped_ptr<Snapshot> Create(const ContextState* state); + + // Save a screenshot of the currently bound framebuffer. + bool SaveScreenshot(const gfx::Size& size); + + // base::debug::ConvertableToTraceFormat implementation. + virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE; + + private: + explicit Snapshot(const ContextState* state); + + const ContextState* state_; + + std::vector<unsigned char> screenshot_pixels_; + gfx::Size screenshot_size_; + + DISALLOW_COPY_AND_ASSIGN(Snapshot); +}; + +} // namespace + +Snapshot::Snapshot(const ContextState* state) : state_(state) {} + +scoped_ptr<Snapshot> Snapshot::Create(const ContextState* state) { + return scoped_ptr<Snapshot>(new Snapshot(state)); +} + +bool Snapshot::SaveScreenshot(const gfx::Size& size) { + screenshot_size_ = size; + screenshot_pixels_.resize(screenshot_size_.width() * + screenshot_size_.height() * kBytesPerPixel); + + glPixelStorei(GL_PACK_ALIGNMENT, kBytesPerPixel); + glReadPixels(0, + 0, + screenshot_size_.width(), + screenshot_size_.height(), + GL_RGBA, + GL_UNSIGNED_BYTE, + &screenshot_pixels_[0]); + glPixelStorei(GL_PACK_ALIGNMENT, state_->pack_alignment); + + // Flip the screenshot vertically. + int bytes_per_row = screenshot_size_.width() * kBytesPerPixel; + for (int y = 0; y < screenshot_size_.height() / 2; y++) { + for (int x = 0; x < bytes_per_row; x++) { + std::swap(screenshot_pixels_[y * bytes_per_row + x], + screenshot_pixels_ + [(screenshot_size_.height() - y - 1) * bytes_per_row + x]); + } + } + return true; +} + +void Snapshot::AppendAsTraceFormat(std::string* out) const { + *out += "{"; + if (screenshot_pixels_.size()) { + std::vector<unsigned char> png_data; + int bytes_per_row = screenshot_size_.width() * kBytesPerPixel; + bool png_ok = gfx::PNGCodec::Encode(&screenshot_pixels_[0], + gfx::PNGCodec::FORMAT_RGBA, + screenshot_size_, + bytes_per_row, + false, + std::vector<gfx::PNGCodec::Comment>(), + &png_data); + DCHECK(png_ok); + + base::StringPiece base64_input(reinterpret_cast<const char*>(&png_data[0]), + png_data.size()); + std::string base64_output; + Base64Encode(base64_input, &base64_output); + + *out += "\"screenshot\":\"" + base64_output + "\""; + } + *out += "}"; +} + +scoped_ptr<GPUStateTracer> GPUStateTracer::Create(const ContextState* state) { + return scoped_ptr<GPUStateTracer>(new GPUStateTracer(state)); +} + +GPUStateTracer::GPUStateTracer(const ContextState* state) : state_(state) { + TRACE_EVENT_OBJECT_CREATED_WITH_ID( + TRACE_DISABLED_BY_DEFAULT("gpu.debug"), "gpu::State", state_); +} + +GPUStateTracer::~GPUStateTracer() { + TRACE_EVENT_OBJECT_DELETED_WITH_ID( + TRACE_DISABLED_BY_DEFAULT("gpu.debug"), "gpu::State", state_); +} + +void GPUStateTracer::TakeSnapshotWithCurrentFramebuffer(const gfx::Size& size) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.debug"), + "GPUStateTracer::TakeSnapshotWithCurrentFramebuffer"); + + scoped_ptr<Snapshot> snapshot(Snapshot::Create(state_)); + + // Only save a screenshot for now. + if (!snapshot->SaveScreenshot(size)) + return; + + TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( + TRACE_DISABLED_BY_DEFAULT("gpu.debug"), + "gpu::State", + state_, + snapshot.PassAs<base::debug::ConvertableToTraceFormat>()); +} + +} // namespace gles2 +} // namespace gpu diff --git a/chromium/gpu/command_buffer/service/gpu_state_tracer.h b/chromium/gpu/command_buffer/service/gpu_state_tracer.h new file mode 100644 index 00000000000..38998f325b9 --- /dev/null +++ b/chromium/gpu/command_buffer/service/gpu_state_tracer.h @@ -0,0 +1,39 @@ +// Copyright 2013 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_STATE_TRACER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GPU_STATE_TRACER_H_ + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" + +namespace gfx { +class Size; +} + +namespace gpu { +namespace gles2 { + +struct ContextState; + +// Saves GPU state such as framebuffer contents while tracing. +class GPUStateTracer { + public: + static scoped_ptr<GPUStateTracer> Create(const ContextState* state); + ~GPUStateTracer(); + + // Take a state snapshot with a screenshot of the currently bound framebuffer. + void TakeSnapshotWithCurrentFramebuffer(const gfx::Size& size); + + private: + explicit GPUStateTracer(const ContextState* state); + + const ContextState* state_; + DISALLOW_COPY_AND_ASSIGN(GPUStateTracer); +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_STATE_TRACER_H_ diff --git a/chromium/gpu/command_buffer/service/image_manager.cc b/chromium/gpu/command_buffer/service/image_manager.cc index 6be4e667721..a09af1586b0 100644 --- a/chromium/gpu/command_buffer/service/image_manager.cc +++ b/chromium/gpu/command_buffer/service/image_manager.cc @@ -15,6 +15,36 @@ ImageManager::ImageManager() { ImageManager::~ImageManager() { } +bool 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; + } + + if (LookupImage(id)) { + DVLOG(0) << "GPU memory buffer ID already in use."; + return false; + } + + scoped_refptr<gfx::GLImage> gl_image = + gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer, + gfx::Size(width, height), + internalformat); + if (!gl_image) + return false; + + AddImage(gl_image.get(), id); + return true; +} + +void ImageManager::DestroyGpuMemoryBuffer(int32 id) { + RemoveImage(id); +} + void ImageManager::AddImage(gfx::GLImage* image, int32 service_id) { gl_images_[service_id] = image; } diff --git a/chromium/gpu/command_buffer/service/image_manager.h b/chromium/gpu/command_buffer/service/image_manager.h index 1b421469443..a125ae80f05 100644 --- a/chromium/gpu/command_buffer/service/image_manager.h +++ b/chromium/gpu/command_buffer/service/image_manager.h @@ -8,6 +8,7 @@ #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" +#include "gpu/command_buffer/service/gpu_memory_buffer_manager.h" #include "gpu/gpu_export.h" namespace gfx { @@ -18,10 +19,20 @@ namespace gpu { namespace gles2 { // Interface used by the cmd decoder to lookup images. -class GPU_EXPORT ImageManager : public base::RefCounted<ImageManager> { +class GPU_EXPORT ImageManager + : public GpuMemoryBufferManagerInterface, + public base::RefCounted<ImageManager> { public: ImageManager(); + // Overridden from GpuMemoryBufferManagerInterface: + virtual bool RegisterGpuMemoryBuffer(int32 id, + gfx::GpuMemoryBufferHandle buffer, + size_t width, + size_t height, + unsigned internalformat) OVERRIDE; + virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE; + void AddImage(gfx::GLImage* gl_image, int32 service_id); void RemoveImage(int32 service_id); gfx::GLImage* LookupImage(int32 service_id); @@ -29,7 +40,7 @@ class GPU_EXPORT ImageManager : public base::RefCounted<ImageManager> { private: friend class base::RefCounted<ImageManager>; - ~ImageManager(); + virtual ~ImageManager(); typedef base::hash_map<uint32, scoped_refptr<gfx::GLImage> > GLImageMap; GLImageMap gl_images_; 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 ccbfb32a504..972533cf94d 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.cc @@ -22,10 +22,10 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/sequence_checker.h" #include "base/threading/thread.h" -#include "gpu/command_buffer/common/id_allocator.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/transfer_buffer_manager.h" @@ -34,6 +34,11 @@ #include "ui/gl/gl_image.h" #include "ui/gl/gl_share_group.h" +#if defined(OS_ANDROID) +#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" +#include "ui/gl/android/surface_texture.h" +#endif + namespace gpu { namespace { @@ -43,6 +48,7 @@ static base::LazyInstance<std::set<InProcessCommandBuffer*> > 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> static void RunTaskWithResult(base::Callback<T(void)> task, @@ -293,7 +299,6 @@ bool InProcessCommandBuffer::Initialize( bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, - const char* allowed_extensions, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference, const base::Closure& context_lost_callback, @@ -316,7 +321,6 @@ bool InProcessCommandBuffer::Initialize( is_offscreen, window, size, - allowed_extensions, attribs, gpu_preference); @@ -332,7 +336,6 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( bool is_offscreen, gfx::AcceleratedWidget window, const gfx::Size& size, - const char* allowed_extensions, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference) { CheckSequencedThread(); @@ -378,11 +381,21 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( share_group = 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; +#endif + bool bind_generates_resource = false; decoder_.reset(gles2::GLES2Decoder::Create( context_group ? context_group->decoder_->GetContextGroup() - : new gles2::ContextGroup( - NULL, NULL, NULL, NULL, bind_generates_resource))); + : new gles2::ContextGroup(NULL, + NULL, + NULL, + stream_texture_manager, + bind_generates_resource))); gpu_scheduler_.reset( new GpuScheduler(command_buffer.get(), decoder_.get(), decoder_.get())); @@ -390,6 +403,10 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); command_buffer_ = command_buffer.Pass(); + gpu_control_.reset( + new GpuControlService(decoder_->GetContextGroup()->image_manager(), + g_gpu_memory_buffer_factory)); + decoder_->set_engine(gpu_scheduler_.get()); if (!surface_) { @@ -445,7 +462,6 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( is_offscreen, size, disallowed_features, - allowed_extensions, attribs)) { LOG(ERROR) << "Could not initialize decoder."; DestroyOnGpuThread(); @@ -496,55 +512,6 @@ void InProcessCommandBuffer::CheckSequencedThread() { sequence_checker_->CalledOnValidSequencedThread()); } -unsigned int InProcessCommandBuffer::CreateImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, - gfx::Size size) { - CheckSequencedThread(); - unsigned int image_id; - { - // TODO: ID allocation should go through CommandBuffer - base::AutoLock lock(command_buffer_lock_); - gles2::ContextGroup* group = decoder_->GetContextGroup(); - image_id = - group->GetIdAllocator(gles2::id_namespaces::kImages)->AllocateID(); - } - base::Closure image_task = - base::Bind(&InProcessCommandBuffer::CreateImageOnGpuThread, - base::Unretained(this), buffer, size, image_id); - QueueTask(image_task); - return image_id; -} - -void InProcessCommandBuffer::CreateImageOnGpuThread( - gfx::GpuMemoryBufferHandle buffer, - gfx::Size size, - unsigned int image_id) { - CheckSequencedThread(); - scoped_refptr<gfx::GLImage> gl_image = - gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer, size); - decoder_->GetContextGroup()->image_manager()->AddImage(gl_image, image_id); -} - -void InProcessCommandBuffer::RemoveImage(unsigned int image_id) { - CheckSequencedThread(); - { - // TODO: ID allocation should go through CommandBuffer - base::AutoLock lock(command_buffer_lock_); - gles2::ContextGroup* group = decoder_->GetContextGroup(); - group->GetIdAllocator(gles2::id_namespaces::kImages)->FreeID(image_id); - } - base::Closure image_manager_task = - base::Bind(&InProcessCommandBuffer::RemoveImageOnGpuThread, - base::Unretained(this), - image_id); - QueueTask(image_manager_task); -} - -void InProcessCommandBuffer::RemoveImageOnGpuThread(unsigned int image_id) { - CheckSequencedThread(); - decoder_->GetContextGroup()->image_manager()->RemoveImage(image_id); -} - void InProcessCommandBuffer::OnContextLost() { CheckSequencedThread(); if (!context_lost_callback_.is_null()) { @@ -680,6 +647,28 @@ void InProcessCommandBuffer::SignalSyncPoint(unsigned sync_point, QueueTask(WrapCallback(callback)); } +gfx::GpuMemoryBuffer* InProcessCommandBuffer::CreateGpuMemoryBuffer( + size_t width, + size_t height, + unsigned internalformat, + int32* id) { + CheckSequencedThread(); + base::AutoLock lock(command_buffer_lock_); + return gpu_control_->CreateGpuMemoryBuffer(width, + height, + internalformat, + id); +} + +void InProcessCommandBuffer::DestroyGpuMemoryBuffer(int32 id) { + CheckSequencedThread(); + base::Closure task = base::Bind(&GpuControl::DestroyGpuMemoryBuffer, + base::Unretained(gpu_control_.get()), + id); + + QueueTask(task); +} + gpu::error::Error InProcessCommandBuffer::GetLastError() { CheckSequencedThread(); return last_state_.error; @@ -734,6 +723,14 @@ base::Closure InProcessCommandBuffer::WrapCallback( return wrapped_callback; } +#if defined(OS_ANDROID) +scoped_refptr<gfx::SurfaceTexture> +InProcessCommandBuffer::GetSurfaceTexture(uint32 stream_id) { + DCHECK(stream_texture_manager_); + return stream_texture_manager_->GetSurfaceTexture(stream_id); +} +#endif + // static void InProcessCommandBuffer::EnableVirtualizedContext() { g_use_virtualized_gl_context = true; @@ -753,4 +750,10 @@ void InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread() { g_gpu_queue.Get().RunTasks(); } +// static +void InProcessCommandBuffer::SetGpuMemoryBufferFactory( + GpuMemoryBufferFactory* factory) { + g_gpu_memory_buffer_factory = factory; +} + } // namespace gpu 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 9bdbd49616d..e63e11aeac7 100644 --- a/chromium/gpu/command_buffer/service/in_process_command_buffer.h +++ b/chromium/gpu/command_buffer/service/in_process_command_buffer.h @@ -14,6 +14,7 @@ #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.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" @@ -26,17 +27,26 @@ class SequenceChecker; namespace gfx { class GLContext; -class GLImage; class GLSurface; class Size; } +#if defined(OS_ANDROID) +namespace gfx { +class SurfaceTexture; +} +namespace gpu { +class StreamTextureManagerInProcess; +} +#endif + namespace gpu { namespace gles2 { class GLES2Decoder; } +class GpuMemoryBufferFactory; class GpuScheduler; class TransferBufferManagerInterface; @@ -44,7 +54,8 @@ class TransferBufferManagerInterface; // example GPU thread) when being run in single process mode. // However, the behavior for accessing one context (i.e. one instance of this // class) from different client threads is undefined. -class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { +class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, + public GpuControl { public: InProcessCommandBuffer(); virtual ~InProcessCommandBuffer(); @@ -61,6 +72,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { static void ProcessGpuWorkOnCurrentThread(); static void EnableVirtualizedContext(); + static void SetGpuMemoryBufferFactory(GpuMemoryBufferFactory* factory); // If |surface| is not NULL, use it directly; in this case, the command // buffer gpu thread must be the same as the client thread. Otherwise create @@ -70,7 +82,6 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, - const char* allowed_extensions, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference, const base::Closure& context_lost_callback, @@ -78,10 +89,6 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { void Destroy(); void SignalSyncPoint(unsigned sync_point, const base::Closure& callback); - unsigned int CreateImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, - gfx::Size size); - void RemoveImage(unsigned int image_id); // CommandBuffer implementation: virtual bool Initialize() OVERRIDE; @@ -102,6 +109,14 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { virtual uint32 InsertSyncPoint() OVERRIDE; virtual gpu::error::Error GetLastError() OVERRIDE; + // GpuControl implementation: + virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( + size_t width, + size_t height, + unsigned internalformat, + int32* id) OVERRIDE; + virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE; + // The serializer interface to the GPU service (i.e. thread). class SchedulerClient { public: @@ -109,19 +124,19 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { virtual void QueueTask(const base::Closure& task) = 0; }; +#if defined(OS_ANDROID) + scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture( + uint32 stream_id); +#endif + private: bool InitializeOnGpuThread(bool is_offscreen, gfx::AcceleratedWidget window, const gfx::Size& size, - const char* allowed_extensions, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference); bool DestroyOnGpuThread(); void FlushOnGpuThread(int32 put_offset); - void CreateImageOnGpuThread(gfx::GpuMemoryBufferHandle buffer, - gfx::Size size, - unsigned int image_id); - void RemoveImageOnGpuThread(unsigned int image_id); bool MakeCurrent(); bool IsContextLost(); base::Closure WrapCallback(const base::Closure& callback); @@ -158,6 +173,11 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { scoped_ptr<SchedulerClient> queue_; State state_after_last_flush_; base::Lock state_after_last_flush_lock_; + scoped_ptr<GpuControl> gpu_control_; + +#if defined(OS_ANDROID) + scoped_refptr<StreamTextureManagerInProcess> stream_texture_manager_; +#endif // Only used with explicit scheduling and the gpu thread is the same as // the client thread. diff --git a/chromium/gpu/command_buffer/service/mailbox_manager.cc b/chromium/gpu/command_buffer/service/mailbox_manager.cc index a569bb5ead7..bb2f7262a2f 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager.cc +++ b/chromium/gpu/command_buffer/service/mailbox_manager.cc @@ -40,14 +40,12 @@ void MailboxManager::GenerateMailboxName(MailboxName* name) { Texture* MailboxManager::ConsumeTexture(unsigned target, const MailboxName& name) { - if (!IsMailboxNameValid(name)) - return NULL; - MailboxToTextureMap::iterator it = mailbox_to_textures_.find(TargetName(target, name)); if (it == mailbox_to_textures_.end()) return NULL; + DCHECK(IsMailboxNameValid(name)); return it->second->first; } diff --git a/chromium/gpu/command_buffer/service/memory_program_cache.cc b/chromium/gpu/command_buffer/service/memory_program_cache.cc index e09d132f6a0..94dc366b8a6 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache.cc +++ b/chromium/gpu/command_buffer/service/memory_program_cache.cc @@ -15,6 +15,7 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/shader_manager.h" +#include "gpu/command_buffer/service/shader_translator.h" #include "ui/gl/gl_bindings.h" namespace { @@ -40,31 +41,42 @@ namespace { enum ShaderMapType { ATTRIB_MAP = 0, - UNIFORM_MAP + UNIFORM_MAP, + VARYING_MAP }; void StoreShaderInfo(ShaderMapType type, ShaderProto *proto, const ShaderTranslator::VariableMap& map) { ShaderTranslator::VariableMap::const_iterator iter; - for (iter = map.begin(); iter != map.end(); iter++) { - ShaderInfoProto* info; - if (type == UNIFORM_MAP) { - info = proto->add_uniforms(); - } else { - info = proto->add_attribs(); + for (iter = map.begin(); iter != map.end(); ++iter) { + ShaderInfoProto* info = NULL; + switch (type) { + case UNIFORM_MAP: + info = proto->add_uniforms(); + break; + case ATTRIB_MAP: + info = proto->add_attribs(); + break; + case VARYING_MAP: + info = proto->add_varyings(); + break; + default: NOTREACHED(); } info->set_key(iter->first); info->set_type(iter->second.type); info->set_size(iter->second.size); + info->set_precision(iter->second.precision); + info->set_static_use(iter->second.static_use); info->set_name(iter->second.name); } } void RetrieveShaderInfo(const ShaderInfoProto& proto, ShaderTranslator::VariableMap* map) { - ShaderTranslator::VariableInfo info(proto.type(), proto.size(), - proto.name()); + ShaderTranslator::VariableInfo info( + proto.type(), proto.size(), proto.precision(), + proto.static_use(), proto.name()); (*map)[proto.key()] = info; } @@ -73,6 +85,7 @@ void FillShaderProto(ShaderProto* proto, const char* sha, proto->set_sha(sha, gpu::gles2::ProgramCache::kHashLength); StoreShaderInfo(ATTRIB_MAP, proto, shader->attrib_map()); StoreShaderInfo(UNIFORM_MAP, proto, shader->uniform_map()); + StoreShaderInfo(VARYING_MAP, proto, shader->varying_map()); } void RunShaderCallback(const ShaderCacheCallback& callback, @@ -147,8 +160,10 @@ ProgramCache::ProgramLoadResult MemoryProgramCache::LoadLinkedProgram( } shader_a->set_attrib_map(value->attrib_map_0()); shader_a->set_uniform_map(value->uniform_map_0()); + shader_a->set_varying_map(value->varying_map_0()); shader_b->set_attrib_map(value->attrib_map_1()); shader_b->set_uniform_map(value->uniform_map_1()); + shader_b->set_varying_map(value->varying_map_1()); if (!shader_callback.is_null() && !CommandLine::ForCurrentProcess()->HasSwitch( @@ -241,9 +256,11 @@ void MemoryProgramCache::SaveLinkedProgram( a_sha, shader_a->attrib_map(), shader_a->uniform_map(), + shader_a->varying_map(), b_sha, shader_b->attrib_map(), shader_b->uniform_map(), + shader_b->varying_map(), this)); UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", @@ -255,6 +272,7 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { if (proto->ParseFromString(program)) { ShaderTranslator::VariableMap vertex_attribs; ShaderTranslator::VariableMap vertex_uniforms; + ShaderTranslator::VariableMap vertex_varyings; for (int i = 0; i < proto->vertex_shader().attribs_size(); i++) { RetrieveShaderInfo(proto->vertex_shader().attribs(i), &vertex_attribs); @@ -264,8 +282,13 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { RetrieveShaderInfo(proto->vertex_shader().uniforms(i), &vertex_uniforms); } + for (int i = 0; i < proto->vertex_shader().varyings_size(); i++) { + RetrieveShaderInfo(proto->vertex_shader().varyings(i), &vertex_varyings); + } + ShaderTranslator::VariableMap fragment_attribs; ShaderTranslator::VariableMap fragment_uniforms; + ShaderTranslator::VariableMap fragment_varyings; for (int i = 0; i < proto->fragment_shader().attribs_size(); i++) { RetrieveShaderInfo(proto->fragment_shader().attribs(i), @@ -277,6 +300,11 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { &fragment_uniforms); } + for (int i = 0; i < proto->fragment_shader().varyings_size(); i++) { + RetrieveShaderInfo(proto->fragment_shader().varyings(i), + &fragment_varyings); + } + scoped_ptr<char[]> binary(new char[proto->program().length()]); memcpy(binary.get(), proto->program().c_str(), proto->program().length()); @@ -288,9 +316,11 @@ void MemoryProgramCache::LoadProgram(const std::string& program) { proto->vertex_shader().sha().c_str(), vertex_attribs, vertex_uniforms, + vertex_varyings, proto->fragment_shader().sha().c_str(), fragment_attribs, fragment_uniforms, + fragment_varyings, this)); UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", @@ -308,9 +338,11 @@ MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( const char* shader_0_hash, const ShaderTranslator::VariableMap& attrib_map_0, const ShaderTranslator::VariableMap& uniform_map_0, + const ShaderTranslator::VariableMap& varying_map_0, const char* shader_1_hash, const ShaderTranslator::VariableMap& attrib_map_1, const ShaderTranslator::VariableMap& uniform_map_1, + const ShaderTranslator::VariableMap& varying_map_1, MemoryProgramCache* program_cache) : length_(length), format_(format), @@ -319,9 +351,11 @@ MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( shader_0_hash_(shader_0_hash, kHashLength), attrib_map_0_(attrib_map_0), uniform_map_0_(uniform_map_0), + varying_map_0_(varying_map_0), shader_1_hash_(shader_1_hash, kHashLength), attrib_map_1_(attrib_map_1), uniform_map_1_(uniform_map_1), + varying_map_1_(varying_map_1), program_cache_(program_cache) { program_cache_->curr_size_bytes_ += length_; program_cache_->LinkedProgramCacheSuccess(program_hash); diff --git a/chromium/gpu/command_buffer/service/memory_program_cache.h b/chromium/gpu/command_buffer/service/memory_program_cache.h index b2f23e6d8c9..e72f9f5f0b1 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache.h +++ b/chromium/gpu/command_buffer/service/memory_program_cache.h @@ -57,9 +57,11 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { const char* shader_0_hash, const ShaderTranslator::VariableMap& attrib_map_0, const ShaderTranslator::VariableMap& uniform_map_0, + const ShaderTranslator::VariableMap& varying_map_0, const char* shader_1_hash, const ShaderTranslator::VariableMap& attrib_map_1, const ShaderTranslator::VariableMap& uniform_map_1, + const ShaderTranslator::VariableMap& varying_map_1, MemoryProgramCache* program_cache); GLsizei length() const { @@ -86,6 +88,10 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { return uniform_map_0_; } + const ShaderTranslator::VariableMap& varying_map_0() const { + return varying_map_0_; + } + const std::string& shader_1_hash() const { return shader_1_hash_; } @@ -98,6 +104,10 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { return uniform_map_1_; } + const ShaderTranslator::VariableMap& varying_map_1() const { + return varying_map_1_; + } + private: friend class base::RefCounted<ProgramCacheValue>; @@ -110,9 +120,11 @@ class GPU_EXPORT MemoryProgramCache : public ProgramCache { const std::string shader_0_hash_; const ShaderTranslator::VariableMap attrib_map_0_; const ShaderTranslator::VariableMap uniform_map_0_; + const ShaderTranslator::VariableMap varying_map_0_; const std::string shader_1_hash_; const ShaderTranslator::VariableMap attrib_map_1_; const ShaderTranslator::VariableMap uniform_map_1_; + const ShaderTranslator::VariableMap varying_map_1_; MemoryProgramCache* const program_cache_; DISALLOW_COPY_AND_ASSIGN(ProgramCacheValue); 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 83fc12a386e..6c6b099a20e 100644 --- a/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc +++ b/chromium/gpu/command_buffer/service/memory_program_cache_unittest.cc @@ -108,19 +108,27 @@ class MemoryProgramCacheTest : public testing::Test { typedef ShaderTranslator::VariableMap VariableMap; VariableMap vertex_attrib_map; VariableMap vertex_uniform_map; + VariableMap vertex_varying_map; VariableMap fragment_attrib_map; VariableMap fragment_uniform_map; - - vertex_attrib_map["a"] = VariableInfo(1, 34, "a"); - vertex_uniform_map["a"] = VariableInfo(0, 10, "a"); - vertex_uniform_map["b"] = VariableInfo(2, 3114, "b"); - fragment_attrib_map["jjjbb"] = VariableInfo(463, 1114, "jjjbb"); - fragment_uniform_map["k"] = VariableInfo(10, 34413, "k"); + VariableMap fragment_varying_map; + + vertex_attrib_map["a"] = VariableInfo(1, 34, SH_PRECISION_LOWP, 0, "a"); + vertex_uniform_map["a"] = VariableInfo(0, 10, SH_PRECISION_MEDIUMP, 1, "a"); + vertex_uniform_map["b"] = VariableInfo(2, 3114, SH_PRECISION_HIGHP, 1, "b"); + vertex_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, 1, "c"); + fragment_attrib_map["jjjbb"] = + VariableInfo(463, 1114, SH_PRECISION_MEDIUMP, 0, "jjjbb"); + fragment_uniform_map["k"] = + VariableInfo(10, 34413, SH_PRECISION_MEDIUMP, 1, "k"); + fragment_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, 1, "c"); vertex_shader_->set_attrib_map(vertex_attrib_map); vertex_shader_->set_uniform_map(vertex_uniform_map); + vertex_shader_->set_varying_map(vertex_varying_map); fragment_shader_->set_attrib_map(vertex_attrib_map); fragment_shader_->set_uniform_map(vertex_uniform_map); + fragment_shader_->set_varying_map(vertex_varying_map); vertex_shader_->UpdateSource("bbbalsldkdkdkd"); fragment_shader_->UpdateSource("bbbal sldkdkdkas 134 ad"); @@ -262,13 +270,17 @@ TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) { VariableMap vertex_attrib_map = vertex_shader_->attrib_map(); VariableMap vertex_uniform_map = vertex_shader_->uniform_map(); + VariableMap vertex_varying_map = vertex_shader_->varying_map(); VariableMap fragment_attrib_map = fragment_shader_->attrib_map(); VariableMap fragment_uniform_map = fragment_shader_->uniform_map(); + VariableMap fragment_varying_map = fragment_shader_->varying_map(); vertex_shader_->set_attrib_map(VariableMap()); vertex_shader_->set_uniform_map(VariableMap()); + vertex_shader_->set_varying_map(VariableMap()); fragment_shader_->set_attrib_map(VariableMap()); fragment_shader_->set_uniform_map(VariableMap()); + fragment_shader_->set_varying_map(VariableMap()); SetExpectationsForLoadLinkedProgram(kProgramId, &emulator); @@ -286,9 +298,11 @@ TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) { // equality operator #if !defined(OS_ANDROID) EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, vertex_shader_->uniform_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->uniform_map()); + EXPECT_EQ(vertex_uniform_map, vertex_shader_->uniform_map()); + EXPECT_EQ(vertex_varying_map, vertex_shader_->varying_map()); + EXPECT_EQ(fragment_attrib_map, fragment_shader_->attrib_map()); + EXPECT_EQ(fragment_uniform_map, fragment_shader_->uniform_map()); + EXPECT_EQ(fragment_varying_map, fragment_shader_->varying_map()); #endif } @@ -311,13 +325,17 @@ TEST_F(MemoryProgramCacheTest, LoadProgramMatchesSave) { VariableMap vertex_attrib_map = vertex_shader_->attrib_map(); VariableMap vertex_uniform_map = vertex_shader_->uniform_map(); + VariableMap vertex_varying_map = vertex_shader_->varying_map(); VariableMap fragment_attrib_map = fragment_shader_->attrib_map(); VariableMap fragment_uniform_map = fragment_shader_->uniform_map(); + VariableMap fragment_varying_map = fragment_shader_->varying_map(); vertex_shader_->set_attrib_map(VariableMap()); vertex_shader_->set_uniform_map(VariableMap()); + vertex_shader_->set_varying_map(VariableMap()); fragment_shader_->set_attrib_map(VariableMap()); fragment_shader_->set_uniform_map(VariableMap()); + fragment_shader_->set_varying_map(VariableMap()); SetExpectationsForLoadLinkedProgram(kProgramId, &emulator); @@ -338,9 +356,11 @@ TEST_F(MemoryProgramCacheTest, LoadProgramMatchesSave) { // equality operator #if !defined(OS_ANDROID) EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, vertex_shader_->uniform_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->attrib_map()); - EXPECT_EQ(vertex_attrib_map, fragment_shader_->uniform_map()); + EXPECT_EQ(vertex_uniform_map, vertex_shader_->uniform_map()); + EXPECT_EQ(vertex_varying_map, vertex_shader_->varying_map()); + EXPECT_EQ(fragment_attrib_map, fragment_shader_->attrib_map()); + EXPECT_EQ(fragment_uniform_map, fragment_shader_->uniform_map()); + EXPECT_EQ(fragment_varying_map, fragment_shader_->varying_map()); #endif } diff --git a/chromium/gpu/command_buffer/service/mocks.h b/chromium/gpu/command_buffer/service/mocks.h index fda872245c9..2a95db5f3c8 100644 --- a/chromium/gpu/command_buffer/service/mocks.h +++ b/chromium/gpu/command_buffer/service/mocks.h @@ -84,12 +84,13 @@ class MockShaderTranslator : public ShaderTranslatorInterface { ShShaderSpec shader_spec, const ShBuiltInResources* resources, GlslImplementationType glsl_implementation_type, - GlslBuiltInFunctionBehavior glsl_built_in_function_behavior)); + ShCompileOptions driver_bug_workarounds)); MOCK_METHOD1(Translate, bool(const char* shader)); MOCK_CONST_METHOD0(translated_shader, const char*()); MOCK_CONST_METHOD0(info_log, const char*()); MOCK_CONST_METHOD0(attrib_map, const VariableMap&()); MOCK_CONST_METHOD0(uniform_map, const VariableMap&()); + MOCK_CONST_METHOD0(varying_map, const VariableMap&()); MOCK_CONST_METHOD0(name_map, const NameMap&()); MOCK_CONST_METHOD0( GetStringForOptionsThatWouldEffectCompilation, std::string()); diff --git a/chromium/gpu/command_buffer/service/program_manager.cc b/chromium/gpu/command_buffer/service/program_manager.cc index 8b1eedea35e..0fb6ab32045 100644 --- a/chromium/gpu/command_buffer/service/program_manager.cc +++ b/chromium/gpu/command_buffer/service/program_manager.cc @@ -34,6 +34,28 @@ namespace gles2 { namespace { +struct UniformType { + explicit UniformType(const ShaderTranslator::VariableInfo uniform) + : type(uniform.type), + size(uniform.size), + precision(uniform.precision) { } + + UniformType() + : type(0), + size(0), + precision(SH_PRECISION_MEDIUMP) { } + + bool operator==(const UniformType& other) const { + return type == other.type && + size == other.size && + precision == other.precision; + } + + int type; + int size; + int precision; +}; + int ShaderTypeToIndex(GLenum shader_type) { switch (shader_type) { case GL_VERTEX_SHADER: @@ -96,6 +118,20 @@ bool GetUniformNameSansElement( return true; } +bool IsBuiltInVarying(const std::string& name) { + // Built-in variables. + const char* kBuiltInVaryings[] = { + "gl_FragCoord", + "gl_FrontFacing", + "gl_PointCoord" + }; + for (size_t ii = 0; ii < arraysize(kBuiltInVaryings); ++ii) { + if (name == kBuiltInVaryings[ii]) + return true; + } + return false; +} + } // anonymous namespace. Program::UniformInfo::UniformInfo() @@ -512,6 +548,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"); + 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"); + return false; + } + if (DetectGlobalNameConflicts()) { + set_log_info("Name conflicts between an uniform and an attribute"); + return false; + } + if (!CheckVaryingsPacking()) { + set_log_info("Varyings over maximum register limit"); + return false; + } TimeTicks before_time = TimeTicks::HighResNow(); bool link = true; @@ -963,6 +1017,135 @@ bool Program::DetectAttribLocationBindingConflicts() const { return false; } +bool Program::DetectUniformsMismatch() const { + typedef std::map<std::string, UniformType> UniformMap; + UniformMap uniform_map; + for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { + const ShaderTranslator::VariableMap& shader_uniforms = + attached_shaders_[ii]->uniform_map(); + for (ShaderTranslator::VariableMap::const_iterator iter = + shader_uniforms.begin(); + iter != shader_uniforms.end(); ++iter) { + const std::string& name = iter->first; + UniformType type(iter->second); + UniformMap::iterator map_entry = uniform_map.find(name); + if (map_entry == uniform_map.end()) { + uniform_map[name] = type; + } else { + // If a uniform is already in the map, i.e., it has already been + // declared by other shader, then the type and precision must match. + if (map_entry->second == type) + continue; + return true; + } + } + } + return false; +} + +bool Program::DetectVaryingsMismatch() const { + DCHECK(attached_shaders_[0] && + attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && + attached_shaders_[1] && + attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); + const ShaderTranslator::VariableMap* vertex_varyings = + &(attached_shaders_[0]->varying_map()); + const ShaderTranslator::VariableMap* fragment_varyings = + &(attached_shaders_[1]->varying_map()); + + for (ShaderTranslator::VariableMap::const_iterator iter = + fragment_varyings->begin(); + iter != fragment_varyings->end(); ++iter) { + const std::string& name = iter->first; + if (IsBuiltInVarying(name)) + continue; + + ShaderTranslator::VariableMap::const_iterator hit = + vertex_varyings->find(name); + if (hit == vertex_varyings->end()) { + if (iter->second.static_use) + return true; + continue; + } + + if (hit->second.type != iter->second.type || + hit->second.size != iter->second.size) + return true; + + } + return false; +} + +bool Program::DetectGlobalNameConflicts() const { + DCHECK(attached_shaders_[0] && + attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && + attached_shaders_[1] && + attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); + const ShaderTranslator::VariableMap* uniforms[2]; + uniforms[0] = &(attached_shaders_[0]->uniform_map()); + uniforms[1] = &(attached_shaders_[1]->uniform_map()); + const ShaderTranslator::VariableMap* attribs = + &(attached_shaders_[0]->attrib_map()); + + 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()) + return true; + } + } + return false; +} + +bool Program::CheckVaryingsPacking() const { + DCHECK(attached_shaders_[0] && + attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && + attached_shaders_[1] && + attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); + const ShaderTranslator::VariableMap* vertex_varyings = + &(attached_shaders_[0]->varying_map()); + const ShaderTranslator::VariableMap* fragment_varyings = + &(attached_shaders_[1]->varying_map()); + + std::map<std::string, ShVariableInfo> combined_map; + + for (ShaderTranslator::VariableMap::const_iterator iter = + fragment_varyings->begin(); + iter != fragment_varyings->end(); ++iter) { + if (!iter->second.static_use) + continue; + if (!IsBuiltInVarying(iter->first)) { + ShaderTranslator::VariableMap::const_iterator vertex_iter = + vertex_varyings->find(iter->first); + if (vertex_iter == vertex_varyings->end() || + !vertex_iter->second.static_use) + continue; + } + + ShVariableInfo var; + var.type = static_cast<ShDataType>(iter->second.type); + var.size = iter->second.size; + combined_map[iter->first] = var; + } + + if (combined_map.size() == 0) + return true; + scoped_ptr<ShVariableInfo[]> variables( + new ShVariableInfo[combined_map.size()]); + size_t index = 0; + for (std::map<std::string, ShVariableInfo>::const_iterator iter = + combined_map.begin(); + iter != combined_map.end(); ++iter) { + variables[index].type = iter->second.type; + variables[index].size = iter->second.size; + ++index; + } + return ShCheckVariablesWithinPackingLimits( + static_cast<int>(manager_->max_varying_vectors()), + variables.get(), + combined_map.size()) == 1; +} + static uint32 ComputeOffset(const void* start, const void* position) { return static_cast<const uint8*>(position) - static_cast<const uint8*>(start); @@ -1060,13 +1243,15 @@ Program::~Program() { } -ProgramManager::ProgramManager(ProgramCache* program_cache) +ProgramManager::ProgramManager(ProgramCache* program_cache, + uint32 max_varying_vectors) : program_count_(0), have_context_(true), disable_workarounds_( CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableGpuDriverBugWorkarounds)), - program_cache_(program_cache) { } + program_cache_(program_cache), + max_varying_vectors_(max_varying_vectors) { } ProgramManager::~ProgramManager() { DCHECK(programs_.empty()); diff --git a/chromium/gpu/command_buffer/service/program_manager.h b/chromium/gpu/command_buffer/service/program_manager.h index dca232bf242..258a3c3cf5f 100644 --- a/chromium/gpu/command_buffer/service/program_manager.h +++ b/chromium/gpu/command_buffer/service/program_manager.h @@ -186,6 +186,22 @@ class GPU_EXPORT Program : public base::RefCounted<Program> { // We only consider the declared attributes in the program. bool DetectAttribLocationBindingConflicts() const; + // 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 if a varying is statically used in fragment shader, but it + // is not declared in vertex shader. + bool DetectVaryingsMismatch() const; + + // Return true if an uniform and an attribute share the same name. + bool DetectGlobalNameConflicts() const; + + // Return false if varyings can't be packed into the max available + // varying registers. + bool CheckVaryingsPacking() const; + // Visible for testing const LocationMap& bind_attrib_location_map() const { return bind_attrib_location_map_; @@ -320,7 +336,8 @@ class GPU_EXPORT Program : public base::RefCounted<Program> { // need to be shared by multiple GLES2Decoders. class GPU_EXPORT ProgramManager { public: - explicit ProgramManager(ProgramCache* program_cache); + explicit ProgramManager(ProgramCache* program_cache, + uint32 max_varying_vectors); ~ProgramManager(); // Must call before destruction. @@ -362,12 +379,19 @@ class GPU_EXPORT ProgramManager { ShaderTranslator* translator, FeatureInfo* feature_info); + uint32 max_varying_vectors() const { + return max_varying_vectors_; + } + private: friend class Program; void StartTracking(Program* program); void StopTracking(Program* program); + void RemoveProgramInfoIfUnused( + ShaderManager* shader_manager, Program* program); + // Info for each "successfully linked" program by service side program Id. // TODO(gman): Choose a faster container. typedef std::map<GLuint, scoped_refptr<Program> > ProgramMap; @@ -386,8 +410,7 @@ class GPU_EXPORT ProgramManager { ProgramCache* program_cache_; - void RemoveProgramInfoIfUnused( - ShaderManager* shader_manager, Program* program); + uint32 max_varying_vectors_; DISALLOW_COPY_AND_ASSIGN(ProgramManager); }; diff --git a/chromium/gpu/command_buffer/service/program_manager_unittest.cc b/chromium/gpu/command_buffer/service/program_manager_unittest.cc index 90ce0af8eff..43217f45212 100644 --- a/chromium/gpu/command_buffer/service/program_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/program_manager_unittest.cc @@ -36,12 +36,14 @@ namespace gpu { namespace gles2 { namespace { +const uint32 kMaxVaryingVectors = 8; + void ShaderCacheCb(const std::string& key, const std::string& shader) {} -} // namespace +} // namespace anonymous class ProgramManagerTest : public testing::Test { public: - ProgramManagerTest() : manager_(NULL) { } + ProgramManagerTest() : manager_(NULL, kMaxVaryingVectors) { } virtual ~ProgramManagerTest() { manager_.Destroy(false); } @@ -139,7 +141,7 @@ TEST_F(ProgramManagerTest, Program) { class ProgramManagerWithShaderTest : public testing::Test { public: ProgramManagerWithShaderTest() - : manager_(NULL), program_(NULL) { + : manager_(NULL, kMaxVaryingVectors), program_(NULL) { } virtual ~ProgramManagerWithShaderTest() { @@ -162,6 +164,10 @@ class ProgramManagerWithShaderTest : public testing::Test { static const GLint kAttrib1Size = 1; static const GLint kAttrib2Size = 1; static const GLint kAttrib3Size = 1; + static const int kAttrib1Precision = SH_PRECISION_MEDIUMP; + static const int kAttrib2Precision = SH_PRECISION_HIGHP; + static const int kAttrib3Precision = SH_PRECISION_LOWP; + static const int kAttribStaticUse = 0; static const GLint kAttrib1Location = 0; static const GLint kAttrib2Location = 1; static const GLint kAttrib3Location = 2; @@ -178,6 +184,12 @@ class ProgramManagerWithShaderTest : public testing::Test { static const GLint kUniform1Size = 1; static const GLint kUniform2Size = 3; static const GLint kUniform3Size = 2; + static const int kUniform1Precision = SH_PRECISION_LOWP; + static const int kUniform2Precision = SH_PRECISION_MEDIUMP; + static const int kUniform3Precision = SH_PRECISION_HIGHP; + static const int kUniform1StaticUse = 1; + static const int kUniform2StaticUse = 1; + static const int kUniform3StaticUse = 1; static const GLint kUniform1FakeLocation = 0; // These are hard coded static const GLint kUniform2FakeLocation = 1; // to match static const GLint kUniform3FakeLocation = 2; // ProgramManager. @@ -200,6 +212,21 @@ class ProgramManagerWithShaderTest : public testing::Test { typedef TestHelper::AttribInfo AttribInfo; typedef TestHelper::UniformInfo UniformInfo; + typedef enum { + kVarUniform, + kVarVarying, + kVarAttribute + } VarCategory; + + typedef struct { + int type; + int size; + int precision; + int static_use; + std::string name; + VarCategory category; + } VarInfo; + virtual void SetUp() { gl_.reset(new StrictMock<gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); @@ -262,6 +289,110 @@ class ProgramManagerWithShaderTest : public testing::Test { return (static_cast<bool>(link_status) == expected_link_status); } + Program* SetupShaderVariableTest(const VarInfo* vertex_variables, + size_t vertex_variable_size, + const VarInfo* fragment_variables, + size_t fragment_variable_size) { + // Set up shader + const GLuint kVShaderClientId = 1; + const GLuint kVShaderServiceId = 11; + const GLuint kFShaderClientId = 2; + const GLuint kFShaderServiceId = 12; + + MockShaderTranslator vertex_shader_translator; + ShaderTranslator::VariableMap vertex_attrib_map; + ShaderTranslator::VariableMap vertex_uniform_map; + ShaderTranslator::VariableMap vertex_varying_map; + for (size_t ii = 0; ii < vertex_variable_size; ++ii) { + ShaderTranslator::VariableMap* map = NULL; + switch (vertex_variables[ii].category) { + case kVarAttribute: + map = &vertex_attrib_map; + break; + case kVarUniform: + map = &vertex_uniform_map; + break; + case kVarVarying: + map = &vertex_varying_map; + break; + default: + NOTREACHED(); + } + (*map)[vertex_variables[ii].name] = + ShaderTranslator::VariableInfo(vertex_variables[ii].type, + vertex_variables[ii].size, + vertex_variables[ii].precision, + vertex_variables[ii].static_use, + vertex_variables[ii].name); + } + ShaderTranslator::NameMap vertex_name_map; + EXPECT_CALL(vertex_shader_translator, attrib_map()) + .WillRepeatedly(ReturnRef(vertex_attrib_map)); + EXPECT_CALL(vertex_shader_translator, uniform_map()) + .WillRepeatedly(ReturnRef(vertex_uniform_map)); + EXPECT_CALL(vertex_shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(vertex_varying_map)); + EXPECT_CALL(vertex_shader_translator, name_map()) + .WillRepeatedly(ReturnRef(vertex_name_map)); + + MockShaderTranslator frag_shader_translator; + ShaderTranslator::VariableMap frag_attrib_map; + ShaderTranslator::VariableMap frag_uniform_map; + ShaderTranslator::VariableMap frag_varying_map; + for (size_t ii = 0; ii < fragment_variable_size; ++ii) { + ShaderTranslator::VariableMap* map = NULL; + switch (fragment_variables[ii].category) { + case kVarAttribute: + map = &frag_attrib_map; + break; + case kVarUniform: + map = &frag_uniform_map; + break; + case kVarVarying: + map = &frag_varying_map; + break; + default: + NOTREACHED(); + } + (*map)[fragment_variables[ii].name] = + ShaderTranslator::VariableInfo(fragment_variables[ii].type, + fragment_variables[ii].size, + fragment_variables[ii].precision, + fragment_variables[ii].static_use, + fragment_variables[ii].name); + } + ShaderTranslator::NameMap frag_name_map; + EXPECT_CALL(frag_shader_translator, attrib_map()) + .WillRepeatedly(ReturnRef(frag_attrib_map)); + EXPECT_CALL(frag_shader_translator, uniform_map()) + .WillRepeatedly(ReturnRef(frag_uniform_map)); + EXPECT_CALL(frag_shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(frag_varying_map)); + EXPECT_CALL(frag_shader_translator, name_map()) + .WillRepeatedly(ReturnRef(frag_name_map)); + + // Check we can create shader. + Shader* vshader = shader_manager_.CreateShader( + kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); + Shader* fshader = shader_manager_.CreateShader( + kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); + // Check shader got created. + EXPECT_TRUE(vshader != NULL && fshader != NULL); + // Set Status + vshader->SetStatus(true, "", &vertex_shader_translator); + fshader->SetStatus(true, "", &frag_shader_translator); + + // Set up program + const GLuint kClientProgramId = 6666; + const GLuint kServiceProgramId = 8888; + Program* program = + manager_.CreateProgram(kClientProgramId, kServiceProgramId); + EXPECT_TRUE(program != NULL); + EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); + EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); + return program; + } + static AttribInfo kAttribs[]; static UniformInfo kUniforms[]; @@ -670,22 +801,31 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) { MockShaderTranslator shader_translator; ShaderTranslator::VariableMap attrib_map; ShaderTranslator::VariableMap uniform_map; + ShaderTranslator::VariableMap varying_map; attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib1Type, kAttrib1Size, kAttrib1Name); + kAttrib1Type, kAttrib1Size, kAttrib1Precision, + kAttribStaticUse, kAttrib1Name); attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib2GoodType, kAttrib2Size, kAttrib2Name); + kAttrib2GoodType, kAttrib2Size, kAttrib2Precision, + kAttribStaticUse, kAttrib2Name); attrib_map[kAttrib3Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib3Type, kAttrib3Size, kAttrib3Name); + kAttrib3Type, kAttrib3Size, kAttrib3Precision, + kAttribStaticUse, kAttrib3Name); uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo( - kUniform1Type, kUniform1Size, kUniform1Name); + kUniform1Type, kUniform1Size, kUniform1Precision, + kUniform1StaticUse, kUniform1Name); uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo( - kUniform2GoodType, kUniform2Size, kUniform2Name); + kUniform2GoodType, kUniform2Size, kUniform2Precision, + kUniform2StaticUse, kUniform2Name); uniform_map[kUniform3GoodName] = ShaderTranslatorInterface::VariableInfo( - kUniform3Type, kUniform3Size, kUniform3GoodName); + kUniform3Type, kUniform3Size, kUniform3Precision, + kUniform3StaticUse, kUniform3GoodName); EXPECT_CALL(shader_translator, attrib_map()) .WillRepeatedly(ReturnRef(attrib_map)); EXPECT_CALL(shader_translator, uniform_map()) .WillRepeatedly(ReturnRef(uniform_map)); + EXPECT_CALL(shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(varying_map)); ShaderTranslator::NameMap name_map; EXPECT_CALL(shader_translator, name_map()) .WillRepeatedly(ReturnRef(name_map)); @@ -937,13 +1077,20 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { ShaderTranslator::VariableMap attrib_map; for (uint32 ii = 0; ii < kNumAttribs; ++ii) { attrib_map[kAttribs[ii].name] = ShaderTranslatorInterface::VariableInfo( - kAttribs[ii].type, kAttribs[ii].size, kAttribs[ii].name); + kAttribs[ii].type, + kAttribs[ii].size, + SH_PRECISION_MEDIUMP, + kAttribStaticUse, + kAttribs[ii].name); } ShaderTranslator::VariableMap uniform_map; + ShaderTranslator::VariableMap varying_map; EXPECT_CALL(shader_translator, attrib_map()) .WillRepeatedly(ReturnRef(attrib_map)); EXPECT_CALL(shader_translator, uniform_map()) .WillRepeatedly(ReturnRef(uniform_map)); + EXPECT_CALL(shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(varying_map)); ShaderTranslator::NameMap name_map; EXPECT_CALL(shader_translator, name_map()) .WillRepeatedly(ReturnRef(name_map)); @@ -964,6 +1111,8 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { ASSERT_TRUE(variable_info != NULL); EXPECT_EQ(it->second.type, variable_info->type); EXPECT_EQ(it->second.size, variable_info->size); + EXPECT_EQ(it->second.precision, variable_info->precision); + EXPECT_EQ(it->second.static_use, variable_info->static_use); EXPECT_EQ(it->second.name, variable_info->name); } fshader->SetStatus(true, "", NULL); @@ -997,6 +1146,185 @@ TEST_F(ProgramManagerWithShaderTest, BindAttribLocationConflicts) { EXPECT_TRUE(LinkAsExpected(program, false)); } +TEST_F(ProgramManagerWithShaderTest, UniformsPrecisionMismatch) { + // Set up shader + const GLuint kVShaderClientId = 1; + const GLuint kVShaderServiceId = 11; + const GLuint kFShaderClientId = 2; + const GLuint kFShaderServiceId = 12; + + MockShaderTranslator vertex_shader_translator; + ShaderTranslator::VariableMap vertex_attrib_map; + ShaderTranslator::VariableMap vertex_uniform_map; + vertex_uniform_map["a"] = ShaderTranslator::VariableInfo( + 1, 3, SH_PRECISION_MEDIUMP, 1, "a"); + ShaderTranslator::VariableMap vertex_varying_map; + ShaderTranslator::NameMap vertex_name_map; + EXPECT_CALL(vertex_shader_translator, attrib_map()) + .WillRepeatedly(ReturnRef(vertex_attrib_map)); + EXPECT_CALL(vertex_shader_translator, uniform_map()) + .WillRepeatedly(ReturnRef(vertex_uniform_map)); + EXPECT_CALL(vertex_shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(vertex_varying_map)); + EXPECT_CALL(vertex_shader_translator, name_map()) + .WillRepeatedly(ReturnRef(vertex_name_map)); + + MockShaderTranslator frag_shader_translator; + ShaderTranslator::VariableMap frag_attrib_map; + ShaderTranslator::VariableMap frag_uniform_map; + frag_uniform_map["a"] = ShaderTranslator::VariableInfo( + 1, 3, SH_PRECISION_LOWP, 1, "a"); + ShaderTranslator::VariableMap frag_varying_map; + ShaderTranslator::NameMap frag_name_map; + EXPECT_CALL(frag_shader_translator, attrib_map()) + .WillRepeatedly(ReturnRef(frag_attrib_map)); + EXPECT_CALL(frag_shader_translator, uniform_map()) + .WillRepeatedly(ReturnRef(frag_uniform_map)); + EXPECT_CALL(frag_shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(frag_varying_map)); + EXPECT_CALL(frag_shader_translator, name_map()) + .WillRepeatedly(ReturnRef(frag_name_map)); + + // Check we can create shader. + Shader* vshader = shader_manager_.CreateShader( + kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); + Shader* fshader = shader_manager_.CreateShader( + kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); + // Check shader got created. + ASSERT_TRUE(vshader != NULL && fshader != NULL); + // Set Status + vshader->SetStatus(true, "", &vertex_shader_translator); + fshader->SetStatus(true, "", &frag_shader_translator); + + // Set up program + const GLuint kClientProgramId = 6666; + const GLuint kServiceProgramId = 8888; + Program* program = + manager_.CreateProgram(kClientProgramId, kServiceProgramId); + ASSERT_TRUE(program != NULL); + EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader)); + EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader)); + + EXPECT_TRUE(program->DetectUniformsMismatch()); + EXPECT_TRUE(LinkAsExpected(program, false)); +} + +// If a varying has different type in the vertex and fragment +// shader, linking should fail. +TEST_F(ProgramManagerWithShaderTest, VaryingTypeMismatch) { + const VarInfo kVertexVarying = + { SH_FLOAT_VEC3, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; + const VarInfo kFragmentVarying = + { SH_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; + Program* program = SetupShaderVariableTest( + &kVertexVarying, 1, &kFragmentVarying, 1); + + EXPECT_TRUE(program->DetectVaryingsMismatch()); + EXPECT_TRUE(LinkAsExpected(program, false)); +} + +// If a varying has different array size in the vertex and fragment +// shader, linking should fail. +TEST_F(ProgramManagerWithShaderTest, VaryingArraySizeMismatch) { + const VarInfo kVertexVarying = + { SH_FLOAT, 2, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; + const VarInfo kFragmentVarying = + { SH_FLOAT, 3, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; + Program* program = SetupShaderVariableTest( + &kVertexVarying, 1, &kFragmentVarying, 1); + + EXPECT_TRUE(program->DetectVaryingsMismatch()); + EXPECT_TRUE(LinkAsExpected(program, false)); +} + +// If a varying has different precision in the vertex and fragment +// shader, linking should succeed. +TEST_F(ProgramManagerWithShaderTest, VaryingPrecisionMismatch) { + const VarInfo kVertexVarying = + { SH_FLOAT, 2, SH_PRECISION_HIGHP, 1, "a", kVarVarying }; + const VarInfo kFragmentVarying = + { SH_FLOAT, 2, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; + Program* program = SetupShaderVariableTest( + &kVertexVarying, 1, &kFragmentVarying, 1); + + EXPECT_FALSE(program->DetectVaryingsMismatch()); + EXPECT_TRUE(LinkAsExpected(program, true)); +} + +// If a varying is statically used in fragment shader but not +// declared in vertex shader, link should fail. +TEST_F(ProgramManagerWithShaderTest, VaryingMissing) { + const VarInfo kFragmentVarying = + { SH_FLOAT, 3, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }; + Program* program = SetupShaderVariableTest( + NULL, 0, &kFragmentVarying, 1); + + EXPECT_TRUE(program->DetectVaryingsMismatch()); + EXPECT_TRUE(LinkAsExpected(program, false)); +} + +// If a varying is declared but not statically used in fragment +// shader, even if it's not declared in vertex shader, link should +// succeed. +TEST_F(ProgramManagerWithShaderTest, InactiveVarying) { + const VarInfo kFragmentVarying = + { SH_FLOAT, 3, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying }; + Program* program = SetupShaderVariableTest( + NULL, 0, &kFragmentVarying, 1); + + EXPECT_FALSE(program->DetectVaryingsMismatch()); + EXPECT_TRUE(LinkAsExpected(program, true)); +} + +// Uniforms and attributes are both global variables, thus sharing +// the same namespace. Any name conflicts should cause link +// failure. +TEST_F(ProgramManagerWithShaderTest, AttribUniformNameConflict) { + const VarInfo kVertexAttribute = + { SH_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarAttribute }; + const VarInfo kFragmentUniform = + { SH_FLOAT_VEC4, 1, SH_PRECISION_MEDIUMP, 1, "a", kVarUniform }; + Program* program = SetupShaderVariableTest( + &kVertexAttribute, 1, &kFragmentUniform, 1); + + EXPECT_TRUE(program->DetectGlobalNameConflicts()); + EXPECT_TRUE(LinkAsExpected(program, false)); +} + +// Varyings go over 8 rows. +TEST_F(ProgramManagerWithShaderTest, TooManyVaryings) { + const VarInfo kVertexVaryings[] = { + { SH_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }, + { SH_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } + }; + const VarInfo kFragmentVaryings[] = { + { SH_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }, + { SH_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } + }; + Program* program = SetupShaderVariableTest( + kVertexVaryings, 2, kFragmentVaryings, 2); + + EXPECT_FALSE(program->CheckVaryingsPacking()); + EXPECT_TRUE(LinkAsExpected(program, false)); +} + +// Varyings go over 8 rows but some are inactive +TEST_F(ProgramManagerWithShaderTest, TooManyInactiveVaryings) { + const VarInfo kVertexVaryings[] = { + { SH_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 1, "a", kVarVarying }, + { SH_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } + }; + const VarInfo kFragmentVaryings[] = { + { SH_FLOAT_VEC4, 4, SH_PRECISION_MEDIUMP, 0, "a", kVarVarying }, + { SH_FLOAT_VEC4, 5, SH_PRECISION_MEDIUMP, 1, "b", kVarVarying } + }; + Program* program = SetupShaderVariableTest( + kVertexVaryings, 2, kFragmentVaryings, 2); + + EXPECT_TRUE(program->CheckVaryingsPacking()); + EXPECT_TRUE(LinkAsExpected(program, true)); +} + TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) { const GLuint kVShaderClientId = 2001; const GLuint kFShaderClientId = 2002; @@ -1155,7 +1483,7 @@ class ProgramManagerWithCacheTest : public testing::Test { ProgramManagerWithCacheTest() : cache_(new MockProgramCache()), - manager_(cache_.get()), + manager_(cache_.get(), kMaxVaryingVectors), vertex_shader_(NULL), fragment_shader_(NULL), program_(NULL) { diff --git a/chromium/gpu/command_buffer/service/query_manager.cc b/chromium/gpu/command_buffer/service/query_manager.cc index 7566099b6f8..85e273c6c3a 100644 --- a/chromium/gpu/command_buffer/service/query_manager.cc +++ b/chromium/gpu/command_buffer/service/query_manager.cc @@ -431,11 +431,12 @@ QueryManager::Query* QueryManager::CreateQuery( case GL_LATENCY_QUERY_CHROMIUM: query = new CommandLatencyQuery(this, target, shm_id, shm_offset); break; - case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM: + // Currently async pixel transfer delegates only support uploads. query = new AsyncPixelTransfersCompletedQuery( this, target, shm_id, shm_offset); break; - case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM: + case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM: query = new AsyncReadPixelsCompletedQuery( this, target, shm_id, shm_offset); break; diff --git a/chromium/gpu/command_buffer/service/query_manager_unittest.cc b/chromium/gpu/command_buffer/service/query_manager_unittest.cc index 63ad4f5b27c..0c0829346a6 100644 --- a/chromium/gpu/command_buffer/service/query_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/query_manager_unittest.cc @@ -47,7 +47,7 @@ class QueryManagerTest : public testing::Test { gl_.get(), "GL_EXT_occlusion_query_boolean"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize("*"); + feature_info->Initialize(); manager_.reset(new QueryManager(decoder_.get(), feature_info.get())); } @@ -474,7 +474,7 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery2) { gl_.get(), "GL_ARB_occlusion_query2"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize("*"); + feature_info->Initialize(); scoped_ptr<QueryManager> manager( new QueryManager(decoder_.get(), feature_info.get())); @@ -508,7 +508,7 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery) { gl_.get(), "GL_ARB_occlusion_query"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize("*"); + feature_info->Initialize(); scoped_ptr<QueryManager> manager( new QueryManager(decoder_.get(), feature_info.get())); @@ -537,7 +537,7 @@ TEST_F(QueryManagerTest, GetErrorQuery) { TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), ""); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize("*"); + feature_info->Initialize(); scoped_ptr<QueryManager> manager( new QueryManager(decoder_.get(), feature_info.get())); diff --git a/chromium/gpu/command_buffer/service/renderbuffer_manager.cc b/chromium/gpu/command_buffer/service/renderbuffer_manager.cc index 0190c449452..03c37cbe2f6 100644 --- a/chromium/gpu/command_buffer/service/renderbuffer_manager.cc +++ b/chromium/gpu/command_buffer/service/renderbuffer_manager.cc @@ -17,11 +17,13 @@ namespace gles2 { RenderbufferManager::RenderbufferManager( MemoryTracker* memory_tracker, GLint max_renderbuffer_size, - GLint max_samples) + GLint max_samples, + bool depth24_supported) : memory_tracker_( new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)), max_renderbuffer_size_(max_renderbuffer_size), max_samples_(max_samples), + depth24_supported_(depth24_supported), num_uncleared_renderbuffers_(0), renderbuffer_count_(0), have_context_(true) { @@ -38,7 +40,7 @@ RenderbufferManager::~RenderbufferManager() { size_t Renderbuffer::EstimatedSize() { uint32 size = 0; - RenderbufferManager::ComputeEstimatedRenderbufferSize( + manager_->ComputeEstimatedRenderbufferSize( width_, height_, samples_, internal_format_, &size); return size; } @@ -149,8 +151,11 @@ void RenderbufferManager::RemoveRenderbuffer(GLuint client_id) { } } -bool RenderbufferManager::ComputeEstimatedRenderbufferSize( - int width, int height, int samples, int internal_format, uint32* size) { +bool RenderbufferManager::ComputeEstimatedRenderbufferSize(int width, + int height, + int samples, + int internal_format, + uint32* size) const { DCHECK(size); uint32 temp = 0; @@ -170,7 +175,7 @@ bool RenderbufferManager::ComputeEstimatedRenderbufferSize( } GLenum RenderbufferManager::InternalRenderbufferFormatToImplFormat( - GLenum impl_format) { + GLenum impl_format) const { if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { switch (impl_format) { case GL_DEPTH_COMPONENT16: @@ -181,6 +186,10 @@ GLenum RenderbufferManager::InternalRenderbufferFormatToImplFormat( case GL_RGB565: return GL_RGB; } + } else { + // Upgrade 16-bit depth to 24-bit if possible. + if (impl_format == GL_DEPTH_COMPONENT16 && depth24_supported_) + return GL_DEPTH_COMPONENT24; } return impl_format; } diff --git a/chromium/gpu/command_buffer/service/renderbuffer_manager.h b/chromium/gpu/command_buffer/service/renderbuffer_manager.h index 73fc2cb1974..707d2638d08 100644 --- a/chromium/gpu/command_buffer/service/renderbuffer_manager.h +++ b/chromium/gpu/command_buffer/service/renderbuffer_manager.h @@ -126,7 +126,8 @@ class GPU_EXPORT RenderbufferManager { public: RenderbufferManager(MemoryTracker* memory_tracker, GLint max_renderbuffer_size, - GLint max_samples); + GLint max_samples, + bool depth24_supported); ~RenderbufferManager(); GLint max_renderbuffer_size() const { @@ -163,9 +164,12 @@ class GPU_EXPORT RenderbufferManager { return memory_tracker_->GetMemRepresented(); } - static bool ComputeEstimatedRenderbufferSize( - int width, int height, int samples, int internal_format, uint32* size); - static GLenum InternalRenderbufferFormatToImplFormat(GLenum impl_format); + bool ComputeEstimatedRenderbufferSize(int width, + int height, + int samples, + int internal_format, + uint32* size) const; + GLenum InternalRenderbufferFormatToImplFormat(GLenum impl_format) const; private: friend class Renderbuffer; @@ -177,6 +181,7 @@ class GPU_EXPORT RenderbufferManager { GLint max_renderbuffer_size_; GLint max_samples_; + bool depth24_supported_; int num_uncleared_renderbuffers_; diff --git a/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc index 20e18c1c7f1..87fde79bf09 100644 --- a/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/renderbuffer_manager_unittest.cc @@ -8,6 +8,7 @@ #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/mocks.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" #include "ui/gl/gl_mock.h" using ::testing::StrictMock; @@ -21,11 +22,11 @@ class RenderbufferManagerTestBase : public testing::Test { static const GLint kMaxSamples = 4; protected: - void SetUpBase(MemoryTracker* memory_tracker) { + void SetUpBase(MemoryTracker* memory_tracker, bool depth24_supported) { gl_.reset(new ::testing::StrictMock<gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); manager_.reset(new RenderbufferManager( - memory_tracker, kMaxSize, kMaxSamples)); + memory_tracker, kMaxSize, kMaxSamples, depth24_supported)); } virtual void TearDown() { @@ -43,7 +44,8 @@ class RenderbufferManagerTestBase : public testing::Test { class RenderbufferManagerTest : public RenderbufferManagerTestBase { protected: virtual void SetUp() { - SetUpBase(NULL); + bool depth24_supported = false; + SetUpBase(NULL, depth24_supported); } }; @@ -52,7 +54,8 @@ class RenderbufferManagerMemoryTrackerTest protected: virtual void SetUp() { mock_memory_tracker_ = new StrictMock<MockMemoryTracker>(); - SetUpBase(mock_memory_tracker_.get()); + bool depth24_supported = false; + SetUpBase(mock_memory_tracker_.get(), depth24_supported); } scoped_refptr<MockMemoryTracker> mock_memory_tracker_; @@ -179,9 +182,9 @@ TEST_F(RenderbufferManagerMemoryTrackerTest, Basic) { const GLsizei kHeight2 = 32; uint32 expected_size_1 = 0; uint32 expected_size_2 = 0; - RenderbufferManager::ComputeEstimatedRenderbufferSize( + manager_->ComputeEstimatedRenderbufferSize( kWidth, kHeight1, kSamples, kFormat, &expected_size_1); - RenderbufferManager::ComputeEstimatedRenderbufferSize( + manager_->ComputeEstimatedRenderbufferSize( kWidth, kHeight2, kSamples, kFormat, &expected_size_2); EXPECT_MEMORY_ALLOCATION_CHANGE( 0, expected_size_1, MemoryTracker::kUnmanaged); @@ -291,6 +294,32 @@ TEST_F(RenderbufferManagerTest, AddToSignature) { .RetiresOnSaturation(); } +class RenderbufferManagerFormatTest : public RenderbufferManagerTestBase { + protected: + virtual void SetUp() { + bool depth24_supported = true; + SetUpBase(NULL, depth24_supported); + } +}; + +TEST_F(RenderbufferManagerFormatTest, UpgradeDepthFormatOnGLES) { + gfx::GLImplementation prev_impl = gfx::GetGLImplementation(); + gfx::SetGLImplementation(gfx::kGLImplementationEGLGLES2); + GLenum impl_format = + manager_->InternalRenderbufferFormatToImplFormat(GL_DEPTH_COMPONENT16); + gfx::SetGLImplementation(prev_impl); + EXPECT_EQ(static_cast<GLenum>(GL_DEPTH_COMPONENT24), impl_format); +} + +TEST_F(RenderbufferManagerFormatTest, UseUnsizedDepthFormatOnNonGLES) { + gfx::GLImplementation prev_impl = gfx::GetGLImplementation(); + gfx::SetGLImplementation(gfx::kGLImplementationDesktopGL); + GLenum impl_format = + manager_->InternalRenderbufferFormatToImplFormat(GL_DEPTH_COMPONENT16); + gfx::SetGLImplementation(prev_impl); + EXPECT_EQ(static_cast<GLenum>(GL_DEPTH_COMPONENT), impl_format); +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/shader_manager.cc b/chromium/gpu/command_buffer/service/shader_manager.cc index a95b04ced08..89f21f924d9 100644 --- a/chromium/gpu/command_buffer/service/shader_manager.cc +++ b/chromium/gpu/command_buffer/service/shader_manager.cc @@ -43,10 +43,12 @@ void Shader::SetStatus( if (translator && valid) { attrib_map_ = translator->attrib_map(); uniform_map_ = translator->uniform_map(); + varying_map_ = translator->varying_map(); name_map_ = translator->name_map(); } else { attrib_map_.clear(); uniform_map_.clear(); + varying_map_.clear(); name_map_.clear(); } if (valid && source_.get()) { diff --git a/chromium/gpu/command_buffer/service/shader_manager.h b/chromium/gpu/command_buffer/service/shader_manager.h index bc68868bf27..1324238f2a9 100644 --- a/chromium/gpu/command_buffer/service/shader_manager.h +++ b/chromium/gpu/command_buffer/service/shader_manager.h @@ -98,6 +98,11 @@ class GPU_EXPORT Shader : public base::RefCounted<Shader> { } // Used by program cache. + const ShaderTranslator::VariableMap& varying_map() const { + return varying_map_; + } + + // Used by program cache. void set_attrib_map(const ShaderTranslator::VariableMap& attrib_map) { // copied because cache might be cleared attrib_map_ = ShaderTranslator::VariableMap(attrib_map); @@ -109,6 +114,12 @@ class GPU_EXPORT Shader : public base::RefCounted<Shader> { uniform_map_ = ShaderTranslator::VariableMap(uniform_map); } + // Used by program cache. + void set_varying_map(const ShaderTranslator::VariableMap& varying_map) { + // copied because cache might be cleared + varying_map_ = ShaderTranslator::VariableMap(varying_map); + } + private: typedef ShaderTranslator::VariableMap VariableMap; typedef ShaderTranslator::NameMap NameMap; @@ -148,6 +159,7 @@ class GPU_EXPORT Shader : public base::RefCounted<Shader> { // The type info when the shader was last compiled. VariableMap attrib_map_; VariableMap uniform_map_; + VariableMap varying_map_; // The name hashing info when the shader was last compiled. NameMap name_map_; diff --git a/chromium/gpu/command_buffer/service/shader_manager_unittest.cc b/chromium/gpu/command_buffer/service/shader_manager_unittest.cc index a225a3cc8c1..d86aca48bcf 100644 --- a/chromium/gpu/command_buffer/service/shader_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/shader_manager_unittest.cc @@ -134,31 +134,46 @@ TEST_F(ShaderManagerTest, GetInfo) { const GLenum kShader1Type = GL_VERTEX_SHADER; const GLenum kAttrib1Type = GL_FLOAT_VEC2; const GLsizei kAttrib1Size = 2; + const int kAttrib1Precision = SH_PRECISION_MEDIUMP; const char* kAttrib1Name = "attr1"; const GLenum kAttrib2Type = GL_FLOAT_VEC3; const GLsizei kAttrib2Size = 4; + const int kAttrib2Precision = SH_PRECISION_HIGHP; const char* kAttrib2Name = "attr2"; + const int kAttribStaticUse = 0; const GLenum kUniform1Type = GL_FLOAT_MAT2; const GLsizei kUniform1Size = 3; + const int kUniform1Precision = SH_PRECISION_LOWP; + const int kUniform1StaticUse = 1; const char* kUniform1Name = "uni1"; const GLenum kUniform2Type = GL_FLOAT_MAT3; const GLsizei kUniform2Size = 5; + const int kUniform2Precision = SH_PRECISION_MEDIUMP; + const int kUniform2StaticUse = 0; const char* kUniform2Name = "uni2"; + MockShaderTranslator shader_translator; ShaderTranslator::VariableMap attrib_map; attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib1Type, kAttrib1Size, kAttrib1Name); + kAttrib1Type, kAttrib1Size, kAttrib1Precision, + kAttribStaticUse, kAttrib1Name); attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo( - kAttrib2Type, kAttrib2Size, kAttrib2Name); + kAttrib2Type, kAttrib2Size, kAttrib2Precision, + kAttribStaticUse, kAttrib2Name); ShaderTranslator::VariableMap uniform_map; uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo( - kUniform1Type, kUniform1Size, kUniform1Name); + kUniform1Type, kUniform1Size, kUniform1Precision, + kUniform1StaticUse, kUniform1Name); uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo( - kUniform2Type, kUniform2Size, kUniform2Name); + kUniform2Type, kUniform2Size, kUniform2Precision, + kUniform2StaticUse, kUniform2Name); EXPECT_CALL(shader_translator, attrib_map()) .WillRepeatedly(ReturnRef(attrib_map)); EXPECT_CALL(shader_translator, uniform_map()) .WillRepeatedly(ReturnRef(uniform_map)); + ShaderTranslator::VariableMap varying_map; + EXPECT_CALL(shader_translator, varying_map()) + .WillRepeatedly(ReturnRef(varying_map)); ShaderTranslator::NameMap name_map; EXPECT_CALL(shader_translator, name_map()) .WillRepeatedly(ReturnRef(name_map)); @@ -177,6 +192,8 @@ TEST_F(ShaderManagerTest, GetInfo) { ASSERT_TRUE(variable_info != NULL); EXPECT_EQ(it->second.type, variable_info->type); EXPECT_EQ(it->second.size, variable_info->size); + EXPECT_EQ(it->second.precision, variable_info->precision); + EXPECT_EQ(it->second.static_use, variable_info->static_use); EXPECT_EQ(it->second.name, variable_info->name); } for (ShaderTranslator::VariableMap::const_iterator it = uniform_map.begin(); @@ -186,6 +203,8 @@ TEST_F(ShaderManagerTest, GetInfo) { ASSERT_TRUE(variable_info != NULL); EXPECT_EQ(it->second.type, variable_info->type); EXPECT_EQ(it->second.size, variable_info->size); + EXPECT_EQ(it->second.precision, variable_info->precision); + EXPECT_EQ(it->second.static_use, variable_info->static_use); EXPECT_EQ(it->second.name, variable_info->name); } // Check attrib and uniform get cleared. diff --git a/chromium/gpu/command_buffer/service/shader_translator.cc b/chromium/gpu/command_buffer/service/shader_translator.cc index 5129bfce734..37e2dc64d33 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.cc +++ b/chromium/gpu/command_buffer/service/shader_translator.cc @@ -48,6 +48,9 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type, case SH_ACTIVE_UNIFORMS: ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &name_len); break; + case SH_VARYINGS: + ShGetInfo(compiler, SH_VARYING_MAX_LENGTH, &name_len); + break; default: NOTREACHED(); } ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_name_len); @@ -61,18 +64,12 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type, ANGLEGetInfoType len = 0; int size = 0; ShDataType type = SH_NONE; + ShPrecisionType precision = SH_PRECISION_UNDEFINED; + int static_use = 0; - switch (var_type) { - case SH_ACTIVE_ATTRIBUTES: - ShGetActiveAttrib( - compiler, i, &len, &size, &type, name.get(), mapped_name.get()); - break; - case SH_ACTIVE_UNIFORMS: - ShGetActiveUniform( - compiler, i, &len, &size, &type, name.get(), mapped_name.get()); - break; - default: NOTREACHED(); - } + ShGetVariableInfo(compiler, var_type, i, + &len, &size, &type, &precision, &static_use, + name.get(), mapped_name.get()); // In theory we should CHECK(len <= name_len - 1) here, but ANGLE needs // to handle long struct field name mapping before we can do this. @@ -81,7 +78,8 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type, std::string name_string(name.get(), std::min(len, name_len - 1)); mapped_name.get()[mapped_name_len - 1] = '\0'; - ShaderTranslator::VariableInfo info(type, size, name_string); + ShaderTranslator::VariableInfo info( + type, size, precision, static_use, name_string); (*var_map)[mapped_name.get()] = info; } } @@ -120,7 +118,7 @@ ShaderTranslator::DestructionObserver::~DestructionObserver() { ShaderTranslator::ShaderTranslator() : compiler_(NULL), implementation_is_glsl_es_(false), - needs_built_in_function_emulation_(false) { + driver_bug_workarounds_(static_cast<ShCompileOptions>(0)) { } bool ShaderTranslator::Init( @@ -128,8 +126,7 @@ bool ShaderTranslator::Init( ShShaderSpec shader_spec, const ShBuiltInResources* resources, ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type, - ShaderTranslatorInterface::GlslBuiltInFunctionBehavior - glsl_built_in_function_behavior) { + ShCompileOptions driver_bug_workarounds) { // Make sure Init is called only once. DCHECK(compiler_ == NULL); DCHECK(shader_type == SH_FRAGMENT_SHADER || shader_type == SH_VERTEX_SHADER); @@ -149,21 +146,19 @@ bool ShaderTranslator::Init( } compiler_options_ = *resources; implementation_is_glsl_es_ = (glsl_implementation_type == kGlslES); - needs_built_in_function_emulation_ = - (glsl_built_in_function_behavior == kGlslBuiltInFunctionEmulated); + driver_bug_workarounds_ = driver_bug_workarounds; return compiler_ != NULL; } int ShaderTranslator::GetCompileOptions() const { int compile_options = - SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | + 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; - if (needs_built_in_function_emulation_) - compile_options |= SH_EMULATE_BUILT_IN_FUNCTIONS; + compile_options |= driver_bug_workarounds_; return compile_options; } @@ -190,6 +185,7 @@ bool ShaderTranslator::Translate(const char* shader) { // Get info for attribs and uniforms. GetVariableInfo(compiler_, SH_ACTIVE_ATTRIBUTES, &attrib_map_); GetVariableInfo(compiler_, SH_ACTIVE_UNIFORMS, &uniform_map_); + GetVariableInfo(compiler_, SH_VARYINGS, &varying_map_); // Get info for name hashing. GetNameHashingInfo(compiler_, &name_map_); } @@ -281,6 +277,11 @@ ShaderTranslator::uniform_map() const { return uniform_map_; } +const ShaderTranslatorInterface::VariableMap& +ShaderTranslator::varying_map() const { + return varying_map_; +} + const ShaderTranslatorInterface::NameMap& ShaderTranslator::name_map() const { return name_map_; @@ -310,6 +311,7 @@ void ShaderTranslator::ClearResults() { info_log_.reset(); attrib_map_.clear(); uniform_map_.clear(); + varying_map_.clear(); name_map_.clear(); } diff --git a/chromium/gpu/command_buffer/service/shader_translator.h b/chromium/gpu/command_buffer/service/shader_translator.h index 957f721bec7..322cb6b2896 100644 --- a/chromium/gpu/command_buffer/service/shader_translator.h +++ b/chromium/gpu/command_buffer/service/shader_translator.h @@ -27,31 +27,34 @@ class ShaderTranslatorInterface { kGlslES }; - enum GlslBuiltInFunctionBehavior { - kGlslBuiltInFunctionOriginal, - kGlslBuiltInFunctionEmulated - }; - struct VariableInfo { VariableInfo() : type(0), - size(0) { + size(0), + precision(SH_PRECISION_UNDEFINED), + static_use(0) { } - VariableInfo(int _type, int _size, std::string _name) + VariableInfo(int _type, int _size, int _precision, + int _static_use, std::string _name) : type(_type), size(_size), + precision(_precision), + static_use(_static_use), name(_name) { } bool operator==( const ShaderTranslatorInterface::VariableInfo& other) const { return type == other.type && size == other.size && + precision == other.precision && strcmp(name.c_str(), other.name.c_str()) == 0; } int type; int size; + int precision; + int static_use; std::string name; // name in the original shader source. }; @@ -67,7 +70,7 @@ class ShaderTranslatorInterface { ShShaderSpec shader_spec, const ShBuiltInResources* resources, GlslImplementationType glsl_implementation_type, - GlslBuiltInFunctionBehavior glsl_built_in_function_behavior) = 0; + ShCompileOptions driver_bug_workarounds) = 0; // Translates the given shader source. // Returns true if translation is successful, false otherwise. @@ -82,6 +85,7 @@ class ShaderTranslatorInterface { virtual const VariableMap& attrib_map() const = 0; virtual const VariableMap& uniform_map() const = 0; + virtual const VariableMap& varying_map() const = 0; virtual const NameMap& name_map() const = 0; // Return a string that is unique for a specfic set of options that would @@ -116,7 +120,7 @@ class GPU_EXPORT ShaderTranslator ShShaderSpec shader_spec, const ShBuiltInResources* resources, GlslImplementationType glsl_implementation_type, - GlslBuiltInFunctionBehavior glsl_built_in_function_behavior) OVERRIDE; + ShCompileOptions driver_bug_workarounds) OVERRIDE; // Overridden from ShaderTranslatorInterface. virtual bool Translate(const char* shader) OVERRIDE; @@ -128,6 +132,7 @@ class GPU_EXPORT ShaderTranslator // Overridden from ShaderTranslatorInterface. virtual const VariableMap& attrib_map() const OVERRIDE; virtual const VariableMap& uniform_map() const OVERRIDE; + virtual const VariableMap& varying_map() const OVERRIDE; virtual const NameMap& name_map() const OVERRIDE; virtual std::string GetStringForOptionsThatWouldEffectCompilation() const @@ -149,9 +154,10 @@ class GPU_EXPORT ShaderTranslator scoped_ptr<char[]> info_log_; VariableMap attrib_map_; VariableMap uniform_map_; + VariableMap varying_map_; NameMap name_map_; bool implementation_is_glsl_es_; - bool needs_built_in_function_emulation_; + ShCompileOptions driver_bug_workarounds_; ObserverList<DestructionObserver> destruction_observers_; DISALLOW_COPY_AND_ASSIGN(ShaderTranslator); diff --git a/chromium/gpu/command_buffer/service/shader_translator_cache.cc b/chromium/gpu/command_buffer/service/shader_translator_cache.cc index 6e888d56c98..9626a0e25ef 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_cache.cc +++ b/chromium/gpu/command_buffer/service/shader_translator_cache.cc @@ -34,13 +34,12 @@ scoped_refptr<ShaderTranslator> ShaderTranslatorCache::GetTranslator( const ShBuiltInResources* resources, ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type, - ShaderTranslatorInterface::GlslBuiltInFunctionBehavior - glsl_built_in_function_behavior) { + ShCompileOptions driver_bug_workarounds) { ShaderTranslatorInitParams params(shader_type, shader_spec, *resources, glsl_implementation_type, - glsl_built_in_function_behavior); + driver_bug_workarounds); Cache::iterator it = cache_.find(params); if (it != cache_.end()) @@ -49,7 +48,7 @@ scoped_refptr<ShaderTranslator> ShaderTranslatorCache::GetTranslator( ShaderTranslator* translator = new ShaderTranslator(); if (translator->Init(shader_type, shader_spec, resources, glsl_implementation_type, - glsl_built_in_function_behavior)) { + driver_bug_workarounds)) { cache_[params] = translator; translator->AddDestructionObserver(this); return translator; diff --git a/chromium/gpu/command_buffer/service/shader_translator_cache.h b/chromium/gpu/command_buffer/service/shader_translator_cache.h index 0d3e777bc20..551522bdbc4 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_cache.h +++ b/chromium/gpu/command_buffer/service/shader_translator_cache.h @@ -36,8 +36,7 @@ class ShaderTranslatorCache : public ShaderTranslator::DestructionObserver { const ShBuiltInResources* resources, ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type, - ShaderTranslatorInterface::GlslBuiltInFunctionBehavior - glsl_built_in_function_behavior); + ShCompileOptions driver_bug_workarounds); private: ShaderTranslatorCache(); @@ -52,8 +51,7 @@ class ShaderTranslatorCache : public ShaderTranslator::DestructionObserver { ShBuiltInResources resources; ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type; - ShaderTranslatorInterface::GlslBuiltInFunctionBehavior - glsl_built_in_function_behavior; + ShCompileOptions driver_bug_workarounds; ShaderTranslatorInitParams( ShShaderType shader_type, @@ -61,13 +59,12 @@ class ShaderTranslatorCache : public ShaderTranslator::DestructionObserver { const ShBuiltInResources& resources, ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type, - ShaderTranslatorInterface::GlslBuiltInFunctionBehavior - glsl_built_in_function_behavior) + ShCompileOptions driver_bug_workarounds) : shader_type(shader_type), shader_spec(shader_spec), resources(resources), glsl_implementation_type(glsl_implementation_type), - glsl_built_in_function_behavior(glsl_built_in_function_behavior) { + driver_bug_workarounds(driver_bug_workarounds) { } ShaderTranslatorInitParams(const ShaderTranslatorInitParams& params) { diff --git a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc index a08851adcf8..1b53c2b768b 100644 --- a/chromium/gpu/command_buffer/service/shader_translator_unittest.cc +++ b/chromium/gpu/command_buffer/service/shader_translator_unittest.cc @@ -28,11 +28,11 @@ class ShaderTranslatorTest : public testing::Test { ASSERT_TRUE(vertex_translator_->Init( SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources, ShaderTranslatorInterface::kGlsl, - ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated)); + SH_EMULATE_BUILT_IN_FUNCTIONS)); ASSERT_TRUE(fragment_translator_->Init( SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources, ShaderTranslatorInterface::kGlsl, - ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal)); + static_cast<ShCompileOptions>(0))); // Post-init the results must be empty. // Vertex translator results. EXPECT_TRUE(vertex_translator_->translated_shader() == NULL); @@ -232,16 +232,16 @@ TEST_F(ShaderTranslatorTest, OptionsString) { ASSERT_TRUE(translator_1->Init( SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources, ShaderTranslatorInterface::kGlsl, - ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated)); + SH_EMULATE_BUILT_IN_FUNCTIONS)); ASSERT_TRUE(translator_2->Init( SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources, ShaderTranslatorInterface::kGlsl, - ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal)); + static_cast<ShCompileOptions>(0))); resources.EXT_draw_buffers = 1; ASSERT_TRUE(translator_3->Init( SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources, ShaderTranslatorInterface::kGlsl, - ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated)); + SH_EMULATE_BUILT_IN_FUNCTIONS)); std::string options_1( translator_1->GetStringForOptionsThatWouldEffectCompilation()); diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager.h b/chromium/gpu/command_buffer/service/stream_texture_manager.h index b4f0a534954..51119fad528 100644 --- a/chromium/gpu/command_buffer/service/stream_texture_manager.h +++ b/chromium/gpu/command_buffer/service/stream_texture_manager.h @@ -6,7 +6,6 @@ #define GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_H_ #include "base/basictypes.h" -#include "gpu/command_buffer/service/gl_utils.h" namespace gpu { @@ -22,8 +21,7 @@ class StreamTextureManager { } // Returns an identifier for the object, or NULL if not successful. - virtual GLuint CreateStreamTexture(uint32 service_id, - uint32 client_id) = 0; + virtual uint32 CreateStreamTexture(uint32 service_id, uint32 client_id) = 0; virtual void DestroyStreamTexture(uint32 service_id) = 0; 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 new file mode 100644 index 00000000000..2fd55358b4a --- /dev/null +++ b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc @@ -0,0 +1,92 @@ +// Copyright 2013 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_in_process_android.h" + +#include "base/bind.h" +#include "ui/gfx/size.h" +#include "ui/gl/android/surface_texture.h" +#include "ui/gl/gl_bindings.h" + +namespace gpu { + +StreamTextureManagerInProcess::StreamTextureImpl::StreamTextureImpl( + uint32 service_id, + uint32 stream_id) + : surface_texture_(new gfx::SurfaceTexture(service_id)), + stream_id_(stream_id) {} + +StreamTextureManagerInProcess::StreamTextureImpl::~StreamTextureImpl() {} + +void StreamTextureManagerInProcess::StreamTextureImpl::Update() { + GLint texture_id = 0; + glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id); + surface_texture_->UpdateTexImage(); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id); +} + +gfx::Size StreamTextureManagerInProcess::StreamTextureImpl::GetSize() { + return size_; +} + +void StreamTextureManagerInProcess::StreamTextureImpl::SetSize(gfx::Size size) { + size_ = size; +} + +scoped_refptr<gfx::SurfaceTexture> +StreamTextureManagerInProcess::StreamTextureImpl::GetSurfaceTexture() { + return surface_texture_; +} + +StreamTextureManagerInProcess::StreamTextureManagerInProcess() : next_id_(1) {} + +StreamTextureManagerInProcess::~StreamTextureManagerInProcess() { + if (!textures_.empty()) { + LOG(WARNING) << "Undestroyed surface textures while tearing down " + "StreamTextureManager."; + } +} + +GLuint StreamTextureManagerInProcess::CreateStreamTexture(uint32 service_id, + uint32 client_id) { + base::AutoLock lock(map_lock_); + uint32 stream_id = next_id_++; + linked_ptr<StreamTextureImpl> texture( + new StreamTextureImpl(service_id, stream_id)); + textures_[service_id] = texture; + + if (next_id_ == 0) + next_id_++; + + return stream_id; +} + +void StreamTextureManagerInProcess::DestroyStreamTexture(uint32 service_id) { + 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; +} + +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(); + } + + return NULL; +} + +} // namespace gpu 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 new file mode 100644 index 00000000000..6753c139989 --- /dev/null +++ b/chromium/gpu/command_buffer/service/stream_texture_manager_in_process_android.h @@ -0,0 +1,75 @@ +// Copyright 2013 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_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ +#define GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ + +#include <map> + +#include "base/memory/linked_ptr.h" +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "gpu/command_buffer/service/stream_texture.h" +#include "gpu/command_buffer/service/stream_texture_manager.h" + +namespace gfx { +class Size; +class SurfaceTexture; +} + +namespace gpu { + +class StreamTextureManagerInProcess + : public gpu::StreamTextureManager, + public base::RefCountedThreadSafe<StreamTextureManagerInProcess> { + public: + 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; + + 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_; + + DISALLOW_COPY_AND_ASSIGN(StreamTextureImpl); + }; + + friend class base::RefCountedThreadSafe<StreamTextureManagerInProcess>; + virtual ~StreamTextureManagerInProcess(); + + typedef std::map<uint32, linked_ptr<StreamTextureImpl> > TextureMap; + TextureMap textures_; + + uint32 next_id_; + + base::Lock map_lock_; + + DISALLOW_COPY_AND_ASSIGN(StreamTextureManagerInProcess); +}; + +} // gpu + +#endif // GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ diff --git a/chromium/gpu/command_buffer/service/stream_texture_manager_mock.h b/chromium/gpu/command_buffer/service/stream_texture_manager_mock.h index ac145ec89f2..4b744f21b1e 100644 --- a/chromium/gpu/command_buffer/service/stream_texture_manager_mock.h +++ b/chromium/gpu/command_buffer/service/stream_texture_manager_mock.h @@ -18,8 +18,8 @@ class MockStreamTextureManager : public StreamTextureManager { MockStreamTextureManager(); virtual ~MockStreamTextureManager(); - MOCK_METHOD2(CreateStreamTexture, GLuint(uint32 service_id, - uint32 client_id)); + MOCK_METHOD2(CreateStreamTexture, + uint32(uint32 service_id, uint32 client_id)); MOCK_METHOD1(DestroyStreamTexture, void(uint32 service_id)); MOCK_METHOD1(LookupStreamTexture, StreamTexture*(uint32 service_id)); diff --git a/chromium/gpu/command_buffer/service/texture_manager.cc b/chromium/gpu/command_buffer/service/texture_manager.cc index 486bdacad32..deb8c8e6645 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.cc +++ b/chromium/gpu/command_buffer/service/texture_manager.cc @@ -6,6 +6,7 @@ #include "base/bits.h" #include "base/strings/stringprintf.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/context_state.h" #include "gpu/command_buffer/service/error_state.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/framebuffer_manager.h" @@ -1236,5 +1237,238 @@ void TextureManager::IncFramebufferStateChangeCount() { } +bool TextureManager::ValidateTextureParameters( + ErrorState* error_state, const char* function_name, + GLenum target, GLenum format, GLenum type, GLint level) { + 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 ") + + GLES2Util::GetStringEnum(type) + " for format " + + GLES2Util::GetStringEnum(format)).c_str()); + return false; + } + return true; +} + +// Gets the texture id for a given target. +TextureRef* TextureManager::GetTextureInfoForTarget( + ContextState* state, GLenum target) { + TextureUnit& unit = state->texture_units[state->active_texture_unit]; + TextureRef* texture = NULL; + switch (target) { + case GL_TEXTURE_2D: + texture = unit.bound_texture_2d.get(); + break; + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + texture = unit.bound_texture_cube_map.get(); + break; + case GL_TEXTURE_EXTERNAL_OES: + texture = unit.bound_texture_external_oes.get(); + break; + case GL_TEXTURE_RECTANGLE_ARB: + texture = unit.bound_texture_rectangle_arb.get(); + break; + default: + NOTREACHED(); + return NULL; + } + return texture; +} + +TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault( + ContextState* state, GLenum target) { + TextureRef* texture = GetTextureInfoForTarget(state, target); + if (!texture) + return NULL; + if (texture == GetDefaultTextureInfo(target)) + return NULL; + return texture; +} + +bool TextureManager::ValidateTexImage2D( + ContextState* state, + const char* function_name, + const DoTextImage2DArguments& args, + TextureRef** texture_ref) { + ErrorState* error_state = state->GetErrorState(); + const Validators* validators = feature_info_->validators(); + if (!validators->texture_target.IsValid(args.target)) { + ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( + error_state, function_name, args.target, "target"); + return false; + } + if (!validators->texture_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"); + return false; + } + if (!ValidateTextureParameters( + error_state, function_name, args.target, args.format, args.type, + args.level)) { + return false; + } + if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) || + args.border != 0) { + ERRORSTATE_SET_GL_ERROR( + error_state, GL_INVALID_VALUE, function_name, + "dimensions out of range"); + return false; + } + if ((GLES2Util::GetChannelsForFormat(args.format) & + (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) { + ERRORSTATE_SET_GL_ERROR( + error_state, GL_INVALID_OPERATION, + function_name, "can not supply data for depth or stencil textures"); + return false; + } + + TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); + if (!local_texture_ref) { + ERRORSTATE_SET_GL_ERROR( + error_state, GL_INVALID_OPERATION, function_name, + "unknown texture for target"); + return false; + } + if (local_texture_ref->texture()->IsImmutable()) { + ERRORSTATE_SET_GL_ERROR( + error_state, GL_INVALID_OPERATION, function_name, + "texture is immutable"); + return false; + } + + // TODO - verify that using the managed vs unmanaged does not matter. + // 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", + "out of memory"); + return false; + } + + // Write the TextureReference since this is valid. + *texture_ref = local_texture_ref; + return true; +} + +void TextureManager::ValidateAndDoTexImage2D( + DecoderTextureState* texture_state, + ContextState* state, + DecoderFramebufferState* framebuffer_state, + const DoTextImage2DArguments& args) { + TextureRef* texture_ref; + if (!ValidateTexImage2D(state, "glTexImage2D", args, &texture_ref)) { + return; + } + + DoTexImage2D(texture_state, state->GetErrorState(), framebuffer_state, + texture_ref, args); +} + +void TextureManager::DoTexImage2D( + DecoderTextureState* texture_state, + ErrorState* error_state, + DecoderFramebufferState* framebuffer_state, + TextureRef* texture_ref, + const DoTextImage2DArguments& args) { + Texture* texture = texture_ref->texture(); + GLsizei tex_width = 0; + GLsizei tex_height = 0; + GLenum tex_type = 0; + GLenum tex_format = 0; + bool level_is_same = + texture->GetLevelSize(args.target, args.level, &tex_width, &tex_height) && + texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) && + args.width == tex_width && args.height == tex_height && + args.type == tex_type && args.format == tex_format; + + if (level_is_same && !args.pixels) { + // Just set the level texture but mark the texture as uncleared. + SetLevelInfo( + texture_ref, + args.target, args.level, args.internal_format, args.width, args.height, + 1, args.border, args.format, args.type, false); + texture_state->tex_image_2d_failed = false; + return; + } + + if (texture->IsAttachedToFramebuffer()) { + framebuffer_state->clear_state_dirty = true; + } + + if (!texture_state->teximage2d_faster_than_texsubimage2d && + level_is_same && args.pixels) { + { + ScopedTextureUploadTimer timer(texture_state); + glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, + args.format, args.type, args.pixels); + } + SetLevelCleared(texture_ref, args.target, args.level, true); + texture_state->tex_image_2d_failed = false; + return; + } + + ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glTexImage2D"); + { + ScopedTextureUploadTimer timer(texture_state); + glTexImage2D( + args.target, args.level, args.internal_format, args.width, args.height, + args.border, args.format, args.type, args.pixels); + } + GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D"); + if (error == GL_NO_ERROR) { + SetLevelInfo( + texture_ref, + args.target, args.level, args.internal_format, args.width, args.height, + 1, args.border, args.format, args.type, args.pixels != NULL); + texture_state->tex_image_2d_failed = false; + } +} + +ScopedTextureUploadTimer::ScopedTextureUploadTimer( + DecoderTextureState* texture_state) + : texture_state_(texture_state), + begin_time_(base::TimeTicks::HighResNow()) { +} + +ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { + texture_state_->texture_upload_count++; + texture_state_->total_texture_upload_time += + base::TimeTicks::HighResNow() - begin_time_; +} + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/texture_manager.h b/chromium/gpu/command_buffer/service/texture_manager.h index cbc659caf4e..db470045751 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.h +++ b/chromium/gpu/command_buffer/service/texture_manager.h @@ -27,6 +27,8 @@ class StreamTextureManager; namespace gles2 { class GLES2Decoder; +struct ContextState; +struct DecoderFramebufferState; class Display; class ErrorState; class FeatureInfo; @@ -429,6 +431,29 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { DISALLOW_COPY_AND_ASSIGN(TextureRef); }; +// Holds data that is per gles2_cmd_decoder, but is related to to the +// TextureManager. +struct DecoderTextureState { + // total_texture_upload_time automatically initialized to 0 in default + // constructor. + DecoderTextureState(): + tex_image_2d_failed(false), + texture_upload_count(0), + teximage2d_faster_than_texsubimage2d(true) {} + + // This indicates all the following texSubImage2D calls that are part of the + // failed texImage2D call should be ignored. + bool tex_image_2d_failed; + + // Command buffer stats. + int texture_upload_count; + base::TimeDelta total_texture_upload_time; + + // This is really not per-decoder, but the logic to decide this value is in + // the decoder for now, so it is simpler to leave it there. + bool teximage2d_faster_than_texsubimage2d; +}; + // This class keeps track of the textures and their sizes so we can do NPOT and // texture complete checking. // @@ -671,6 +696,43 @@ class GPU_EXPORT TextureManager { destruction_observers_.RemoveObserver(observer); } + struct DoTextImage2DArguments { + GLenum target; + GLint level; + GLenum internal_format; + GLsizei width; + GLsizei height; + GLint border; + GLenum format; + GLenum type; + const void* pixels; + uint32 pixels_size; + }; + + bool ValidateTexImage2D( + ContextState* state, + const char* function_name, + const DoTextImage2DArguments& args, + // Pointer to TextureRef filled in if validation successful. + // Presumes the pointer is valid. + TextureRef** texture_ref); + + void ValidateAndDoTexImage2D( + DecoderTextureState* texture_state, + ContextState* state, + DecoderFramebufferState* framebuffer_state, + const DoTextImage2DArguments& args); + + // TODO(kloveless): Make GetTexture* private once this is no longer called + // from gles2_cmd_decoder. + TextureRef* GetTextureInfoForTarget(ContextState* state, GLenum target); + TextureRef* GetTextureInfoForTargetUnlessDefault( + ContextState* state, GLenum target); + + bool ValidateTextureParameters( + ErrorState* error_state, const char* function_name, + GLenum target, GLenum format, GLenum type, GLint level); + private: friend class Texture; friend class TextureRef; @@ -680,6 +742,13 @@ class GPU_EXPORT TextureManager { GLenum target, GLuint* black_texture); + void DoTexImage2D( + DecoderTextureState* texture_state, + ErrorState* error_state, + DecoderFramebufferState* framebuffer_state, + TextureRef* texture_ref, + const DoTextImage2DArguments& args); + void StartTracking(TextureRef* texture); void StopTracking(TextureRef* texture); @@ -730,6 +799,18 @@ class GPU_EXPORT TextureManager { DISALLOW_COPY_AND_ASSIGN(TextureManager); }; +// This class records texture upload time when in scope. +class ScopedTextureUploadTimer { + public: + explicit ScopedTextureUploadTimer(DecoderTextureState* texture_state); + ~ScopedTextureUploadTimer(); + + private: + DecoderTextureState* texture_state_; + base::TimeTicks begin_time_; + DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer); +}; + } // namespace gles2 } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc index 402cc8d0eff..483aaf20fa6 100644 --- a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc @@ -318,7 +318,7 @@ TEST_F(TextureManagerTest, ValidForTargetNPOT) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_npot"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); // Check NPOT width on level 0 @@ -356,7 +356,7 @@ class TextureTestBase : public testing::Test { if (!extensions.empty()) { TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions.c_str()); - feature_info_->Initialize(NULL); + feature_info_->Initialize(); } manager_.reset(new TextureManager( @@ -796,7 +796,7 @@ TEST_F(TextureTest, NPOT2DNPOTOK) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_npot"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); manager.CreateTexture(kClient1Id, kService1Id); @@ -1087,7 +1087,7 @@ TEST_F(TextureTest, FloatNotLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_float"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); manager.CreateTexture(kClient1Id, kService1Id); @@ -1114,7 +1114,7 @@ TEST_F(TextureTest, FloatLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_float GL_OES_texture_float_linear"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); manager.CreateTexture(kClient1Id, kService1Id); @@ -1133,7 +1133,7 @@ TEST_F(TextureTest, HalfFloatNotLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_half_float"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); manager.CreateTexture(kClient1Id, kService1Id); @@ -1160,7 +1160,7 @@ TEST_F(TextureTest, HalfFloatLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_half_float GL_OES_texture_half_float_linear"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); manager.CreateTexture(kClient1Id, kService1Id); @@ -1179,7 +1179,7 @@ TEST_F(TextureTest, EGLImageExternal) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_EGL_image_external"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); manager.CreateTexture(kClient1Id, kService1Id); @@ -1196,7 +1196,7 @@ TEST_F(TextureTest, DepthTexture) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_ANGLE_depth_texture"); scoped_refptr<FeatureInfo> feature_info(new FeatureInfo()); - feature_info->Initialize(NULL); + feature_info->Initialize(); TextureManager manager( NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); manager.CreateTexture(kClient1Id, kService1Id); diff --git a/chromium/gpu/command_buffer_common.gypi b/chromium/gpu/command_buffer_common.gypi index f159355d3e0..4c1044ac775 100644 --- a/chromium/gpu/command_buffer_common.gypi +++ b/chromium/gpu/command_buffer_common.gypi @@ -24,6 +24,7 @@ 'command_buffer/common/gles2_cmd_format_autogen.h', 'command_buffer/common/gles2_cmd_format.cc', 'command_buffer/common/gles2_cmd_format.h', + 'command_buffer/common/gpu_control.h', 'command_buffer/common/id_allocator.cc', 'command_buffer/common/id_allocator.h', 'command_buffer/common/mailbox.cc', diff --git a/chromium/gpu/command_buffer_service.gypi b/chromium/gpu/command_buffer_service.gypi index f8e94c18eb2..729baf0fe83 100644 --- a/chromium/gpu/command_buffer_service.gypi +++ b/chromium/gpu/command_buffer_service.gypi @@ -75,13 +75,18 @@ 'command_buffer/service/gl_state_restorer_impl.cc', 'command_buffer/service/gl_state_restorer_impl.h', 'command_buffer/service/gl_utils.h', - 'command_buffer/service/gpu_scheduler.h', + 'command_buffer/service/gpu_control_service.cc', + 'command_buffer/service/gpu_control_service.h', + 'command_buffer/service/gpu_memory_buffer_manager.h', 'command_buffer/service/gpu_scheduler.cc', + 'command_buffer/service/gpu_scheduler.h', 'command_buffer/service/gpu_scheduler_mock.h', - 'command_buffer/service/gpu_switches.h', + 'command_buffer/service/gpu_state_tracer.cc', + 'command_buffer/service/gpu_state_tracer.h', 'command_buffer/service/gpu_switches.cc', - 'command_buffer/service/gpu_tracer.h', + 'command_buffer/service/gpu_switches.h', 'command_buffer/service/gpu_tracer.cc', + 'command_buffer/service/gpu_tracer.h', 'command_buffer/service/id_manager.h', 'command_buffer/service/id_manager.cc', 'command_buffer/service/image_manager.cc', @@ -113,6 +118,8 @@ 'command_buffer/service/shader_translator_cache.cc', 'command_buffer/service/stream_texture.h', 'command_buffer/service/stream_texture_manager.h', + 'command_buffer/service/stream_texture_manager_in_process_android.h', + 'command_buffer/service/stream_texture_manager_in_process_android.cc', 'command_buffer/service/texture_manager.h', 'command_buffer/service/texture_manager.cc', 'command_buffer/service/transfer_buffer_manager.cc', diff --git a/chromium/gpu/config/gpu_blacklist_unittest.cc b/chromium/gpu/config/gpu_blacklist_unittest.cc index 3282437d6d3..b1ed3336fae 100644 --- a/chromium/gpu/config/gpu_blacklist_unittest.cc +++ b/chromium/gpu/config/gpu_blacklist_unittest.cc @@ -80,7 +80,6 @@ TEST_F(GpuBlacklistTest, CurrentBlacklistValidation) { scoped_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create()); EXPECT_TRUE(blacklist->LoadList( kSoftwareRenderingListJson, GpuBlacklist::kAllOs)); - EXPECT_FALSE(blacklist->contains_unknown_fields()); } #define GPU_BLACKLIST_FEATURE_TEST(test_name, feature_name, feature_type) \ diff --git a/chromium/gpu/config/gpu_control_list.cc b/chromium/gpu/config/gpu_control_list.cc index 5eb09c489f1..1d45d726614 100644 --- a/chromium/gpu/config/gpu_control_list.cc +++ b/chromium/gpu/config/gpu_control_list.cc @@ -486,8 +486,8 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue( const base::DictionaryValue* os_version_value = NULL; if (os_value->GetDictionary("version", &os_version_value)) { os_version_value->GetString(kOp, &os_version_op); - os_version_value->GetString("number", &os_version_string); - os_version_value->GetString("number2", &os_version_string2); + os_version_value->GetString("value", &os_version_string); + os_version_value->GetString("value2", &os_version_string2); } if (!entry->SetOsInfo(os_type, os_version_op, os_version_string, os_version_string2)) { @@ -558,8 +558,8 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue( std::string driver_version_string2; driver_version_value->GetString(kOp, &driver_version_op); driver_version_value->GetString("style", &driver_version_style); - driver_version_value->GetString("number", &driver_version_string); - driver_version_value->GetString("number2", &driver_version_string2); + driver_version_value->GetString("value", &driver_version_string); + driver_version_value->GetString("value2", &driver_version_string2); if (!entry->SetDriverVersionInfo(driver_version_op, driver_version_style, driver_version_string, @@ -576,8 +576,8 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue( std::string driver_date_string; std::string driver_date_string2; driver_date_value->GetString(kOp, &driver_date_op); - driver_date_value->GetString("number", &driver_date_string); - driver_date_value->GetString("number2", &driver_date_string2); + driver_date_value->GetString("value", &driver_date_string); + driver_date_value->GetString("value2", &driver_date_string2); if (!entry->SetDriverDateInfo(driver_date_op, driver_date_string, driver_date_string2)) { LOG(WARNING) << "Malformed driver_date entry " << entry->id(); @@ -717,8 +717,8 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue( const base::DictionaryValue* version_value = NULL; if (machine_model_value->GetDictionary("version", &version_value)) { version_value->GetString(kOp, &version_op); - version_value->GetString("number", &version_string); - version_value->GetString("number2", &version_string2); + version_value->GetString("value", &version_string); + version_value->GetString("value2", &version_string2); } if (!entry->SetMachineModelInfo( name_op, name_value, version_op, version_string, version_string2)) { @@ -784,12 +784,7 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue( // device_ids are specified in Exception, the info will be incomplete. if (exception->vendor_id_ == 0 && entry->vendor_id_ != 0) exception->vendor_id_ = entry->vendor_id_; - if (exception->contains_unknown_fields_) { - LOG(WARNING) << "Exception with unknown fields " << entry->id(); - entry->contains_unknown_fields_ = true; - } else { - entry->AddException(exception); - } + entry->AddException(exception); } dictionary_entry_count++; } @@ -802,7 +797,7 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue( if (value->size() != dictionary_entry_count) { LOG(WARNING) << "Entry with unknown fields " << entry->id(); - entry->contains_unknown_fields_ = true; + return NULL; } return entry; } @@ -812,9 +807,7 @@ GpuControlList::GpuControlListEntry::GpuControlListEntry() disabled_(false), vendor_id_(0), multi_gpu_style_(kMultiGpuStyleNone), - multi_gpu_category_(kMultiGpuCategoryPrimary), - contains_unknown_fields_(false), - contains_unknown_features_(false) { + multi_gpu_category_(kMultiGpuCategoryPrimary) { } GpuControlList::GpuControlListEntry::~GpuControlListEntry() { } @@ -999,10 +992,11 @@ bool GpuControlList::GpuControlListEntry::SetFeatures( features_.insert(iter->second); continue; } - if (StringToFeature(feature_strings[i], &feature, feature_map)) - features_.insert(feature); - else - contains_unknown_features_ = true; + if (!StringToFeature(feature_strings[i], &feature, feature_map)) { + features_.clear(); + return false; + } + features_.insert(feature); } return true; } @@ -1190,7 +1184,6 @@ bool GpuControlList::GpuControlListEntry::StringToFeature( GpuControlList::GpuControlList() : max_entry_id_(0), - contains_unknown_fields_(false), needs_more_info_(false), supports_feature_type_all_(false) { } @@ -1239,7 +1232,6 @@ bool GpuControlList::LoadList(const base::DictionaryValue& parsed_json, return false; uint32 max_entry_id = 0; - bool contains_unknown_fields = false; for (size_t i = 0; i < list->GetSize(); ++i) { const base::DictionaryValue* list_item = NULL; bool valid = list->GetDictionary(i, &list_item); @@ -1260,14 +1252,6 @@ bool GpuControlList::LoadList(const base::DictionaryValue& parsed_json, return false; if (entry->id() > max_entry_id) max_entry_id = entry->id(); - // If an unknown field is encountered, skip the entry; if an unknown - // feature is encountered, ignore the feature, but keep the entry. - if (entry->contains_unknown_fields()) { - contains_unknown_fields = true; - continue; - } - if (entry->contains_unknown_features()) - contains_unknown_fields = true; entries.push_back(entry); } @@ -1280,7 +1264,6 @@ bool GpuControlList::LoadList(const base::DictionaryValue& parsed_json, entries_.push_back(entries[i]); } max_entry_id_ = max_entry_id; - contains_unknown_fields_ = contains_unknown_fields; return true; } @@ -1390,7 +1373,6 @@ void GpuControlList::Clear() { entries_.clear(); active_entries_.clear(); max_entry_id_ = 0; - contains_unknown_fields_ = false; } GpuControlList::BrowserVersionSupport @@ -1403,8 +1385,8 @@ GpuControlList::IsEntrySupportedByCurrentBrowserVersion( std::string version_string; std::string version_string2; browser_version_value->GetString(kOp, &version_op); - browser_version_value->GetString("number", &version_string); - browser_version_value->GetString("number2", &version_string2); + browser_version_value->GetString("value", &version_string); + browser_version_value->GetString("value2", &version_string2); scoped_ptr<VersionInfo> browser_version_info; browser_version_info.reset(new VersionInfo( version_op, std::string(), version_string, version_string2)); diff --git a/chromium/gpu/config/gpu_control_list.h b/chromium/gpu/config/gpu_control_list.h index 62b66ec2782..ced3b525d2b 100644 --- a/chromium/gpu/config/gpu_control_list.h +++ b/chromium/gpu/config/gpu_control_list.h @@ -85,9 +85,6 @@ class GPU_EXPORT GpuControlList { // If yes, we should create a gl context and do a full gpu info collection. bool needs_more_info() const { return needs_more_info_; } - // Check if any entries contain unknown fields. This is only for tests. - bool contains_unknown_fields() const { return contains_unknown_fields_; } - // Returns the number of entries. This is only for tests. size_t num_entries() const; @@ -320,15 +317,6 @@ class GPU_EXPORT GpuControlList { // Returns the blacklisted features in this entry. const std::set<int>& features() const; - // Returns true if an unknown field is encountered. - bool contains_unknown_fields() const { - return contains_unknown_fields_; - } - // Returns true if an unknown blacklist feature is encountered. - bool contains_unknown_features() const { - return contains_unknown_features_; - } - private: friend class base::RefCounted<GpuControlListEntry>; @@ -457,8 +445,6 @@ class GPU_EXPORT GpuControlList { scoped_ptr<IntInfo> gpu_count_info_; std::set<int> features_; std::vector<ScopedGpuControlListEntry> exceptions_; - bool contains_unknown_fields_; - bool contains_unknown_features_; }; // Gets the current OS type. @@ -488,8 +474,6 @@ class GPU_EXPORT GpuControlList { uint32 max_entry_id_; - bool contains_unknown_fields_; - bool needs_more_info_; // The features a GpuControlList recognizes and handles. diff --git a/chromium/gpu/config/gpu_control_list_entry_unittest.cc b/chromium/gpu/config/gpu_control_list_entry_unittest.cc index 8991334f17c..63cf48eb34c 100644 --- a/chromium/gpu/config/gpu_control_list_entry_unittest.cc +++ b/chromium/gpu/config/gpu_control_list_entry_unittest.cc @@ -78,14 +78,14 @@ TEST_F(GpuControlListEntryTest, DetailedEntry) { "type": "macosx", "version": { "op": "=", - "number": "10.6.4" + "value": "10.6.4" } }, "vendor_id": "0x10de", "device_id": ["0x0640"], "driver_version": { "op": "=", - "number": "1.6.18" + "value": "1.6.18" }, "features": [ "test_feature_0" @@ -106,8 +106,6 @@ TEST_F(GpuControlListEntryTest, DetailedEntry) { EXPECT_EQ(1950, entry->webkit_bugs()[0]); EXPECT_EQ(1u, entry->features().size()); EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0)); - EXPECT_FALSE(entry->contains_unknown_fields()); - EXPECT_FALSE(entry->contains_unknown_features()); EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info())); EXPECT_TRUE(entry->Contains( GpuControlList::kOsMacosx, "10.6.4", gpu_info())); @@ -241,7 +239,7 @@ TEST_F(GpuControlListEntryTest, DateOnWindowsEntry) { }, "driver_date": { "op": "<", - "number": "2010.5.8" + "value": "2010.5.8" }, "features": [ "test_feature_0" @@ -343,9 +341,7 @@ TEST_F(GpuControlListEntryTest, UnknownFieldEntry) { } ); ScopedEntry entry(GetEntryFromString(json)); - EXPECT_TRUE(entry.get() != NULL); - EXPECT_TRUE(entry->contains_unknown_fields()); - EXPECT_FALSE(entry->contains_unknown_features()); + EXPECT_TRUE(entry.get() == NULL); } TEST_F(GpuControlListEntryTest, UnknownExceptionFieldEntry) { @@ -363,9 +359,7 @@ TEST_F(GpuControlListEntryTest, UnknownExceptionFieldEntry) { } ); ScopedEntry entry(GetEntryFromString(json)); - EXPECT_TRUE(entry.get() != NULL); - EXPECT_TRUE(entry->contains_unknown_fields()); - EXPECT_FALSE(entry->contains_unknown_features()); + EXPECT_TRUE(entry.get() == NULL); } TEST_F(GpuControlListEntryTest, UnknownFeatureEntry) { @@ -379,21 +373,7 @@ TEST_F(GpuControlListEntryTest, UnknownFeatureEntry) { } ); ScopedEntry entry(GetEntryFromString(json)); - EXPECT_TRUE(entry.get() != NULL); - EXPECT_FALSE(entry->contains_unknown_fields()); - EXPECT_TRUE(entry->contains_unknown_features()); - EXPECT_EQ(1u, entry->features().size()); - EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0)); - - const GpuControlList::OsType os_type[] = { - GpuControlList::kOsMacosx, - GpuControlList::kOsWin, - GpuControlList::kOsLinux, - GpuControlList::kOsChromeOS, - GpuControlList::kOsAndroid - }; - for (size_t i = 0; i < arraysize(os_type); ++i) - EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info())); + EXPECT_TRUE(entry.get() == NULL); } TEST_F(GpuControlListEntryTest, GlVendorEntry) { @@ -577,7 +557,7 @@ TEST_F(GpuControlListEntryTest, LexicalDriverVersionEntry) { "driver_version": { "op": "=", "style": "lexical", - "number": "8.76" + "value": "8.76" }, "features": [ "test_feature_0" @@ -677,7 +657,7 @@ TEST_F(GpuControlListEntryTest, NeedsMoreInfoEntry) { "vendor_id": "0x8086", "driver_version": { "op": "<", - "number": "10.7" + "value": "10.7" }, "features": [ "test_feature_1" diff --git a/chromium/gpu/config/gpu_control_list_format.txt b/chromium/gpu/config/gpu_control_list_format.txt new file mode 100644 index 00000000000..421bb1a2a18 --- /dev/null +++ b/chromium/gpu/config/gpu_control_list_format.txt @@ -0,0 +1,75 @@ +// Copyright (c) 2013 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. + +// A valid gpu control list json file is in the format of +// { +// "version": "x.y", +// "entries": [ +// { // entry 1 +// }, +// ... +// { // entry n +// } +// ] +// } +// +// Each entry contains the following fields (fields are optional unless +// specifically described as mandatory below): +// 1. "id" is an integer. 0 is reserved. This field is mandatory. +// 2. "os" contains "type" and an optional "version". "type" could be "macosx", +// "linux", "win", "chromeos", or "any". "any" is the same as not specifying +// "os". +// "version" is a VERSION structure (defined below). +// 3. "vendor_id" is a string. 0 is reserved. +// 4. "device_id" is an array of strings. 0 is reserved. +// 5. "multi_gpu_style" is a string, valid values include "optimus", and +// "amd_switchable". +// 6. "multi_gpu_category" is a string, valid values include "any", "primary", +// and "secondary". If unspecified, the default value is "primary". +// 7. "driver_vendor" is a STRING structure (defined below). +// 8. "driver_version" is a VERSION structure (defined below). +// 9. "driver_date" is a VERSION structure (defined below). +// The version is interpreted as "year.month.day". +// 10. "gl_vendor" is a STRING structure (defined below). +// 11. "gl_renderer" is a STRING structure (defined below). +// 12. "gl_extensions" is a STRING structure (defined below). +// 13. "perf_graphics" is a FLOAT structure (defined below). +// 14. "perf_gaming" is a FLOAT structure (defined below). +// 15. "perf_overall" is a FLOAT structure (defined below). +// 16. "machine_model" contais "name" and an optional "version". "name" is a +// STRING structure and "version" is a VERSION structure (defined below). +// 17. "gpu_count" is a INT structure (defined below). +// 18 "cpu_info" is a STRING structure (defined below). +// 19. "exceptions" is a list of entries. +// 20. "features" is a list of gpu control list options, which can be +// configured by a specific list. See its *_json.cc file for a list of +// supported features. This field is mandatory. +// 21. "description" has the description of the entry. +// 22. "webkit_bugs" is an array of associated webkit bug numbers. +// 23. "cr_bugs" is an array of associated webkit bug numbers. +// 24. "browser_version" is a VERSION structure (defined below). If this +// condition is not satisfied, the entry will be ignored. If it is not +// present, then the entry applies to all versions of the browser. +// 25. "disabled" is a boolean. If it is present, the entry will be skipped. +// This can not be used in exceptions. +// +// VERSION includes "op", "style", "value", and "value2". "op" can be any of +// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style" +// is optional and can be "lexical" or "numerical"; if it's not specified, it +// defaults to "numerical". "value2" is only used if "op" is "between". +// "between" is "value <= * <= value2". +// "value" is used for all "op" values except "any". "value" and "value2" +// are in the format of x, x.x, x.x.x, etc. +// Only "driver_version" supports lexical style if the format is major.minor; +// in that case, major is still numerical, but minor is lexical. +// +// STRING includes "op" and "value". "op" can be any of the following values: +// "contains", "beginwith", "endwith", "=". "value" is a string. +// +// FLOAT includes "op" "value", and "value2". "op" can be any of the +// following values: "=", "<", "<=", ">", ">=", "any", "between". "value2" is +// only used if "op" is "between". "value" is used for all "op" values except +// "any". "value" and "value2" are valid float numbers. +// INT is very much like FLOAT, except that the values need to be integers. + diff --git a/chromium/gpu/config/gpu_control_list_unittest.cc b/chromium/gpu/config/gpu_control_list_unittest.cc index f20e9bb7634..0113a8490df 100644 --- a/chromium/gpu/config/gpu_control_list_unittest.cc +++ b/chromium/gpu/config/gpu_control_list_unittest.cc @@ -110,14 +110,14 @@ TEST_F(GpuControlListTest, DetailedEntryAndInvalidJson) { "type": "macosx", "version": { "op": "=", - "number": "10.6.4" + "value": "10.6.4" } }, "vendor_id": "0x10de", "device_id": ["0x0640"], "driver_version": { "op": "=", - "number": "1.6.18" + "value": "1.6.18" }, "features": [ "test_feature_0" @@ -204,7 +204,7 @@ TEST_F(GpuControlListTest, ChromeVersionEntry) { "id": 1, "browser_version": { "op": ">=", - "number": "10" + "value": "10" }, "features": [ "test_feature_0" @@ -252,13 +252,8 @@ TEST_F(GpuControlListTest, UnknownField) { ); scoped_ptr<GpuControlList> control_list(Create()); - EXPECT_TRUE(control_list->LoadList( + EXPECT_FALSE(control_list->LoadList( unknown_field_json, GpuControlList::kAllOs)); - EXPECT_EQ(1u, control_list->num_entries()); - EXPECT_TRUE(control_list->contains_unknown_fields()); - std::set<int> features = control_list->MakeDecision( - GpuControlList::kOsWin, kOsVersion, gpu_info()); - EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0); } TEST_F(GpuControlListTest, UnknownExceptionField) { @@ -296,13 +291,8 @@ TEST_F(GpuControlListTest, UnknownExceptionField) { ); scoped_ptr<GpuControlList> control_list(Create()); - EXPECT_TRUE(control_list->LoadList( + EXPECT_FALSE(control_list->LoadList( unknown_exception_field_json, GpuControlList::kAllOs)); - EXPECT_EQ(1u, control_list->num_entries()); - EXPECT_TRUE(control_list->contains_unknown_fields()); - std::set<int> features = control_list->MakeDecision( - GpuControlList::kOsWin, kOsVersion, gpu_info()); - EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0); } TEST_F(GpuControlListTest, DisabledEntry) { @@ -420,7 +410,7 @@ TEST_F(GpuControlListTest, IgnorableEntries) { "vendor_id": "0x8086", "driver_version": { "op": "<", - "number": "10.7" + "value": "10.7" }, "features": [ "test_feature_0" @@ -457,14 +447,14 @@ TEST_F(GpuControlListTest, ExceptionWithoutVendorId) { "device_id": ["0x2a06"], "driver_version": { "op": ">=", - "number": "8.1" + "value": "8.1" } }, { "device_id": ["0x2a02"], "driver_version": { "op": ">=", - "number": "9.1" + "value": "9.1" } } ], diff --git a/chromium/gpu/config/gpu_driver_bug_list_json.cc b/chromium/gpu/config/gpu_driver_bug_list_json.cc index 7b2d8df827f..eacbe0503b8 100644 --- a/chromium/gpu/config/gpu_driver_bug_list_json.cc +++ b/chromium/gpu/config/gpu_driver_bug_list_json.cc @@ -3,76 +3,10 @@ // found in the LICENSE file. // Determines whether a certain driver bug exists in the current system. -// A valid gpu_driver_bug_list.json file are in the format of -// { -// "version": "x.y", -// "entries": [ -// { // entry 1 -// }, -// ... -// { // entry n -// } -// ] -// } -// -// Each entry contains the following fields (fields are optional unless -// specifically described as mandatory below): -// 1. "id" is an integer. 0 is reserved. This field is mandatory. -// 2. "os" contains "type" and an optional "version". "type" could be "macosx", -// "linux", "win", "chromeos", or "any". "any" is the same as not specifying -// "os". -// "version" is a VERSION structure (defined below). -// 3. "vendor_id" is a string. 0 is reserved. -// 4. "device_id" is an array of strings. 0 is reserved. -// 5. "multi_gpu_style" is a string, valid values include "optimus", and -// "amd_switchable". -// 6. "multi_gpu_category" is a string, valid values include "any", "primary", -// and "secondary". If unspecified, the default value is "primary". -// 7. "driver_vendor" is a STRING structure (defined below). -// 8. "driver_version" is a VERSION structure (defined below). -// 9. "driver_date" is a VERSION structure (defined below). -// The version is interpreted as "year.month.day". -// 10. "gl_vendor" is a STRING structure (defined below). -// 11. "gl_renderer" is a STRING structure (defined below). -// 12. "gl_extensions" is a STRING structure (defined below). -// 13. "perf_graphics" is a FLOAT structure (defined below). -// 14. "perf_gaming" is a FLOAT structure (defined below). -// 15. "perf_overall" is a FLOAT structure (defined below). -// 16. "machine_model" contains "name" and an optional "version". "name" is a -// STRING structure and "version" is a VERSION structure (defined below). -// 17. "gpu_count" is a INT structure (defined below). -// 18 "cpu_info" is a STRING structure (defined below). -// 19. "exceptions" is a list of entries. -// 20. "features" is a list of driver bug types. For a list of supported types, -// see src/gpu/command_buffer/service/gpu_driver_bug_workaround_type.h -// This field is mandatory. -// 21. "description" has the description of the entry. -// 22. "webkit_bugs" is an array of associated webkit bug numbers. -// 23. "cr_bugs" is an array of associated chromium bug numbers. -// 24. "browser_version" is a VERSION structure (defined below). If this -// condition is not satisfied, the entry will be ignored. If it is not -// present, then the entry applies to all versions of the browser. -// 25. "disabled" is a boolean. If it is present, the entry will be skipped. -// This can not be used in exceptions. -// -// VERSION includes "op", "style", "number", and "number2". "op" can be any of -// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style" -// is optional and can be "lexical" or "numerical"; if it's not specified, it -// defaults to "numerical". "number2" is only used if "op" is "between". -// "between" is "number <= * <= number2". -// "number" is used for all "op" values except "any". "number" and "number2" -// are in the format of x, x.x, x.x.x, etc. -// Only "driver_version" supports lexical style if the format is major.minor; -// in that case, major is still numerical, but minor is lexical. -// -// STRING includes "op" and "value". "op" can be any of the following values: -// "contains", "beginwith", "endwith", "=". "value" is a string. -// -// FLOAT includes "op" "value", and "value2". "op" can be any of the -// following values: "=", "<", "<=", ">", ">=", "any", "between". "value2" is -// only used if "op" is "between". "value" is used for all "op" values except -// "any". "value" and "value2" are valid float numbers. -// INT is very much like FLOAT, except that the values need to be integers. +// The format of a valid gpu_driver_bug_list.json file is defined in +// <gpu/config/gpu_control_list_format.txt>. +// The supported "features" can be found in +// <gpu/config/gpu_driver_bug_workaround_type.h>. #include "gpu/config/gpu_control_list_jsons.h" @@ -85,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "2.6", + "version": "2.22", "entries": [ { "id": 1, @@ -137,16 +71,20 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( }, { "id": 6, + "cr_bugs": [165493, 222018], "os": { - "type": "android" + "type": "android", + "version": { + "op": "<", + "value": "4.3" + } }, "gl_vendor": { "op": "beginwith", "value": "Qualcomm" }, "features": [ - "restore_scissor_on_fbo_change", - "delete_instead_of_resize_fbo" // Only need this on the ICS driver. + "restore_scissor_on_fbo_change" ] }, { @@ -178,7 +116,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.9" + "value": "10.9" } }, "vendor_id": "0x1002", @@ -194,7 +132,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.9" + "value": "10.9" } }, "vendor_id": "0x8086", @@ -228,7 +166,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.7.3" + "value": "10.7.3" } }, "vendor_id": "0x8086", @@ -394,7 +332,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.8" + "value": "10.8" } }, "vendor_id": "0x8086", @@ -404,9 +342,13 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( }, { "id": 26, - "description": "Disable use of Direct3D 11 on Windows", + "description": "Disable use of Direct3D 11 on Windows Vista and lower.", "os": { - "type": "win" + "type": "win", + "version": { + "op": "<=", + "value": "6.0" + } }, "features": [ "disable_d3d11" @@ -436,6 +378,247 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "features": [ "disable_angle_instanced_arrays" ] + }, + { + "id": 29, + "cr_bugs": [278606], + "description": "Testing fences is broken on QualComm.", + "os": { + "type": "android" + }, + "gl_vendor": { + "op": "beginwith", + "value": "Qualcomm" + }, + "features": [ + "disable_async_readpixels" + ] + }, + { + "id": 30, + "cr_bugs": [237931], + "description": "Multisampling is buggy on OSX when multiple monitors are connected", + "os": { + "type": "macosx" + }, + "features": [ + "disable_multimonitor_multisampling" + ] + }, + { + "id": 31, + "cr_bugs": [154715, 10068, 269829], + "description": "The Nexus 10 Mali driver does not guarantee flush ordering.", + "os": { + "type": "android" + }, + "gl_vendor": { + "op": "beginwith", + "value": "ARM" + }, + "gl_renderer": { + "op": "contains", + "value": "Mali-T604" + }, + "features": [ + "use_virtualized_gl_contexts" + ] + }, + { + "id": 32, + "cr_bugs": [179815], + "description": "Share groups are not working on (older?) Broadcom drivers.", + "os": { + "type": "android" + }, + "gl_vendor": { + "op": "beginwith", + "value": "Broadcom" + }, + "features": [ + "use_virtualized_gl_contexts" + ] + }, + { + "id": 33, + "description": "Share group-related crashes and poor context switching perf on Galaxy Nexus.", + "os": { + "type": "android" + }, + "gl_vendor": { + "op": "beginwith", + "value": "Imagination" + }, + "features": [ + "use_virtualized_gl_contexts" + ] + }, + { + "id": 34, + "cr_bugs": [179250, 229643, 230896], + "description": "Share groups are not working on (older?) Vivante drivers.", + "os": { + "type": "android" + }, + "gl_extensions": { + "op": "contains", + "value": "GL_VIV_shader_binary" + }, + "features": [ + "use_virtualized_gl_contexts" + ] + }, + { + "id": 35, + "cr_bugs": [163464], + "description": "Share-group related crashes on older NVIDIA drivers.", + "os": { + "type": "android", + "version": { + "op": "<", + "value": "4.3" + } + }, + "gl_vendor": { + "op": "beginwith", + "value": "NVIDIA" + }, + "features": [ + "use_virtualized_gl_contexts" + ] + }, + { + "id": 36, + "cr_bugs": [163464, 233612], + "description": "Share-group related crashes on Qualcomm drivers.", + "os": { + "type": "android", + "version": { + "op": "<", + "value": "4.3" + } + }, + "gl_vendor": { + "op": "beginwith", + "value": "Qualcomm" + }, + "features": [ + "use_virtualized_gl_contexts" + ] + }, + { + "id": 37, + "cr_bugs": [286468], + "description": "Program link fails in NVIDIA Linux if gl_Position is not set", + "os": { + "type": "linux" + }, + "vendor_id": "0x10de", + "features": [ + "init_gl_position_in_vertex_shader" + ] + }, + { + "id": 38, + "cr_bugs": [289461], + "description": "Non-virtual contexts on Qualcomm sometimes cause out-of-order frames", + "os": { + "type": "android" + }, + "gl_vendor": { + "op": "beginwith", + "value": "Qualcomm" + }, + "features": [ + "use_virtualized_gl_contexts" + ] + }, + { + "id": 39, + "cr_bugs": [290391], + "description": "Multisampled renderbuffer allocation must be validated on some Macs", + "os": { + "type": "macosx" + }, + "features": [ + "validate_multisample_buffer_allocation" + ] + }, + { + "id": 40, + "cr_bugs": [290876], + "description": "Framebuffer discarding causes flickering on ARM", + "os": { + "type": "android" + }, + "gl_vendor": { + "op": "beginwith", + "value": "ARM" + }, + "features": [ + "disable_ext_discard_framebuffer" + ] + }, + { + "id": 41, + "cr_bugs": [259978], + "description": "Intel D3D driver crashes when sharing surfaces between D3D9 and D3D11.", + "os": { + "type": "win" + }, + "vendor_id": "0x8086", + "driver_version": { + "op": ">=", + "value": "9.18.10.0" + }, + "features": [ + "disable_d3d11" + ] + }, + { + "id": 42, + "cr_bugs": [290876], + "description": "Framebuffer discarding causes flickering on older IMG drivers.", + "os": { + "type": "android" + }, + "gl_vendor": { + "op": "beginwith", + "value": "Imagination" + }, + "gl_renderer": { + "op": "=", + "value": "PowerVR SGX 540" + }, + "features": [ + "disable_ext_discard_framebuffer" + ] + }, + { + "id": 43, + "cr_bugs": [299494], + "description": "Framebuffer discarding doesn't accept trivial attachments on Vivante.", + "os": { + "type": "android" + }, + "gl_extensions": { + "op": "contains", + "value": "GL_VIV_shader_binary" + }, + "features": [ + "disable_ext_discard_framebuffer" + ] + }, + { + "id": 44, + "cr_bugs": [301988], + "description": "Framebuffer discarding causes jumpy scrolling on Mali drivers", + "os": { + "type": "chromeos" + }, + "features": [ + "disable_ext_discard_framebuffer" + ] } ] } diff --git a/chromium/gpu/config/gpu_driver_bug_list_unittest.cc b/chromium/gpu/config/gpu_driver_bug_list_unittest.cc index 60bc3392c8f..014c24efc16 100644 --- a/chromium/gpu/config/gpu_driver_bug_list_unittest.cc +++ b/chromium/gpu/config/gpu_driver_bug_list_unittest.cc @@ -50,7 +50,6 @@ TEST_F(GpuDriverBugListTest, CurrentDriverBugListValidation) { scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create()); std::string json; EXPECT_TRUE(list->LoadList(kGpuDriverBugListJson, GpuControlList::kAllOs)); - EXPECT_FALSE(list->contains_unknown_fields()); } TEST_F(GpuDriverBugListTest, CurrentListForARM) { diff --git a/chromium/gpu/config/gpu_driver_bug_workaround_type.h b/chromium/gpu/config/gpu_driver_bug_workaround_type.h index c9b19ac986c..e9b3524606e 100644 --- a/chromium/gpu/config/gpu_driver_bug_workaround_type.h +++ b/chromium/gpu/config/gpu_driver_bug_workaround_type.h @@ -14,22 +14,30 @@ clear_alpha_in_readpixels) \ GPU_OP(CLEAR_UNIFORMS_BEFORE_PROGRAM_USE, \ clear_uniforms_before_program_use) \ - GPU_OP(DELETE_INSTEAD_OF_RESIZE_FBO, \ - delete_instead_of_resize_fbo) \ GPU_OP(DISABLE_ANGLE_FRAMEBUFFER_MULTISAMPLE, \ disable_angle_framebuffer_multisample) \ + GPU_OP(DISABLE_ANGLE_INSTANCED_ARRAYS, \ + disable_angle_instanced_arrays) \ + GPU_OP(DISABLE_ASYNC_READPIXELS, \ + disable_async_readpixels) \ + GPU_OP(DISABLE_D3D11, \ + disable_d3d11) \ GPU_OP(DISABLE_DEPTH_TEXTURE, \ disable_depth_texture) \ GPU_OP(DISABLE_EXT_DRAW_BUFFERS, \ disable_ext_draw_buffers) \ GPU_OP(DISABLE_EXT_OCCLUSION_QUERY, \ disable_ext_occlusion_query) \ + GPU_OP(DISABLE_MULTIMONITOR_MULTISAMPLING, \ + disable_multimonitor_multisampling) \ GPU_OP(DISABLE_OES_STANDARD_DERIVATIVES, \ disable_oes_standard_derivatives) \ GPU_OP(ENABLE_CHROMIUM_FAST_NPOT_MO8_TEXTURES, \ enable_chromium_fast_npot_mo8_textures) \ GPU_OP(EXIT_ON_CONTEXT_LOST, \ exit_on_context_lost) \ + GPU_OP(INIT_GL_POSITION_IN_VERTEX_SHADER, \ + init_gl_position_in_vertex_shader) \ GPU_OP(MAX_CUBE_MAP_TEXTURE_SIZE_LIMIT_1024, \ max_cube_map_texture_size_limit_1024) \ GPU_OP(MAX_CUBE_MAP_TEXTURE_SIZE_LIMIT_4096, \ @@ -48,6 +56,8 @@ reverse_point_sprite_coord_origin) \ GPU_OP(SET_TEXTURE_FILTER_BEFORE_GENERATING_MIPMAP, \ set_texture_filter_before_generating_mipmap) \ + GPU_OP(SWIZZLE_RGBA_FOR_ASYNC_READPIXELS, \ + swizzle_rgba_for_async_readpixels) \ GPU_OP(UNBIND_FBO_ON_CONTEXT_SWITCH, \ unbind_fbo_on_context_switch) \ GPU_OP(USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS, \ @@ -56,14 +66,12 @@ use_current_program_after_successful_link) \ GPU_OP(USE_NON_ZERO_SIZE_FOR_CLIENT_SIDE_STREAM_BUFFERS, \ use_non_zero_size_for_client_side_stream_buffers) \ - GPU_OP(DISABLE_ASYNC_READPIXELS, \ - disable_async_readpixels) \ - GPU_OP(DISABLE_D3D11, \ - disable_d3d11) \ - GPU_OP(SWIZZLE_RGBA_FOR_ASYNC_READPIXELS, \ - swizzle_rgba_for_async_readpixels) \ - GPU_OP(DISABLE_ANGLE_INSTANCED_ARRAYS, \ - disable_angle_instanced_arrays) \ + GPU_OP(USE_VIRTUALIZED_GL_CONTEXTS, \ + use_virtualized_gl_contexts) \ + GPU_OP(VALIDATE_MULTISAMPLE_BUFFER_ALLOCATION, \ + validate_multisample_buffer_allocation) \ + GPU_OP(DISABLE_EXT_DISCARD_FRAMEBUFFER, \ + disable_ext_discard_framebuffer) \ namespace gpu { diff --git a/chromium/gpu/config/gpu_info.cc b/chromium/gpu/config/gpu_info.cc index 827c76c17ce..c3dc16f1a0f 100644 --- a/chromium/gpu/config/gpu_info.cc +++ b/chromium/gpu/config/gpu_info.cc @@ -4,6 +4,20 @@ #include "gpu/config/gpu_info.h" +namespace { + +void EnumerateGPUDevice(gpu::GPUInfo::Enumerator* enumerator, + const gpu::GPUInfo::GPUDevice& device) { + enumerator->BeginGPUDevice(); + enumerator->AddInt("vendorId", device.vendor_id); + enumerator->AddInt("deviceId", device.device_id); + enumerator->AddString("vendorString", device.vendor_string); + enumerator->AddString("deviceString", device.device_string); + enumerator->EndGPUDevice(); +} + +} // namespace + namespace gpu { GPUInfo::GPUDevice::GPUDevice() @@ -27,4 +41,89 @@ GPUInfo::GPUInfo() GPUInfo::~GPUInfo() { } +void GPUInfo::EnumerateFields(Enumerator* enumerator) const { + struct GPUInfoKnownFields { + bool finalized; + base::TimeDelta initialization_time; + bool optimus; + bool amd_switchable; + bool lenovo_dcute; + Version display_link_version; + GPUDevice gpu; + std::vector<GPUDevice> secondary_gpus; + uint64 adapter_luid; + std::string driver_vendor; + std::string driver_version; + std::string driver_date; + std::string pixel_shader_version; + std::string vertex_shader_version; + std::string machine_model; + std::string gl_version; + std::string gl_version_string; + std::string gl_vendor; + std::string gl_renderer; + std::string gl_extensions; + std::string gl_ws_vendor; + std::string gl_ws_version; + std::string gl_ws_extensions; + uint32 gl_reset_notification_strategy; + bool can_lose_context; + GpuPerformanceStats performance_stats; + bool software_rendering; + bool sandboxed; +#if defined(OS_WIN) + DxDiagNode dx_diagnostics; +#endif + }; + + // If this assert fails then most likely something below needs to be updated. + // Note that this assert is only approximate. If a new field is added to + // GPUInfo which fits within the current padding then it will not be caught. + COMPILE_ASSERT( + sizeof(GPUInfo) == sizeof(GPUInfoKnownFields), + Fields_Have_Changed_In_GPUInfo_So_Update_Below); + + // Required fields (according to DevTools protocol) first. + enumerator->AddString("machineModel", machine_model); + EnumerateGPUDevice(enumerator, gpu); + for (size_t ii = 0; ii < secondary_gpus.size(); ++ii) { + EnumerateGPUDevice(enumerator, secondary_gpus[ii]); + } + + enumerator->BeginAuxAttributes(); + enumerator->AddBool("finalized", finalized); + enumerator->AddTimeDeltaInSecondsF("initializationTime", + initialization_time); + enumerator->AddBool("optimus", optimus); + enumerator->AddBool("amdSwitchable", amd_switchable); + enumerator->AddBool("lenovoDcute", lenovo_dcute); + if (display_link_version.IsValid()) { + enumerator->AddString("displayLinkVersion", + display_link_version.GetString()); + } + enumerator->AddInt64("adapterLuid", adapter_luid); + enumerator->AddString("driverVendor", driver_vendor); + enumerator->AddString("driverVersion", driver_version); + enumerator->AddString("driverDate", driver_date); + enumerator->AddString("pixelShaderVersion", pixel_shader_version); + enumerator->AddString("vertexShaderVersion", vertex_shader_version); + enumerator->AddString("glVersion", gl_version); + enumerator->AddString("glVersionString", gl_version_string); + enumerator->AddString("glVendor", gl_vendor); + enumerator->AddString("glRenderer", gl_renderer); + enumerator->AddString("glExtensions", gl_extensions); + enumerator->AddString("glWsVendor", gl_ws_vendor); + enumerator->AddString("glWsVersion", gl_ws_version); + enumerator->AddString("glWsExtensions", gl_ws_extensions); + enumerator->AddInt( + "glResetNotificationStrategy", + static_cast<int>(gl_reset_notification_strategy)); + enumerator->AddBool("can_lose_context", can_lose_context); + // TODO(kbr): add performance_stats. + enumerator->AddBool("softwareRendering", software_rendering); + enumerator->AddBool("sandboxed", sandboxed); + // TODO(kbr): add dx_diagnostics on Windows. + enumerator->EndAuxAttributes(); +} + } // namespace gpu diff --git a/chromium/gpu/config/gpu_info.h b/chromium/gpu/config/gpu_info.h index 98ab80ca300..456f4e9d03b 100644 --- a/chromium/gpu/config/gpu_info.h +++ b/chromium/gpu/config/gpu_info.h @@ -140,6 +140,41 @@ struct GPU_EXPORT GPUInfo { // The information returned by the DirectX Diagnostics Tool. DxDiagNode dx_diagnostics; #endif + // Note: when adding new members, please remember to update EnumerateFields + // in gpu_info.cc. + + // In conjunction with EnumerateFields, this allows the embedder to + // enumerate the values in this structure without having to embed + // references to its specific member variables. This simplifies the + // addition of new fields to this type. + class Enumerator { + public: + // The following methods apply to the "current" object. Initially this + // is the root object, but calls to BeginGPUDevice/EndGPUDevice and + // BeginAuxAttributes/EndAuxAttributes change the object to which these + // calls should apply. + virtual void AddInt64(const char* name, int64 value) = 0; + virtual void AddInt(const char* name, int value) = 0; + virtual void AddString(const char* name, const std::string& value) = 0; + virtual void AddBool(const char* name, bool value) = 0; + virtual void AddTimeDeltaInSecondsF(const char* name, + const base::TimeDelta& value) = 0; + + // Markers indicating that a GPUDevice is being described. + virtual void BeginGPUDevice() = 0; + virtual void EndGPUDevice() = 0; + + // Markers indicating that "auxiliary" attributes of the GPUInfo + // (according to the DevTools protocol) are being described. + virtual void BeginAuxAttributes() = 0; + virtual void EndAuxAttributes() = 0; + + protected: + virtual ~Enumerator() {} + }; + + // Outputs the fields in this structure to the provided enumerator. + void EnumerateFields(Enumerator* enumerator) const; }; } // namespace gpu diff --git a/chromium/gpu/config/gpu_info_collector_x11.cc b/chromium/gpu/config/gpu_info_collector_x11.cc index a19ef9cd9ea..e0374fa907b 100644 --- a/chromium/gpu/config/gpu_info_collector_x11.cc +++ b/chromium/gpu/config/gpu_info_collector_x11.cc @@ -48,7 +48,7 @@ std::string CollectDriverVersionATI() { if (!base::PathExists(ati_file_path)) return std::string(); std::string contents; - if (!file_util::ReadFileToString(ati_file_path, &contents)) + if (!base::ReadFileToString(ati_file_path, &contents)) return std::string(); base::StringTokenizer t(contents, "\r\n"); while (t.GetNext()) { diff --git a/chromium/gpu/config/gpu_switching_list_json.cc b/chromium/gpu/config/gpu_switching_list_json.cc index 9916b020cbb..81a8d226493 100644 --- a/chromium/gpu/config/gpu_switching_list_json.cc +++ b/chromium/gpu/config/gpu_switching_list_json.cc @@ -3,76 +3,9 @@ // found in the LICENSE file. // Determines whether a certain gpu is prefered in a dual-gpu situation. -// A valid gpu_switching_list.json file are in the format of -// { -// "version": "x.y", -// "entries": [ -// { // entry 1 -// }, -// ... -// { // entry n -// } -// ] -// } -// -// Each entry contains the following fields (fields are optional unless -// specifically described as mandatory below): -// 1. "id" is an integer. 0 is reserved. This field is mandatory. -// 2. "os" contains "type" and an optional "version". "type" could be "macosx", -// "linux", "win", "chromeos", or "any". "any" is the same as not specifying -// "os". -// "version" is a VERSION structure (defined below). -// 3. "vendor_id" is a string. 0 is reserved. -// 4. "device_id" is an array of strings. 0 is reserved. -// 5. "multi_gpu_style" is a string, valid values include "optimus", and -// "amd_switchable". -// 6. "multi_gpu_category" is a string, valid values include "any", "primary", -// and "secondary". If unspecified, the default value is "primary". -// 7. "driver_vendor" is a STRING structure (defined below). -// 8. "driver_version" is a VERSION structure (defined below). -// 9. "driver_date" is a VERSION structure (defined below). -// The version is interpreted as "year.month.day". -// 10. "gl_vendor" is a STRING structure (defined below). -// 11. "gl_renderer" is a STRING structure (defined below). -// 12. "gl_extensions" is a STRING structure (defined below). -// 13. "perf_graphics" is a FLOAT structure (defined below). -// 14. "perf_gaming" is a FLOAT structure (defined below). -// 15. "perf_overall" is a FLOAT structure (defined below). -// 16. "machine_model" contais "name" and an optional "version". "name" is a -// STRING structure and "version" is a VERSION structure (defined below). -// 17. "gpu_count" is a INT structure (defined below). -// 18 "cpu_info" is a STRING structure (defined below). -// 19. "exceptions" is a list of entries. -// 20. "features" is a list of gpu switching options, including -// "force_discrete" and "force_integrated". -// This field is mandatory. -// 21. "description" has the description of the entry. -// 22. "webkit_bugs" is an array of associated webkit bug numbers. -// 23. "cr_bugs" is an array of associated webkit bug numbers. -// 24. "browser_version" is a VERSION structure (defined below). If this -// condition is not satisfied, the entry will be ignored. If it is not -// present, then the entry applies to all versions of the browser. -// 25. "disabled" is a boolean. If it is present, the entry will be skipped. -// This can not be used in exceptions. -// -// VERSION includes "op", "style", "number", and "number2". "op" can be any of -// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style" -// is optional and can be "lexical" or "numerical"; if it's not specified, it -// defaults to "numerical". "number2" is only used if "op" is "between". -// "between" is "number <= * <= number2". -// "number" is used for all "op" values except "any". "number" and "number2" -// are in the format of x, x.x, x.x.x, etc. -// Only "driver_version" supports lexical style if the format is major.minor; -// in that case, major is still numerical, but minor is lexical. -// -// STRING includes "op" and "value". "op" can be any of the following values: -// "contains", "beginwith", "endwith", "=". "value" is a string. -// -// FLOAT includes "op" "value", and "value2". "op" can be any of the -// following values: "=", "<", "<=", ">", ">=", "any", "between". "value2" is -// only used if "op" is "between". "value" is used for all "op" values except -// "any". "value" and "value2" are valid float numbers. -// INT is very much like FLOAT, except that the values need to be integers. +// The format of a valid gpu_switching_list.json file is defined in +// <gpu/config/gpu_control_list_format.txt>. +// The supported "features" can be found in <gpu/config/gpu_switching_list.cc>. #include "gpu/config/gpu_control_list_jsons.h" @@ -95,7 +28,7 @@ const char kGpuSwitchingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": ">=", - "number": "10.7" + "value": "10.7" } }, "machine_model": { @@ -105,7 +38,7 @@ const char kGpuSwitchingListJson[] = LONG_STRING_CONST( }, "version": { "op": "<", - "number": "8" + "value": "8" } }, "gpu_count": { diff --git a/chromium/gpu/config/gpu_switching_list_unittest.cc b/chromium/gpu/config/gpu_switching_list_unittest.cc index 78dc74d93f4..56d0f8fe28d 100644 --- a/chromium/gpu/config/gpu_switching_list_unittest.cc +++ b/chromium/gpu/config/gpu_switching_list_unittest.cc @@ -53,7 +53,6 @@ TEST_F(GpuSwitchingListTest, CurrentSwitchingListValidation) { scoped_ptr<GpuSwitchingList> switching_list(GpuSwitchingList::Create()); EXPECT_TRUE(switching_list->LoadList( kGpuSwitchingListJson, GpuControlList::kAllOs)); - EXPECT_FALSE(switching_list->contains_unknown_fields()); } TEST_F(GpuSwitchingListTest, GpuSwitching) { diff --git a/chromium/gpu/config/gpu_test_expectations_parser.cc b/chromium/gpu/config/gpu_test_expectations_parser.cc index c746bed89c8..83bb30008fd 100644 --- a/chromium/gpu/config/gpu_test_expectations_parser.cc +++ b/chromium/gpu/config/gpu_test_expectations_parser.cc @@ -191,7 +191,7 @@ bool GPUTestExpectationsParser::LoadTestExpectations( error_messages_.clear(); std::string data; - if (!file_util::ReadFileToString(path, &data)) { + if (!base::ReadFileToString(path, &data)) { error_messages_.push_back(kErrorMessage[kErrorFileIO]); return false; } diff --git a/chromium/gpu/config/software_rendering_list_json.cc b/chromium/gpu/config/software_rendering_list_json.cc index b7c5c539801..52567403343 100644 --- a/chromium/gpu/config/software_rendering_list_json.cc +++ b/chromium/gpu/config/software_rendering_list_json.cc @@ -3,80 +3,9 @@ // found in the LICENSE file. // Determines whether certain gpu-related features are blacklisted or not. -// A valid software_rendering_list.json file are in the format of -// { -// "version": "x.y", -// "entries": [ -// { // entry 1 -// }, -// ... -// { // entry n -// } -// ] -// } -// -// Each entry contains the following fields (fields are optional unless -// specifically described as mandatory below): -// 1. "id" is an integer. 0 is reserved. This field is mandatory. -// 2. "os" contains "type" and an optional "version". "type" could be "macosx", -// "linux", "win", "chromeos", or "any". "any" is the same as not specifying -// "os". -// "version" is a VERSION structure (defined below). -// 3. "vendor_id" is a string. 0 is reserved. -// 4. "device_id" is an array of strings. 0 is reserved. -// 5. "multi_gpu_style" is a string, valid values include "optimus", and -// "amd_switchable". -// 6. "multi_gpu_category" is a string, valid values include "any", "primary", -// and "secondary". If unspecified, the default value is "primary". -// 7. "driver_vendor" is a STRING structure (defined below). -// 8. "driver_version" is a VERSION structure (defined below). -// 9. "driver_date" is a VERSION structure (defined below). -// The version is interpreted as "year.month.day". -// 10. "gl_vendor" is a STRING structure (defined below). -// 11. "gl_renderer" is a STRING structure (defined below). -// 12. "gl_extensions" is a STRING structure (defined below). -// 13. "gl_reset_notification_strategy" is an INT structure (defined below). -// 14. "perf_graphics" is a FLOAT structure (defined below). -// 15. "perf_gaming" is a FLOAT structure (defined below). -// 16. "perf_overall" is a FLOAT structure (defined below). -// 17. "machine_model" contais "name" and an optional "version". "name" is a -// STRING structure and "version" is a VERSION structure (defined below). -// 18. "gpu_count" is a INT structure (defined below). -// 19 "cpu_info" is a STRING structure (defined below). -// 20. "exceptions" is a list of entries. -// 21. "features" is a list of gpu feature strings, valid values include -// "accelerated_2d_canvas", "accelerated_compositing", "webgl", -// "multisampling", "flash_3d", "flash_stage3d", "texture_sharing", -// "accelerated_video", "accelerated_video_decode", "panel_fitting", -// "force_compositing_mode", and "all". -// This field is mandatory. -// 22. "description" has the description of the entry. -// 23. "webkit_bugs" is an array of associated webkit bug numbers. -// 24. "cr_bugs" is an array of associated webkit bug numbers. -// 25. "browser_version" is a VERSION structure (defined below). If this -// condition is not satisfied, the entry will be ignored. If it is not -// present, then the entry applies to all versions of the browser. -// 26. "disabled" is a boolean. If it is present, the entry will be skipped. -// This can not be used in exceptions. -// -// VERSION includes "op", "style", "number", and "number2". "op" can be any of -// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style" -// is optional and can be "lexical" or "numerical"; if it's not specified, it -// defaults to "numerical". "number2" is only used if "op" is "between". -// "between" is "number <= * <= number2". -// "number" is used for all "op" values except "any". "number" and "number2" -// are in the format of x, x.x, x.x.x, etc. -// Only "driver_version" supports lexical style if the format is major.minor; -// in that case, major is still numerical, but minor is lexical. -// -// STRING includes "op" and "value". "op" can be any of the following values: -// "contains", "beginwith", "endwith", "=". "value" is a string. -// -// FLOAT includes "op" "value", and "value2". "op" can be any of the -// following values: "=", "<", "<=", ">", ">=", "any", "between". "value2" is -// only used if "op" is "between". "value" is used for all "op" values except -// "any". "value" and "value2" are valid float numbers. -// INT is very much like FLOAT, except that the values need to be integers. +// The format of a valid software_rendering_list.json file is defined in +// <gpu/config/gpu_control_list_format.txt>. +// The supported "features" can be found in <gpu/config/gpu_blacklist.cc>. #include "gpu/config/gpu_control_list_jsons.h" @@ -89,7 +18,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( { "name": "software rendering list", // Please update the version number whenever you change this file. - "version": "6.5", + "version": "6.11", "entries": [ { "id": 1, @@ -154,7 +83,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "driver_version": { "op": ">=", "style": "lexical", - "number": "8.98" + "value": "8.98" } } ], @@ -199,7 +128,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( }, "driver_date": { "op": "<", - "number": "2009.1" + "value": "2009.1" }, "exceptions": [ { @@ -207,7 +136,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "device_id": ["0x29a2"], "driver_version": { "op": ">=", - "number": "7.15.10.1624" + "value": "7.15.10.1624" } } ], @@ -218,6 +147,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "3d_css", "multisampling", "flash_3d", + "flash_stage3d", "force_compositing_mode" ] }, @@ -229,13 +159,13 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "5" + "value": "5" } }, "vendor_id": "0x1002", "driver_version": { "op": "<", - "number": "8.741" + "value": "8.741" }, "features": [ "accelerated_video", @@ -243,6 +173,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "3d_css", "multisampling", "flash_3d", + "flash_stage3d", "force_compositing_mode" ] }, @@ -254,13 +185,13 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "5" + "value": "5" } }, "vendor_id": "0x10de", "driver_version": { "op": "<", - "number": "6.14.12.5721" + "value": "6.14.12.5721" }, "features": [ "accelerated_video", @@ -268,6 +199,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "3d_css", "multisampling", "flash_3d", + "flash_stage3d", "force_compositing_mode" ] }, @@ -279,13 +211,13 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "5" + "value": "5" } }, "vendor_id": "0x8086", "driver_version": { "op": "<", - "number": "6.14.10.5294" + "value": "6.14.10.5294" }, "features": [ "accelerated_video", @@ -293,6 +225,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "3d_css", "multisampling", "flash_3d", + "flash_stage3d", "force_compositing_mode" ] }, @@ -304,7 +237,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.7.2" + "value": "10.7.2" } }, "vendor_id": "0x1002", @@ -325,28 +258,28 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "device_id": ["0x0102", "0x0106", "0x0112", "0x0116", "0x0122", "0x0126", "0x010a", "0x0152", "0x0156", "0x015a", "0x0162", "0x0166"], "driver_version": { "op": ">=", - "number": "8.0" + "value": "8.0" } }, { "device_id": ["0xa001", "0xa002", "0xa011", "0xa012", "0x29a2", "0x2992", "0x2982", "0x2972", "0x2a12", "0x2a42", "0x2e02", "0x2e12", "0x2e22", "0x2e32", "0x2e42", "0x2e92"], "driver_version": { "op": ">", - "number": "8.0.2" + "value": "8.0.2" } }, { "device_id": ["0x0042", "0x0046"], "driver_version": { "op": ">", - "number": "8.0.4" + "value": "8.0.4" } }, { "device_id": ["0x2a02"], "driver_version": { "op": ">=", - "number": "9.1" + "value": "9.1" } } ], @@ -375,7 +308,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "=", - "number": "10.5" + "value": "10.5" } }, "features": [ @@ -394,7 +327,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( }, "driver_version": { "op": "<", - "number": "7.11" + "value": "7.11" }, "features": [ "all" @@ -430,7 +363,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "driver_version": { "op": ">=", "style": "lexical", - "number": "8.98" + "value": "8.98" } } ], @@ -578,7 +511,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "=", - "number": "10.7" + "value": "10.7" } }, "vendor_id": "0x10de", @@ -595,7 +528,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "5" + "value": "5" } }, "features": [ @@ -604,17 +537,17 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( }, { "id": 42, - "description": "AMD Radeon HD 6490M on Snow Leopard is buggy.", - "cr_bugs": [137307], + "description": "AMD Radeon HD 6490M and 6970M on Snow Leopard are buggy.", + "cr_bugs": [137307, 285350], "os": { "type": "macosx", "version": { "op": "=", - "number": "10.6" + "value": "10.6" } }, "vendor_id": "0x1002", - "device_id": ["0x6760"], + "device_id": ["0x6760", "0x6720"], "features": [ "webgl" ] @@ -629,7 +562,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "vendor_id": "0x8086", "driver_version": { "op": "=", - "number": "8.15.10.1749" + "value": "8.15.10.1749" }, "features": [ "texture_sharing" @@ -643,8 +576,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "between", - "number": "10.7.0", - "number2": "10.7.4" + "value": "10.7.0", + "value2": "10.7.4" } }, "vendor_id": "0x8086", @@ -664,7 +597,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "vendor_id": "0x1ab8", "driver_version": { "op": "<", - "number": "7" + "value": "7" }, "features": [ "all" @@ -697,7 +630,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( }, "driver_version": { "op": "<", - "number": "295" + "value": "295" }, "features": [ "all" @@ -732,8 +665,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "between", - "number": "10.8.0", - "number2": "10.8.1" + "value": "10.8.0", + "value2": "10.8.1" } }, "multi_gpu_style": "optimus", @@ -767,13 +700,13 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "5" + "value": "5" } }, "vendor_id": "0x10de", "driver_version": { "op": "=", - "number": "6.14.11.9621" + "value": "6.14.11.9621" }, "features": [ "all" @@ -787,13 +720,13 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "5" + "value": "5" } }, "vendor_id": "0x10de", "driver_version": { "op": "=", - "number": "6.14.11.8267" + "value": "6.14.11.8267" }, "features": [ "all" @@ -818,7 +751,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( }, "driver_date": { "op": "<", - "number": "2007.1" + "value": "2007.1" }, "exceptions": [ { @@ -826,7 +759,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "device_id": ["0x29a2"], "driver_version": { "op": ">=", - "number": "7.15.10.1624" + "value": "7.15.10.1624" } } ], @@ -883,7 +816,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "vendor_id": "0x10de", "driver_version": { "op": "=", - "number": "8.15.11.8593" + "value": "8.15.11.8593" }, "features": [ "accelerated_video_decode" @@ -897,7 +830,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.8.3" + "value": "10.8.3" } }, "vendor_id": "0x10de", @@ -913,7 +846,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.8.3" + "value": "10.8.3" } }, "vendor_id": "0x8086", @@ -934,7 +867,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( }, "driver_version": { "op": "<", - "number": "4.1" + "value": "4.1" }, "features": [ "accelerated_2d_canvas" @@ -948,7 +881,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.8.3" + "value": "10.8.3" } }, "vendor_id": "0x1002", @@ -964,7 +897,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "<", - "number": "6.1" + "value": "6.1" } }, "features": [ @@ -979,10 +912,12 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "6.0" + "value": "6.0" } }, "features": [ + "flash_3d", + "flash_stage3d", "force_compositing_mode" ] }, @@ -994,7 +929,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.8" + "value": "10.8" } }, "features": [ @@ -1009,7 +944,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": "=", - "number": "5" + "value": "5" } }, "features": [ @@ -1024,13 +959,13 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "win", "version": { "op": ">=", - "number": "6.0" + "value": "6.0" } }, "vendor_id": "0x15ad", "driver_version": { "op": "<=", - "number": "7.14.1.1134" + "value": "7.14.1.1134" }, "features": [ "all" @@ -1046,7 +981,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "vendor_id": "0x10de", "driver_version": { "op": "=", - "number": "8.17.11.9621" + "value": "8.17.11.9621" }, "features": [ "flash_stage3d_baseline" @@ -1062,7 +997,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "vendor_id": "0x10de", "driver_version": { "op": "=", - "number": "8.17.11.8267" + "value": "8.17.11.8267" }, "features": [ "flash_stage3d_baseline" @@ -1078,7 +1013,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "vendor_id": "0x8086", "driver_version": { "op": "<", - "number": "8.15.10.2021" + "value": "8.15.10.2021" }, "features": [ "flash_stage3d_baseline" @@ -1105,7 +1040,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST( "type": "macosx", "version": { "op": "<", - "number": "10.8" + "value": "10.8" } }, "vendor_id": "0x10de", @@ -1160,6 +1095,40 @@ LONG_STRING_CONST( "features": [ "webgl" ] + }, + { + "id": 77, + "description": "Multisampling is reportedly very slow on Quadro NVS 135M/GeForce 8400M GS", + "cr_bugs": [279446], + "os": { + "type": "win", + "version": { + "op": "=", + "value": "5" + } + }, + "vendor_id": "0x10de", + "device_id": ["0x0429", "0x042b"], + "features": [ + "multisampling" + ] + }, + { + "id": 78, + "description": "Accelerated video decode interferes with GPU blacklist on older Intel drivers", + "cr_bugs": [180695], + "os": { + "type": "win" + }, + "vendor_id": "0x8086", + "driver_version": { + "op": "between", + "value": "8.15.10.1883", + "value2": "8.15.10.2702" + }, + "features": [ + "accelerated_video_decode" + ] } ] } diff --git a/chromium/gpu/gles2_conform_support/dummy.cc b/chromium/gpu/gles2_conform_support/dummy.cc new file mode 100644 index 00000000000..0ebcbbc5f53 --- /dev/null +++ b/chromium/gpu/gles2_conform_support/dummy.cc @@ -0,0 +1,7 @@ +// Copyright (c) 2013 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. + +// gles2_conform_test_windowless target contains only .c files, and it no +// longer links against libstdc++. We have to create this empty dummy.cc +// file and add it to the target. diff --git a/chromium/gpu/gles2_conform_support/egl/display.cc b/chromium/gpu/gles2_conform_support/egl/display.cc index 66934bb9010..87bd809ab1d 100644 --- a/chromium/gpu/gles2_conform_support/egl/display.cc +++ b/chromium/gpu/gles2_conform_support/egl/display.cc @@ -165,7 +165,6 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, gl_surface_->IsOffscreen(), size, gpu::gles2::DisallowedFeatures(), - NULL, attribs)) { return EGL_NO_SURFACE; } @@ -234,7 +233,8 @@ EGLContext Display::CreateContext(EGLConfig config, if (!context_->Initialize( kTransferBufferSize, kTransferBufferSize / 2, - kTransferBufferSize * 2)) { + kTransferBufferSize * 2, + gpu::gles2::GLES2Implementation::kNoLimit)) { return EGL_NO_CONTEXT; } diff --git a/chromium/gpu/gpu_common.gypi b/chromium/gpu/gpu_common.gypi index da2be68476b..015d9c6e337 100644 --- a/chromium/gpu/gpu_common.gypi +++ b/chromium/gpu/gpu_common.gypi @@ -39,7 +39,6 @@ 'command_buffer/client/gpu_memory_buffer_factory.h', 'command_buffer/client/gpu_memory_buffer_tracker.cc', 'command_buffer/client/gpu_memory_buffer_tracker.h', - 'command_buffer/client/image_factory.h', 'command_buffer/client/program_info_manager.cc', 'command_buffer/client/program_info_manager.h', 'command_buffer/client/query_tracker.cc', diff --git a/chromium/gpu/gpu_untrusted.gyp b/chromium/gpu/gpu_untrusted.gyp index a1f755cc89b..7974d12c5d7 100644 --- a/chromium/gpu/gpu_untrusted.gyp +++ b/chromium/gpu/gpu_untrusted.gyp @@ -22,7 +22,7 @@ 'nacl_untrusted_build': 1, 'nlib_target': 'libgles2_implementation_untrusted.a', 'build_glibc': 0, - 'build_newlib': 1, + 'build_newlib': 0, 'build_irt': 1, }, 'defines': [ @@ -46,7 +46,7 @@ 'nacl_untrusted_build': 1, 'nlib_target': 'libcommand_buffer_common_untrusted.a', 'build_glibc': 0, - 'build_newlib': 1, + 'build_newlib': 0, 'build_irt': 1, }, 'includes': [ @@ -65,7 +65,7 @@ 'nacl_untrusted_build': 1, 'nlib_target': 'libgles2_cmd_helper_untrusted.a', 'build_glibc': 0, - 'build_newlib': 1, + 'build_newlib': 0, 'build_irt': 1, }, 'includes': [ @@ -84,7 +84,7 @@ 'nacl_untrusted_build': 1, 'nlib_target': 'libcommand_buffer_client_untrusted.a', 'build_glibc': 0, - 'build_newlib': 1, + 'build_newlib': 0, 'build_irt': 1, }, 'includes': [ @@ -103,7 +103,7 @@ 'nacl_untrusted_build': 1, 'nlib_target': 'libgpu_ipc_untrusted.a', 'build_glibc': 0, - 'build_newlib': 1, + 'build_newlib': 0, 'build_irt': 1, }, 'includes': [ diff --git a/chromium/gpu/tools/compositor_model_bench/render_tree.cc b/chromium/gpu/tools/compositor_model_bench/render_tree.cc index 2e231860928..8473a3c0657 100644 --- a/chromium/gpu/tools/compositor_model_bench/render_tree.cc +++ b/chromium/gpu/tools/compositor_model_bench/render_tree.cc @@ -20,7 +20,7 @@ using base::JSONReader; using base::JSONWriter; using base::Value; -using file_util::ReadFileToString; +using base::ReadFileToString; using std::string; using std::vector; |