diff options
author | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-12 00:31:58 +0000 |
---|---|---|
committer | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-12 00:31:58 +0000 |
commit | 60f22d35af1bcf81ebe4e2c69bc7415379721d9d (patch) | |
tree | c3f5f7fc7a2b966cb173850ab305c8793986f16c /gpu | |
parent | a14c9b9ae0e15becb11dc2a7e8940722a00374af (diff) | |
download | chromium_src-60f22d35af1bcf81ebe4e2c69bc7415379721d9d.zip chromium_src-60f22d35af1bcf81ebe4e2c69bc7415379721d9d.tar.gz chromium_src-60f22d35af1bcf81ebe4e2c69bc7415379721d9d.tar.bz2 |
Plumb glDiscardFramebufferEXT entry point through command buffer
BUG=
Review URL: https://chromiumcodereview.appspot.com/11465018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@172468 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
29 files changed, 450 insertions, 34 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index a6da12a..88ac0cf 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -730,6 +730,14 @@ _ENUM_LISTS = { 'GL_STENCIL_ATTACHMENT', ], }, + 'BackbufferAttachment': { + 'type': 'GLenum', + 'valid': [ + 'GL_COLOR_EXT', + 'GL_DEPTH_EXT', + 'GL_STENCIL_EXT', + ], + }, 'BufferParameter': { 'type': 'GLenum', 'valid': [ @@ -2269,6 +2277,17 @@ _FUNCTION_INFO = { 'extension': True, 'chromium': True, }, + 'DiscardFramebufferEXT': { + 'type': 'PUTn', + 'count': 1, + 'data_type': 'GLenum', + 'cmd_args': 'GLenum target, GLsizei count, ' + 'const GLenum* attachments', + 'decoder_func': 'DoDiscardFramebufferEXT', + 'unit_test': False, + 'client_test': False, + 'extension': True, + }, } diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 6a4ad9c..b4d8e0f 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -711,6 +711,10 @@ void GLES2AsyncTexImage2DCHROMIUM( target, level, internalformat, width, height, border, format, type, pixels); } +void GLES2DiscardFramebufferEXT( + GLenum target, GLsizei count, const GLenum* attachments) { + gles2::GetGLContext()->DiscardFramebufferEXT(target, count, attachments); +} namespace gles2 { @@ -1042,6 +1046,8 @@ NameToFunc g_gles2_function_table[] = { glAsyncTexSubImage2DCHROMIUM), }, { "glAsyncTexImage2DCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( glAsyncTexImage2DCHROMIUM), }, + { "glDiscardFramebufferEXT", reinterpret_cast<GLES2FunctionPointer>( + glDiscardFramebufferEXT), }, { NULL, NULL, }, }; diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 26e703b..66a5c8a5 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1958,5 +1958,27 @@ } } + void DiscardFramebufferEXT( + GLenum target, GLsizei count, uint32 attachments_shm_id, + uint32 attachments_shm_offset) { + gles2::DiscardFramebufferEXT* c = + GetCmdSpace<gles2::DiscardFramebufferEXT>(); + if (c) { + c->Init(target, count, attachments_shm_id, attachments_shm_offset); + } + } + + void DiscardFramebufferEXTImmediate( + GLenum target, GLsizei count, const GLenum* attachments) { + const uint32 size = + gles2::DiscardFramebufferEXTImmediate::ComputeSize(count); + gles2::DiscardFramebufferEXTImmediate* c = + GetImmediateCmdSpaceTotalSize<gles2::DiscardFramebufferEXTImmediate>( + size); + if (c) { + c->Init(target, count, attachments); + } + } + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index db4ded8..b0ed75f 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -519,5 +519,8 @@ virtual void AsyncTexImage2DCHROMIUM( GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) OVERRIDE; +virtual void DiscardFramebufferEXT( + GLenum target, GLsizei count, const GLenum* attachments) OVERRIDE; + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 93af490..fdedf43 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -1679,5 +1679,21 @@ void GLES2Implementation::TraceEndCHROMIUM() { CheckGLError(); } +void GLES2Implementation::DiscardFramebufferEXT( + GLenum target, GLsizei count, const GLenum* attachments) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDiscardFramebufferEXT(" << GLES2Util::GetStringEnum(target) << ", " << count << ", " << static_cast<const void*>(attachments) << ")"); // NOLINT + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < count; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << attachments[0 + i * 1]); + } + }); + if (count < 0) { + SetGLError(GL_INVALID_VALUE, "glDiscardFramebufferEXT", "count < 0"); + return; + } + helper_->DiscardFramebufferEXTImmediate(target, count, attachments); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_IMPL_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index b75123f..f23a512 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -1769,5 +1769,22 @@ TEST_F(GLES2ImplementationTest, TraceEndCHROMIUM) { gl_->TraceEndCHROMIUM(); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } + +TEST_F(GLES2ImplementationTest, DiscardFramebufferEXT) { + struct Cmds { + DiscardFramebufferEXTImmediate cmd; + GLenum data[2][1]; + }; + + Cmds expected; + for (int ii = 0; ii < 2; ++ii) { + for (int jj = 0; jj < 1; ++jj) { + expected.data[ii][jj] = static_cast<GLenum>(ii * 1 + jj); + } + } + expected.cmd.Init(1, 2, &expected.data[0][0]); + gl_->DiscardFramebufferEXT(1, 2, &expected.data[0][0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_UNITTEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index aed2cc9..163361d 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -299,5 +299,7 @@ virtual void AsyncTexImage2DCHROMIUM( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) = 0; +virtual void DiscardFramebufferEXT( + GLenum target, GLsizei count, const GLenum* attachments) = 0; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 3ac1250..f3d51d8 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -331,5 +331,7 @@ virtual void AsyncTexImage2DCHROMIUM( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) OVERRIDE; +virtual void DiscardFramebufferEXT( + GLenum target, GLsizei count, const GLenum* attachments) OVERRIDE; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 60c22b2..cf516e3 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -623,5 +623,9 @@ void GLES2InterfaceStub::AsyncTexImage2DCHROMIUM( GLsizei /* width */, GLsizei /* height */, GLint /* border */, GLenum /* format */, GLenum /* type */, const void* /* pixels */) { } +void GLES2InterfaceStub::DiscardFramebufferEXT( + GLenum /* target */, GLsizei /* count */, + const GLenum* /* attachments */) { +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_IMPL_AUTOGEN_H_ diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 75167d5..fb53030 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt @@ -205,3 +205,4 @@ GL_APICALL void GL_APIENTRY glTraceBeginCHROMIUM (const char* name); GL_APICALL void GL_APIENTRY glTraceEndCHROMIUM (void); GL_APICALL void GL_APIENTRY glAsyncTexSubImage2DCHROMIUM (GLenumTextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenumTextureFormat format, GLenumPixelType type, const void* data); GL_APICALL void GL_APIENTRY glAsyncTexImage2DCHROMIUM (GLenumTextureTarget target, GLint level, GLintTextureInternalFormat internalformat, GLsizei width, GLsizei height, GLintTextureBorder border, GLenumTextureFormat format, GLenumPixelType type, const void* pixels); +GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei count, const GLenum* attachments); diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 3d291c0..d7e887d 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -10730,6 +10730,106 @@ COMPILE_ASSERT(offsetof(AsyncTexImage2DCHROMIUM, pixels_shm_id) == 36, COMPILE_ASSERT(offsetof(AsyncTexImage2DCHROMIUM, pixels_shm_offset) == 40, OffsetOf_AsyncTexImage2DCHROMIUM_pixels_shm_offset_not_40); +struct DiscardFramebufferEXT { + typedef DiscardFramebufferEXT ValueType; + static const CommandId kCmdId = kDiscardFramebufferEXT; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init( + GLenum _target, GLsizei _count, uint32 _attachments_shm_id, + uint32 _attachments_shm_offset) { + SetHeader(); + target = _target; + count = _count; + attachments_shm_id = _attachments_shm_id; + attachments_shm_offset = _attachments_shm_offset; + } + + void* Set( + void* cmd, GLenum _target, GLsizei _count, uint32 _attachments_shm_id, + uint32 _attachments_shm_offset) { + static_cast<ValueType*>( + cmd)->Init( + _target, _count, _attachments_shm_id, _attachments_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 target; + int32 count; + uint32 attachments_shm_id; + uint32 attachments_shm_offset; +}; + +COMPILE_ASSERT(sizeof(DiscardFramebufferEXT) == 20, + Sizeof_DiscardFramebufferEXT_is_not_20); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXT, header) == 0, + OffsetOf_DiscardFramebufferEXT_header_not_0); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXT, target) == 4, + OffsetOf_DiscardFramebufferEXT_target_not_4); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXT, count) == 8, + OffsetOf_DiscardFramebufferEXT_count_not_8); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXT, attachments_shm_id) == 12, + OffsetOf_DiscardFramebufferEXT_attachments_shm_id_not_12); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXT, attachments_shm_offset) == 16, + OffsetOf_DiscardFramebufferEXT_attachments_shm_offset_not_16); + +struct DiscardFramebufferEXTImmediate { + typedef DiscardFramebufferEXTImmediate ValueType; + static const CommandId kCmdId = kDiscardFramebufferEXTImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + + static uint32 ComputeDataSize(GLsizei count) { + return static_cast<uint32>( + sizeof(GLenum) * 1 * count); // NOLINT + } + + static uint32 ComputeSize(GLsizei count) { + return static_cast<uint32>( + sizeof(ValueType) + ComputeDataSize(count)); // NOLINT + } + + void SetHeader(GLsizei count) { + header.SetCmdByTotalSize<ValueType>(ComputeSize(count)); + } + + void Init(GLenum _target, GLsizei _count, const GLenum* _attachments) { + SetHeader(_count); + target = _target; + count = _count; + memcpy(ImmediateDataAddress(this), + _attachments, ComputeDataSize(_count)); + } + + void* Set( + void* cmd, GLenum _target, GLsizei _count, const GLenum* _attachments) { + static_cast<ValueType*>(cmd)->Init(_target, _count, _attachments); + const uint32 size = ComputeSize(_count); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + uint32 target; + int32 count; +}; + +COMPILE_ASSERT(sizeof(DiscardFramebufferEXTImmediate) == 12, + Sizeof_DiscardFramebufferEXTImmediate_is_not_12); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXTImmediate, header) == 0, + OffsetOf_DiscardFramebufferEXTImmediate_header_not_0); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXTImmediate, target) == 4, + OffsetOf_DiscardFramebufferEXTImmediate_target_not_4); +COMPILE_ASSERT(offsetof(DiscardFramebufferEXTImmediate, count) == 8, + OffsetOf_DiscardFramebufferEXTImmediate_count_not_8); + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 55009c2..54795a7 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -4318,5 +4318,51 @@ TEST_F(GLES2FormatTest, AsyncTexImage2DCHROMIUM) { next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, DiscardFramebufferEXT) { + DiscardFramebufferEXT& cmd = *GetBufferAs<DiscardFramebufferEXT>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<GLsizei>(12), + static_cast<uint32>(13), + static_cast<uint32>(14)); + EXPECT_EQ(static_cast<uint32>(DiscardFramebufferEXT::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLsizei>(12), cmd.count); + EXPECT_EQ(static_cast<uint32>(13), cmd.attachments_shm_id); + EXPECT_EQ(static_cast<uint32>(14), cmd.attachments_shm_offset); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, DiscardFramebufferEXTImmediate) { + const int kSomeBaseValueToTestWith = 51; + static GLenum data[] = { + static_cast<GLenum>(kSomeBaseValueToTestWith + 0), + static_cast<GLenum>(kSomeBaseValueToTestWith + 1), + }; + DiscardFramebufferEXTImmediate& cmd = + *GetBufferAs<DiscardFramebufferEXTImmediate>(); + const GLsizei kNumElements = 2; + const size_t kExpectedCmdSize = + sizeof(cmd) + kNumElements * sizeof(GLenum) * 1; + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(1), + static_cast<GLsizei>(2), + data); + EXPECT_EQ(static_cast<uint32>(DiscardFramebufferEXTImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(kExpectedCmdSize, cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(1), cmd.target); + EXPECT_EQ(static_cast<GLsizei>(2), cmd.count); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd) + + RoundSizeToMultipleOfEntries(sizeof(data))); + // TODO(gman): Check that data was inserted; +} + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 70925cd..0a7a577 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -245,6 +245,8 @@ OP(TraceEndCHROMIUM) /* 488 */ \ OP(AsyncTexSubImage2DCHROMIUM) /* 489 */ \ OP(AsyncTexImage2DCHROMIUM) /* 490 */ \ + OP(DiscardFramebufferEXT) /* 491 */ \ + OP(DiscardFramebufferEXTImmediate) /* 492 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h index bc004e8..b2d155c 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h @@ -10,6 +10,7 @@ #define GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_UTILS_AUTOGEN_H_ static std::string GetStringAttachment(uint32 value); +static std::string GetStringBackbufferAttachment(uint32 value); static std::string GetStringBlitFilter(uint32 value); static std::string GetStringBufferParameter(uint32 value); static std::string GetStringBufferTarget(uint32 value); diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index a358e7b..c17da70 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -680,6 +680,16 @@ std::string GLES2Util::GetStringAttachment(uint32 value) { string_table, arraysize(string_table), value); } +std::string GLES2Util::GetStringBackbufferAttachment(uint32 value) { + static EnumToString string_table[] = { + { GL_COLOR_EXT, "GL_COLOR_EXT" }, + { GL_DEPTH_EXT, "GL_DEPTH_EXT" }, + { GL_STENCIL_EXT, "GL_STENCIL_EXT" }, + }; + return GLES2Util::GetQualifiedEnumString( + string_table, arraysize(string_table), value); +} + std::string GLES2Util::GetStringBlitFilter(uint32 value) { static EnumToString string_table[] = { { GL_NEAREST, "GL_NEAREST" }, diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc index 0d73f96..95d225a 100644 --- a/gpu/command_buffer/service/framebuffer_manager.cc +++ b/gpu/command_buffer/service/framebuffer_manager.cc @@ -50,8 +50,9 @@ class RenderbufferAttachment virtual void SetCleared( RenderbufferManager* renderbuffer_manager, - TextureManager* /* texture_manager */) OVERRIDE { - renderbuffer_manager->SetCleared(renderbuffer_); + TextureManager* /* texture_manager */, + bool cleared) OVERRIDE { + renderbuffer_manager->SetCleared(renderbuffer_, cleared); } virtual bool IsTexture( @@ -139,8 +140,9 @@ class TextureAttachment virtual void SetCleared( RenderbufferManager* /* renderbuffer_manager */, - TextureManager* texture_manager) OVERRIDE { - texture_manager->SetLevelCleared(texture_, target_, level_); + TextureManager* texture_manager, + bool cleared) OVERRIDE { + texture_manager->SetLevelCleared(texture_, target_, level_, cleared); } virtual bool IsTexture(TextureManager::TextureInfo* texture) const OVERRIDE { @@ -273,14 +275,31 @@ bool FramebufferManager::FramebufferInfo::HasUnclearedAttachment( return false; } +void FramebufferManager::FramebufferInfo::MarkAttachmentAsCleared( + RenderbufferManager* renderbuffer_manager, + TextureManager* texture_manager, + GLenum attachment, + bool cleared) { + AttachmentMap::iterator it = attachments_.find(attachment); + if (it != attachments_.end()) { + Attachment* a = it->second; + if (a->cleared() != cleared) { + a->SetCleared(renderbuffer_manager, + texture_manager, + cleared); + } + } +} + void FramebufferManager::FramebufferInfo::MarkAttachmentsAsCleared( RenderbufferManager* renderbuffer_manager, - TextureManager* texture_manager) { + TextureManager* texture_manager, + bool cleared) { for (AttachmentMap::iterator it = attachments_.begin(); it != attachments_.end(); ++it) { Attachment* attachment = it->second; - if (!attachment->cleared()) { - attachment->SetCleared(renderbuffer_manager, texture_manager); + if (attachment->cleared() != cleared) { + attachment->SetCleared(renderbuffer_manager, texture_manager, cleared); } } } @@ -496,7 +515,9 @@ void FramebufferManager::MarkAttachmentsAsCleared( RenderbufferManager* renderbuffer_manager, TextureManager* texture_manager) { DCHECK(framebuffer); - framebuffer->MarkAttachmentsAsCleared(renderbuffer_manager, texture_manager); + framebuffer->MarkAttachmentsAsCleared(renderbuffer_manager, + texture_manager, + true); MarkAsComplete(framebuffer); } diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h index 80cf428..7d04948 100644 --- a/gpu/command_buffer/service/framebuffer_manager.h +++ b/gpu/command_buffer/service/framebuffer_manager.h @@ -37,7 +37,8 @@ class GPU_EXPORT FramebufferManager { virtual bool cleared() const = 0; virtual void SetCleared( RenderbufferManager* renderbuffer_manager, - TextureManager* texture_manager) = 0; + TextureManager* texture_manager, + bool cleared) = 0; virtual bool IsTexture(TextureManager::TextureInfo* texture) const = 0; virtual bool IsRenderbuffer( RenderbufferManager::RenderbufferInfo* renderbuffer) const = 0; @@ -60,6 +61,12 @@ class GPU_EXPORT FramebufferManager { bool HasUnclearedAttachment(GLenum attachment) const; + void MarkAttachmentAsCleared( + RenderbufferManager* renderbuffer_manager, + TextureManager* texture_manager, + GLenum attachment, + bool cleared); + // Attaches a renderbuffer to a particlar attachment. // Pass null to detach. void AttachRenderbuffer( @@ -123,7 +130,8 @@ class GPU_EXPORT FramebufferManager { void MarkAttachmentsAsCleared( RenderbufferManager* renderbuffer_manager, - TextureManager* texture_manager); + TextureManager* texture_manager, + bool cleared); void MarkAsComplete(unsigned state_id) { framebuffer_complete_state_count_id_ = state_id; diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc index a32e197..c817da4 100644 --- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -283,7 +283,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { ASSERT_TRUE(rb_info3 != NULL); renderbuffer_manager_.SetInfo( rb_info3, kSamples3, kFormat3, kWidth3, kHeight3); - renderbuffer_manager_.SetCleared(rb_info3); + renderbuffer_manager_.SetCleared(rb_info3, true); info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, rb_info3); EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT)); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index d7f7dec..54c95eb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1119,6 +1119,12 @@ class GLES2DecoderImpl : public GLES2Decoder { // Wrapper for glDisableVertexAttribArray. void DoDisableVertexAttribArray(GLuint index); + // Wrapper for glDiscardFramebufferEXT, since we need to track undefined + // attachments. + void DoDiscardFramebufferEXT(GLenum target, + GLsizei numAttachments, + const GLenum* attachments); + // Wrapper for glEnable void DoEnable(GLenum cap); @@ -1596,6 +1602,9 @@ class GLES2DecoderImpl : public GLES2Decoder { bool back_buffer_has_depth_; bool back_buffer_has_stencil_; + // Backbuffer attachments that are currently undefined. + uint32 backbuffer_needs_clear_bits_; + bool teximage2d_faster_than_texsubimage2d_; // The last error message set. @@ -2030,6 +2039,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) back_buffer_color_format_(0), back_buffer_has_depth_(false), back_buffer_has_stencil_(false), + backbuffer_needs_clear_bits_(0), teximage2d_faster_than_texsubimage2d_(true), log_message_count_(0), current_decoder_error_(error::kNoError), @@ -2698,6 +2708,19 @@ bool GLES2DecoderImpl::CheckFramebufferValid( FramebufferManager::FramebufferInfo* framebuffer, GLenum target, const char* func_name) { if (!framebuffer) { + if (backbuffer_needs_clear_bits_) { + glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat( + offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClearStencil(0); + glStencilMask(-1); + glClearDepth(1.0f); + glDepthMask(true); + glDisable(GL_SCISSOR_TEST); + glClear(backbuffer_needs_clear_bits_); + backbuffer_needs_clear_bits_ = 0; + RestoreClearState(); + } return true; } @@ -3632,6 +3655,53 @@ void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) { } } +void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, + GLsizei numAttachments, + const GLenum* attachments) { + FramebufferManager::FramebufferInfo* framebuffer = + GetFramebufferInfoForTarget(GL_FRAMEBUFFER); + + // Validates the attachments. If one of them fails + // the whole command fails. + for (GLsizei i = 0; i < numAttachments; ++i) { + if ((framebuffer && + !validators_->attachment.IsValid(attachments[i])) || + (!framebuffer && + !validators_->backbuffer_attachment.IsValid(attachments[i]))) { + SetGLErrorInvalidEnum("glDiscardFramebufferEXT", + attachments[i], + "attachments"); + return; + } + } + + // Marks each one of them as not cleared + for (GLsizei i = 0; i < numAttachments; ++i) { + if (framebuffer) { + framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(), + texture_manager(), + attachments[i], + false); + } else { + switch (attachments[i]) { + case GL_COLOR_EXT: + backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT; + break; + case GL_DEPTH_EXT: + backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT; + case GL_STENCIL_EXT: + backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT; + break; + default: + NOTREACHED(); + break; + } + } + } + + glDiscardFramebufferEXT(target, numAttachments, attachments); +} + void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { if (state_.vertex_attrib_manager->Enable(index, true)) { glEnableVertexAttribArray(index); @@ -7536,7 +7606,7 @@ void GLES2DecoderImpl::DoTexImage2D( if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) { glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels); - texture_manager()->SetLevelCleared(info, target, level); + texture_manager()->SetLevelCleared(info, target, level, true); tex_image_2d_failed_ = false; return; } @@ -8004,7 +8074,7 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( glTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, data); } - texture_manager()->SetLevelCleared(info, target, level); + texture_manager()->SetLevelCleared(info, target, level, true); return error::kNoError; } @@ -9253,7 +9323,7 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( dest_info, GL_TEXTURE_2D, level, internal_format, source_width, source_height, 1, 0, internal_format, dest_type, true); } else { - texture_manager()->SetLevelCleared(dest_info, GL_TEXTURE_2D, level); + texture_manager()->SetLevelCleared(dest_info, GL_TEXTURE_2D, level, true); } clear_state_dirty_ = true; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 2d317a0..5c41cc3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -3118,6 +3118,52 @@ error::Error GLES2DecoderImpl::HandleTraceEndCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXT( + uint32 immediate_data_size, const gles2::DiscardFramebufferEXT& c) { + GLenum target = static_cast<GLenum>(c.target); + GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size; + if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { + return error::kOutOfBounds; + } + const GLenum* attachments = GetSharedMemoryAs<const GLenum*>( + c.attachments_shm_id, c.attachments_shm_offset, data_size); + if (count < 0) { + SetGLError(GL_INVALID_VALUE, "glDiscardFramebufferEXT", "count < 0"); + return error::kNoError; + } + if (attachments == NULL) { + return error::kOutOfBounds; + } + DoDiscardFramebufferEXT(target, count, attachments); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXTImmediate( + uint32 immediate_data_size, + const gles2::DiscardFramebufferEXTImmediate& c) { + GLenum target = static_cast<GLenum>(c.target); + GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size; + if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) { + return error::kOutOfBounds; + } + if (data_size > immediate_data_size) { + return error::kOutOfBounds; + } + const GLenum* attachments = GetImmediateDataAs<const GLenum*>( + c, data_size, immediate_data_size); + if (count < 0) { + SetGLError(GL_INVALID_VALUE, "glDiscardFramebufferEXT", "count < 0"); + return error::kNoError; + } + if (attachments == NULL) { + return error::kOutOfBounds; + } + DoDiscardFramebufferEXT(target, count, attachments); + return error::kNoError; +} + bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { switch (cap) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index 2d88af0..983269b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -64,5 +64,7 @@ // TODO(gman): AsyncTexImage2DCHROMIUM +// TODO(gman): DiscardFramebufferEXT +// TODO(gman): DiscardFramebufferEXTImmediate #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index d127f25..f0b81df 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -10,6 +10,7 @@ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_AUTOGEN_H_ ValueValidator<GLenum> attachment; +ValueValidator<GLenum> backbuffer_attachment; ValueValidator<GLenum> blit_filter; ValueValidator<GLenum> buffer_parameter; ValueValidator<GLenum> buffer_target; diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 26d73c7..6817dda 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -15,6 +15,12 @@ static GLenum valid_attachment_table[] = { GL_STENCIL_ATTACHMENT, }; +static GLenum valid_backbuffer_attachment_table[] = { + GL_COLOR_EXT, + GL_DEPTH_EXT, + GL_STENCIL_EXT, +}; + static GLenum valid_blit_filter_table[] = { GL_NEAREST, GL_LINEAR, @@ -504,6 +510,9 @@ static GLint valid_zero_only_table[] = { Validators::Validators() : attachment( valid_attachment_table, arraysize(valid_attachment_table)), + backbuffer_attachment( + valid_backbuffer_attachment_table, arraysize( + valid_backbuffer_attachment_table)), blit_filter( valid_blit_filter_table, arraysize(valid_blit_filter_table)), buffer_parameter( diff --git a/gpu/command_buffer/service/renderbuffer_manager.cc b/gpu/command_buffer/service/renderbuffer_manager.cc index 496b746..56a8490 100644 --- a/gpu/command_buffer/service/renderbuffer_manager.cc +++ b/gpu/command_buffer/service/renderbuffer_manager.cc @@ -100,12 +100,13 @@ void RenderbufferManager::SetInfo( } } -void RenderbufferManager::SetCleared(RenderbufferInfo* renderbuffer) { +void RenderbufferManager::SetCleared(RenderbufferInfo* renderbuffer, + bool cleared) { DCHECK(renderbuffer); if (!renderbuffer->cleared()) { --num_uncleared_renderbuffers_; } - renderbuffer->set_cleared(); + renderbuffer->set_cleared(cleared); if (!renderbuffer->cleared()) { ++num_uncleared_renderbuffers_; } diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h index 2edfc34..f440ab0 100644 --- a/gpu/command_buffer/service/renderbuffer_manager.h +++ b/gpu/command_buffer/service/renderbuffer_manager.h @@ -88,8 +88,8 @@ class GPU_EXPORT RenderbufferManager { ~RenderbufferInfo(); - void set_cleared() { - cleared_ = true; + void set_cleared(bool cleared) { + cleared_ = cleared; } void SetInfo( @@ -151,7 +151,7 @@ class GPU_EXPORT RenderbufferManager { RenderbufferInfo* renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); - void SetCleared(RenderbufferInfo* renderbuffer); + void SetCleared(RenderbufferInfo* renderbuffer, bool cleared); // Must call before destruction. void Destroy(bool have_context); diff --git a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc index 15218bc..b9d7287 100644 --- a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc @@ -125,7 +125,7 @@ TEST_F(RenderbufferManagerTest, RenderbufferInfo) { EXPECT_TRUE(manager_.HaveUnclearedRenderbuffers()); EXPECT_EQ(kWidth * kHeight * 4u * 2u, info1->EstimatedSize()); - manager_.SetCleared(info1); + manager_.SetCleared(info1, true); EXPECT_TRUE(info1->cleared()); EXPECT_FALSE(manager_.HaveUnclearedRenderbuffers()); @@ -157,7 +157,7 @@ TEST_F(RenderbufferManagerTest, UseDeletedRenderbufferInfo) { manager_.SetInfo(info1, kSamples, kFormat, kWidth, kHeight); // See that it still affects manager. EXPECT_TRUE(manager_.HaveUnclearedRenderbuffers()); - manager_.SetCleared(info1); + manager_.SetCleared(info1, true); EXPECT_FALSE(manager_.HaveUnclearedRenderbuffers()); // Check that the renderbuffer is deleted when the last ref is released. EXPECT_CALL(*gl_, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id))) diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 1c36999..ce54615 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -293,7 +293,9 @@ bool TextureManager::TextureInfo::CanGenerateMipmaps( return true; } -void TextureManager::TextureInfo::SetLevelCleared(GLenum target, GLint level) { +void TextureManager::TextureInfo::SetLevelCleared(GLenum target, + GLint level, + bool cleared) { DCHECK_GE(level, 0); DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), level_infos_.size()); @@ -304,8 +306,10 @@ void TextureManager::TextureInfo::SetLevelCleared(GLenum target, GLint level) { if (!info.cleared) { DCHECK_NE(0, num_uncleared_mips_); --num_uncleared_mips_; + } else { + ++num_uncleared_mips_; } - info.cleared = true; + info.cleared = cleared; UpdateCleared(); } @@ -827,8 +831,10 @@ void TextureManager::SetInfoTarget( } } -void TextureManager::SetLevelCleared( - TextureManager::TextureInfo* info, GLenum target, GLint level) { +void TextureManager::SetLevelCleared(TextureManager::TextureInfo* info, + GLenum target, + GLint level, + bool cleared) { DCHECK(info); if (!info->SafeToRenderFrom()) { DCHECK_NE(0, num_unsafe_textures_); @@ -836,7 +842,7 @@ void TextureManager::SetLevelCleared( } num_uncleared_mips_ -= info->num_uncleared_mips(); DCHECK_GE(num_uncleared_mips_, 0); - info->SetLevelCleared(target, level); + info->SetLevelCleared(target, level, cleared); num_uncleared_mips_ += info->num_uncleared_mips(); if (!info->SafeToRenderFrom()) { ++num_unsafe_textures_; diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 5113499..f2e7963 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -226,7 +226,7 @@ class GPU_EXPORT TextureManager { bool cleared); // Marks a particular level as cleared or uncleared. - void SetLevelCleared(GLenum target, GLint level); + void SetLevelCleared(GLenum target, GLint level, bool cleared); // Updates the cleared flag for this texture by inspecting all the mips. void UpdateCleared(); @@ -432,7 +432,8 @@ class GPU_EXPORT TextureManager { TextureDefinition* definition); // Sets a mip as cleared. - void SetLevelCleared(TextureInfo* info, GLenum target, GLint level); + void SetLevelCleared(TextureInfo* info, GLenum target, + GLint level, bool cleared); // Sets a texture parameter of a TextureInfo // Returns GL_NO_ERROR on success. Otherwise the error to generate. diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index 698cabf..701954c 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -834,7 +834,7 @@ TEST_F(TextureInfoTest, SafeUnsafe) { EXPECT_TRUE(manager_.HaveUnsafeTextures()); EXPECT_TRUE(manager_.HaveUnclearedMips()); EXPECT_EQ(1, info_->num_uncleared_mips()); - manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 0); + manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 0, true); EXPECT_TRUE(info_->SafeToRenderFrom()); EXPECT_FALSE(manager_.HaveUnsafeTextures()); EXPECT_FALSE(manager_.HaveUnclearedMips()); @@ -845,7 +845,7 @@ TEST_F(TextureInfoTest, SafeUnsafe) { EXPECT_TRUE(manager_.HaveUnsafeTextures()); EXPECT_TRUE(manager_.HaveUnclearedMips()); EXPECT_EQ(1, info_->num_uncleared_mips()); - manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 1); + manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 1, true); EXPECT_TRUE(info_->SafeToRenderFrom()); EXPECT_FALSE(manager_.HaveUnsafeTextures()); EXPECT_FALSE(manager_.HaveUnclearedMips()); @@ -858,12 +858,12 @@ TEST_F(TextureInfoTest, SafeUnsafe) { EXPECT_TRUE(manager_.HaveUnsafeTextures()); EXPECT_TRUE(manager_.HaveUnclearedMips()); EXPECT_EQ(2, info_->num_uncleared_mips()); - manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 0); + manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 0, true); EXPECT_FALSE(info_->SafeToRenderFrom()); EXPECT_TRUE(manager_.HaveUnsafeTextures()); EXPECT_TRUE(manager_.HaveUnclearedMips()); EXPECT_EQ(1, info_->num_uncleared_mips()); - manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 1); + manager_.SetLevelCleared(info_, GL_TEXTURE_2D, 1, true); EXPECT_TRUE(info_->SafeToRenderFrom()); EXPECT_FALSE(manager_.HaveUnsafeTextures()); EXPECT_FALSE(manager_.HaveUnclearedMips()); @@ -907,11 +907,11 @@ TEST_F(TextureInfoTest, SafeUnsafe) { EXPECT_TRUE(manager_.HaveUnsafeTextures()); EXPECT_TRUE(manager_.HaveUnclearedMips()); EXPECT_EQ(1, info3->num_uncleared_mips()); - manager_.SetLevelCleared(info2, GL_TEXTURE_2D, 0); + manager_.SetLevelCleared(info2, GL_TEXTURE_2D, 0, true); EXPECT_TRUE(manager_.HaveUnsafeTextures()); EXPECT_TRUE(manager_.HaveUnclearedMips()); EXPECT_EQ(0, info2->num_uncleared_mips()); - manager_.SetLevelCleared(info3, GL_TEXTURE_2D, 0); + manager_.SetLevelCleared(info3, GL_TEXTURE_2D, 0, true); EXPECT_FALSE(manager_.HaveUnsafeTextures()); EXPECT_FALSE(manager_.HaveUnclearedMips()); EXPECT_EQ(0, info3->num_uncleared_mips()); |