From 44429f23f3899d52c9493c114ae9b62e1ddeb7af Mon Sep 17 00:00:00 2001 From: reveman Date: Mon, 19 Oct 2015 16:38:48 -0700 Subject: Revert of ui: Move GLImage::BindTexImage fallback from GLImage implementations to GLES2CmdDecoder. (patchset #15 id:280001 of https://codereview.chromium.org/1401423003/ ) Reason for revert: Causing android gpu bots to fail Original issue's description: > ui: Move GLImage::BindTexImage fallback from GLImage implementations to GLES2CmdDecoder. > > This allows the GPU service to properly track the memory usage > image backed textures. > > It also reduces the complexity of GLImage implementations > significantly and makes it easier to support format and > buffer types that require a copy or conversion of data to > be used for sampling. > > This change also includes a few minor GLImage cleanups such > as removing gfx:: namespace prefix in places where it's not > needed and making the CopyTexImage GLImage test not part of > the core GLImage tests as it's optional to support that > function. > > BUG=526298 > TEST=gl_tests --gtest_filter=GpuMemoryBuffer*, gpu_unittests, gl_unittests --gtest_filter=GLImage* > > Committed: https://crrev.com/ac2696e324bda3824952148f831e76a8b80594b3 > Cr-Commit-Position: refs/heads/master@{#354870} TBR=dcastagna@chromium.org,ericrk@chromium.org,fsamuel@chromium.org,liberato@chromium.org,sievers@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=526298 Review URL: https://codereview.chromium.org/1418483003 Cr-Commit-Position: refs/heads/master@{#354914} --- components/mus/gles2/command_buffer_local.cc | 11 +- .../android_deferred_rendering_backing_strategy.cc | 2 +- content/common/gpu/media/avda_codec_image.cc | 50 ++-- content/common/gpu/media/avda_codec_image.h | 5 +- .../gpu/media/gpu_video_decode_accelerator.cc | 6 +- content/common/gpu/stream_texture_android.cc | 26 +- content/common/gpu/stream_texture_android.h | 6 +- gpu/command_buffer/service/framebuffer_manager.cc | 47 ++++ gpu/command_buffer/service/framebuffer_manager.h | 37 +++ gpu/command_buffer/service/gles2_cmd_decoder.cc | 276 +++++++++++++++------ .../service/gles2_cmd_decoder_unittest_textures.cc | 99 +++++--- gpu/command_buffer/service/mailbox_manager_sync.cc | 8 +- .../stream_texture_manager_in_process_android.cc | 46 ++-- gpu/command_buffer/service/texture_definition.cc | 37 ++- gpu/command_buffer/service/texture_manager.cc | 63 ++--- gpu/command_buffer/service/texture_manager.h | 48 ++-- .../service/texture_manager_unittest.cc | 18 +- ui/gl/BUILD.gn | 1 - ui/gl/gl_image.h | 32 +-- ui/gl/gl_image_egl.cc | 15 +- ui/gl/gl_image_egl.h | 13 +- ui/gl/gl_image_glx.cc | 52 ++-- ui/gl/gl_image_glx.h | 13 +- ui/gl/gl_image_io_surface.h | 23 +- ui/gl/gl_image_io_surface.mm | 28 +-- ui/gl/gl_image_memory.cc | 224 +++++++++++++++-- ui/gl/gl_image_memory.h | 29 ++- ui/gl/gl_image_ozone_native_pixmap.cc | 23 +- ui/gl/gl_image_ozone_native_pixmap.h | 2 +- ui/gl/gl_image_ref_counted_memory.cc | 15 +- ui/gl/gl_image_ref_counted_memory.h | 4 +- ui/gl/gl_image_ref_counted_memory_unittest.cc | 4 - ui/gl/gl_image_shared_memory.cc | 29 ++- ui/gl/gl_image_shared_memory.h | 9 +- ui/gl/gl_image_shared_memory_unittest.cc | 4 - ui/gl/gl_image_stub.cc | 10 +- ui/gl/gl_image_stub.h | 9 +- ui/gl/gl_image_surface_texture.cc | 15 +- ui/gl/gl_image_surface_texture.h | 13 +- ui/gl/gl_tests.gyp | 1 - ui/gl/test/gl_image_test_template.h | 62 +---- 41 files changed, 867 insertions(+), 548 deletions(-) diff --git a/components/mus/gles2/command_buffer_local.cc b/components/mus/gles2/command_buffer_local.cc index 138f707..ede0274 100644 --- a/components/mus/gles2/command_buffer_local.cc +++ b/components/mus/gles2/command_buffer_local.cc @@ -5,7 +5,6 @@ #include "components/mus/gles2/command_buffer_local.h" #include "base/bind.h" -#include "base/memory/shared_memory.h" #include "components/mus/gles2/command_buffer_local_client.h" #include "components/mus/gles2/gpu_memory_tracker.h" #include "components/mus/gles2/mojo_gpu_memory_buffer.h" @@ -20,7 +19,7 @@ #include "gpu/command_buffer/service/valuebuffer_manager.h" #include "ui/gfx/vsync_provider.h" #include "ui/gl/gl_context.h" -#include "ui/gl/gl_image_shared_memory.h" +#include "ui/gl/gl_image_memory.h" #include "ui/gl/gl_surface.h" namespace mus { @@ -136,12 +135,12 @@ int32_t CommandBufferLocal::CreateImage(ClientBuffer buffer, MojoGpuMemoryBufferImpl* gpu_memory_buffer = MojoGpuMemoryBufferImpl::FromClientBuffer(buffer); - gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->GetHandle(); - scoped_refptr image(new gfx::GLImageSharedMemory( + scoped_refptr image(new gfx::GLImageMemory( gfx::Size(static_cast(width), static_cast(height)), internalformat)); - if (!image->Initialize(base::SharedMemory::DuplicateHandle(handle.handle), - handle.id, gpu_memory_buffer->GetFormat())) { + if (!image->Initialize( + static_cast(gpu_memory_buffer->GetMemory()), + gpu_memory_buffer->GetFormat())) { return -1; } diff --git a/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc b/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc index db83791..cdfc7af 100644 --- a/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc +++ b/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc @@ -110,7 +110,7 @@ void AndroidDeferredRenderingBackingStrategy::SetImageForPicture( } texture_manager->SetLevelImage(texture_ref, GetTextureTarget(), 0, - image.get(), gpu::gles2::Texture::UNBOUND); + image.get()); } void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( diff --git a/content/common/gpu/media/avda_codec_image.cc b/content/common/gpu/media/avda_codec_image.cc index b6242a9..062b39b 100644 --- a/content/common/gpu/media/avda_codec_image.cc +++ b/content/common/gpu/media/avda_codec_image.cc @@ -5,7 +5,6 @@ #include "content/common/gpu/media/avda_codec_image.h" #include "content/common/gpu/media/avda_shared_state.h" -#include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/context_state.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/texture_manager.h" @@ -51,12 +50,18 @@ unsigned AVDACodecImage::GetInternalFormat() { } bool AVDACodecImage::BindTexImage(unsigned target) { - return false; + return true; } void AVDACodecImage::ReleaseTexImage(unsigned target) {} -bool AVDACodecImage::CopyTexImage(unsigned target) { +bool AVDACodecImage::CopyTexSubImage(unsigned target, + const gfx::Point& offset, + const gfx::Rect& rect) { + return false; +} + +void AVDACodecImage::WillUseTexImage() { // Have we bound the SurfaceTexture's texture handle to the active // texture unit yet? bool bound_texture = false; @@ -70,38 +75,29 @@ bool AVDACodecImage::CopyTexImage(unsigned target) { // Make sure that we have the right image in the front buffer. bound_texture |= UpdateSurfaceTexture(); + // TODO(liberato): Handle the texture matrix properly. + // Either we can update the shader with it or we can move all of the logic + // to updateTexImage() to the right place in the cc to send it to the shader. + // For now, we just skip it. crbug.com/530681 + // Sneakily bind the ST texture handle in the real GL context. // If we called UpdateTexImage() to update the ST front buffer, then we can // skip this. Since one draw/frame is the common case, we optimize for it. if (!bound_texture) glBindTexture(GL_TEXTURE_EXTERNAL_OES, shared_state_->surface_texture_service_id()); - - // TODO(liberato): Handle the texture matrix properly. - // Either we can update the shader with it or we can move all of the logic - // to updateTexImage() to the right place in the cc to send it to the shader. - // For now, we just skip it. crbug.com/530681 - - gpu::gles2::TextureManager* texture_manager = - decoder_->GetContextGroup()->texture_manager(); - gpu::gles2::Texture* texture = - texture_manager->GetTextureForServiceId( - shared_state_->surface_texture_service_id()); - if (texture) { - // By setting image state to UNBOUND instead of COPIED we ensure that - // CopyTexImage() is called each time the surface texture is used for - // drawing. - texture->SetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0, this, - gpu::gles2::Texture::UNBOUND); - } - - return true; } -bool AVDACodecImage::CopyTexSubImage(unsigned target, - const gfx::Point& offset, - const gfx::Rect& rect) { - return false; +void AVDACodecImage::DidUseTexImage() { + // Unbind the ST's service_id in the real GL context in favor of whatever + // the decoder thinks is bound there. + const gpu::gles2::ContextState* state = decoder_->GetContextState(); + const gpu::gles2::TextureUnit& active_unit = + state->texture_units[state->active_texture_unit]; + glBindTexture(GL_TEXTURE_EXTERNAL_OES, + active_unit.bound_texture_external_oes.get() + ? active_unit.bound_texture_external_oes->service_id() + : 0); } bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, diff --git a/content/common/gpu/media/avda_codec_image.h b/content/common/gpu/media/avda_codec_image.h index 0ced55c..7550dee 100644 --- a/content/common/gpu/media/avda_codec_image.h +++ b/content/common/gpu/media/avda_codec_image.h @@ -29,10 +29,13 @@ class AVDACodecImage : public gfx::GLImage { unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) override; + void WillUseTexImage() override; + void DidUseTexImage() override; + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, gfx::OverlayTransform transform, diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc index 3a0071f..0de11be 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc @@ -341,10 +341,8 @@ void GpuVideoDecodeAccelerator::BindImage(uint32 client_texture_id, gpu::gles2::TextureManager* texture_manager = command_decoder->GetContextGroup()->texture_manager(); gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id); - if (ref) { - texture_manager->SetLevelImage(ref, texture_target, 0, image.get(), - gpu::gles2::Texture::BOUND); - } + if (ref) + texture_manager->SetLevelImage(ref, texture_target, 0, image.get()); } scoped_ptr diff --git a/content/common/gpu/stream_texture_android.cc b/content/common/gpu/stream_texture_android.cc index 3dabc09..20f1da7 100644 --- a/content/common/gpu/stream_texture_android.cc +++ b/content/common/gpu/stream_texture_android.cc @@ -45,9 +45,8 @@ bool StreamTexture::Create( texture_manager->SetLevelInfo(texture, GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, size.width(), size.height(), 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(size)); - texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, - gl_image.get(), - gpu::gles2::Texture::UNBOUND); + texture_manager->SetLevelImage( + texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image.get()); return true; } @@ -64,7 +63,6 @@ StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub, owner_stub_(owner_stub), route_id_(route_id), has_listener_(false), - texture_id_(texture_id), weak_factory_(this) { owner_stub->AddDestructionObserver(this); memset(current_matrix_, 0, sizeof(current_matrix_)); @@ -94,11 +92,9 @@ void StreamTexture::Destroy(bool have_context) { NOTREACHED(); } -bool StreamTexture::CopyTexImage(unsigned target) { - DCHECK_EQ(target, static_cast(GL_TEXTURE_EXTERNAL_OES)); - +void StreamTexture::WillUseTexImage() { if (!owner_stub_ || !surface_texture_.get()) - return true; + return; if (has_pending_frame_) { scoped_ptr scoped_make_current; @@ -132,18 +128,6 @@ bool StreamTexture::CopyTexImage(unsigned target) { ? active_unit.bound_texture_external_oes->service_id() : 0); } - - TextureManager* texture_manager = - owner_stub_->decoder()->GetContextGroup()->texture_manager(); - gpu::gles2::Texture* texture = - texture_manager->GetTextureForServiceId(texture_id_); - if (texture) { - // By setting image state to UNBOUND instead of COPIED we ensure that - // CopyTexImage() is called each time the surface texture is used for - // drawing. - texture->SetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0, this, - gpu::gles2::Texture::UNBOUND); - } } if (has_listener_ && has_valid_frame_) { @@ -160,8 +144,6 @@ bool StreamTexture::CopyTexImage(unsigned target) { new GpuStreamTextureMsg_MatrixChanged(route_id_, params)); } } - - return true; } void StreamTexture::OnFrameAvailable() { diff --git a/content/common/gpu/stream_texture_android.h b/content/common/gpu/stream_texture_android.h index 94a0848..cce4502c 100644 --- a/content/common/gpu/stream_texture_android.h +++ b/content/common/gpu/stream_texture_android.h @@ -38,10 +38,13 @@ class StreamTexture : public gfx::GLImage, unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) override; + void WillUseTexImage() override; + void DidUseTexImage() override {} + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, gfx::OverlayTransform transform, @@ -82,7 +85,6 @@ class StreamTexture : public gfx::GLImage, GpuCommandBufferStub* owner_stub_; int32 route_id_; bool has_listener_; - uint32 texture_id_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(StreamTexture); diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc index 2460a1e..b78a5dc 100644 --- a/gpu/command_buffer/service/framebuffer_manager.cc +++ b/gpu/command_buffer/service/framebuffer_manager.cc @@ -87,6 +87,8 @@ class RenderbufferAttachment renderbuffer_->AddToSignature(signature); } + void OnWillRenderTo() const override {} + void OnDidRenderTo() const override {} bool FormsFeedbackLoop(TextureRef* /* texture */, GLint /*level */) const override { return false; @@ -177,6 +179,7 @@ class TextureAttachment void DetachFromFramebuffer(Framebuffer* framebuffer) const override { texture_ref_->texture()->DetachFromFramebuffer(); + framebuffer->OnTextureRefDetached(texture_ref_.get()); } bool ValidForAttachmentType(GLenum attachment_type, @@ -211,6 +214,14 @@ class TextureAttachment texture_ref_.get(), target_, level_, signature); } + void OnWillRenderTo() const override { + texture_ref_->texture()->OnWillModifyPixels(); + } + + void OnDidRenderTo() const override { + texture_ref_->texture()->OnDidModifyPixels(); + } + bool FormsFeedbackLoop(TextureRef* texture, GLint level) const override { return texture == texture_ref_.get() && level == level_; } @@ -227,6 +238,10 @@ class TextureAttachment DISALLOW_COPY_AND_ASSIGN(TextureAttachment); }; +FramebufferManager::TextureDetachObserver::TextureDetachObserver() {} + +FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {} + FramebufferManager::FramebufferManager( uint32 max_draw_buffers, uint32 max_color_attachments, @@ -698,6 +713,28 @@ const Framebuffer::Attachment* Framebuffer::GetReadBufferAttachment() const { return GetAttachment(read_buffer_); } +void Framebuffer::OnTextureRefDetached(TextureRef* texture) { + manager_->OnTextureRefDetached(texture); +} + +void Framebuffer::OnWillRenderTo(GLenum attachment) const { + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + if (attachment == 0 || attachment == it->first) { + it->second->OnWillRenderTo(); + } + } +} + +void Framebuffer::OnDidRenderTo(GLenum attachment) const { + for (AttachmentMap::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) { + if (attachment == 0 || attachment == it->first) { + it->second->OnDidRenderTo(); + } + } +} + bool FramebufferManager::GetClientId( GLuint service_id, GLuint* client_id) const { // This doesn't need to be fast. It's only used during slow queries. @@ -735,5 +772,15 @@ bool FramebufferManager::IsComplete( framebuffer_state_change_count_; } +void FramebufferManager::OnTextureRefDetached(TextureRef* texture) { + for (TextureDetachObserverVector::iterator it = + texture_detach_observers_.begin(); + it != texture_detach_observers_.end(); + ++it) { + TextureDetachObserver* observer = *it; + observer->OnTextureRefDetachedFromFramebuffer(texture); + } +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h index db78ffe..7216654 100644 --- a/gpu/command_buffer/service/framebuffer_manager.h +++ b/gpu/command_buffer/service/framebuffer_manager.h @@ -52,6 +52,8 @@ class GPU_EXPORT Framebuffer : public base::RefCounted { virtual size_t GetSignatureSize(TextureManager* texture_manager) const = 0; virtual void AddToSignature( TextureManager* texture_manager, std::string* signature) const = 0; + virtual void OnWillRenderTo() const = 0; + virtual void OnDidRenderTo() const = 0; virtual bool FormsFeedbackLoop(TextureRef* texture, GLint level) const = 0; protected: @@ -158,6 +160,13 @@ class GPU_EXPORT Framebuffer : public base::RefCounted { // formats. bool HasSameInternalFormatsMRT() const; + void OnTextureRefDetached(TextureRef* texture); + + // If attachment is 0, apply to all attachments; otherwise, apply only to + // the specified attachment. + void OnWillRenderTo(GLenum attachment) const; + void OnDidRenderTo(GLenum attachment) const; + void set_read_buffer(GLenum read_buffer) { read_buffer_ = read_buffer; } @@ -233,6 +242,17 @@ struct DecoderFramebufferState { // so we can correctly clear them. class GPU_EXPORT FramebufferManager { public: + class GPU_EXPORT TextureDetachObserver { + public: + TextureDetachObserver(); + virtual ~TextureDetachObserver(); + + virtual void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureDetachObserver); + }; + FramebufferManager(uint32 max_draw_buffers, uint32 max_color_attachments, ContextType context_type, @@ -270,6 +290,18 @@ class GPU_EXPORT FramebufferManager { (framebuffer_state_change_count_ + 1) | 0x80000000U; } + void AddObserver(TextureDetachObserver* observer) { + texture_detach_observers_.push_back(observer); + } + + void RemoveObserver(TextureDetachObserver* observer) { + texture_detach_observers_.erase( + std::remove(texture_detach_observers_.begin(), + texture_detach_observers_.end(), + observer), + texture_detach_observers_.end()); + } + ContextType context_type() const { return context_type_; } private: @@ -278,6 +310,8 @@ class GPU_EXPORT FramebufferManager { void StartTracking(Framebuffer* framebuffer); void StopTracking(Framebuffer* framebuffer); + void OnTextureRefDetached(TextureRef* texture); + FramebufferCompletenessCache* GetFramebufferComboCompleteCache() { return framebuffer_combo_complete_cache_.get(); } @@ -302,6 +336,9 @@ class GPU_EXPORT FramebufferManager { ContextType context_type_; + typedef std::vector TextureDetachObserverVector; + TextureDetachObserverVector texture_detach_observers_; + scoped_refptr framebuffer_combo_complete_cache_; DISALLOW_COPY_AND_ASSIGN(FramebufferManager); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 3b45922..c8ffe3a 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -639,6 +639,49 @@ class ScopedResolvedFrameBufferBinder { DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder); }; +class ScopedModifyPixels { + public: + explicit ScopedModifyPixels(TextureRef* ref); + ~ScopedModifyPixels(); + + private: + TextureRef* ref_; +}; + +ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) { + if (ref_) + ref_->texture()->OnWillModifyPixels(); +} + +ScopedModifyPixels::~ScopedModifyPixels() { + if (ref_) + ref_->texture()->OnDidModifyPixels(); +} + +class ScopedRenderTo { + public: + explicit ScopedRenderTo(Framebuffer* framebuffer) + : ScopedRenderTo(framebuffer, 0) {} + ScopedRenderTo(Framebuffer* framebuffer, GLenum attachment); + ~ScopedRenderTo(); + + private: + const Framebuffer* framebuffer_; + GLenum attachment_; +}; + +ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer, GLenum attachment) + : framebuffer_(framebuffer), + attachment_(attachment) { + if (framebuffer_) + framebuffer_->OnWillRenderTo(attachment_); +} + +ScopedRenderTo::~ScopedRenderTo() { + if (framebuffer_) + framebuffer_->OnDidRenderTo(attachment_); +} + // Encapsulates an OpenGL texture. class BackTexture { public: @@ -791,7 +834,9 @@ void GLES2Decoder::EndDecoding() {} // This class implements GLES2Decoder so we don't have to expose all the GLES2 // cmd stuff to outside this class. -class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { +class GLES2DecoderImpl : public GLES2Decoder, + public FramebufferManager::TextureDetachObserver, + public ErrorStateClient { public: explicit GLES2DecoderImpl(ContextGroup* group); ~GLES2DecoderImpl() override; @@ -920,6 +965,9 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { error::ContextLostReason GetContextLostReason() override; + // Overridden from FramebufferManager::TextureDetachObserver: + void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override; + // Overriden from ErrorStateClient. void OnContextLostError() override; void OnOutOfMemoryError() override; @@ -1921,13 +1969,10 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { const char* function_name, GLuint max_vertex_accessed, bool* simulated); void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding); - // Copies the image to the texture currently bound to |textarget|. The image - // state of |texture| is updated to reflect the new state. - void DoCopyTexImage(Texture* texture, GLenum textarget, gfx::GLImage* image); - - // This will call DoCopyTexImage if texture has an image but that image is - // not bound or copied to the texture. - void DoCopyTexImageIfNeeded(Texture* texture, GLenum textarget); + // If an image is bound to texture, this will call Will/DidUseTexImage + // if needed. + void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget); + void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget); // Returns false if textures were replaced. bool PrepareTexturesForRender(); @@ -3247,6 +3292,8 @@ bool GLES2DecoderImpl::Initialize( return false; } + framebuffer_manager()->AddObserver(this); + return true; } @@ -4346,6 +4393,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) { } if (group_.get()) { + framebuffer_manager()->RemoveObserver(this); group_->Destroy(this, have_context); group_ = NULL; } @@ -5189,6 +5237,7 @@ void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target, translated_attachments[i] = attachment; } + ScopedRenderTo do_render(framebuffer); if (feature_info_->gl_version_info().is_es3) { glInvalidateFramebuffer( target, numAttachments, translated_attachments.get()); @@ -5966,6 +6015,7 @@ error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) { ApplyDirtyState(); // TODO(zmo): Filter out INTEGER/SIGNED INTEGER images to avoid // undefined results. + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get()); if (workarounds().gl_clear_broken) { ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround", GetErrorState()); @@ -5999,6 +6049,7 @@ void GLES2DecoderImpl::DoClearBufferiv( GL_INVALID_ENUM, "glClearBufferiv", "invalid buffer"); return; } + GLenum attachment = 0; if (buffer == GL_COLOR) { if (drawbuffer < 0 || drawbuffer >= static_cast(group_->max_draw_buffers())) { @@ -6012,6 +6063,7 @@ void GLES2DecoderImpl::DoClearBufferiv( // To avoid undefined results, return without calling the gl function. return; } + attachment = static_cast(GL_COLOR_ATTACHMENT0 + drawbuffer); } else { DCHECK(buffer == GL_STENCIL); if (drawbuffer != 0) { @@ -6022,9 +6074,14 @@ void GLES2DecoderImpl::DoClearBufferiv( if (!BoundFramebufferHasStencilAttachment()) { return; } + attachment = GL_STENCIL_ATTACHMENT; } MarkDrawBufferAsCleared(buffer, drawbuffer); - glClearBufferiv(buffer, drawbuffer, value); + { + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(), + attachment); + glClearBufferiv(buffer, drawbuffer, value); + } } void GLES2DecoderImpl::DoClearBufferuiv( @@ -6054,7 +6111,12 @@ void GLES2DecoderImpl::DoClearBufferuiv( return; } MarkDrawBufferAsCleared(buffer, drawbuffer); - glClearBufferuiv(buffer, drawbuffer, value); + GLenum attachment = static_cast(GL_COLOR_ATTACHMENT0 + drawbuffer); + { + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(), + attachment); + glClearBufferuiv(buffer, drawbuffer, value); + } } void GLES2DecoderImpl::DoClearBufferfv( @@ -6072,6 +6134,7 @@ void GLES2DecoderImpl::DoClearBufferfv( GL_INVALID_ENUM, "glClearBufferfv", "invalid buffer"); return; } + GLenum attachment = 0; if (buffer == GL_COLOR) { if (drawbuffer < 0 || drawbuffer >= static_cast(group_->max_draw_buffers())) { @@ -6085,6 +6148,7 @@ void GLES2DecoderImpl::DoClearBufferfv( // To avoid undefined results, return without calling the gl function. return; } + attachment = static_cast(GL_COLOR_ATTACHMENT0 + drawbuffer); } else { DCHECK(buffer == GL_DEPTH); if (drawbuffer != 0) { @@ -6095,9 +6159,14 @@ void GLES2DecoderImpl::DoClearBufferfv( if (!BoundFramebufferHasDepthAttachment()) { return; } + attachment = GL_DEPTH_ATTACHMENT; } MarkDrawBufferAsCleared(buffer, drawbuffer); - glClearBufferfv(buffer, drawbuffer, value); + { + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get(), + attachment); + glClearBufferfv(buffer, drawbuffer, value); + } } void GLES2DecoderImpl::DoClearBufferfi( @@ -6125,7 +6194,15 @@ void GLES2DecoderImpl::DoClearBufferfi( } MarkDrawBufferAsCleared(GL_DEPTH, drawbuffer); MarkDrawBufferAsCleared(GL_STENCIL, drawbuffer); - glClearBufferfi(buffer, drawbuffer, depth, stencil); + { + ScopedRenderTo do_render_depth( + framebuffer_state_.bound_draw_framebuffer.get(), + GL_DEPTH_ATTACHMENT); + ScopedRenderTo do_render_stencil( + framebuffer_state_.bound_draw_framebuffer.get(), + GL_STENCIL_ATTACHMENT); + glClearBufferfi(buffer, drawbuffer, depth, stencil); + } } void GLES2DecoderImpl::DoFramebufferRenderbuffer( @@ -6336,7 +6413,7 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon( } if (texture_ref) - DoCopyTexImageIfNeeded(texture_ref->texture(), textarget); + DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget); LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name); if (0 == samples) { @@ -6359,6 +6436,9 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon( framebuffer_state_.clear_state_dirty = true; } + if (texture_ref) + DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget); + OnFboChanged(); } @@ -6498,6 +6578,7 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM( } state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get()); BlitFramebufferHelper( srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, @@ -7557,29 +7638,33 @@ void GLES2DecoderImpl::PerformanceWarning( std::string("PERFORMANCE WARNING: ") + msg); } -void GLES2DecoderImpl::DoCopyTexImage(Texture* texture, - GLenum textarget, - gfx::GLImage* image) { - // Note: We update the state to COPIED prior to calling CopyTexImage() - // as that allows the GLImage implemenatation to set it back to UNBOUND - // and ensure that CopyTexImage() is called each time the texture is - // used. - texture->SetLevelImage(textarget, 0, image, Texture::COPIED); - bool rv = image->CopyTexImage(textarget); - DCHECK(rv) << "Both BindTexImage() and CopyTexImage() failed"; +void GLES2DecoderImpl::DoWillUseTexImageIfNeeded( + Texture* texture, GLenum textarget) { + // Image is already in use if texture is attached to a framebuffer. + if (texture && !texture->IsAttachedToFramebuffer()) { + gfx::GLImage* image = texture->GetLevelImage(textarget, 0); + if (image) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::DoWillUseTexImageIfNeeded", + GetErrorState()); + glBindTexture(textarget, texture->service_id()); + image->WillUseTexImage(); + RestoreCurrentTextureBindings(&state_, textarget); + } + } } -void GLES2DecoderImpl::DoCopyTexImageIfNeeded(Texture* texture, - GLenum textarget) { - // Image is already in use if texture is attached to a framebuffer. +void GLES2DecoderImpl::DoDidUseTexImageIfNeeded( + Texture* texture, GLenum textarget) { + // Image is still in use if texture is attached to a framebuffer. if (texture && !texture->IsAttachedToFramebuffer()) { - Texture::ImageState image_state; - gfx::GLImage* image = texture->GetLevelImage(textarget, 0, &image_state); - if (image && image_state == Texture::UNBOUND) { + gfx::GLImage* image = texture->GetLevelImage(textarget, 0); + if (image) { ScopedGLErrorSuppressor suppressor( - "GLES2DecoderImpl::DoCopyTexImageIfNeeded", GetErrorState()); + "GLES2DecoderImpl::DoDidUseTexImageIfNeeded", + GetErrorState()); glBindTexture(textarget, texture->service_id()); - DoCopyTexImage(texture, textarget, image); + image->DidUseTexImage(); RestoreCurrentTextureBindings(&state_, textarget); } } @@ -7627,16 +7712,13 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() { if (textarget != GL_TEXTURE_CUBE_MAP) { Texture* texture = texture_ref->texture(); - Texture::ImageState image_state; - gfx::GLImage* image = - texture->GetLevelImage(textarget, 0, &image_state); - if (image && image_state == Texture::UNBOUND && - !texture->IsAttachedToFramebuffer()) { + gfx::GLImage* image = texture->GetLevelImage(textarget, 0); + if (image && !texture->IsAttachedToFramebuffer()) { ScopedGLErrorSuppressor suppressor( "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState()); textures_set = true; glActiveTexture(GL_TEXTURE0 + texture_unit_index); - DoCopyTexImage(texture, textarget, image); + image->WillUseTexImage(); continue; } } @@ -7671,6 +7753,19 @@ void GLES2DecoderImpl::RestoreStateForTextures() { texture_ref ? texture_ref->service_id() : 0); continue; } + + if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) { + Texture* texture = texture_ref->texture(); + gfx::GLImage* image = + texture->GetLevelImage(texture_unit.bind_target, 0); + if (image && !texture->IsAttachedToFramebuffer()) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState()); + glActiveTexture(GL_TEXTURE0 + texture_unit_index); + image->DidUseTexImage(); + continue; + } + } } } } @@ -8026,6 +8121,7 @@ error::Error GLES2DecoderImpl::DoDrawArrays( primcount)) { bool textures_set = !PrepareTexturesForRender(); ApplyDirtyState(); + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get()); if (!instanced) { glDrawArrays(mode, first, count); } else { @@ -8162,6 +8258,7 @@ error::Error GLES2DecoderImpl::DoDrawElements( indices = element_array_buffer->GetRange(offset, 0); } + ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get()); if (!instanced) { glDrawElements(mode, count, type, indices); } else { @@ -9392,10 +9489,9 @@ error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM( "unknown texture"); return error::kNoError; } - Texture::ImageState image_state; gfx::GLImage* image = - ref->texture()->GetLevelImage(ref->texture()->target(), 0, &image_state); - if (!image || image_state != Texture::BOUND) { + ref->texture()->GetLevelImage(ref->texture()->target(), 0); + if (!image) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScheduleOverlayPlaneCHROMIUM", "unsupported texture format"); @@ -10999,6 +11095,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D( // some part was clipped so clear the rect. scoped_ptr zero(new char[pixels_size]); memset(zero.get(), 0, pixels_size); + ScopedModifyPixels modify(texture_ref); glTexImage2D(target, level, internal_format, width, height, border, format, type, zero.get()); if (copyHeight > 0 && copyWidth > 0) { @@ -11011,6 +11108,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D( copyWidth, copyHeight); } } else { + ScopedModifyPixels modify(texture_ref); glCopyTexImage2D(target, level, internal_format, copyX, copyY, copyWidth, copyHeight, border); } @@ -11137,6 +11235,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( } scoped_ptr zero(new char[pixels_size]); memset(zero.get(), 0, pixels_size); + ScopedModifyPixels modify(texture_ref); glTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, zero.get()); @@ -11147,6 +11246,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( GLint dy = copyY - y; GLint destX = xoffset + dx; GLint destY = yoffset + dy; + ScopedModifyPixels modify(texture_ref); glCopyTexSubImage2D(target, level, destX, destY, copyX, copyY, copyWidth, copyHeight); @@ -13129,16 +13229,20 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( true); } - // Try using GLImage::CopyTexImage when possible. + ScopedModifyPixels modify(dest_texture_ref); + + // Try using GLImage::CopyTexSubImage when possible. bool unpack_premultiply_alpha_change = (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0; if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) { glBindTexture(GL_TEXTURE_2D, dest_texture->service_id()); - if (image->CopyTexImage(GL_TEXTURE_2D)) + if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0), + gfx::Rect(0, 0, source_width, source_height))) { return; + } } - DoCopyTexImageIfNeeded(source_texture, source_texture->target()); + DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix // before presenting. @@ -13161,6 +13265,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( unpack_premultiply_alpha == GL_TRUE, unpack_unmultiply_alpha == GL_TRUE); } + + DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); } void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( @@ -13293,6 +13399,8 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( true); } + ScopedModifyPixels modify(dest_texture_ref); + // Try using GLImage::CopyTexSubImage when possible. bool unpack_premultiply_alpha_change = (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0; @@ -13305,7 +13413,7 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( } } - DoCopyTexImageIfNeeded(source_texture, source_texture->target()); + DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); // TODO(hkuang): get the StreamTexture transform matrix in GPU process. // crbug.com/226218. @@ -13317,6 +13425,8 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM( unpack_flip_y == GL_TRUE, unpack_premultiply_alpha == GL_TRUE, unpack_unmultiply_alpha == GL_TRUE); + + DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); } void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target, @@ -13402,6 +13512,8 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target, ScopedTextureBinder binder( &state_, dest_texture->service_id(), GL_TEXTURE_2D); + ScopedModifyPixels modify(dest_texture_ref); + // Try using GLImage::CopyTexImage when possible. if (image) { GLenum dest_type = 0; @@ -13447,15 +13559,17 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target, true); } - if (image->CopyTexImage(GL_TEXTURE_2D)) + if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0), + gfx::Rect(0, 0, source_width, source_height))) { return; + } } TRACE_EVENT0( "gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback"); - DoCopyTexImageIfNeeded(source_texture, source_texture->target()); + DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); // As a fallback, copy into a non-compressed GL_RGBA texture. LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM"); @@ -13487,6 +13601,8 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target, source_internal_format, dest_texture->service_id(), GL_RGBA, source_width, source_height, false, false, false); } + + DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); } void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target, @@ -13635,18 +13751,21 @@ void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target, ScopedTextureBinder binder( &state_, dest_texture->service_id(), GL_TEXTURE_2D); + ScopedModifyPixels modify(dest_texture_ref); + // Try using GLImage::CopyTexSubImage when possible. - if (image && - image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset), - gfx::Rect(x, y, width, height))) { - return; + if (image) { + if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset), + gfx::Rect(x, y, width, height))) { + return; + } } TRACE_EVENT0( "gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback"); - DoCopyTexImageIfNeeded(source_texture, source_texture->target()); + DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); // As a fallback, copy into a non-compressed GL_RGBA texture. if (dest_internal_format != GL_RGBA) { @@ -13699,6 +13818,8 @@ void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target, source_internal_format, dest_texture->service_id(), GL_RGBA, xoffset, yoffset, x, y, width, height, dest_width, dest_height, source_width, source_height, false, false, false); + + DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); } void GLES2DecoderImpl::DoTexStorage2DEXT( @@ -14111,32 +14232,31 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM( return; } - gfx::GLImage* image = image_manager()->LookupImage(image_id); - if (!image) { + gfx::GLImage* gl_image = image_manager()->LookupImage(image_id); + if (!gl_image) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glBindTexImage2DCHROMIUM", "no image found with the given ID"); return; } - Texture::ImageState image_state = Texture::UNBOUND; - { ScopedGLErrorSuppressor suppressor( "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState()); - - // Note: We fallback to using CopyTexImage() before the texture is used - // when BindTexImage() fails. - if (image->BindTexImage(target)) - image_state = Texture::BOUND; + if (!gl_image->BindTexImage(target)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID"); + return; + } } - gfx::Size size = image->GetSize(); - GLenum internalformat = image->GetInternalFormat(); + gfx::Size size = gl_image->GetSize(); texture_manager()->SetLevelInfo( - texture_ref, target, 0, internalformat, size.width(), size.height(), 1, 0, - internalformat, GL_UNSIGNED_BYTE, gfx::Rect(size)); - texture_manager()->SetLevelImage(texture_ref, target, 0, image, image_state); + texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(), + size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, + gfx::Rect(size)); + texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image); } void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM( @@ -14154,31 +14274,27 @@ void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM( return; } - gfx::GLImage* image = image_manager()->LookupImage(image_id); - if (!image) { + gfx::GLImage* gl_image = image_manager()->LookupImage(image_id); + if (!gl_image) { LOCAL_SET_GL_ERROR( GL_INVALID_OPERATION, "glReleaseTexImage2DCHROMIUM", "no image found with the given ID"); return; } - Texture::ImageState image_state; - // Do nothing when image is not currently bound. - if (texture_ref->texture()->GetLevelImage(target, 0, &image_state) != image) + if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image) return; - if (image_state == Texture::BOUND) { + { ScopedGLErrorSuppressor suppressor( "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState()); - - image->ReleaseTexImage(target); - texture_manager()->SetLevelInfo(texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); + gl_image->ReleaseTexImage(target); } - texture_manager()->SetLevelImage(texture_ref, target, 0, nullptr, - Texture::UNBOUND); + texture_manager()->SetLevelInfo( + texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0, + gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect()); } error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM( @@ -14533,6 +14649,12 @@ error::Error GLES2DecoderImpl::HandleUnmapBuffer( return error::kNoError; } +void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer( + TextureRef* texture_ref) { + Texture* texture = texture_ref->texture(); + DoDidUseTexImageIfNeeded(texture, texture->target()); +} + // Note that GL_LOST_CONTEXT is specific to GLES. // For desktop GL we have to query the reset status proactively. void GLES2DecoderImpl::OnContextLostError() { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc index 4a8f9cf..89dec15 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc @@ -2830,9 +2830,12 @@ class MockGLImage : public gfx::GLImage { MOCK_METHOD1(Destroy, void(bool)); MOCK_METHOD1(BindTexImage, bool(unsigned)); MOCK_METHOD1(ReleaseTexImage, void(unsigned)); - MOCK_METHOD1(CopyTexImage, bool(unsigned)); MOCK_METHOD3(CopyTexSubImage, bool(unsigned, const gfx::Point&, const gfx::Rect&)); + MOCK_METHOD0(WillUseTexImage, void()); + MOCK_METHOD0(DidUseTexImage, void()); + MOCK_METHOD0(WillModifyTexImage, void()); + MOCK_METHOD0(DidModifyTexImage, void()); MOCK_METHOD5(ScheduleOverlayPlane, bool(gfx::AcceleratedWidget, int, gfx::OverlayTransform, @@ -2847,7 +2850,7 @@ class MockGLImage : public gfx::GLImage { virtual ~MockGLImage() {} }; -TEST_P(GLES2DecoderWithShaderTest, CopyTexImage) { +TEST_P(GLES2DecoderWithShaderTest, UseTexImage) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D(GL_TEXTURE_2D, 0, @@ -2873,16 +2876,12 @@ TEST_P(GLES2DecoderWithShaderTest, CopyTexImage) { // Bind image to texture. EXPECT_CALL(*image.get(), BindTexImage(GL_TEXTURE_2D)) .Times(1) - .WillOnce(Return(false)) + .WillOnce(Return(true)) .RetiresOnSaturation(); EXPECT_CALL(*image.get(), GetSize()) .Times(1) .WillOnce(Return(gfx::Size(1, 1))) .RetiresOnSaturation(); - EXPECT_CALL(*image.get(), GetInternalFormat()) - .Times(1) - .WillOnce(Return(GL_RGBA)) - .RetiresOnSaturation(); // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. DoBindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId); @@ -2893,12 +2892,12 @@ TEST_P(GLES2DecoderWithShaderTest, CopyTexImage) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(2).RetiresOnSaturation(); - EXPECT_CALL(*image.get(), CopyTexImage(GL_TEXTURE_2D)) - .Times(1) - .WillOnce(Return(true)) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(3).RetiresOnSaturation(); + EXPECT_CALL(*image.get(), WillUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*image.get(), DidUseTexImage()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) .Times(1) .RetiresOnSaturation(); @@ -2907,25 +2906,6 @@ TEST_P(GLES2DecoderWithShaderTest, CopyTexImage) { EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); - // Re-bind image to texture. - ReleaseTexImage2DCHROMIUM release_tex_image_2d_cmd; - release_tex_image_2d_cmd.Init(GL_TEXTURE_2D, kImageId); - EXPECT_EQ(error::kNoError, ExecuteCmd(release_tex_image_2d_cmd)); - EXPECT_CALL(*image.get(), BindTexImage(GL_TEXTURE_2D)) - .Times(1) - .WillOnce(Return(false)) - .RetiresOnSaturation(); - EXPECT_CALL(*image.get(), GetSize()) - .Times(1) - .WillOnce(Return(gfx::Size(1, 1))) - .RetiresOnSaturation(); - EXPECT_CALL(*image.get(), GetInternalFormat()) - .Times(1) - .WillOnce(Return(GL_RGBA)) - .RetiresOnSaturation(); - DoBindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId); - DoBindFramebuffer( GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. @@ -2937,10 +2917,8 @@ TEST_P(GLES2DecoderWithShaderTest, CopyTexImage) { EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) .Times(2) .RetiresOnSaturation(); - EXPECT_CALL(*image.get(), CopyTexImage(GL_TEXTURE_2D)) - .Times(1) - .WillOnce(Return(true)) - .RetiresOnSaturation(); + // Image will be 'in use' as long as bound to a framebuffer. + EXPECT_CALL(*image.get(), WillUseTexImage()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, FramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -2961,8 +2939,34 @@ TEST_P(GLES2DecoderWithShaderTest, CopyTexImage) { EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_CALL(*image.get(), Destroy(true)).Times(1).RetiresOnSaturation(); - image = nullptr; + // ScopedGLErrorSuppressor calls GetError on its constructor and destructor. + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + FramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) + .Times(2) + .RetiresOnSaturation(); + // Image should no longer be 'in use' after being unbound from framebuffer. + EXPECT_CALL(*image.get(), DidUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + FramebufferRenderbuffer fbrb_cmd; + fbrb_cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); } TEST_P(GLES2DecoderManualInitTest, DrawWithGLImageExternal) { @@ -2982,8 +2986,8 @@ TEST_P(GLES2DecoderManualInitTest, DrawWithGLImageExternal) { group().texture_manager()->SetLevelInfo(texture_ref, GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); - group().texture_manager()->SetLevelImage(texture_ref, GL_TEXTURE_EXTERNAL_OES, - 0, image.get(), Texture::BOUND); + group().texture_manager()->SetLevelImage( + texture_ref, GL_TEXTURE_EXTERNAL_OES, 0, image.get()); DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); EXPECT_EQ(GL_NO_ERROR, GetGLError()); @@ -2995,7 +2999,24 @@ TEST_P(GLES2DecoderManualInitTest, DrawWithGLImageExternal) { EXPECT_TRUE(group().texture_manager()->CanRender(texture_ref)); InSequence s; + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*image.get(), WillUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*image.get(), DidUseTexImage()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)).Times(1).RetiresOnSaturation(); DrawElements cmd; cmd.Init(GL_TRIANGLES, kValidIndexRangeCount, diff --git a/gpu/command_buffer/service/mailbox_manager_sync.cc b/gpu/command_buffer/service/mailbox_manager_sync.cc index a48d032..7463f92 100644 --- a/gpu/command_buffer/service/mailbox_manager_sync.cc +++ b/gpu/command_buffer/service/mailbox_manager_sync.cc @@ -273,7 +273,7 @@ void MailboxManagerSync::UpdateDefinitionLocked( if (SkipTextureWorkarounds(texture)) return; - gfx::GLImage* image = texture->GetLevelImage(texture->target(), 0); + gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0); TextureGroup* group = group_ref->group.get(); const TextureDefinition& definition = group->GetDefinition(); scoped_refptr image_buffer = definition.image(); @@ -287,14 +287,14 @@ void MailboxManagerSync::UpdateDefinitionLocked( if (definition.Matches(texture)) return; - DCHECK_IMPLIES(image, image_buffer.get()); - if (image && !image_buffer->IsClient(image)) { + DCHECK_IMPLIES(gl_image, image_buffer.get()); + if (gl_image && !image_buffer->IsClient(gl_image)) { LOG(ERROR) << "MailboxSync: Incompatible attachment"; return; } group->SetDefinition(TextureDefinition(texture, ++group_ref->version, - image ? image_buffer : NULL)); + gl_image ? image_buffer : NULL)); } void MailboxManagerSync::PushTextureUpdates(const SyncToken& token) { diff --git a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc index 0883f75..e7e3a1f 100644 --- a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc +++ b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc @@ -19,9 +19,7 @@ namespace { // Simply wraps a SurfaceTexture reference as a GLImage. class GLImageImpl : public gfx::GLImage { public: - GLImageImpl(uint32 texture_id, - gles2::TextureManager* texture_manager, - const scoped_refptr& surface_texture, + GLImageImpl(const scoped_refptr& surface_texture, const base::Closure& release_callback); // implement gfx::GLImage @@ -30,10 +28,13 @@ class GLImageImpl : public gfx::GLImage { unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) override; + void WillUseTexImage() override; + void DidUseTexImage() override {} + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, gfx::OverlayTransform transform, @@ -46,8 +47,6 @@ class GLImageImpl : public gfx::GLImage { private: ~GLImageImpl() override; - uint32 texture_id_; - gles2::TextureManager* texture_manager_; scoped_refptr surface_texture_; base::Closure release_callback_; @@ -55,14 +54,9 @@ class GLImageImpl : public gfx::GLImage { }; GLImageImpl::GLImageImpl( - uint32 texture_id, - gles2::TextureManager* texture_manager, const scoped_refptr& surface_texture, const base::Closure& release_callback) - : texture_id_(texture_id), - texture_manager_(texture_manager), - surface_texture_(surface_texture), - release_callback_(release_callback) {} + : surface_texture_(surface_texture), release_callback_(release_callback) {} GLImageImpl::~GLImageImpl() { release_callback_.Run(); @@ -89,27 +83,16 @@ void GLImageImpl::ReleaseTexImage(unsigned target) { NOTREACHED(); } -bool GLImageImpl::CopyTexImage(unsigned target) { - surface_texture_->UpdateTexImage(); - - gles2::Texture* texture = - texture_manager_->GetTextureForServiceId(texture_id_); - if (texture) { - // By setting image state to UNBOUND instead of COPIED we ensure that - // CopyTexImage() is called each time the surface texture is used for - // drawing. - texture->SetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0, this, - gles2::Texture::UNBOUND); - } - return true; -} - bool GLImageImpl::CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) { return false; } +void GLImageImpl::WillUseTexImage() { + surface_texture_->UpdateTexImage(); +} + bool GLImageImpl::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, gfx::OverlayTransform transform, @@ -156,17 +139,16 @@ GLuint StreamTextureManagerInProcess::CreateStreamTexture( base::Closure release_callback = base::Bind(&StreamTextureManagerInProcess::OnReleaseStreamTexture, weak_factory_.GetWeakPtr(), stream_id); - scoped_refptr gl_image( - new GLImageImpl(texture->service_id(), texture_manager, surface_texture, - release_callback)); + scoped_refptr gl_image(new GLImageImpl(surface_texture, + release_callback)); gfx::Size size = gl_image->GetSize(); texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES); texture_manager->SetLevelInfo(texture, GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, size.width(), size.height(), 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(size)); - texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, - gl_image.get(), gles2::Texture::UNBOUND); + texture_manager->SetLevelImage( + texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image.get()); { base::AutoLock lock(map_lock_); diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc index 38fd956..1f1372a 100644 --- a/gpu/command_buffer/service/texture_definition.cc +++ b/gpu/command_buffer/service/texture_definition.cc @@ -36,10 +36,13 @@ class GLImageSync : public gfx::GLImage { unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) override; + void WillUseTexImage() override; + void WillModifyTexImage() override; + void DidModifyTexImage() override; + void DidUseTexImage() override; bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, gfx::OverlayTransform transform, @@ -91,18 +94,24 @@ void GLImageSync::ReleaseTexImage(unsigned target) { NOTREACHED(); } -bool GLImageSync::CopyTexImage(unsigned target) { - NOTREACHED(); - return false; -} - bool GLImageSync::CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) { - NOTREACHED(); return false; } +void GLImageSync::WillUseTexImage() { +} + +void GLImageSync::DidUseTexImage() { +} + +void GLImageSync::WillModifyTexImage() { +} + +void GLImageSync::DidModifyTexImage() { +} + bool GLImageSync::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, gfx::OverlayTransform transform, @@ -348,7 +357,7 @@ TextureDefinition::TextureDefinition( new GLImageSync(image_buffer_, gfx::Size(first_face.level_infos[0].width, first_face.level_infos[0].height))); - texture->SetLevelImage(target_, 0, gl_image.get(), Texture::BOUND); + texture->SetLevelImage(NULL, target_, 0, gl_image.get()); } const Texture::LevelInfo& level = first_face.level_infos[0]; @@ -397,10 +406,12 @@ void TextureDefinition::UpdateTextureInternal(Texture* texture) const { if (image_buffer_.get()) { texture->SetLevelImage( - target_, 0, - new GLImageSync(image_buffer_, - gfx::Size(level_info_.width, level_info_.height)), - Texture::BOUND); + NULL, + target_, + 0, + new GLImageSync( + image_buffer_, + gfx::Size(level_info_.width, level_info_.height))); } texture->target_ = target_; @@ -426,7 +437,7 @@ void TextureDefinition::UpdateTexture(Texture* texture) const { if (bound_id == static_cast(old_service_id)) { glBindTexture(target_, service_id); } - texture->SetLevelImage(target_, 0, NULL, Texture::UNBOUND); + texture->SetLevelImage(NULL, target_, 0, NULL); } UpdateTextureInternal(texture); diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 4fb92c6..716bedc 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -392,8 +392,8 @@ Texture::LevelInfo::LevelInfo() border(0), format(0), type(0), - image_state(UNBOUND), - estimated_size(0) {} + estimated_size(0) { +} Texture::LevelInfo::LevelInfo(const LevelInfo& rhs) : cleared_rect(rhs.cleared_rect), @@ -407,8 +407,8 @@ Texture::LevelInfo::LevelInfo(const LevelInfo& rhs) format(rhs.format), type(rhs.type), image(rhs.image), - image_state(rhs.image_state), - estimated_size(rhs.estimated_size) {} + estimated_size(rhs.estimated_size) { +} Texture::LevelInfo::~LevelInfo() { } @@ -832,7 +832,6 @@ void Texture::SetLevelInfo(const FeatureInfo* feature_info, info.format = format; info.type = type; info.image = 0; - info.image_state = UNBOUND; UpdateMipCleared(&info, width, height, cleared_rect); @@ -1238,10 +1237,11 @@ bool Texture::ClearLevel( return true; } -void Texture::SetLevelImage(GLenum target, - GLint level, - gfx::GLImage* image, - ImageState state) { +void Texture::SetLevelImage( + const FeatureInfo* feature_info, + GLenum target, + GLint level, + gfx::GLImage* image) { DCHECK_GE(level, 0); size_t face_index = GLES2Util::GLTargetToFaceIndex(target); DCHECK_LT(static_cast(face_index), @@ -1253,14 +1253,15 @@ void Texture::SetLevelImage(GLenum target, DCHECK_EQ(info.target, target); DCHECK_EQ(info.level, level); info.image = image; - info.image_state = state; UpdateCanRenderCondition(); UpdateHasImages(); + + // TODO(ericrk): Images may have complex sizing not accounted for by + // |estimated_size_|, we should add logic here to update |estimated_size_| + // based on the new GLImage. crbug.com/526298 } -gfx::GLImage* Texture::GetLevelImage(GLint target, - GLint level, - ImageState* state) const { +gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const { if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES && target != GL_TEXTURE_RECTANGLE_ARB) { return NULL; @@ -1271,16 +1272,22 @@ gfx::GLImage* Texture::GetLevelImage(GLint target, static_cast(level) < face_infos_[face_index].level_infos.size()) { const LevelInfo& info = face_infos_[face_index].level_infos[level]; if (info.target != 0) { - if (state) - *state = info.image_state; return info.image.get(); } } return NULL; } -gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const { - return GetLevelImage(target, level, nullptr); +void Texture::OnWillModifyPixels() { + gfx::GLImage* image = GetLevelImage(target(), 0); + if (image) + image->WillModifyTexImage(); +} + +void Texture::OnDidModifyPixels() { + gfx::GLImage* image = GetLevelImage(target(), 0); + if (image) + image->DidModifyTexImage(); } void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump* pmd, @@ -1295,18 +1302,14 @@ void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump* pmd, if (!level_infos[level_index].estimated_size) continue; - // If a level has a GLImage, ask the GLImage to dump itself. if (level_infos[level_index].image) { + // If a level is backed by a GLImage, ask the GLImage to dump itself. level_infos[level_index].image->OnMemoryDump( pmd, client_tracing_id, base::StringPrintf("%s/face_%d/level_%d", dump_name.c_str(), face_index, level_index)); - } - - // If a level does not have a GLImage bound to it, then dump the - // texture allocation also as the storage is not provided by the - // GLImage in that case. - if (level_infos[level_index].image_state != BOUND) { + } else { + // If a level is not backed by a GLImage, create a simple dump. base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump( base::StringPrintf("%s/face_%d/level_%d", dump_name.c_str(), face_index, level_index)); @@ -1722,13 +1725,13 @@ GLsizei TextureManager::ComputeMipMapCount(GLenum target, } } -void TextureManager::SetLevelImage(TextureRef* ref, - GLenum target, - GLint level, - gfx::GLImage* image, - Texture::ImageState state) { +void TextureManager::SetLevelImage( + TextureRef* ref, + GLenum target, + GLint level, + gfx::GLImage* image) { DCHECK(ref); - ref->texture()->SetLevelImage(target, level, image, state); + ref->texture()->SetLevelImage(feature_info_.get(), target, level, image); } size_t TextureManager::GetSignatureSize() const { diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 33cd54a..a04cfa2 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -39,22 +39,6 @@ class TextureRef; // jointly owned by possibly multiple TextureRef. class GPU_EXPORT Texture { public: - enum ImageState { - // If an image is associated with the texture and image state is UNBOUND, - // then sampling out of the texture or using it as a target for drawing - // will not read/write from/to the image. - UNBOUND, - // If image state is BOUND, then sampling from the texture will return the - // contents of the image and using it as a target will modify the image. - BOUND, - // Image state is set to COPIED if the contents of the image has been - // copied to the texture. Sampling from the texture will be equivalent - // to sampling out the image (assuming image has not been changed since - // it was copied). Using the texture as a target for drawing will only - // modify the texture and not the image. - COPIED - }; - explicit Texture(GLuint service_id); GLenum min_filter() const { @@ -149,17 +133,8 @@ class GPU_EXPORT Texture { bool GetLevelType( GLint target, GLint level, GLenum* type, GLenum* internal_format) const; - // Set the image for a particular level. - void SetLevelImage(GLenum target, - GLint level, - gfx::GLImage* image, - ImageState state); - - // Get the image associated with a particular level. Returns NULL if level + // Get the image bound to a particular level. Returns NULL if level // does not exist. - gfx::GLImage* GetLevelImage(GLint target, - GLint level, - ImageState* state) const; gfx::GLImage* GetLevelImage(GLint target, GLint level) const; bool HasImages() const { @@ -218,6 +193,9 @@ class GPU_EXPORT Texture { // Initialize TEXTURE_MAX_ANISOTROPY to 1 if we haven't done so yet. void InitTextureMaxAnisotropyIfNeeded(GLenum target); + void OnWillModifyPixels(); + void OnDidModifyPixels(); + void DumpLevelMemory(base::trace_event::ProcessMemoryDump* pmd, uint64_t client_tracing_id, const std::string& dump_name) const; @@ -264,7 +242,6 @@ class GPU_EXPORT Texture { GLenum format; GLenum type; scoped_refptr image; - ImageState image_state; uint32 estimated_size; }; @@ -385,6 +362,13 @@ class GPU_EXPORT Texture { // Update info about this texture. void Update(const FeatureInfo* feature_info); + // Set the image for a particular level. + void SetLevelImage( + const FeatureInfo* feature_info, + GLenum target, + GLint level, + gfx::GLImage* image); + // Appends a signature for the given level. void AddToSignature( const FeatureInfo* feature_info, @@ -806,11 +790,11 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { return memory_type_tracker_->GetMemRepresented(); } - void SetLevelImage(TextureRef* ref, - GLenum target, - GLint level, - gfx::GLImage* image, - Texture::ImageState state); + void SetLevelImage( + TextureRef* ref, + GLenum target, + GLint level, + gfx::GLImage* image); size_t GetSignatureSize() const; diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index 516f478..90e90c4 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -1391,15 +1391,12 @@ TEST_F(TextureTest, GetLevelImage) { EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); // Set image. scoped_refptr image(new gfx::GLImageStub); - manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, image.get(), - Texture::BOUND); + manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, image.get()); EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); // Remove it. - manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, nullptr, - Texture::UNBOUND); + manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, NULL); EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); - manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, image.get(), - Texture::UNBOUND); + manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, image.get()); // Image should be reset when SetLevelInfo is called. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); @@ -1740,8 +1737,7 @@ TEST_P(ProduceConsumeTextureTest, ProduceConsumeTextureWithImage) { scoped_refptr image(new gfx::GLImageStub); manager_->SetLevelInfo(texture_ref_.get(), target, 0, GL_RGBA, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); - manager_->SetLevelImage(texture_ref_.get(), target, 0, image.get(), - Texture::BOUND); + manager_->SetLevelImage(texture_ref_.get(), target, 0, image.get()); GLuint service_id = texture->service_id(); Texture* produced_texture = Produce(texture_ref_.get()); @@ -2061,15 +2057,13 @@ TEST_F(SharedTextureTest, Images) { EXPECT_FALSE(texture_manager1_->HaveImages()); EXPECT_FALSE(texture_manager2_->HaveImages()); scoped_refptr image1(new gfx::GLImageStub); - texture_manager1_->SetLevelImage(ref1.get(), GL_TEXTURE_2D, 1, image1.get(), - Texture::BOUND); + texture_manager1_->SetLevelImage(ref1.get(), GL_TEXTURE_2D, 1, image1.get()); EXPECT_TRUE(ref1->texture()->HasImages()); EXPECT_TRUE(ref2->texture()->HasImages()); EXPECT_TRUE(texture_manager1_->HaveImages()); EXPECT_TRUE(texture_manager2_->HaveImages()); scoped_refptr image2(new gfx::GLImageStub); - texture_manager1_->SetLevelImage(ref1.get(), GL_TEXTURE_2D, 1, image2.get(), - Texture::BOUND); + texture_manager1_->SetLevelImage(ref1.get(), GL_TEXTURE_2D, 1, image2.get()); EXPECT_TRUE(ref1->texture()->HasImages()); EXPECT_TRUE(ref2->texture()->HasImages()); EXPECT_TRUE(texture_manager1_->HaveImages()); diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 2e04ee0..bfd095b 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn @@ -356,7 +356,6 @@ test("gl_unittests") { "//testing/gmock", "//testing/gtest", "//ui/gfx", - "//ui/gfx/geometry", ] data_deps = [ diff --git a/ui/gl/gl_image.h b/ui/gl/gl_image.h index aba2651..a236699 100644 --- a/ui/gl/gl_image.h +++ b/ui/gl/gl_image.h @@ -5,8 +5,6 @@ #ifndef UI_GL_GL_IMAGE_H_ #define UI_GL_GL_IMAGE_H_ -#include - #include "base/memory/ref_counted.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" @@ -24,8 +22,8 @@ class ProcessMemoryDump; namespace gfx { -// Encapsulates an image that can be bound and/or copied to a texture, hiding -// platform specific management. +// Encapsulates an image that can be bound to a texture, hiding platform +// specific management. class GL_EXPORT GLImage : public base::RefCounted { public: GLImage() {} @@ -34,32 +32,36 @@ class GL_EXPORT GLImage : public base::RefCounted { virtual void Destroy(bool have_context) = 0; // Get the size of the image. - virtual Size GetSize() = 0; + virtual gfx::Size GetSize() = 0; // Get the internal format of the image. virtual unsigned GetInternalFormat() = 0; - // Bind image to texture currently bound to |target|. Returns true on success. - // It is valid for an implementation to always return false. + // Bind image to texture currently bound to |target|. virtual bool BindTexImage(unsigned target) = 0; // Release image from texture currently bound to |target|. virtual void ReleaseTexImage(unsigned target) = 0; - // Define texture currently bound to |target| by copying image into it. - // Returns true on success. It is valid for an implementation to always - // return false. - virtual bool CopyTexImage(unsigned target) = 0; - // Copy |rect| of image to |offset| in texture currently bound to |target|. - // Returns true on success. It is valid for an implementation to always - // return false. virtual bool CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) = 0; + // Called before the texture is used for drawing. + virtual void WillUseTexImage() = 0; + + // Called after the texture has been used for drawing. + virtual void DidUseTexImage() = 0; + + // Called before the texture image data will be modified. + virtual void WillModifyTexImage() = 0; + + // Called after the texture image data has been modified. + virtual void DidModifyTexImage() = 0; + // Schedule image as an overlay plane to be shown at swap time for |widget|. - virtual bool ScheduleOverlayPlane(AcceleratedWidget widget, + virtual bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, diff --git a/ui/gl/gl_image_egl.cc b/ui/gl/gl_image_egl.cc index 6f72c4f..0ebd7cc 100644 --- a/ui/gl/gl_image_egl.cc +++ b/ui/gl/gl_image_egl.cc @@ -9,8 +9,9 @@ namespace gfx { -GLImageEGL::GLImageEGL(const Size& size) - : egl_image_(EGL_NO_IMAGE_KHR), size_(size) {} +GLImageEGL::GLImageEGL(const gfx::Size& size) + : egl_image_(EGL_NO_IMAGE_KHR), size_(size) { +} GLImageEGL::~GLImageEGL() { DCHECK(thread_checker_.CalledOnValidThread()); @@ -48,9 +49,7 @@ void GLImageEGL::Destroy(bool have_context) { } } -Size GLImageEGL::GetSize() { - return size_; -} +gfx::Size GLImageEGL::GetSize() { return size_; } unsigned GLImageEGL::GetInternalFormat() { return GL_RGBA; } @@ -62,17 +61,13 @@ bool GLImageEGL::BindTexImage(unsigned target) { return true; } -bool GLImageEGL::CopyTexImage(unsigned target) { - return false; -} - bool GLImageEGL::CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) { return false; } -bool GLImageEGL::ScheduleOverlayPlane(AcceleratedWidget widget, +bool GLImageEGL::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, diff --git a/ui/gl/gl_image_egl.h b/ui/gl/gl_image_egl.h index 4110fd0d..14cc40b 100644 --- a/ui/gl/gl_image_egl.h +++ b/ui/gl/gl_image_egl.h @@ -13,21 +13,24 @@ namespace gfx { class GL_EXPORT GLImageEGL : public GLImage { public: - explicit GLImageEGL(const Size& size); + explicit GLImageEGL(const gfx::Size& size); bool Initialize(EGLenum target, EGLClientBuffer buffer, const EGLint* attrs); // Overridden from GLImage: void Destroy(bool have_context) override; - Size GetSize() override; + gfx::Size GetSize() override; unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override {} - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) override; - bool ScheduleOverlayPlane(AcceleratedWidget widget, + void WillUseTexImage() override {} + void DidUseTexImage() override {} + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} + bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, @@ -37,7 +40,7 @@ class GL_EXPORT GLImageEGL : public GLImage { ~GLImageEGL() override; EGLImageKHR egl_image_; - const Size size_; + const gfx::Size size_; base::ThreadChecker thread_checker_; private: diff --git a/ui/gl/gl_image_glx.cc b/ui/gl/gl_image_glx.cc index f2eddf9..496cf44 100644 --- a/ui/gl/gl_image_glx.cc +++ b/ui/gl/gl_image_glx.cc @@ -13,6 +13,7 @@ extern "C" { #include "ui/gl/gl_surface_glx.h" namespace gfx { + namespace { bool ValidFormat(unsigned internalformat) { @@ -61,7 +62,7 @@ unsigned PixmapDepth(unsigned internalformat) { } } -bool ActualPixmapGeometry(XID pixmap, Size* size, unsigned* depth) { +bool ActualPixmapGeometry(XID pixmap, gfx::Size* size, unsigned* depth) { XID root_return; int x_return; int y_return; @@ -69,13 +70,19 @@ bool ActualPixmapGeometry(XID pixmap, Size* size, unsigned* depth) { unsigned height_return; unsigned border_width_return; unsigned depth_return; - if (!XGetGeometry(GetXDisplay(), pixmap, &root_return, &x_return, &y_return, - &width_return, &height_return, &border_width_return, + if (!XGetGeometry(gfx::GetXDisplay(), + pixmap, + &root_return, + &x_return, + &y_return, + &width_return, + &height_return, + &border_width_return, &depth_return)) return false; if (size) - *size = Size(width_return, height_return); + *size = gfx::Size(width_return, height_return); if (depth) *depth = depth_return; return true; @@ -89,18 +96,19 @@ unsigned ActualPixmapDepth(XID pixmap) { return depth; } -Size ActualPixmapSize(XID pixmap) { - Size size; +gfx::Size ActualPixmapSize(XID pixmap) { + gfx::Size size; if (!ActualPixmapGeometry(pixmap, &size, NULL)) - return Size(); + return gfx::Size(); return size; } -} // namespace +} // namespace anonymous -GLImageGLX::GLImageGLX(const Size& size, unsigned internalformat) - : glx_pixmap_(0), size_(size), internalformat_(internalformat) {} +GLImageGLX::GLImageGLX(const gfx::Size& size, unsigned internalformat) + : glx_pixmap_(0), size_(size), internalformat_(internalformat) { +} GLImageGLX::~GLImageGLX() { DCHECK_EQ(0u, glx_pixmap_); @@ -126,8 +134,8 @@ bool GLImageGLX::Initialize(XID pixmap) { BindToTextureFormat(internalformat_), GL_TRUE, 0}; int num_elements = 0; - XScopedPtr config( - glXChooseFBConfig(GetXDisplay(), DefaultScreen(GetXDisplay()), + gfx::XScopedPtr config( + glXChooseFBConfig(gfx::GetXDisplay(), DefaultScreen(gfx::GetXDisplay()), config_attribs, &num_elements)); if (!config.get()) { DVLOG(0) << "glXChooseFBConfig failed."; @@ -141,8 +149,8 @@ bool GLImageGLX::Initialize(XID pixmap) { int pixmap_attribs[] = {GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, TextureFormat(internalformat_), 0}; - glx_pixmap_ = - glXCreatePixmap(GetXDisplay(), *config.get(), pixmap, pixmap_attribs); + glx_pixmap_ = glXCreatePixmap( + gfx::GetXDisplay(), *config.get(), pixmap, pixmap_attribs); if (!glx_pixmap_) { DVLOG(0) << "glXCreatePixmap failed."; return false; @@ -153,14 +161,12 @@ bool GLImageGLX::Initialize(XID pixmap) { void GLImageGLX::Destroy(bool have_context) { if (glx_pixmap_) { - glXDestroyGLXPixmap(GetXDisplay(), glx_pixmap_); + glXDestroyGLXPixmap(gfx::GetXDisplay(), glx_pixmap_); glx_pixmap_ = 0; } } -Size GLImageGLX::GetSize() { - return size_; -} +gfx::Size GLImageGLX::GetSize() { return size_; } unsigned GLImageGLX::GetInternalFormat() { return internalformat_; } @@ -172,7 +178,7 @@ bool GLImageGLX::BindTexImage(unsigned target) { if (target != GL_TEXTURE_2D) return false; - glXBindTexImageEXT(GetXDisplay(), glx_pixmap_, GLX_FRONT_LEFT_EXT, 0); + glXBindTexImageEXT(gfx::GetXDisplay(), glx_pixmap_, GLX_FRONT_LEFT_EXT, 0); return true; } @@ -180,11 +186,7 @@ void GLImageGLX::ReleaseTexImage(unsigned target) { DCHECK_NE(0u, glx_pixmap_); DCHECK_EQ(static_cast(GL_TEXTURE_2D), target); - glXReleaseTexImageEXT(GetXDisplay(), glx_pixmap_, GLX_FRONT_LEFT_EXT); -} - -bool GLImageGLX::CopyTexImage(unsigned target) { - return false; + glXReleaseTexImageEXT(gfx::GetXDisplay(), glx_pixmap_, GLX_FRONT_LEFT_EXT); } bool GLImageGLX::CopyTexSubImage(unsigned target, @@ -193,7 +195,7 @@ bool GLImageGLX::CopyTexSubImage(unsigned target, return false; } -bool GLImageGLX::ScheduleOverlayPlane(AcceleratedWidget widget, +bool GLImageGLX::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, diff --git a/ui/gl/gl_image_glx.h b/ui/gl/gl_image_glx.h index e22512e..5de1d0d 100644 --- a/ui/gl/gl_image_glx.h +++ b/ui/gl/gl_image_glx.h @@ -14,21 +14,24 @@ namespace gfx { class GL_EXPORT GLImageGLX : public GLImage { public: - GLImageGLX(const Size& size, unsigned internalformat); + GLImageGLX(const gfx::Size& size, unsigned internalformat); bool Initialize(XID pixmap); // Overridden from GLImage: void Destroy(bool have_context) override; - Size GetSize() override; + gfx::Size GetSize() override; unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) override; - bool ScheduleOverlayPlane(AcceleratedWidget widget, + void WillUseTexImage() override {} + void DidUseTexImage() override {} + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} + bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, @@ -42,7 +45,7 @@ class GL_EXPORT GLImageGLX : public GLImage { private: XID glx_pixmap_; - const Size size_; + const gfx::Size size_; unsigned internalformat_; DISALLOW_COPY_AND_ASSIGN(GLImageGLX); diff --git a/ui/gl/gl_image_io_surface.h b/ui/gl/gl_image_io_surface.h index 45bd3ac..56b4478 100644 --- a/ui/gl/gl_image_io_surface.h +++ b/ui/gl/gl_image_io_surface.h @@ -9,8 +9,7 @@ #include "base/mac/scoped_cftyperef.h" #include "base/threading/thread_checker.h" -#include "ui/gfx/buffer_types.h" -#include "ui/gfx/generic_shared_memory_id.h" +#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gl/gl_image.h" #if defined(__OBJC__) @@ -23,23 +22,26 @@ namespace gfx { class GL_EXPORT GLImageIOSurface : public GLImage { public: - GLImageIOSurface(const Size& size, unsigned internalformat); + GLImageIOSurface(const gfx::Size& size, unsigned internalformat); bool Initialize(IOSurfaceRef io_surface, - GenericSharedMemoryId io_surface_id, + gfx::GenericSharedMemoryId io_surface_id, BufferFormat format); // Overridden from GLImage: void Destroy(bool have_context) override; - Size GetSize() override; + gfx::Size GetSize() override; unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override {} - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) override; - bool ScheduleOverlayPlane(AcceleratedWidget widget, + void WillUseTexImage() override {} + void DidUseTexImage() override {} + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} + bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, @@ -50,17 +52,18 @@ class GL_EXPORT GLImageIOSurface : public GLImage { base::ScopedCFTypeRef io_surface(); - static void SetLayerForWidget(AcceleratedWidget widget, CALayer* layer); + static void SetLayerForWidget(gfx::AcceleratedWidget widget, + CALayer* layer); protected: ~GLImageIOSurface() override; private: - const Size size_; + const gfx::Size size_; const unsigned internalformat_; BufferFormat format_; base::ScopedCFTypeRef io_surface_; - GenericSharedMemoryId io_surface_id_; + gfx::GenericSharedMemoryId io_surface_id_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(GLImageIOSurface); diff --git a/ui/gl/gl_image_io_surface.mm b/ui/gl/gl_image_io_surface.mm index 4294298..3f4964e 100644 --- a/ui/gl/gl_image_io_surface.mm +++ b/ui/gl/gl_image_io_surface.mm @@ -8,9 +8,6 @@ #include "base/lazy_instance.h" #include "base/mac/foundation_util.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/process_memory_dump.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" @@ -21,7 +18,7 @@ namespace gfx { namespace { -using WidgetToLayerMap = std::map; +typedef std::map WidgetToLayerMap; base::LazyInstance g_widget_to_layer_map; bool ValidInternalFormat(unsigned internalformat) { @@ -141,7 +138,8 @@ GLenum DataType(BufferFormat format) { } // namespace -GLImageIOSurface::GLImageIOSurface(const Size& size, unsigned internalformat) +GLImageIOSurface::GLImageIOSurface(const gfx::Size& size, + unsigned internalformat) : size_(size), internalformat_(internalformat), format_(BufferFormat::RGBA_8888) {} @@ -152,7 +150,7 @@ GLImageIOSurface::~GLImageIOSurface() { } bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface, - GenericSharedMemoryId io_surface_id, + gfx::GenericSharedMemoryId io_surface_id, BufferFormat format) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!io_surface_); @@ -178,9 +176,7 @@ void GLImageIOSurface::Destroy(bool have_context) { io_surface_.reset(); } -Size GLImageIOSurface::GetSize() { - return size_; -} +gfx::Size GLImageIOSurface::GetSize() { return size_; } unsigned GLImageIOSurface::GetInternalFormat() { return internalformat_; } @@ -209,17 +205,13 @@ bool GLImageIOSurface::BindTexImage(unsigned target) { return true; } -bool GLImageIOSurface::CopyTexImage(unsigned target) { - return false; -} - bool GLImageIOSurface::CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) { return false; } -bool GLImageIOSurface::ScheduleOverlayPlane(AcceleratedWidget widget, +bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, @@ -241,8 +233,8 @@ void GLImageIOSurface::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, base::trace_event::MemoryAllocatorDump::kUnitsBytes, static_cast(size_bytes)); - auto guid = - GetGenericSharedMemoryGUIDForTracing(process_tracing_id, io_surface_id_); + auto guid = gfx::GetGenericSharedMemoryGUIDForTracing(process_tracing_id, + io_surface_id_); pmd->CreateSharedGlobalAllocatorDump(guid); pmd->AddOwnershipEdge(dump->guid(), guid); } @@ -252,8 +244,8 @@ base::ScopedCFTypeRef GLImageIOSurface::io_surface() { } // static -void GLImageIOSurface::SetLayerForWidget(AcceleratedWidget widget, - CALayer* layer) { +void GLImageIOSurface::SetLayerForWidget( + gfx::AcceleratedWidget widget, CALayer* layer) { if (layer) g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer)); else diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc index 045c50c..c91ad56 100644 --- a/ui/gl/gl_image_memory.cc +++ b/ui/gl/gl_image_memory.cc @@ -7,6 +7,12 @@ #include "base/logging.h" #include "base/trace_event/trace_event.h" #include "ui/gl/gl_bindings.h" +#include "ui/gl/scoped_binders.h" + +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) +#include "ui/gl/gl_surface_egl.h" +#endif namespace gfx { namespace { @@ -146,11 +152,26 @@ GLsizei SizeInBytes(const Size& size, BufferFormat format) { GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat) : size_(size), internalformat_(internalformat), - memory_(nullptr), - format_(BufferFormat::RGBA_8888) {} + memory_(NULL), + format_(BufferFormat::RGBA_8888), + in_use_(false), + target_(0), + need_do_bind_tex_image_(false) +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + , + egl_texture_id_(0u), + egl_image_(EGL_NO_IMAGE_KHR) +#endif +{ +} GLImageMemory::~GLImageMemory() { - DCHECK(!memory_); +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); + DCHECK_EQ(0u, egl_texture_id_); +#endif } // static @@ -222,7 +243,20 @@ bool GLImageMemory::Initialize(const unsigned char* memory, } void GLImageMemory::Destroy(bool have_context) { - memory_ = nullptr; +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + if (egl_image_ != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); + egl_image_ = EGL_NO_IMAGE_KHR; + } + + if (egl_texture_id_) { + if (have_context) + glDeleteTextures(1, &egl_texture_id_); + egl_texture_id_ = 0u; + } +#endif + memory_ = NULL; } Size GLImageMemory::GetSize() { @@ -234,27 +268,19 @@ unsigned GLImageMemory::GetInternalFormat() { } bool GLImageMemory::BindTexImage(unsigned target) { - return false; -} - -bool GLImageMemory::CopyTexImage(unsigned target) { - TRACE_EVENT2("gpu", "GLImageMemory::CopyTexImage", "width", size_.width(), - "height", size_.height()); - - // GL_TEXTURE_EXTERNAL_OES is not a supported target. - if (target == GL_TEXTURE_EXTERNAL_OES) + if (target_ && target_ != target) { + LOG(ERROR) << "GLImage can only be bound to one target"; return false; + } + target_ = target; - if (IsCompressedFormat(format_)) { - glCompressedTexImage2D(target, 0, TextureFormat(format_), size_.width(), - size_.height(), 0, SizeInBytes(size_, format_), - memory_); - } else { - glTexImage2D(target, 0, TextureFormat(format_), size_.width(), - size_.height(), 0, DataFormat(format_), DataType(format_), - memory_); + // Defer DoBindTexImage if not currently in use. + if (!in_use_) { + need_do_bind_tex_image_ = true; + return true; } + DoBindTexImage(target); return true; } @@ -264,7 +290,7 @@ bool GLImageMemory::CopyTexSubImage(unsigned target, TRACE_EVENT2("gpu", "GLImageMemory::CopyTexSubImage", "width", rect.width(), "height", rect.height()); - // GL_TEXTURE_EXTERNAL_OES is not a supported target. + // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexSubImage target. if (target == GL_TEXTURE_EXTERNAL_OES) return false; @@ -282,18 +308,36 @@ bool GLImageMemory::CopyTexSubImage(unsigned target, DCHECK(memory_); const unsigned char* data = memory_ + rect.y() * stride_in_bytes; if (IsCompressedFormat(format_)) { - glCompressedTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), + glCompressedTexSubImage2D(target, + 0, // level + offset.x(), offset.y(), rect.width(), rect.height(), DataFormat(format_), SizeInBytes(rect.size(), format_), data); } else { - glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), - rect.height(), DataFormat(format_), DataType(format_), - data); + glTexSubImage2D(target, 0, // level + offset.x(), offset.y(), rect.width(), rect.height(), + DataFormat(format_), DataType(format_), data); } return true; } +void GLImageMemory::WillUseTexImage() { + DCHECK(!in_use_); + in_use_ = true; + + if (!need_do_bind_tex_image_) + return; + + DCHECK(target_); + DoBindTexImage(target_); +} + +void GLImageMemory::DidUseTexImage() { + DCHECK(in_use_); + in_use_ = false; +} + bool GLImageMemory::ScheduleOverlayPlane(AcceleratedWidget widget, int z_order, OverlayTransform transform, @@ -302,4 +346,132 @@ bool GLImageMemory::ScheduleOverlayPlane(AcceleratedWidget widget, return false; } +void GLImageMemory::DoBindTexImage(unsigned target) { + TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage"); + + DCHECK(need_do_bind_tex_image_); + need_do_bind_tex_image_ = false; + + DCHECK(memory_); +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + if (target == GL_TEXTURE_EXTERNAL_OES) { + if (egl_image_ == EGL_NO_IMAGE_KHR) { + DCHECK_EQ(0u, egl_texture_id_); + glGenTextures(1, &egl_texture_id_); + + { + ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (IsCompressedFormat(format_)) { + glCompressedTexImage2D(GL_TEXTURE_2D, + 0, // mip level + TextureFormat(format_), size_.width(), + size_.height(), + 0, // border + SizeInBytes(size_, format_), memory_); + } else { + glTexImage2D(GL_TEXTURE_2D, + 0, // mip level + TextureFormat(format_), + size_.width(), + size_.height(), + 0, // border + DataFormat(format_), + DataType(format_), + memory_); + } + } + + EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; + // Need to pass current EGL rendering context to eglCreateImageKHR for + // target type EGL_GL_TEXTURE_2D_KHR. + egl_image_ = + eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), + eglGetCurrentContext(), + EGL_GL_TEXTURE_2D_KHR, + reinterpret_cast(egl_texture_id_), + attrs); + DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) + << "Error creating EGLImage: " << eglGetError(); + } else { + ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); + + if (IsCompressedFormat(format_)) { + glCompressedTexSubImage2D(GL_TEXTURE_2D, + 0, // mip level + 0, // x-offset + 0, // y-offset + size_.width(), size_.height(), + DataFormat(format_), + SizeInBytes(size_, format_), memory_); + } else { + glTexSubImage2D(GL_TEXTURE_2D, + 0, // mip level + 0, // x-offset + 0, // y-offset + size_.width(), + size_.height(), + DataFormat(format_), + DataType(format_), + memory_); + } + } + + glEGLImageTargetTexture2DOES(target, egl_image_); + DCHECK_EQ(static_cast(GL_NO_ERROR), glGetError()); + return; + } +#endif + + DCHECK_NE(static_cast(GL_TEXTURE_EXTERNAL_OES), target); + if (IsCompressedFormat(format_)) { + glCompressedTexImage2D(target, + 0, // mip level + TextureFormat(format_), size_.width(), + size_.height(), + 0, // border + SizeInBytes(size_, format_), memory_); + } else { + glTexImage2D(target, + 0, // mip level + TextureFormat(format_), + size_.width(), + size_.height(), + 0, // border + DataFormat(format_), + DataType(format_), + memory_); + } +} + +void GLImageMemory::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, + uint64_t process_tracing_id, + const std::string& dump_name) { + // Note that the following calculation does not consider whether this GLImage + // has been un-bound from a texture. It also relies on this GLImage only ever + // being bound to a single texture. We could check these conditions more + // thoroughly, but at the cost of extra GL queries. + bool is_bound_to_texture = target_ && !need_do_bind_tex_image_; + +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + is_bound_to_texture |= !!egl_texture_id_; +#endif + + size_t size_in_bytes = is_bound_to_texture ? SizeInBytes(size_, format_) : 0; + + base::trace_event::MemoryAllocatorDump* dump = + pmd->CreateAllocatorDump(dump_name + "/texture_memory"); + dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, + base::trace_event::MemoryAllocatorDump::kUnitsBytes, + static_cast(size_in_bytes)); + + // No need for a global shared edge here. This object in the GPU process is + // the sole owner of this texture id. +} + } // namespace gfx diff --git a/ui/gl/gl_image_memory.h b/ui/gl/gl_image_memory.h index 4f1fe04..10b1a3b 100644 --- a/ui/gl/gl_image_memory.h +++ b/ui/gl/gl_image_memory.h @@ -7,8 +7,14 @@ #include "ui/gl/gl_image.h" +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) +#include +#include +#endif + #include "base/numerics/safe_math.h" -#include "ui/gfx/buffer_types.h" +#include "ui/gfx/gpu_memory_buffer.h" namespace gfx { @@ -28,26 +34,45 @@ class GL_EXPORT GLImageMemory : public GLImage { unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override {} - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) override; + void WillUseTexImage() override; + void DidUseTexImage() override; + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} bool ScheduleOverlayPlane(AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, const RectF& crop_rect) override; + // Only dumps the GLTexture portion of the memory usage. Subclasses are + // responsible for dumping the CPU-side memory. + void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, + uint64_t process_tracing_id, + const std::string& dump_name) override; + protected: ~GLImageMemory() override; BufferFormat format() const { return format_; } private: + void DoBindTexImage(unsigned target); + const Size size_; const unsigned internalformat_; const unsigned char* memory_; BufferFormat format_; + bool in_use_; + unsigned target_; + bool need_do_bind_tex_image_; +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + unsigned egl_texture_id_; + EGLImageKHR egl_image_; +#endif DISALLOW_COPY_AND_ASSIGN(GLImageMemory); }; diff --git a/ui/gl/gl_image_ozone_native_pixmap.cc b/ui/gl/gl_image_ozone_native_pixmap.cc index e0d0e37..3e0cfb5 100644 --- a/ui/gl/gl_image_ozone_native_pixmap.cc +++ b/ui/gl/gl_image_ozone_native_pixmap.cc @@ -26,7 +26,7 @@ bool ValidInternalFormat(unsigned internalformat) { } } -bool ValidFormat(BufferFormat format) { +bool ValidFormat(gfx::BufferFormat format) { switch (format) { case BufferFormat::RGBA_8888: case BufferFormat::BGRA_8888: @@ -49,7 +49,7 @@ bool ValidFormat(BufferFormat format) { return false; } -EGLint FourCC(BufferFormat format) { +EGLint FourCC(gfx::BufferFormat format) { switch (format) { case BufferFormat::RGBA_8888: return DRM_FORMAT_ABGR8888; @@ -87,12 +87,12 @@ GLImageOzoneNativePixmap::~GLImageOzoneNativePixmap() { bool GLImageOzoneNativePixmap::Initialize(ui::NativePixmap* pixmap, BufferFormat format) { DCHECK(!pixmap_); + + bool result = true; if (pixmap->GetEGLClientBuffer()) { EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; - if (!GLImageEGL::Initialize(EGL_NATIVE_PIXMAP_KHR, - pixmap->GetEGLClientBuffer(), attrs)) { - return false; - } + result = GLImageEGL::Initialize(EGL_NATIVE_PIXMAP_KHR, + pixmap->GetEGLClientBuffer(), attrs); } else if (pixmap->GetDmaBufFd() >= 0) { if (!ValidInternalFormat(internalformat_)) { LOG(ERROR) << "Invalid internalformat: " << internalformat_; @@ -119,14 +119,13 @@ bool GLImageOzoneNativePixmap::Initialize(ui::NativePixmap* pixmap, EGL_DMA_BUF_PLANE0_PITCH_EXT, pixmap->GetDmaBufPitch(), EGL_NONE}; - if (!GLImageEGL::Initialize(EGL_LINUX_DMA_BUF_EXT, - static_cast(nullptr), attrs)) { - return false; - } + result = GLImageEGL::Initialize( + EGL_LINUX_DMA_BUF_EXT, static_cast(nullptr), attrs); } - pixmap_ = pixmap; - return true; + if (result) + pixmap_ = pixmap; + return result; } unsigned GLImageOzoneNativePixmap::GetInternalFormat() { diff --git a/ui/gl/gl_image_ozone_native_pixmap.h b/ui/gl/gl_image_ozone_native_pixmap.h index 6505299..e164f39 100644 --- a/ui/gl/gl_image_ozone_native_pixmap.h +++ b/ui/gl/gl_image_ozone_native_pixmap.h @@ -5,7 +5,7 @@ #ifndef UI_GL_GL_IMAGE_OZONE_NATIVE_PIXMAP_H_ #define UI_GL_GL_IMAGE_OZONE_NATIVE_PIXMAP_H_ -#include "ui/gfx/buffer_types.h" +#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gl/gl_image_egl.h" #include "ui/ozone/public/native_pixmap.h" diff --git a/ui/gl/gl_image_ref_counted_memory.cc b/ui/gl/gl_image_ref_counted_memory.cc index 6533568..7aadd24 100644 --- a/ui/gl/gl_image_ref_counted_memory.cc +++ b/ui/gl/gl_image_ref_counted_memory.cc @@ -6,15 +6,13 @@ #include "base/logging.h" #include "base/memory/ref_counted_memory.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/process_memory_dump.h" namespace gfx { -GLImageRefCountedMemory::GLImageRefCountedMemory(const Size& size, +GLImageRefCountedMemory::GLImageRefCountedMemory(const gfx::Size& size, unsigned internalformat) - : GLImageMemory(size, internalformat) {} + : GLImageMemory(size, internalformat) { +} GLImageRefCountedMemory::~GLImageRefCountedMemory() { DCHECK(!ref_counted_memory_.get()); @@ -22,7 +20,7 @@ GLImageRefCountedMemory::~GLImageRefCountedMemory() { bool GLImageRefCountedMemory::Initialize( base::RefCountedMemory* ref_counted_memory, - BufferFormat format) { + gfx::BufferFormat format) { if (!GLImageMemory::Initialize(ref_counted_memory->front(), format)) return false; @@ -33,7 +31,7 @@ bool GLImageRefCountedMemory::Initialize( void GLImageRefCountedMemory::Destroy(bool have_context) { GLImageMemory::Destroy(have_context); - ref_counted_memory_ = nullptr; + ref_counted_memory_ = NULL; } void GLImageRefCountedMemory::OnMemoryDump( @@ -54,6 +52,9 @@ void GLImageRefCountedMemory::OnMemoryDump( pmd->AddSuballocation(dump->guid(), base::trace_event::MemoryDumpManager::GetInstance() ->system_allocator_pool_name()); + + // Also dump the base class's texture memory. + GLImageMemory::OnMemoryDump(pmd, process_tracing_id, dump_name); } } // namespace gfx diff --git a/ui/gl/gl_image_ref_counted_memory.h b/ui/gl/gl_image_ref_counted_memory.h index f68acc5..db07954 100644 --- a/ui/gl/gl_image_ref_counted_memory.h +++ b/ui/gl/gl_image_ref_counted_memory.h @@ -16,10 +16,10 @@ namespace gfx { class GL_EXPORT GLImageRefCountedMemory : public GLImageMemory { public: - GLImageRefCountedMemory(const Size& size, unsigned internalformat); + GLImageRefCountedMemory(const gfx::Size& size, unsigned internalformat); bool Initialize(base::RefCountedMemory* ref_counted_memory, - BufferFormat format); + gfx::BufferFormat format); // Overridden from GLImage: void Destroy(bool have_context) override; diff --git a/ui/gl/gl_image_ref_counted_memory_unittest.cc b/ui/gl/gl_image_ref_counted_memory_unittest.cc index c3d77e2..1edccf2 100644 --- a/ui/gl/gl_image_ref_counted_memory_unittest.cc +++ b/ui/gl/gl_image_ref_counted_memory_unittest.cc @@ -37,9 +37,5 @@ INSTANTIATE_TYPED_TEST_CASE_P(GLImageRefCountedMemory, GLImageTest, GLImageRefCountedMemoryTestDelegate); -INSTANTIATE_TYPED_TEST_CASE_P(GLImageRefCountedMemory, - GLImageCopyTest, - GLImageRefCountedMemoryTestDelegate); - } // namespace } // namespace gfx diff --git a/ui/gl/gl_image_shared_memory.cc b/ui/gl/gl_image_shared_memory.cc index 6ca7905..16ec6cb 100644 --- a/ui/gl/gl_image_shared_memory.cc +++ b/ui/gl/gl_image_shared_memory.cc @@ -5,18 +5,16 @@ #include "ui/gl/gl_image_shared_memory.h" #include "base/logging.h" -#include "base/memory/shared_memory.h" #include "base/numerics/safe_math.h" #include "base/process/process_handle.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/process_memory_dump.h" namespace gfx { namespace { // Returns true if the size is valid and false otherwise. -bool SizeInBytes(const Size& size, BufferFormat format, size_t* size_in_bytes) { +bool SizeInBytes(const gfx::Size& size, + gfx::BufferFormat format, + size_t* size_in_bytes) { if (size.IsEmpty()) return false; @@ -33,17 +31,19 @@ bool SizeInBytes(const Size& size, BufferFormat format, size_t* size_in_bytes) { } // namespace -GLImageSharedMemory::GLImageSharedMemory(const Size& size, +GLImageSharedMemory::GLImageSharedMemory(const gfx::Size& size, unsigned internalformat) - : GLImageMemory(size, internalformat) {} + : GLImageMemory(size, internalformat) { +} GLImageSharedMemory::~GLImageSharedMemory() { DCHECK(!shared_memory_); } -bool GLImageSharedMemory::Initialize(const base::SharedMemoryHandle& handle, - GenericSharedMemoryId shared_memory_id, - BufferFormat format) { +bool GLImageSharedMemory::Initialize( + const base::SharedMemoryHandle& handle, + gfx::GenericSharedMemoryId shared_memory_id, + gfx::BufferFormat format) { size_t size_in_bytes; if (!SizeInBytes(GetSize(), format, &size_in_bytes)) return false; @@ -98,15 +98,18 @@ void GLImageSharedMemory::OnMemoryDump( // Dump under "/shared_memory", as the base class may also dump to // "/texture_memory". base::trace_event::MemoryAllocatorDump* dump = - pmd->CreateAllocatorDump(dump_name + "/shared_memory"); + pmd->CreateAllocatorDump(dump_name + "/private_memory"); dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, base::trace_event::MemoryAllocatorDump::kUnitsBytes, static_cast(size_in_bytes)); - auto guid = GetGenericSharedMemoryGUIDForTracing(process_tracing_id, - shared_memory_id_); + auto guid = gfx::GetGenericSharedMemoryGUIDForTracing(process_tracing_id, + shared_memory_id_); pmd->CreateSharedGlobalAllocatorDump(guid); pmd->AddOwnershipEdge(dump->guid(), guid); + + // Also dump the base class's texture memory. + GLImageMemory::OnMemoryDump(pmd, process_tracing_id, dump_name); } } // namespace gfx diff --git a/ui/gl/gl_image_shared_memory.h b/ui/gl/gl_image_shared_memory.h index 2e6374b5..622eb3d 100644 --- a/ui/gl/gl_image_shared_memory.h +++ b/ui/gl/gl_image_shared_memory.h @@ -7,21 +7,16 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory_handle.h" -#include "ui/gfx/generic_shared_memory_id.h" #include "ui/gl/gl_image_memory.h" -namespace base { -class SharedMemory; -} - namespace gfx { class GL_EXPORT GLImageSharedMemory : public GLImageMemory { public: - GLImageSharedMemory(const Size& size, unsigned internalformat); + GLImageSharedMemory(const gfx::Size& size, unsigned internalformat); bool Initialize(const base::SharedMemoryHandle& handle, - GenericSharedMemoryId shared_memory_id, + gfx::GenericSharedMemoryId shared_memory_id, BufferFormat format); // Overridden from GLImage: diff --git a/ui/gl/gl_image_shared_memory_unittest.cc b/ui/gl/gl_image_shared_memory_unittest.cc index 9c280f9..44c8e97 100644 --- a/ui/gl/gl_image_shared_memory_unittest.cc +++ b/ui/gl/gl_image_shared_memory_unittest.cc @@ -39,9 +39,5 @@ INSTANTIATE_TYPED_TEST_CASE_P(GLImageSharedMemory, GLImageTest, GLImageSharedMemoryTestDelegate); -INSTANTIATE_TYPED_TEST_CASE_P(GLImageSharedMemory, - GLImageCopyTest, - GLImageSharedMemoryTestDelegate); - } // namespace } // namespace gfx diff --git a/ui/gl/gl_image_stub.cc b/ui/gl/gl_image_stub.cc index 803a05f..afbf6e0 100644 --- a/ui/gl/gl_image_stub.cc +++ b/ui/gl/gl_image_stub.cc @@ -12,25 +12,19 @@ GLImageStub::GLImageStub() {} GLImageStub::~GLImageStub() {} -Size GLImageStub::GetSize() { - return Size(1, 1); -} +gfx::Size GLImageStub::GetSize() { return gfx::Size(1, 1); } unsigned GLImageStub::GetInternalFormat() { return GL_RGBA; } bool GLImageStub::BindTexImage(unsigned target) { return true; } -bool GLImageStub::CopyTexImage(unsigned target) { - return true; -} - bool GLImageStub::CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) { return true; } -bool GLImageStub::ScheduleOverlayPlane(AcceleratedWidget widget, +bool GLImageStub::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, diff --git a/ui/gl/gl_image_stub.h b/ui/gl/gl_image_stub.h index c95fda9..be31bff 100644 --- a/ui/gl/gl_image_stub.h +++ b/ui/gl/gl_image_stub.h @@ -16,15 +16,18 @@ class GL_EXPORT GLImageStub : public GLImage { // Overridden from GLImage: void Destroy(bool have_context) override {} - Size GetSize() override; + gfx::Size GetSize() override; unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override {} - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) override; - bool ScheduleOverlayPlane(AcceleratedWidget widget, + void WillUseTexImage() override {} + void DidUseTexImage() override {} + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} + bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, diff --git a/ui/gl/gl_image_surface_texture.cc b/ui/gl/gl_image_surface_texture.cc index 6ad3667..910551d 100644 --- a/ui/gl/gl_image_surface_texture.cc +++ b/ui/gl/gl_image_surface_texture.cc @@ -9,8 +9,9 @@ namespace gfx { -GLImageSurfaceTexture::GLImageSurfaceTexture(const Size& size) - : size_(size), texture_id_(0) {} +GLImageSurfaceTexture::GLImageSurfaceTexture(const gfx::Size& size) + : size_(size), texture_id_(0) { +} GLImageSurfaceTexture::~GLImageSurfaceTexture() { DCHECK(thread_checker_.CalledOnValidThread()); @@ -31,9 +32,7 @@ void GLImageSurfaceTexture::Destroy(bool have_context) { texture_id_ = 0; } -Size GLImageSurfaceTexture::GetSize() { - return size_; -} +gfx::Size GLImageSurfaceTexture::GetSize() { return size_; } unsigned GLImageSurfaceTexture::GetInternalFormat() { return GL_RGBA; } @@ -79,17 +78,13 @@ bool GLImageSurfaceTexture::BindTexImage(unsigned target) { return true; } -bool GLImageSurfaceTexture::CopyTexImage(unsigned target) { - return false; -} - bool GLImageSurfaceTexture::CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) { return false; } -bool GLImageSurfaceTexture::ScheduleOverlayPlane(AcceleratedWidget widget, +bool GLImageSurfaceTexture::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, diff --git a/ui/gl/gl_image_surface_texture.h b/ui/gl/gl_image_surface_texture.h index f18eaa2..d8c4abb 100644 --- a/ui/gl/gl_image_surface_texture.h +++ b/ui/gl/gl_image_surface_texture.h @@ -15,21 +15,24 @@ class SurfaceTexture; class GL_EXPORT GLImageSurfaceTexture : public GLImage { public: - explicit GLImageSurfaceTexture(const Size& size); + explicit GLImageSurfaceTexture(const gfx::Size& size); bool Initialize(SurfaceTexture* surface_texture); // Overridden from GLImage: void Destroy(bool have_context) override; - Size GetSize() override; + gfx::Size GetSize() override; unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override {} - bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const Point& offset, const Rect& rect) override; - bool ScheduleOverlayPlane(AcceleratedWidget widget, + void WillUseTexImage() override {} + void DidUseTexImage() override {} + void WillModifyTexImage() override {} + void DidModifyTexImage() override {} + bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, OverlayTransform transform, const Rect& bounds_rect, @@ -43,7 +46,7 @@ class GL_EXPORT GLImageSurfaceTexture : public GLImage { private: scoped_refptr surface_texture_; - const Size size_; + const gfx::Size size_; GLint texture_id_; base::ThreadChecker thread_checker_; diff --git a/ui/gl/gl_tests.gyp b/ui/gl/gl_tests.gyp index eaf0df0..09821e7 100644 --- a/ui/gl/gl_tests.gyp +++ b/ui/gl/gl_tests.gyp @@ -28,7 +28,6 @@ '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/mesa/mesa.gyp:osmesa', '<(DEPTH)/ui/gfx/gfx.gyp:gfx', - '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry', '<(DEPTH)/ui/gl/gl.gyp:gl', '<(DEPTH)/ui/gl/gl.gyp:gl_test_support', '<(DEPTH)/ui/gl/gl.gyp:gl_unittest_utils', diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h index e7b685d..8533ce2 100644 --- a/ui/gl/test/gl_image_test_template.h +++ b/ui/gl/test/gl_image_test_template.h @@ -51,51 +51,9 @@ class GLImageTest : public testing::Test { TYPED_TEST_CASE_P(GLImageTest); -TYPED_TEST_P(GLImageTest, CreateAndDestroy) { - const Size small_image_size(4, 4); - const Size large_image_size(512, 512); - const uint8_t image_color[] = {0, 0xff, 0, 0xff}; - - // Create a small solid color green image of preferred format. This must - // succeed in order for a GLImage to be conformant. - scoped_refptr small_image = this->delegate_.CreateSolidColorImage( - small_image_size, GLImageTestSupport::GetPreferredInternalFormat(), - GLImageTestSupport::GetPreferredBufferFormat(), image_color); - ASSERT_TRUE(small_image); - - // Create a large solid color green image of preferred format. This must - // succeed in order for a GLImage to be conformant. - scoped_refptr large_image = this->delegate_.CreateSolidColorImage( - large_image_size, GLImageTestSupport::GetPreferredInternalFormat(), - GLImageTestSupport::GetPreferredBufferFormat(), image_color); - ASSERT_TRUE(large_image); - - // Verify that image size is correct. - EXPECT_EQ(small_image->GetSize().ToString(), small_image_size.ToString()); - EXPECT_EQ(large_image->GetSize().ToString(), large_image_size.ToString()); - - // Verify that internal format is correct. - EXPECT_EQ(small_image->GetInternalFormat(), - GLImageTestSupport::GetPreferredInternalFormat()); - EXPECT_EQ(large_image->GetInternalFormat(), - GLImageTestSupport::GetPreferredInternalFormat()); - - // Verify that destruction of images work correctly both when we have a - // context and when we don't. - small_image->Destroy(true /* have_context */); - large_image->Destroy(false /* have_context */); -} - -// The GLImageTest test case verifies the behaviour that is expected from a -// GLImage in order to be conformant. -REGISTER_TYPED_TEST_CASE_P(GLImageTest, CreateAndDestroy); - -template -class GLImageCopyTest : public GLImageTest {}; - -TYPED_TEST_CASE_P(GLImageCopyTest); - -TYPED_TEST_P(GLImageCopyTest, CopyTexImage) { +// Copy image to texture. Support is optional. Texels should be updated if +// supported, and left unchanged if not. +TYPED_TEST_P(GLImageTest, CopyTexSubImage) { const Size image_size(256, 256); const uint8_t image_color[] = {0, 0xff, 0, 0xff}; const uint8_t texture_color[] = {0, 0, 0xff, 0xff}; @@ -133,9 +91,9 @@ TYPED_TEST_P(GLImageCopyTest, CopyTexImage) { GLImageTestSupport::GetPreferredInternalFormat(), GL_UNSIGNED_BYTE, pixels.get()); - // Copy |image| to |texture|. - bool rv = image->CopyTexImage(GL_TEXTURE_2D); - EXPECT_TRUE(rv); + // Attempt to copy |image| to |texture|. + // Returns true on success, false on failure. + bool rv = image->CopyTexSubImage(GL_TEXTURE_2D, Point(), Rect(image_size)); // clang-format off const char kVertexShader[] = STRINGIZE( @@ -203,7 +161,7 @@ TYPED_TEST_P(GLImageCopyTest, CopyTexImage) { // Draw |texture| to viewport and read back pixels to check expectations. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); GLTestHelper::CheckPixels(0, 0, image_size.width(), image_size.height(), - image_color); + rv ? image_color : texture_color); // Clean up. glDeleteProgram(program); @@ -215,9 +173,9 @@ TYPED_TEST_P(GLImageCopyTest, CopyTexImage) { image->Destroy(true); } -// The GLImageCopyTest test case verifies that the GLImage implementation -// handles CopyTexImage correctly. -REGISTER_TYPED_TEST_CASE_P(GLImageCopyTest, CopyTexImage); +// The GLImageTest test case verifies behaviour that is expected from a +// GLImage in order to be conformant. +REGISTER_TYPED_TEST_CASE_P(GLImageTest, CopyTexSubImage); } // namespace gfx -- cgit v1.1