diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 22:28:10 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 22:28:10 +0000 |
commit | 62e65f0cc982cf66eb00a1a2fc40fb6d82510e31 (patch) | |
tree | a57c4c457c3acb0c93f4650c4ffb06d5e1a26c81 /gpu | |
parent | 150c18a1e10ec3422780680d43ceb85867229bd9 (diff) | |
download | chromium_src-62e65f0cc982cf66eb00a1a2fc40fb6d82510e31.zip chromium_src-62e65f0cc982cf66eb00a1a2fc40fb6d82510e31.tar.gz chromium_src-62e65f0cc982cf66eb00a1a2fc40fb6d82510e31.tar.bz2 |
gpu: Change Produce/ConsumeTexture to allow texture sharing
This changes the semantics of ProduceTexture to not replacing the current texture by a dud, but instead keeping the existing one, that it also puts into the mailbox. It changes the semantics of ConsumeTexture to deleting the current texture, and replacing it by the mailbox contents (without taking it out of the mailbox). The texture becomes shared. The mailbox is now effectively a weak pointer onto the texture.
BUG=230137
Review URL: https://chromiumcodereview.appspot.com/14188053
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202992 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
20 files changed, 457 insertions, 721 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_texture_mailbox.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_texture_mailbox.txt index 277b60d..f3c476b 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_texture_mailbox.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_texture_mailbox.txt @@ -20,9 +20,9 @@ Overview objects in different contexts where the contexts would not normally share texture resources. Three new functions are exported. glGenMailboxCHROMIUM generates a name that can be used to identify texture image data outside - the scope of a context group. glProduceMailboxCHROMIUM moves texture image - data out of a texture object and into a mailbox. glConsumeMailboxCHROMIUM - moves texture image data out of a mailbox and into a texture object. + the scope of a context group. glProduceMailboxCHROMIUM associates a texture + object with a global mailbox name. glConsumeMailboxCHROMIUM associates the + texture object referenced by a mailbox name to a texture name. New Procedures and Functions @@ -38,18 +38,19 @@ New Procedures and Functions void glProduceTextureCHROMIUM (GLenum target, const GLbyte *mailbox) - Moves the image data and parameters of the currently bound texture object - into the mailbox. The texture object is redefined as though all its levels - had been resized to zero by zero and the texture object is therefore - incomplete. The texture object parameters are undefined. The texture - object is no longer immutable. If the mailbox previously contained image - data, the old image data is deleted. + Associates the currently bound texture object with the mailbox name. A + given texture object can be associated with several mailbox names. If a + mailbox name was previously associated with a texture object, that + previous association is broken. The currently bound texture object is not + modified by the operation. - If glProduceTextureCHROMIUM generates an error, the associated image data - and state is preserved in the texture object. + If glProduceTextureCHROMIUM generates an error, the mailbox name keeps its + current association, if any. - The mailbox is emptied and the texture image data deleted if the context - is destroyed before being consumed. See glConsumeTextureCHROMIUM. + The mailbox does not keep a reference to the texture object. When the + texture object is destroyed (deleted from all context groups, and unbound + from all texture units and framebuffer attachments), the mailbox is + disassociated from the texture object. <target> uses the same parameters as TexImage2D. @@ -58,10 +59,6 @@ New Procedures and Functions INVALID_OPERATION is generated if <target> is not a valid target. - INVALID_OPERATION is generated if the texture is attached to a framebuffer. - - INVALID_OPERATION is generated if the texture is immutable. - INVALID_OPERATION is generated if <mailbox> is invalid. @@ -71,30 +68,32 @@ New Procedures and Functions <mailbox> identifies a GL_MAILBOX_SIZE_CHROMIUM byte sized name returned by glGenMailboxCHROMIUM. - - Redefines the image data and parameters of the currently bound texture - object with the image data and parameters in the mailbox and empties the - mailbox. All levels are redefined, and the immutable state is set according - to the contents of the mailbox. - - If glConsumeTextureCHROMIUM generates an error, the associated image data - is preserved in the texture object. + + Deletes the currently bound texture object, and redefines its texture name + to point to the texture object associated with the mailbox name. All the + contexts that have consumed the texture object, as well as produced it share + the texture object, as if the contexts were part of the share group. The + texture object is deleted once all contexts have deleted the texture name + associated with the texture object, and detached it from all framebuffer + objects as well as texture unit bindings. See Appendix C of the OpenGL ES + 2.0 specification for details relative to visibility in one context of + changes to the shared texture object in another context. + + If glConsumeTextureCHROMIUM generates an error, the currently bound texture + object is preserved. INVALID_OPERATION is generated if <target> is not a valid target. - INVALID_OPERATION is generated if <mailbox> is empty. - - INVALID_OPERATION is generated if <mailbox> is not in the scope of the - context. - INVALID_OPERATION is generated if <mailbox> is invalid. - INVALID_OPERATION is generated if the texture is attached to a framebuffer. + INVALID_OPERATION is generated if <mailbox> is not associated with a texture + object. - INVALID_OPERATION is generated if the texture is immutable. + INVALID_OPERATION is generated if the texture object associated with + <mailbox> has a different target than <target>. - INVALID_OPERATION is generated if the image data is invalid in the current - context. + INVALID_OPERATION is generated if the currently bound texture was previously + deleted (for example in another context), hence doesn't have a name. New Tokens @@ -117,3 +116,5 @@ New State Revision History 4/25/2011 Documented the extension + 5/23/2013 Major revision in Produce/Consume semantics, introducing + sharing. diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 2a3809d..3924465 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -277,8 +277,6 @@ void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) { } if (texture_manager_ != NULL) { - mailbox_manager_->DestroyOwnedTextures(texture_manager_.get(), - have_context); texture_manager_->Destroy(have_context); texture_manager_.reset(); } diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc index 29fd55d..ce08830 100644 --- a/gpu/command_buffer/service/framebuffer_manager.cc +++ b/gpu/command_buffer/service/framebuffer_manager.cc @@ -55,6 +55,10 @@ class RenderbufferAttachment return renderbuffer_->samples(); } + virtual GLuint object_name() const OVERRIDE { + return renderbuffer_->client_id(); + } + virtual bool cleared() const OVERRIDE { return renderbuffer_->cleared(); } @@ -149,6 +153,10 @@ class TextureAttachment return 0; } + virtual GLuint object_name() const OVERRIDE { + return texture_ref_->client_id(); + } + virtual bool cleared() const OVERRIDE { return texture_ref_->texture()->IsLevelCleared(target_, level_); } diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h index 9b7b131..eb6125d 100644 --- a/gpu/command_buffer/service/framebuffer_manager.h +++ b/gpu/command_buffer/service/framebuffer_manager.h @@ -31,6 +31,7 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { virtual GLsizei height() const = 0; virtual GLenum internal_format() const = 0; virtual GLsizei samples() const = 0; + virtual GLuint object_name() const = 0; virtual bool cleared() const = 0; virtual void SetCleared( RenderbufferManager* renderbuffer_manager, diff --git a/gpu/command_buffer/service/gl_context_virtual.cc b/gpu/command_buffer/service/gl_context_virtual.cc index 8051e06..e03c041 100644 --- a/gpu/command_buffer/service/gl_context_virtual.cc +++ b/gpu/command_buffer/service/gl_context_virtual.cc @@ -72,8 +72,8 @@ 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->GetBackingFrameBufferObject() && - !surface->IsOffscreen()) + !surface->IsOffscreen() && + !surface->GetBackingFrameBufferObject()) return shared_context_->IsCurrent(surface); // Otherwise, only insure the context itself is current. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 2fad005..28d3b57 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -52,7 +52,6 @@ #include "gpu/command_buffer/service/shader_translator_cache.h" #include "gpu/command_buffer/service/stream_texture.h" #include "gpu/command_buffer/service/stream_texture_manager.h" -#include "gpu/command_buffer/service/texture_definition.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" @@ -2261,25 +2260,6 @@ bool GLES2DecoderImpl::Initialize( if (!attrib_parser.Parse(attribs)) return false; - // These are NOT if the back buffer has these proprorties. They are - // if we want the command buffer to enforce them regardless of what - // the real backbuffer is assuming the real back buffer gives us more than - // we ask for. In other words, if we ask for RGB and we get RGBA then we'll - // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we - // can't do anything about that. - - GLint v = 0; - glGetIntegerv(GL_ALPHA_BITS, &v); - // This checks if the user requested RGBA and we have RGBA then RGBA. If the - // user requested RGB then RGB. If the user did not specify a preference than - // use whatever we were given. Same for DEPTH and STENCIL. - back_buffer_color_format_ = - (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB; - glGetIntegerv(GL_DEPTH_BITS, &v); - back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0; - glGetIntegerv(GL_STENCIL_BITS, &v); - back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0; - if (offscreen) { if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 && features().chromium_framebuffer_multisample) { @@ -2408,6 +2388,26 @@ bool GLES2DecoderImpl::Initialize( // Bind to the new default frame buffer (the offscreen target frame buffer). // This should now be associated with ID zero. DoBindFramebuffer(GL_FRAMEBUFFER, 0); + } else { + glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId()); + // These are NOT if the back buffer has these proprorties. They are + // if we want the command buffer to enforce them regardless of what + // the real backbuffer is assuming the real back buffer gives us more than + // we ask for. In other words, if we ask for RGB and we get RGBA then we'll + // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we + // can't do anything about that. + + GLint v = 0; + glGetIntegerv(GL_ALPHA_BITS, &v); + // This checks if the user requested RGBA and we have RGBA then RGBA. If the + // user requested RGB then RGB. If the user did not specify a preference + // than use whatever we were given. Same for DEPTH and STENCIL. + back_buffer_color_format_ = + (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB; + glGetIntegerv(GL_DEPTH_BITS, &v); + back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0; + glGetIntegerv(GL_STENCIL_BITS, &v); + back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0; } // OpenGL ES 2.0 implicitly enables the desktop GL capability @@ -3234,10 +3234,10 @@ bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent, parent_->children_.erase(it); // First check the texture has been mapped into the parent. This might not // be the case if initialization failed midway through. - GLuint service_id = offscreen_saved_color_texture_->id(); - GLuint client_id = 0; - if (parent_->texture_manager()->GetClientId(service_id, &client_id)) { - parent_->texture_manager()->RemoveTexture(client_id); + if (offscreen_saved_color_texture_info_ && + offscreen_saved_color_texture_info_->client_id()) { + parent_->texture_manager()->RemoveTexture( + offscreen_saved_color_texture_info_->client_id()); } } @@ -3704,9 +3704,8 @@ void GLES2DecoderImpl::RestoreFramebufferBindings() const { } void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const { - GLuint client_id = 0; - if (texture_manager()->GetClientId(service_id, &client_id)) { - Texture* texture = GetTexture(client_id)->texture(); + Texture* texture = texture_manager()->GetTextureForServiceId(service_id); + if (texture) { GLenum target = texture->target(); glBindTexture(target, service_id); glTexParameteri( @@ -4213,10 +4212,7 @@ bool GLES2DecoderImpl::GetHelper( Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER); if (renderbuffer) { - GLuint client_id = 0; - renderbuffer_manager()->GetClientId( - renderbuffer->service_id(), &client_id); - *params = client_id; + *params = renderbuffer->client_id(); } else { *params = 0; } @@ -4253,10 +4249,7 @@ bool GLES2DecoderImpl::GetHelper( if (params) { TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; if (unit.bound_texture_2d) { - GLuint client_id = 0; - texture_manager()->GetClientId( - unit.bound_texture_2d->service_id(), &client_id); - *params = client_id; + *params = unit.bound_texture_2d->client_id(); } else { *params = 0; } @@ -4267,10 +4260,7 @@ bool GLES2DecoderImpl::GetHelper( if (params) { TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; if (unit.bound_texture_cube_map) { - GLuint client_id = 0; - texture_manager()->GetClientId( - unit.bound_texture_cube_map->service_id(), &client_id); - *params = client_id; + *params = unit.bound_texture_cube_map->client_id(); } else { *params = 0; } @@ -4281,10 +4271,7 @@ bool GLES2DecoderImpl::GetHelper( if (params) { TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; if (unit.bound_texture_external_oes) { - GLuint client_id = 0; - texture_manager()->GetClientId( - unit.bound_texture_external_oes->service_id(), &client_id); - *params = client_id; + *params = unit.bound_texture_external_oes->client_id(); } else { *params = 0; } @@ -4295,10 +4282,7 @@ bool GLES2DecoderImpl::GetHelper( if (params) { TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; if (unit.bound_texture_rectangle_arb) { - GLuint client_id = 0; - texture_manager()->GetClientId( - unit.bound_texture_rectangle_arb->service_id(), &client_id); - *params = client_id; + *params = unit.bound_texture_rectangle_arb->client_id(); } else { *params = 0; } @@ -4932,25 +4916,12 @@ void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv( "glFramebufferAttachmentParameteriv", "no framebuffer bound"); return; } - glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params); if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) { - GLint type = 0; - GLuint client_id = 0; - glGetFramebufferAttachmentParameterivEXT( - target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type); - switch (type) { - case GL_RENDERBUFFER: { - renderbuffer_manager()->GetClientId(*params, &client_id); - break; - } - case GL_TEXTURE: { - texture_manager()->GetClientId(*params, &client_id); - break; - } - default: - break; - } - *params = client_id; + const Framebuffer::Attachment* attachment_object = + framebuffer->GetAttachment(attachment); + *params = attachment_object ? attachment_object->object_name() : 0; + } else { + glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params); } } @@ -9858,8 +9829,8 @@ void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target, return; } - TextureDefinition* definition = texture_manager()->Save(texture_ref); - if (!definition) { + Texture* produced = texture_manager()->Produce(texture_ref); + if (!produced) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glProduceTextureCHROMIUM", "invalid texture"); @@ -9869,18 +9840,12 @@ void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target, if (!group_->mailbox_manager()->ProduceTexture( target, *reinterpret_cast<const MailboxName*>(mailbox), - definition, - texture_manager())) { - bool success = texture_manager()->Restore( - "glProductTextureCHROMIUM", this, texture_ref, definition); - DCHECK(success); + produced)) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glProduceTextureCHROMIUM", "invalid mailbox name"); return; } - - glBindTexture(texture_ref->texture()->target(), texture_ref->service_id()); } void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target, @@ -9889,32 +9854,61 @@ void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target, "context", logger_.GetLogPrefix(), "mailbox[0]", static_cast<unsigned char>(mailbox[0])); - TextureRef* texture_ref = GetTextureInfoForTarget(target); + scoped_refptr<TextureRef> texture_ref = + GetTextureInfoForTargetUnlessDefault(target); if (!texture_ref) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glConsumeTextureCHROMIUM", "unknown texture for target"); return; } - - scoped_ptr<TextureDefinition> definition( + GLuint client_id = texture_ref->client_id(); + if (!client_id) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glConsumeTextureCHROMIUM", "unknown texture for target"); + return; + } + Texture* texture = group_->mailbox_manager()->ConsumeTexture( target, - *reinterpret_cast<const MailboxName*>(mailbox))); - if (!definition.get()) { + *reinterpret_cast<const MailboxName*>(mailbox)); + if (!texture) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glConsumeTextureCHROMIUM", "invalid mailbox name"); return; } - - if (!texture_manager()->Restore( - "glConsumeTextureCHROMIUM", this, texture_ref, definition.release())) { + if (texture->target() != target) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, - "glConsumeTextureCHROMIUM", "invalid texture"); + "glConsumeTextureCHROMIUM", "invalid target"); return; } + + DeleteTexturesHelper(1, &client_id); + texture_ref = texture_manager()->Consume(client_id, texture); + glBindTexture(target, texture_ref->service_id()); + + TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; + unit.bind_target = target; + switch (target) { + case GL_TEXTURE_2D: + unit.bound_texture_2d = texture_ref; + break; + case GL_TEXTURE_CUBE_MAP: + unit.bound_texture_cube_map = texture_ref; + break; + case GL_TEXTURE_EXTERNAL_OES: + unit.bound_texture_external_oes = texture_ref; + break; + case GL_TEXTURE_RECTANGLE_ARB: + unit.bound_texture_rectangle_arb = texture_ref; + break; + default: + NOTREACHED(); // Validation should prevent us getting here. + break; + } } void GLES2DecoderImpl::DoInsertEventMarkerEXT( diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index cd62780..c2413d1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -2087,18 +2087,6 @@ TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithRenderbuffer) { .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, _)) - .WillOnce(SetArgumentPointee<3>(kServiceRenderbufferId)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, _)) - .WillOnce(SetArgumentPointee<3>(GL_RENDERBUFFER)) - .RetiresOnSaturation(); GetFramebufferAttachmentParameteriv::Result* result = static_cast<GetFramebufferAttachmentParameteriv::Result*>( shared_memory_address_); @@ -2137,18 +2125,6 @@ TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithTexture) { .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, _)) - .WillOnce(SetArgumentPointee<3>(kServiceTextureId)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, _)) - .WillOnce(SetArgumentPointee<3>(GL_TEXTURE)) - .RetiresOnSaturation(); GetFramebufferAttachmentParameteriv::Result* result = static_cast<GetFramebufferAttachmentParameteriv::Result*>( shared_memory_address_); @@ -5971,20 +5947,18 @@ TEST_F(GLES2DecoderManualInitTest, ProduceAndConsumeStreamTextureCHROMIUM) { EXPECT_EQ(kServiceTextureId, texture_ref->service_id()); - // Assigns and binds new service side texture ID. - EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kNewServiceId)) - .Times(1) - .RetiresOnSaturation(); - ProduceTextureCHROMIUM produce_cmd; produce_cmd.Init( GL_TEXTURE_EXTERNAL_OES, kSharedMemoryId, kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); + // Create new texture for consume. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)) + .RetiresOnSaturation(); + DoBindTexture(GL_TEXTURE_EXTERNAL_OES, kNewClientId, kNewServiceId); + // Assigns and binds original service size texture ID. EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(1) @@ -5993,30 +5967,6 @@ TEST_F(GLES2DecoderManualInitTest, ProduceAndConsumeStreamTextureCHROMIUM) { .Times(1) .RetiresOnSaturation(); - // TextureManager::Restore will set TexParameters. - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)) - .Times(1) - .RetiresOnSaturation(); - #if 0 - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_NONE)) - .Times(1) - .RetiresOnSaturation(); - #endif - // Shared mem got clobbered from GetError() above. memcpy(shared_memory_address_, mailbox, sizeof(mailbox)); ConsumeTextureCHROMIUM consume_cmd; @@ -7405,40 +7355,39 @@ TEST_F(GLES2DecoderTest, ProduceAndConsumeTextureCHROMIUM) { Texture* texture = texture_ref->texture(); EXPECT_EQ(kServiceTextureId, texture->service_id()); - // Assigns and binds new service side texture ID. - EXPECT_CALL(*gl_, GenTextures(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kNewServiceId)) - .Times(1) - .RetiresOnSaturation(); - ProduceTextureCHROMIUM produce_cmd; produce_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); - // Texture is zero-by-zero. + // Texture didn't change. GLsizei width; GLsizei height; GLenum type; GLenum internal_format; EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); - EXPECT_EQ(0, width); - EXPECT_EQ(0, height); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); - EXPECT_EQ(0, width); - EXPECT_EQ(0, height); + EXPECT_EQ(2, width); + EXPECT_EQ(4, height); EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); - // Service ID has changed. - EXPECT_EQ(kNewServiceId, texture->service_id()); + // Service ID has not changed. + EXPECT_EQ(kServiceTextureId, texture->service_id()); + + // Create new texture for consume. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)) + .RetiresOnSaturation(); + DoBindTexture(GL_TEXTURE_2D, kNewClientId, kNewServiceId); // Assigns and binds original service size texture ID. EXPECT_CALL(*gl_, DeleteTextures(1, _)) @@ -7448,33 +7397,11 @@ TEST_F(GLES2DecoderTest, ProduceAndConsumeTextureCHROMIUM) { .Times(1) .RetiresOnSaturation(); - // TextureManager::Restore will set TexParameters. - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)) - .Times(1) - .RetiresOnSaturation(); - #if 0 - EXPECT_CALL(*gl_, TexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_NONE)) - .Times(1) - .RetiresOnSaturation(); - #endif - + memcpy(shared_memory_address_, mailbox, sizeof(mailbox)); ConsumeTextureCHROMIUM consume_cmd; consume_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(consume_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); // Texture is redefined. EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 6592535..5cc2b96 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -175,6 +175,9 @@ void GLES2DecoderTestBase::InitDecoder( .Times(1) .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER, 0)) + .Times(1) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) .WillOnce(SetArgumentPointee<1>(has_alpha ? 8 : 0)) .RetiresOnSaturation(); diff --git a/gpu/command_buffer/service/mailbox_manager.cc b/gpu/command_buffer/service/mailbox_manager.cc index 9019393..972bf5d 100644 --- a/gpu/command_buffer/service/mailbox_manager.cc +++ b/gpu/command_buffer/service/mailbox_manager.cc @@ -8,8 +8,7 @@ #include "base/rand_util.h" #include "crypto/hmac.h" -#include "gpu/command_buffer/service/gl_utils.h" -#include "gpu/command_buffer/service/texture_definition.h" +#include "gpu/command_buffer/service/texture_manager.h" namespace gpu { namespace gles2 { @@ -21,7 +20,7 @@ MailboxName::MailboxName() { MailboxManager::MailboxManager() : hmac_(crypto::HMAC::SHA256), - textures_(std::ptr_fun(&MailboxManager::TargetNameLess)) { + mailbox_to_textures_(std::ptr_fun(&MailboxManager::TargetNameLess)) { base::RandBytes(private_key_, sizeof(private_key_)); bool success = hmac_.Init( base::StringPiece(private_key_, sizeof(private_key_))); @@ -30,7 +29,8 @@ MailboxManager::MailboxManager() } MailboxManager::~MailboxManager() { - DCHECK(!textures_.size()); + DCHECK(mailbox_to_textures_.empty()); + DCHECK(textures_to_mailboxes_.empty()); } void MailboxManager::GenerateMailboxName(MailboxName* name) { @@ -38,58 +38,53 @@ void MailboxManager::GenerateMailboxName(MailboxName* name) { SignMailboxName(name); } -TextureDefinition* MailboxManager::ConsumeTexture(unsigned target, - const MailboxName& name) { +Texture* MailboxManager::ConsumeTexture(unsigned target, + const MailboxName& name) { if (!IsMailboxNameValid(name)) return NULL; - TextureDefinitionMap::iterator it = - textures_.find(TargetName(target, name)); - if (it == textures_.end()) + MailboxToTextureMap::iterator it = + mailbox_to_textures_.find(TargetName(target, name)); + if (it == mailbox_to_textures_.end()) return NULL; - TextureDefinition* definition = it->second.definition.release(); - textures_.erase(it); - - return definition; + return it->second->first; } bool MailboxManager::ProduceTexture(unsigned target, const MailboxName& name, - TextureDefinition* definition, - TextureManager* owner) { + Texture* texture) { if (!IsMailboxNameValid(name)) return false; - TextureDefinitionMap::iterator it = - textures_.find(TargetName(target, name)); - if (it != textures_.end()) { - NOTREACHED(); - GLuint service_id = it->second.definition->ReleaseServiceId(); - glDeleteTextures(1, &service_id); - it->second = OwnedTextureDefinition(definition, owner); - } else { - textures_.insert(std::make_pair( - TargetName(target, name), - OwnedTextureDefinition(definition, owner))); + texture->SetMailboxManager(this); + TargetName target_name(target, name); + MailboxToTextureMap::iterator it = mailbox_to_textures_.find(target_name); + if (it != mailbox_to_textures_.end()) { + TextureToMailboxMap::iterator texture_it = it->second; + mailbox_to_textures_.erase(it); + textures_to_mailboxes_.erase(texture_it); } + TextureToMailboxMap::iterator texture_it = + textures_to_mailboxes_.insert(std::make_pair(texture, target_name)); + mailbox_to_textures_.insert(std::make_pair(target_name, texture_it)); + DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size()); return true; } -void MailboxManager::DestroyOwnedTextures(TextureManager* owner, - bool have_context) { - TextureDefinitionMap::iterator it = textures_.begin(); - while (it != textures_.end()) { - TextureDefinitionMap::iterator current_it = it; - ++it; - if (current_it->second.owner == owner) { - GLuint service_id = current_it->second.definition->ReleaseServiceId(); - if (have_context) - glDeleteTextures(1, &service_id); - textures_.erase(current_it); - } +void MailboxManager::TextureDeleted(Texture* texture) { + std::pair<TextureToMailboxMap::iterator, + TextureToMailboxMap::iterator> range = + textures_to_mailboxes_.equal_range(texture); + DCHECK(range.first != range.second); + for (TextureToMailboxMap::iterator it = range.first; + it != range.second; ++it) { + size_t count = mailbox_to_textures_.erase(it->second); + DCHECK(count == 1); } + textures_to_mailboxes_.erase(range.first, range.second); + DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size()); } void MailboxManager::SignMailboxName(MailboxName* name) { @@ -118,15 +113,5 @@ bool MailboxManager::TargetNameLess(const MailboxManager::TargetName& lhs, return memcmp(&lhs, &rhs, sizeof(lhs)) < 0; } -MailboxManager::OwnedTextureDefinition::OwnedTextureDefinition( - TextureDefinition* definition, - TextureManager* owner) - : definition(definition), - owner(owner) { -} - -MailboxManager::OwnedTextureDefinition::~OwnedTextureDefinition() { -} - } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h index 8f97dd4..c973028 100644 --- a/gpu/command_buffer/service/mailbox_manager.h +++ b/gpu/command_buffer/service/mailbox_manager.h @@ -24,7 +24,7 @@ typedef signed char GLbyte; namespace gpu { namespace gles2 { -class TextureDefinition; +class Texture; class TextureManager; // Identifies a mailbox where a texture definition can be stored for @@ -44,18 +44,16 @@ class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> { // Generate a unique mailbox name signed with the manager's private key. void GenerateMailboxName(MailboxName* name); - // Remove the texture definition from the named mailbox and empty the mailbox. - TextureDefinition* ConsumeTexture(unsigned target, const MailboxName& name); + // Look up the texture definition from the named mailbox. + Texture* ConsumeTexture(unsigned target, const MailboxName& name); - // Put the texture definition in the named mailbox. + // Put the texture into the named mailbox. bool ProduceTexture(unsigned target, const MailboxName& name, - TextureDefinition* definition, - TextureManager* owner); + Texture* texture); - // Destroy any texture definitions and mailboxes owned by the given texture - // manager. - void DestroyOwnedTextures(TextureManager* owner, bool have_context); + // Destroy any mailbox that reference the given texture. + void TextureDeleted(Texture* texture); std::string private_key() { return std::string(private_key_, sizeof(private_key_)); @@ -77,23 +75,21 @@ class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> { static bool TargetNameLess(const TargetName& lhs, const TargetName& rhs); - struct OwnedTextureDefinition { - OwnedTextureDefinition(TextureDefinition* definition, - TextureManager* owner); - ~OwnedTextureDefinition(); - linked_ptr<TextureDefinition> definition; - TextureManager* owner; - }; - + // This is a bidirectional map between mailbox and textures. We can have + // multiple mailboxes per texture, but one texture per mailbox. We keep an + // iterator in the MailboxToTextureMap to be able to manage changes to + // the TextureToMailboxMap efficiently. + typedef std::multimap<Texture*, TargetName> TextureToMailboxMap; typedef std::map< TargetName, - OwnedTextureDefinition, + TextureToMailboxMap::iterator, std::pointer_to_binary_function< - const TargetName&, const TargetName&, bool> > TextureDefinitionMap; + const TargetName&, const TargetName&, bool> > MailboxToTextureMap; char private_key_[GL_MAILBOX_SIZE_CHROMIUM / 2]; crypto::HMAC hmac_; - TextureDefinitionMap textures_; + MailboxToTextureMap mailbox_to_textures_; + TextureToMailboxMap textures_to_mailboxes_; DISALLOW_COPY_AND_ASSIGN(MailboxManager); }; diff --git a/gpu/command_buffer/service/renderbuffer_manager.cc b/gpu/command_buffer/service/renderbuffer_manager.cc index 0525ad5..416de3b 100644 --- a/gpu/command_buffer/service/renderbuffer_manager.cc +++ b/gpu/command_buffer/service/renderbuffer_manager.cc @@ -51,9 +51,11 @@ void Renderbuffer::AddToSignature( internal_format_, samples_, width_, height_); } -Renderbuffer::Renderbuffer(RenderbufferManager* manager, GLuint service_id) +Renderbuffer::Renderbuffer(RenderbufferManager* manager, + GLuint client_id, + GLuint service_id) : manager_(manager), - deleted_(false), + client_id_(client_id), service_id_(service_id), cleared_(true), has_been_bound_(false), @@ -122,7 +124,8 @@ void RenderbufferManager::SetCleared(Renderbuffer* renderbuffer, void RenderbufferManager::CreateRenderbuffer( GLuint client_id, GLuint service_id) { - scoped_refptr<Renderbuffer> renderbuffer(new Renderbuffer(this, service_id)); + scoped_refptr<Renderbuffer> renderbuffer( + new Renderbuffer(this, client_id, service_id)); std::pair<RenderbufferMap::iterator, bool> result = renderbuffers_.insert(std::make_pair(client_id, renderbuffer)); DCHECK(result.second); @@ -146,19 +149,6 @@ void RenderbufferManager::RemoveRenderbuffer(GLuint client_id) { } } -bool RenderbufferManager::GetClientId( - GLuint service_id, GLuint* client_id) const { - // This doesn't need to be fast. It's only used during slow queries. - for (RenderbufferMap::const_iterator it = renderbuffers_.begin(); - it != renderbuffers_.end(); ++it) { - if (it->second->service_id() == service_id) { - *client_id = it->first; - return true; - } - } - return false; -} - bool RenderbufferManager::ComputeEstimatedRenderbufferSize( int width, int height, int samples, int internal_format, uint32* size) { DCHECK(size); diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h index d27fd0f..6283f23 100644 --- a/gpu/command_buffer/service/renderbuffer_manager.h +++ b/gpu/command_buffer/service/renderbuffer_manager.h @@ -23,12 +23,18 @@ class RenderbufferManager; class GPU_EXPORT Renderbuffer : public base::RefCounted<Renderbuffer> { public: - Renderbuffer(RenderbufferManager* manager, GLuint service_id); + Renderbuffer(RenderbufferManager* manager, + GLuint client_id, + GLuint service_id); GLuint service_id() const { return service_id_; } + GLuint client_id() const { + return client_id_; + } + bool cleared() const { return cleared_; } @@ -50,7 +56,7 @@ class GPU_EXPORT Renderbuffer } bool IsDeleted() const { - return deleted_; + return client_id_ == 0; } void MarkAsValid() { @@ -85,13 +91,14 @@ class GPU_EXPORT Renderbuffer } void MarkAsDeleted() { - deleted_ = true; + client_id_ = 0; } // RenderbufferManager that owns this Renderbuffer. RenderbufferManager* manager_; - bool deleted_; + // Client side renderbuffer id. + GLuint client_id_; // Service side renderbuffer id. GLuint service_id_; @@ -152,9 +159,6 @@ class GPU_EXPORT RenderbufferManager { // Removes a renderbuffer for the given renderbuffer id. void RemoveRenderbuffer(GLuint client_id); - // Gets a client id for a given service id. - bool GetClientId(GLuint service_id, GLuint* client_id) const; - size_t mem_represented() const { return memory_tracker_->GetMemRepresented(); } diff --git a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc index d92a2bc..5b654af 100644 --- a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc @@ -80,13 +80,11 @@ TEST_F(RenderbufferManagerTest, Basic) { // Check we can create renderbuffer. manager_->CreateRenderbuffer(kClient1Id, kService1Id); // Check renderbuffer got created. - Renderbuffer* renderbuffer1 = + scoped_refptr<Renderbuffer> renderbuffer1 = manager_->GetRenderbuffer(kClient1Id); ASSERT_TRUE(renderbuffer1 != NULL); EXPECT_FALSE(manager_->HaveUnclearedRenderbuffers()); - GLuint client_id = 0; - EXPECT_TRUE(manager_->GetClientId(renderbuffer1->service_id(), &client_id)); - EXPECT_EQ(kClient1Id, client_id); + EXPECT_EQ(kClient1Id, renderbuffer1->client_id()); // Check we get nothing for a non-existent renderbuffer. EXPECT_TRUE(manager_->GetRenderbuffer(kClient2Id) == NULL); // Check trying to a remove non-existent renderbuffers does not crash. @@ -99,6 +97,7 @@ TEST_F(RenderbufferManagerTest, Basic) { manager_->RemoveRenderbuffer(kClient1Id); EXPECT_TRUE(manager_->GetRenderbuffer(kClient1Id) == NULL); EXPECT_FALSE(manager_->HaveUnclearedRenderbuffers()); + EXPECT_EQ(0u, renderbuffer1->client_id()); } TEST_F(RenderbufferManagerTest, Destroy) { diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc deleted file mode 100644 index 31b9711..0000000 --- a/gpu/command_buffer/service/texture_definition.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu/command_buffer/service/texture_definition.h" - -namespace gpu { -namespace gles2 { - -TextureDefinition::LevelInfo::LevelInfo(GLenum target, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - bool cleared) - : target(target), - internal_format(internal_format), - width(width), - height(height), - depth(depth), - border(border), - format(format), - type(type), - cleared(cleared) { -} - -TextureDefinition::LevelInfo::LevelInfo() - : target(0), - internal_format(0), - width(0), - height(0), - depth(0), - border(0), - format(0), - type(0), - cleared(true) { -} - -TextureDefinition::TextureDefinition(GLenum target, - GLuint service_id, - GLenum min_filter, - GLenum mag_filter, - GLenum wrap_s, - GLenum wrap_t, - GLenum usage, - bool immutable, - bool stream_texture, - const LevelInfos& level_infos) - : target_(target), - service_id_(service_id), - min_filter_(min_filter), - mag_filter_(mag_filter), - wrap_s_(wrap_s), - wrap_t_(wrap_t), - usage_(usage), - immutable_(immutable), - stream_texture_(stream_texture), - level_infos_(level_infos) { -} - -TextureDefinition::~TextureDefinition() { - DCHECK_EQ(0U, service_id_) << "TextureDefinition leaked texture."; -} - -GLuint TextureDefinition::ReleaseServiceId() { - GLuint service_id = service_id_; - service_id_ = 0; - return service_id; -} - -} // namespace gles2 -} // namespace gpu diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h deleted file mode 100644 index d55ef3c..0000000 --- a/gpu/command_buffer/service/texture_definition.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ -#define GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ - -#include <vector> - -#include "base/callback.h" -#include "gpu/command_buffer/service/gl_utils.h" -#include "gpu/gpu_export.h" - -namespace gpu { -namespace gles2 { - -// A saved definition of a texture that still exists in the underlying -// GLShareGroup and can be used to redefine a client visible texture in any -// context using the same GLShareGroup with the corresponding service ID. -class GPU_EXPORT TextureDefinition { - public: - struct GPU_EXPORT LevelInfo { - LevelInfo(GLenum target, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLsizei depth, - GLint border, - GLenum format, - GLenum type, - bool cleared); - LevelInfo(); - - GLenum target; - GLenum internal_format; - GLsizei width; - GLsizei height; - GLsizei depth; - GLint border; - GLenum format; - GLenum type; - bool cleared; - }; - - typedef std::vector<std::vector<LevelInfo> > LevelInfos; - - typedef base::Callback<void(TextureDefinition*)> DestroyCallback; - - TextureDefinition(GLenum target, - GLuint service_id, - GLenum min_filter, - GLenum mag_filter, - GLenum wrap_s, - GLenum wrap_t, - GLenum usage, - bool immutable, - bool stream_texture, - const LevelInfos& level_infos); - ~TextureDefinition(); - - GLenum target() const { - return target_; - } - - GLuint ReleaseServiceId(); - GLuint service_id() const { return service_id_; } - GLenum min_filter() const { return min_filter_; } - GLenum mag_filter() const { return mag_filter_; } - GLenum wrap_s() const { return wrap_s_; } - GLenum wrap_t() const { return wrap_t_; } - GLenum usage() const { return usage_; } - - bool immutable() const { return immutable_; } - bool stream_texture() const { return stream_texture_; } - - const LevelInfos& level_infos() const { - return level_infos_; - } - - private: - GLenum target_; - GLuint service_id_; - GLenum min_filter_; - GLenum mag_filter_; - GLenum wrap_s_; - GLenum wrap_t_; - GLenum usage_; - bool immutable_; - bool stream_texture_; - std::vector<std::vector<LevelInfo> > level_infos_; - - DISALLOW_COPY_AND_ASSIGN(TextureDefinition); -}; - -} // namespage gles2 -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index e2fac59..9e67849 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -12,7 +12,6 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" -#include "gpu/command_buffer/service/texture_definition.h" namespace gpu { namespace gles2 { @@ -89,7 +88,8 @@ void TextureManager::Destroy(bool have_context) { } Texture::Texture(GLuint service_id) - : memory_tracking_ref_(NULL), + : mailbox_manager_(NULL), + memory_tracking_ref_(NULL), service_id_(service_id), cleared_(true), num_uncleared_mips_(0), @@ -114,6 +114,8 @@ Texture::Texture(GLuint service_id) } Texture::~Texture() { + if (mailbox_manager_) + mailbox_manager_->TextureDeleted(this); } void Texture::AddTextureRef(TextureRef* ref) { @@ -266,6 +268,11 @@ void Texture::AddToSignature( usage_); } +void Texture::SetMailboxManager(MailboxManager* mailbox_manager) { + DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager); + mailbox_manager_ = mailbox_manager; +} + bool Texture::MarkMipmapsGenerated( const FeatureInfo* feature_info) { if (!CanGenerateMipmaps(feature_info)) { @@ -794,9 +801,12 @@ gfx::GLImage* Texture::GetLevelImage( } -TextureRef::TextureRef(TextureManager* manager, Texture* texture) +TextureRef::TextureRef(TextureManager* manager, + GLuint client_id, + Texture* texture) : manager_(manager), - texture_(texture) { + texture_(texture), + client_id_(client_id) { DCHECK(manager_); DCHECK(texture_); texture_->AddTextureRef(this); @@ -804,8 +814,9 @@ TextureRef::TextureRef(TextureManager* manager, Texture* texture) } scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager, + GLuint client_id, GLuint service_id) { - return new TextureRef(manager, new Texture(service_id)); + return new TextureRef(manager, client_id, new Texture(service_id)); } TextureRef::~TextureRef() { @@ -814,7 +825,6 @@ TextureRef::~TextureRef() { manager_ = NULL; } - TextureManager::TextureManager( MemoryTracker* memory_tracker, FeatureInfo* feature_info, @@ -897,7 +907,8 @@ scoped_refptr<TextureRef> } glBindTexture(target, 0); - scoped_refptr<TextureRef> default_texture(TextureRef::Create(this, ids[1])); + scoped_refptr<TextureRef> default_texture( + TextureRef::Create(this, 0, ids[1])); SetTarget(default_texture, target); if (needs_faces) { for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { @@ -999,140 +1010,22 @@ void TextureManager::SetLevelInfo( texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); } -TextureDefinition* TextureManager::Save(TextureRef* ref) { +Texture* TextureManager::Produce(TextureRef* ref) { DCHECK(ref); Texture* texture = ref->texture(); - DCHECK(texture->owned_); - - if (texture->IsAttachedToFramebuffer()) + if (!texture->owned_) return NULL; + return texture; +} - TextureDefinition::LevelInfos level_infos(texture->level_infos_.size()); - for (size_t face = 0; face < level_infos.size(); ++face) { - GLenum target = - texture->target() == GL_TEXTURE_CUBE_MAP ? FaceIndexToGLTarget(face) - : texture->target(); - for (GLint level = 0; level <= texture->max_level_set_; ++level) { - const Texture::LevelInfo& level_info = - texture->level_infos_[face][level]; - - level_infos[face].push_back( - TextureDefinition::LevelInfo(target, - level_info.internal_format, - level_info.width, - level_info.height, - level_info.depth, - level_info.border, - level_info.format, - level_info.type, - level_info.cleared)); - - SetLevelInfo(ref, - target, - level, - GL_RGBA, - 0, - 0, - 0, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); - } - } - - GLuint old_service_id = texture->service_id(); - bool immutable = texture->IsImmutable(); - bool stream_texture = texture->IsStreamTexture(); - - GLuint new_service_id = 0; - glGenTextures(1, &new_service_id); - texture->SetServiceId(new_service_id); - texture->SetImmutable(false); - texture->SetStreamTexture(false); - - return new TextureDefinition(texture->target(), - old_service_id, - texture->min_filter(), - texture->mag_filter(), - texture->wrap_s(), - texture->wrap_t(), - texture->usage(), - immutable, - stream_texture, - level_infos); -} - -bool TextureManager::Restore( - const char* function_name, - GLES2Decoder* decoder, - TextureRef* ref, - TextureDefinition* definition) { - DCHECK(ref); - Texture* texture = ref->texture(); - DCHECK(texture->owned_); - - scoped_ptr<TextureDefinition> scoped_definition(definition); - - if (texture->IsAttachedToFramebuffer()) - return false; - - if (texture->target() != definition->target()) - return false; - - if (texture->level_infos_.size() < definition->level_infos().size()) - return false; - - if (texture->level_infos_[0].size() < definition->level_infos()[0].size()) - return false; - - for (size_t face = 0; face < definition->level_infos().size(); ++face) { - GLenum target = - texture->target() == GL_TEXTURE_CUBE_MAP ? FaceIndexToGLTarget(face) - : texture->target(); - GLint new_max_level = definition->level_infos()[face].size() - 1; - for (GLint level = 0; - level <= std::max(texture->max_level_set_, new_max_level); - ++level) { - const TextureDefinition::LevelInfo& level_info = - level <= new_max_level ? definition->level_infos()[face][level] - : TextureDefinition::LevelInfo(); - SetLevelInfo(ref, - target, - level, - level_info.internal_format, - level_info.width, - level_info.height, - level_info.depth, - level_info.border, - level_info.format, - level_info.type, - level_info.cleared); - } - } - - GLuint old_service_id = texture->service_id(); - glDeleteTextures(1, &old_service_id); - texture->SetServiceId(definition->ReleaseServiceId()); - glBindTexture(texture->target(), texture->service_id()); - texture->SetImmutable(definition->immutable()); - texture->SetStreamTexture(definition->stream_texture()); - ErrorState* error_state = decoder->GetErrorState(); - SetParameter(function_name, error_state, ref, GL_TEXTURE_MIN_FILTER, - definition->min_filter()); - SetParameter(function_name, error_state, ref, GL_TEXTURE_MAG_FILTER, - definition->mag_filter()); - SetParameter(function_name, error_state, ref, GL_TEXTURE_WRAP_S, - definition->wrap_s()); - SetParameter(function_name, error_state, ref, GL_TEXTURE_WRAP_T, - definition->wrap_t()); - if (feature_info_->validators()->texture_parameter.IsValid( - GL_TEXTURE_USAGE_ANGLE)) { - SetParameter(function_name, error_state, ref, GL_TEXTURE_USAGE_ANGLE, - definition->usage()); - } - - return true; +TextureRef* TextureManager::Consume( + GLuint client_id, + Texture* texture) { + DCHECK(client_id); + scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture)); + bool result = textures_.insert(std::make_pair(client_id, ref)).second; + DCHECK(result); + return ref.get(); } void TextureManager::SetParameter( @@ -1171,7 +1064,8 @@ bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) { TextureRef* TextureManager::CreateTexture( GLuint client_id, GLuint service_id) { DCHECK_NE(0u, service_id); - scoped_refptr<TextureRef> ref(TextureRef::Create(this, service_id)); + scoped_refptr<TextureRef> ref(TextureRef::Create( + this, client_id, service_id)); std::pair<TextureMap::iterator, bool> result = textures_.insert(std::make_pair(client_id, ref)); DCHECK(result.second); @@ -1187,6 +1081,7 @@ TextureRef* TextureManager::GetTexture( void TextureManager::RemoveTexture(GLuint client_id) { TextureMap::iterator it = textures_.find(client_id); if (it != textures_.end()) { + it->second->reset_client_id(); textures_.erase(it); } } @@ -1231,16 +1126,15 @@ MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) { return NULL; } -bool TextureManager::GetClientId(GLuint service_id, GLuint* client_id) const { +Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const { // This doesn't need to be fast. It's only used during slow queries. for (TextureMap::const_iterator it = textures_.begin(); it != textures_.end(); ++it) { - if (it->second->texture()->service_id() == service_id) { - *client_id = it->first; - return true; - } + Texture* texture = it->second->texture(); + if (texture->service_id() == service_id) + return texture; } - return false; + return NULL; } GLsizei TextureManager::ComputeMipMapCount( diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index af5eb0c..ec0b5a6 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -27,7 +27,7 @@ class Display; class ErrorState; class FeatureInfo; class FramebufferManager; -class TextureDefinition; +class MailboxManager; class TextureManager; class TextureRef; @@ -170,6 +170,7 @@ class GPU_EXPORT Texture { } private: + friend class MailboxManager; friend class TextureManager; friend class TextureRef; friend class TextureTestHelper; @@ -304,6 +305,8 @@ class GPU_EXPORT Texture { const FeatureInfo* feature_info, GLenum target, GLint level, std::string* signature) const; + void SetMailboxManager(MailboxManager* mailbox_manager); + // Updates the unsafe textures count in all the managers referencing this // texture. void UpdateSafeToRenderFrom(bool cleared); @@ -323,6 +326,8 @@ class GPU_EXPORT Texture { // referencing this texture. void IncAllFramebufferStateChangeCount(); + MailboxManager* mailbox_manager_; + // Info about each face and level of texture. std::vector<std::vector<LevelInfo> > level_infos_; @@ -397,11 +402,13 @@ class GPU_EXPORT Texture { // Multiple TextureRef can point to the same texture with cross-context sharing. class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { public: - TextureRef(TextureManager* manager, Texture* texture); + TextureRef(TextureManager* manager, GLuint client_id, Texture* texture); static scoped_refptr<TextureRef> Create(TextureManager* manager, + GLuint client_id, GLuint service_id); const Texture* texture() const { return texture_; } Texture* texture() { return texture_; } + GLuint client_id() const { return client_id_; } GLuint service_id() const { return texture_->service_id(); } // Sets the async transfer state for this texture. Only a single TextureRef @@ -424,9 +431,11 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { AsyncPixelTransferState* async_transfer_state() const { return async_transfer_state_.get(); } + void reset_client_id() { client_id_ = 0; } TextureManager* manager_; Texture* texture_; + GLuint client_id_; // State to facilitate async transfers on this texture. scoped_ptr<AsyncPixelTransferState> async_transfer_state_; @@ -543,15 +552,10 @@ class GPU_EXPORT TextureManager { params.type, true /* cleared */ ); } - // Save the texture definition and leave it undefined. - TextureDefinition* Save(TextureRef* ref); + Texture* Produce(TextureRef* ref); - // Redefine all the levels from the texture definition. - bool Restore( - const char* function_name, - GLES2Decoder* decoder, - TextureRef* ref, - TextureDefinition* definition); + // Maps an existing texture into the texture manager, at a given client ID. + TextureRef* Consume(GLuint client_id, Texture* texture); // Sets a mip as cleared. void SetLevelCleared(TextureRef* ref, GLenum target, @@ -584,8 +588,9 @@ class GPU_EXPORT TextureManager { // Removes a texture info. void RemoveTexture(GLuint client_id); - // Gets a client id for a given service id. - bool GetClientId(GLuint service_id, GLuint* client_id) const; + // Gets a Texture for a given service id (note: it assumes the texture object + // is still mapped in this TextureManager). + Texture* GetTextureForServiceId(GLuint service_id) const; TextureRef* GetDefaultTextureInfo(GLenum target) { switch (target) { diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index c66ffa6..b5a0e61 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -9,10 +9,10 @@ #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/mocks.h" #include "gpu/command_buffer/service/test_helper.h" -#include "gpu/command_buffer/service/texture_definition.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" @@ -109,12 +109,12 @@ TEST_F(TextureManagerTest, Basic) { // Check we can create texture. manager_->CreateTexture(kClient1Id, kService1Id); // Check texture got created. - TextureRef* texture = manager_->GetTexture(kClient1Id); + scoped_refptr<TextureRef> texture = manager_->GetTexture(kClient1Id); ASSERT_TRUE(texture != NULL); EXPECT_EQ(kService1Id, texture->service_id()); - GLuint client_id = 0; - EXPECT_TRUE(manager_->GetClientId(texture->service_id(), &client_id)); - EXPECT_EQ(kClient1Id, client_id); + EXPECT_EQ(kClient1Id, texture->client_id()); + EXPECT_EQ(texture->texture(), manager_->GetTextureForServiceId( + texture->service_id())); // Check we get nothing for a non-existent texture. EXPECT_TRUE(manager_->GetTexture(kClient2Id) == NULL); // Check trying to a remove non-existent textures does not crash. @@ -126,6 +126,7 @@ TEST_F(TextureManagerTest, Basic) { // Check we can't get the texture after we remove it. manager_->RemoveTexture(kClient1Id); EXPECT_TRUE(manager_->GetTexture(kClient1Id) == NULL); + EXPECT_EQ(0u, texture->client_id()); } TEST_F(TextureManagerTest, SetParameter) { @@ -393,10 +394,9 @@ class TextureTestBase : public testing::Test { virtual void TearDown() { if (texture_ref_.get()) { - GLuint client_id = 0; // If it's not in the manager then setting texture_ref_ to NULL will // delete the texture. - if (!manager_->GetClientId(texture_ref_->service_id(), &client_id)) { + if (!texture_ref_->client_id()) { // Check that it gets deleted when the last reference is released. EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(texture_ref_->service_id()))) @@ -1326,7 +1326,7 @@ TEST_F(TextureTest, AddToSignature) { EXPECT_EQ(11u, string_set.size()); } -class SaveRestoreTextureTest : public TextureTest { +class ProduceConsumeTextureTest : public TextureTest { public: virtual void SetUp() { TextureTest::SetUpBase(NULL, "GL_OES_EGL_image_external"); @@ -1339,10 +1339,9 @@ class SaveRestoreTextureTest : public TextureTest { virtual void TearDown() { if (texture2_.get()) { - GLuint client_id = 0; // If it's not in the manager then setting texture2_ to NULL will // delete the texture. - if (!manager_->GetClientId(texture2_->service_id(), &client_id)) { + if (!texture2_->client_id()) { // Check that it gets deleted when the last reference is released. EXPECT_CALL( *gl_, @@ -1430,39 +1429,27 @@ class SaveRestoreTextureTest : public TextureTest { return info; } - TextureDefinition* Save(TextureRef* texture_ref) { - EXPECT_CALL(*gl_, GenTextures(_, _)) - .WillOnce(SetArgumentPointee<1>(kEmptyTextureServiceId)); - TextureDefinition* definition = manager_->Save(texture_ref); - EXPECT_TRUE(definition != NULL); - return definition; + Texture* Produce(TextureRef* texture_ref) { + Texture* texture = manager_->Produce(texture_ref); + EXPECT_TRUE(texture != NULL); + return texture; } - void Restore(TextureRef* texture_ref, TextureDefinition* definition) { - EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(texture_ref->service_id()))) - .Times(1).RetiresOnSaturation(); - EXPECT_CALL(*gl_, - BindTexture(definition->target(), definition->service_id())) - .Times(1).RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(AtLeast(1)); - - EXPECT_TRUE(manager_->Restore("TextureTest", decoder_.get(), - texture_ref, definition)); + void Consume(GLuint client_id, Texture* texture) { + EXPECT_TRUE(manager_->Consume(client_id, texture)); } scoped_refptr<TextureRef> texture2_; private: - static const GLuint kEmptyTextureServiceId; static const GLuint kClient2Id; static const GLuint kService2Id; }; -const GLuint SaveRestoreTextureTest::kClient2Id = 2; -const GLuint SaveRestoreTextureTest::kService2Id = 12; -const GLuint SaveRestoreTextureTest::kEmptyTextureServiceId = 13; +const GLuint ProduceConsumeTextureTest::kClient2Id = 2; +const GLuint ProduceConsumeTextureTest::kService2Id = 12; -TEST_F(SaveRestoreTextureTest, SaveRestore2D) { +TEST_F(ProduceConsumeTextureTest, ProduceConsume2D) { manager_->SetTarget(texture_ref_, GL_TEXTURE_2D); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); @@ -1473,13 +1460,11 @@ TEST_F(SaveRestoreTextureTest, SaveRestore2D) { EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); LevelInfo level1 = GetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1); LevelInfo level2 = GetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2); - scoped_ptr<TextureDefinition> definition(Save(texture_ref_)); - const TextureDefinition::LevelInfos& infos = definition->level_infos(); - EXPECT_EQ(1U, infos.size()); - EXPECT_EQ(3U, infos[0].size()); + Texture* produced_texture = Produce(texture_ref_); + EXPECT_EQ(produced_texture, texture); // Make this texture bigger with more levels, and make sure they get - // clobbered correctly during Restore(). + // clobbered correctly during Consume(). manager_->SetTarget(texture2_, GL_TEXTURE_2D); SetLevelInfo( texture2_, @@ -1489,18 +1474,26 @@ TEST_F(SaveRestoreTextureTest, SaveRestore2D) { texture = texture2_->texture(); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_EQ(1024U + 256U + 64U + 16U + 4U, texture->estimated_size()); - Restore(texture2_, definition.release()); - EXPECT_EQ(level0, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 0)); - EXPECT_EQ(level1, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 1)); - EXPECT_EQ(level2, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 2)); + + GLuint client_id = texture2_->client_id(); + manager_->RemoveTexture(client_id); + Consume(client_id, produced_texture); + scoped_refptr<TextureRef> restored_texture = manager_->GetTexture(client_id); + EXPECT_EQ(produced_texture, restored_texture->texture()); + EXPECT_EQ(level0, GetLevelInfo(restored_texture.get(), GL_TEXTURE_2D, 0)); + EXPECT_EQ(level1, GetLevelInfo(restored_texture.get(), GL_TEXTURE_2D, 1)); + EXPECT_EQ(level2, GetLevelInfo(restored_texture.get(), GL_TEXTURE_2D, 2)); + texture = restored_texture->texture(); EXPECT_EQ(64U + 16U + 4U, texture->estimated_size()); GLint w, h; - EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 3, &w, &h)); - EXPECT_EQ(0, w); - EXPECT_EQ(0, h); + EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 3, &w, &h)); + + // However the old texture ref still exists if it was referenced somewhere. + EXPECT_EQ(1024U + 256U + 64U + 16U + 4U, + texture2_->texture()->estimated_size()); } -TEST_F(SaveRestoreTextureTest, SaveRestoreClearRectangle) { +TEST_F(ProduceConsumeTextureTest, ProduceConsumeClearRectangle) { manager_->SetTarget(texture_ref_, GL_TEXTURE_RECTANGLE_ARB); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), texture->target()); @@ -1508,38 +1501,46 @@ TEST_F(SaveRestoreTextureTest, SaveRestoreClearRectangle) { GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, false); SetLevelInfo(texture_ref_, 0, level0); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); - scoped_ptr<TextureDefinition> definition(Save(texture_ref_)); - const TextureDefinition::LevelInfos& infos = definition->level_infos(); - EXPECT_EQ(1U, infos.size()); - EXPECT_EQ(1U, infos[0].size()); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), infos[0][0].target); - manager_->SetTarget(texture2_, GL_TEXTURE_RECTANGLE_ARB); - Restore(texture2_, definition.release()); + Texture* produced_texture = Produce(texture_ref_); + EXPECT_EQ(produced_texture, texture); + EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), + produced_texture->target()); + + GLuint client_id = texture2_->client_id(); + manager_->RemoveTexture(client_id); + Consume(client_id, produced_texture); + scoped_refptr<TextureRef> restored_texture = manager_->GetTexture(client_id); + EXPECT_EQ(produced_texture, restored_texture->texture()); // See if we can clear the previously uncleared level now. - EXPECT_EQ(level0, GetLevelInfo(texture2_.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); + EXPECT_EQ(level0, + GetLevelInfo(restored_texture.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); EXPECT_TRUE(manager_->ClearTextureLevel( - decoder_.get(), texture2_, GL_TEXTURE_RECTANGLE_ARB, 0)); + decoder_.get(), restored_texture, GL_TEXTURE_RECTANGLE_ARB, 0)); } -TEST_F(SaveRestoreTextureTest, SaveRestoreStreamTexture) { +TEST_F(ProduceConsumeTextureTest, ProduceConsumeStreamTexture) { manager_->SetTarget(texture_ref_, GL_TEXTURE_EXTERNAL_OES); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target()); manager_->SetStreamTexture(texture_ref_, true); GLuint service_id = texture->service_id(); - scoped_ptr<TextureDefinition> definition(Save(texture_ref_)); - EXPECT_FALSE(texture->IsStreamTexture()); - manager_->SetTarget(texture2_, GL_TEXTURE_EXTERNAL_OES); - Restore(texture2_, definition.release()); - EXPECT_TRUE(texture2_->texture()->IsStreamTexture()); - EXPECT_TRUE(texture2_->texture()->IsImmutable()); - EXPECT_EQ(service_id, texture2_->service_id()); + Texture* produced_texture = Produce(texture_ref_); + EXPECT_TRUE(texture->IsStreamTexture()); + + GLuint client_id = texture2_->client_id(); + manager_->RemoveTexture(client_id); + Consume(client_id, produced_texture); + scoped_refptr<TextureRef> restored_texture = manager_->GetTexture(client_id); + EXPECT_EQ(produced_texture, restored_texture->texture()); + EXPECT_TRUE(restored_texture->texture()->IsStreamTexture()); + EXPECT_TRUE(restored_texture->texture()->IsImmutable()); + EXPECT_EQ(service_id, restored_texture->service_id()); } -TEST_F(SaveRestoreTextureTest, SaveRestoreCube) { +TEST_F(ProduceConsumeTextureTest, ProduceConsumeCube) { manager_->SetTarget(texture_ref_, GL_TEXTURE_CUBE_MAP); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture->target()); @@ -1562,16 +1563,18 @@ TEST_F(SaveRestoreTextureTest, SaveRestoreCube) { SetLevelInfo(texture_ref_, 0, face0); SetLevelInfo(texture_ref_, 0, face5); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); - scoped_ptr<TextureDefinition> definition(Save(texture_ref_)); - const TextureDefinition::LevelInfos& infos = definition->level_infos(); - EXPECT_EQ(6U, infos.size()); - EXPECT_EQ(1U, infos[0].size()); - manager_->SetTarget(texture2_, GL_TEXTURE_CUBE_MAP); - Restore(texture2_, definition.release()); + Texture* produced_texture = Produce(texture_ref_); + EXPECT_EQ(produced_texture, texture); + + GLuint client_id = texture2_->client_id(); + manager_->RemoveTexture(client_id); + Consume(client_id, produced_texture); + scoped_refptr<TextureRef> restored_texture = manager_->GetTexture(client_id); + EXPECT_EQ(produced_texture, restored_texture->texture()); EXPECT_EQ(face0, - GetLevelInfo(texture2_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)); + GetLevelInfo(restored_texture, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)); EXPECT_EQ(face5, - GetLevelInfo(texture2_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0)); + GetLevelInfo(restored_texture, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0)); } class CountingMemoryTracker : public MemoryTracker { @@ -1653,8 +1656,8 @@ class SharedTextureTest : public testing::Test { TEST_F(SharedTextureTest, DeleteTextures) { scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10); - scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(), - ref1->texture()); + scoped_refptr<TextureRef> ref2 = + texture_manager2_->Consume(20, ref1->texture()); EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(0); ref1 = NULL; @@ -1665,6 +1668,7 @@ TEST_F(SharedTextureTest, DeleteTextures) { .Times(1) .RetiresOnSaturation(); ref2 = NULL; + texture_manager2_->RemoveTexture(20); testing::Mock::VerifyAndClearExpectations(gl_.get()); } @@ -1676,7 +1680,7 @@ TEST_F(SharedTextureTest, TextureSafetyAccounting) { EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager2_->HaveUnclearedMips()); - // Newly created texture is unrenderable. + // Newly created texture is renderable. scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10); EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures()); @@ -1684,8 +1688,8 @@ TEST_F(SharedTextureTest, TextureSafetyAccounting) { // Associate new texture ref to other texture manager, should account for it // too. - scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(), - ref1->texture()); + scoped_refptr<TextureRef> ref2 = + texture_manager2_->Consume(20, ref1->texture()); EXPECT_FALSE(texture_manager2_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager2_->HaveUnclearedMips()); @@ -1720,6 +1724,7 @@ TEST_F(SharedTextureTest, TextureSafetyAccounting) { .Times(1) .RetiresOnSaturation(); texture_manager1_->RemoveTexture(10); + texture_manager2_->RemoveTexture(20); } TEST_F(SharedTextureTest, FBOCompletenessCheck) { @@ -1746,8 +1751,8 @@ TEST_F(SharedTextureTest, FBOCompletenessCheck) { EXPECT_TRUE(framebuffer_manager1.IsComplete(framebuffer1)); // Share texture with manager 2. - scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(), - ref1->texture()); + scoped_refptr<TextureRef> ref2 = + texture_manager2_->Consume(20, ref1->texture()); framebuffer_manager2.CreateFramebuffer(20, 20); scoped_refptr<Framebuffer> framebuffer2 = framebuffer_manager2.GetFramebuffer(20); @@ -1778,6 +1783,7 @@ TEST_F(SharedTextureTest, FBOCompletenessCheck) { .Times(1) .RetiresOnSaturation(); texture_manager1_->RemoveTexture(10); + texture_manager2_->RemoveTexture(20); } TEST_F(SharedTextureTest, Memory) { @@ -1796,8 +1802,8 @@ TEST_F(SharedTextureTest, Memory) { // Associate new texture ref to other texture manager, it doesn't account for // the texture memory, the first memory tracker still has it. - scoped_refptr<TextureRef> ref2 = new TextureRef(texture_manager2_.get(), - ref1->texture()); + scoped_refptr<TextureRef> ref2 = + texture_manager2_->Consume(20, ref1->texture()); EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(), memory_tracker1_->GetSize(MemoryTracker::kUnmanaged)); EXPECT_EQ(initial_memory2, @@ -1815,6 +1821,7 @@ TEST_F(SharedTextureTest, Memory) { .Times(1) .RetiresOnSaturation(); ref2 = NULL; + texture_manager2_->RemoveTexture(20); EXPECT_EQ(initial_memory2, memory_tracker2_->GetSize(MemoryTracker::kUnmanaged)); } diff --git a/gpu/command_buffer/tests/gl_texture_mailbox_unittests.cc b/gpu/command_buffer/tests/gl_texture_mailbox_unittests.cc index 6491e41..566189f 100644 --- a/gpu/command_buffer/tests/gl_texture_mailbox_unittests.cc +++ b/gpu/command_buffer/tests/gl_texture_mailbox_unittests.cc @@ -167,5 +167,104 @@ TEST_F(GLTextureMailboxTest, ConsumeTextureValidatesKey) { EXPECT_EQ(source_pixel, ReadTexel(tex, 0, 0)); EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); } + +TEST_F(GLTextureMailboxTest, SharedTextures) { + gl1_.MakeCurrent(); + GLuint tex1; + glGenTextures(1, &tex1); + + glBindTexture(GL_TEXTURE_2D, tex1); + uint32 source_pixel = 0xFF0000FF; + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + &source_pixel); + GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; + glGenMailboxCHROMIUM(mailbox); + + glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + glFlush(); + + gl2_.MakeCurrent(); + GLuint tex2; + glGenTextures(1, &tex2); + + glBindTexture(GL_TEXTURE_2D, tex2); + glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // Change texture in context 2. + source_pixel = 0xFF00FF00; + glTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, 0, + 1, 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + &source_pixel); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + glFlush(); + + // Check it in context 1. + gl1_.MakeCurrent(); + EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0)); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // Change parameters (note: ReadTexel will reset those). + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_NEAREST); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + glFlush(); + + // Check in context 2. + gl2_.MakeCurrent(); + GLint parameter = 0; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ¶meter); + EXPECT_EQ(GL_REPEAT, parameter); + parameter = 0; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ¶meter); + EXPECT_EQ(GL_LINEAR, parameter); + parameter = 0; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ¶meter); + EXPECT_EQ(GL_LINEAR_MIPMAP_NEAREST, parameter); + + // Delete texture in context 1. + gl1_.MakeCurrent(); + glDeleteTextures(1, &tex1); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // Check texture still exists in context 2. + gl2_.MakeCurrent(); + EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // The mailbox should still exist too. + GLuint tex3; + glGenTextures(1, &tex3); + glBindTexture(GL_TEXTURE_2D, tex3); + glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // Delete both textures. + glDeleteTextures(1, &tex2); + glDeleteTextures(1, &tex3); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // Mailbox should be gone now. + glGenTextures(1, &tex2); + glBindTexture(GL_TEXTURE_2D, tex2); + glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); + glDeleteTextures(1, &tex2); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); +} + } // namespace gpu diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi index 9e291da..8895526 100644 --- a/gpu/command_buffer_service.gypi +++ b/gpu/command_buffer_service.gypi @@ -112,8 +112,6 @@ 'command_buffer/service/shader_translator_cache.cc', 'command_buffer/service/stream_texture.h', 'command_buffer/service/stream_texture_manager.h', - 'command_buffer/service/texture_definition.cc', - 'command_buffer/service/texture_definition.h', 'command_buffer/service/texture_manager.h', 'command_buffer/service/texture_manager.cc', 'command_buffer/service/transfer_buffer_manager.cc', |