diff --git content/browser/compositor/browser_compositor_output_surface.cc content/browser/compositor/browser_compositor_output_surface.cc index 0a1231d4e16c..11e1cbc521d4 100644 --- content/browser/compositor/browser_compositor_output_surface.cc +++ content/browser/compositor/browser_compositor_output_surface.cc @@ -53,6 +53,10 @@ void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) { OnReflectorChanged(); } +void* BrowserCompositorOutputSurface::GetSharedTexture() const { + return nullptr; +} + void BrowserCompositorOutputSurface::OnReflectorChanged() { } diff --git content/browser/compositor/browser_compositor_output_surface.h content/browser/compositor/browser_compositor_output_surface.h index 3c4d448b972f..fa3f01f59484 100644 --- content/browser/compositor/browser_compositor_output_surface.h +++ content/browser/compositor/browser_compositor_output_surface.h @@ -40,6 +40,8 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface void SetReflector(ReflectorImpl* reflector); + virtual void* GetSharedTexture() const; + // Called when |reflector_| was updated. virtual void OnReflectorChanged(); diff --git content/browser/compositor/gpu_process_transport_factory.cc content/browser/compositor/gpu_process_transport_factory.cc index 0da5e9c1ecbc..49c79455b4aa 100644 --- content/browser/compositor/gpu_process_transport_factory.cc +++ content/browser/compositor/gpu_process_transport_factory.cc @@ -208,6 +208,18 @@ GpuProcessTransportFactory::~GpuProcessTransportFactory() { task_graph_runner_->Shutdown(); } +void* GpuProcessTransportFactory::GetSharedTexture(ui::Compositor* compositor) { + PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor); + if (it == per_compositor_data_.end()) + return nullptr; + PerCompositorData* data = it->second.get(); + DCHECK(data); + + if (data->display_output_surface) + return data->display_output_surface->GetSharedTexture(); + return nullptr; +} + std::unique_ptr GpuProcessTransportFactory::CreateSoftwareOutputDevice( gfx::AcceleratedWidget widget, @@ -450,11 +462,20 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( // surfaces as they are not following the correct mode. DisableGpuCompositing(compositor.get()); } + + std::unique_ptr output_device; + if (compositor->delegate()) { + output_device = compositor->delegate()->CreateSoftwareOutputDevice( + compositor.get()); + } + if (!output_device) { + output_device = CreateSoftwareOutputDevice(compositor->widget(), + compositor->task_runner()); + } + display_output_surface = std::make_unique( - CreateSoftwareOutputDevice(compositor->widget(), - compositor->task_runner()), - std::move(vsync_callback)); + std::move(output_device), std::move(vsync_callback)); } else { DCHECK(context_provider); const auto& capabilities = context_provider->ContextCapabilities(); @@ -462,7 +483,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( display_output_surface = std::make_unique( context_provider, std::move(vsync_callback), - std::unique_ptr()); + std::unique_ptr(), + compositor->shared_texture_enabled()); } else if (capabilities.surfaceless) { #if defined(OS_MACOSX) const auto& gpu_feature_info = context_provider->GetGpuFeatureInfo(); @@ -914,7 +936,8 @@ GpuProcessTransportFactory::CreatePerCompositorData( gfx::AcceleratedWidget widget = compositor->widget(); auto data = std::make_unique(); - if (widget == gfx::kNullAcceleratedWidget) { + if (widget == gfx::kNullAcceleratedWidget || + compositor->shared_texture_enabled()) { data->surface_handle = gpu::kNullSurfaceHandle; } else { #if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) diff --git content/browser/compositor/gpu_process_transport_factory.h content/browser/compositor/gpu_process_transport_factory.h index 525fa0c06b33..1f95b4f53496 100644 --- content/browser/compositor/gpu_process_transport_factory.h +++ content/browser/compositor/gpu_process_transport_factory.h @@ -101,6 +101,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory, void IssueExternalBeginFrame(ui::Compositor* compositor, const viz::BeginFrameArgs& args) override; void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override; + void* GetSharedTexture(ui::Compositor* compositor) override; // ImageTransportFactory implementation. void DisableGpuCompositing() override; diff --git content/browser/compositor/offscreen_browser_compositor_output_surface.cc content/browser/compositor/offscreen_browser_compositor_output_surface.cc index e719683c37e9..a51294913fc4 100644 --- content/browser/compositor/offscreen_browser_compositor_output_surface.cc +++ content/browser/compositor/offscreen_browser_compositor_output_surface.cc @@ -34,10 +34,12 @@ OffscreenBrowserCompositorOutputSurface:: scoped_refptr context, const UpdateVSyncParametersCallback& update_vsync_parameters_callback, std::unique_ptr - overlay_candidate_validator) + overlay_candidate_validator, + bool shared_texture_enabled) : BrowserCompositorOutputSurface(std::move(context), update_vsync_parameters_callback, std::move(overlay_candidate_validator)), + shared_texture_enabled_(shared_texture_enabled), weak_ptr_factory_(this) { capabilities_.uses_default_gl_framebuffer = false; } @@ -47,6 +49,10 @@ OffscreenBrowserCompositorOutputSurface:: DiscardBackbuffer(); } +void* OffscreenBrowserCompositorOutputSurface::GetSharedTexture() const { + return (void*)shared_handle_; +} + void OffscreenBrowserCompositorOutputSurface::BindToClient( viz::OutputSurfaceClient* client) { DCHECK(client); @@ -55,42 +61,72 @@ void OffscreenBrowserCompositorOutputSurface::BindToClient( } void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() { - bool update_source_texture = !reflector_texture_ || reflector_changed_; - reflector_changed_ = false; - if (!reflector_texture_) { - reflector_texture_.reset(new ReflectorTexture(context_provider())); - - GLES2Interface* gl = context_provider_->ContextGL(); - - const int max_texture_size = - context_provider_->ContextCapabilities().max_texture_size; - int texture_width = std::min(max_texture_size, reshape_size_.width()); - int texture_height = std::min(max_texture_size, reshape_size_.height()); - - gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id()); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(kFboTextureFormat), - texture_width, texture_height, 0, - GLDataFormat(kFboTextureFormat), - GLDataType(kFboTextureFormat), nullptr); + GLES2Interface* gl = context_provider_->ContextGL(); + + const int max_texture_size = + context_provider_->ContextCapabilities().max_texture_size; + int texture_width = std::min(max_texture_size, reshape_size_.width()); + int texture_height = std::min(max_texture_size, reshape_size_.height()); + + GLuint color_attachment = 0; + + if (shared_texture_enabled_) { + if (!shared_handle_ && (texture_width > 0) && (texture_height > 0)) { + gl->GenTextures(1, &shared_texture_); + gl->BindTexture(GL_TEXTURE_2D, shared_texture_); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + shared_handle_ = gl->CreateSharedTexture(shared_texture_, texture_width, + texture_height); + + if (shared_handle_) { + color_attachment = shared_texture_; + } else { + gl->DeleteTextures(1, &shared_texture_); + shared_texture_ = 0; + } + } + } else { + // The shared texture code above in theory could work with the reflector + // texture However, there were issues making associating it a shared surface + // and then attaching it to the FBO (incomplete?) + bool update_source_texture = !reflector_texture_ || reflector_changed_; + reflector_changed_ = false; + if (!reflector_texture_) { + reflector_texture_.reset(new ReflectorTexture(context_provider())); + + gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id()); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(kFboTextureFormat), + texture_width, texture_height, 0, + GLDataFormat(kFboTextureFormat), + GLDataType(kFboTextureFormat), nullptr); + + color_attachment = reflector_texture_->texture_id(); + + // The reflector may be created later or detached and re-attached, + // so don't assume it always exists. For example, ChromeOS always + // creates a reflector asynchronosly when creating this for software + // mirroring. See |DisplayManager::CreateMirrorWindowAsyncIfAny|. + if (reflector_ && update_source_texture) + reflector_->OnSourceTextureMailboxUpdated( + reflector_texture_->mailbox()); + } + } + + if (color_attachment) { if (!fbo_) gl->GenFramebuffers(1, &fbo_); gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, reflector_texture_->texture_id(), - 0); + GL_TEXTURE_2D, color_attachment, 0); } - - // The reflector may be created later or detached and re-attached, - // so don't assume it always exists. For example, ChromeOS always - // creates a reflector asynchronosly when creating this for software - // mirroring. See |DisplayManager::CreateMirrorWindowAsyncIfAny|. - if (reflector_ && update_source_texture) - reflector_->OnSourceTextureMailboxUpdated(reflector_texture_->mailbox()); } void OffscreenBrowserCompositorOutputSurface::DiscardBackbuffer() { @@ -102,6 +138,16 @@ void OffscreenBrowserCompositorOutputSurface::DiscardBackbuffer() { reflector_->OnSourceTextureMailboxUpdated(nullptr); } + if (shared_handle_) { + gl->DeleteSharedTexture(shared_handle_); + shared_handle_ = 0ull; + } + + if (shared_texture_) { + gl->DeleteTextures(1, &shared_texture_); + shared_texture_ = 0; + } + if (fbo_) { gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); gl->DeleteFramebuffers(1, &fbo_); @@ -124,15 +170,20 @@ void OffscreenBrowserCompositorOutputSurface::Reshape( } void OffscreenBrowserCompositorOutputSurface::BindFramebuffer() { - bool need_to_bind = !!reflector_texture_.get(); + GLES2Interface* gl = context_provider_->ContextGL(); + bool need_to_bind = !!reflector_texture_.get(); EnsureBackbuffer(); - DCHECK(reflector_texture_.get()); DCHECK(fbo_); - if (need_to_bind) { - GLES2Interface* gl = context_provider_->ContextGL(); + if (shared_handle_) { gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); + gl->LockSharedTexture(shared_handle_); + } else { + DCHECK(reflector_texture_.get()); + if (need_to_bind) { + gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); + } } } @@ -153,6 +204,12 @@ void OffscreenBrowserCompositorOutputSurface::SwapBuffers( // The original implementation had a flickering issue (crbug.com/515332). gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); + // If using a shared texture we need to Flush. + if (shared_handle_) { + gl->UnlockSharedTexture(shared_handle_); + gl->Flush(); + } + gpu::SyncToken sync_token; gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); context_provider_->ContextSupport()->SignalSyncToken( @@ -192,7 +249,9 @@ void OffscreenBrowserCompositorOutputSurface::OnSwapBuffersComplete( const std::vector& latency_info) { latency_tracker_.OnGpuSwapBuffersCompleted(latency_info); client_->DidReceiveSwapBuffersAck(); - client_->DidReceivePresentationFeedback(gfx::PresentationFeedback()); + gfx::PresentationFeedback feedback; + feedback.timestamp = base::TimeTicks::Now(); + client_->DidReceivePresentationFeedback(feedback); } unsigned OffscreenBrowserCompositorOutputSurface::UpdateGpuFence() { diff --git content/browser/compositor/offscreen_browser_compositor_output_surface.h content/browser/compositor/offscreen_browser_compositor_output_surface.h index 71830777ae56..6a0857b02a04 100644 --- content/browser/compositor/offscreen_browser_compositor_output_surface.h +++ content/browser/compositor/offscreen_browser_compositor_output_surface.h @@ -31,7 +31,8 @@ class OffscreenBrowserCompositorOutputSurface scoped_refptr context, const UpdateVSyncParametersCallback& update_vsync_parameters_callback, std::unique_ptr - overlay_candidate_validator); + overlay_candidate_validator, + bool shared_texture_enabled); ~OffscreenBrowserCompositorOutputSurface() override; @@ -53,11 +54,15 @@ class OffscreenBrowserCompositorOutputSurface gfx::BufferFormat GetOverlayBufferFormat() const override; uint32_t GetFramebufferCopyTextureFormat() override; + void* GetSharedTexture() const override; + // BrowserCompositorOutputSurface implementation. void OnReflectorChanged() override; unsigned UpdateGpuFence() override; + void NotifyRenderHost(const std::vector& latency_info); + void OnSwapBuffersComplete(const std::vector& latency_info); viz::OutputSurfaceClient* client_ = nullptr; @@ -65,6 +70,11 @@ class OffscreenBrowserCompositorOutputSurface uint32_t fbo_ = 0; bool reflector_changed_ = false; std::unique_ptr reflector_texture_; + + bool shared_texture_enabled_ = false; + uint64_t shared_handle_ = 0ull; + uint32_t shared_texture_ = 0; + ui::LatencyTracker latency_tracker_; base::WeakPtrFactory weak_ptr_factory_; diff --git gpu/GLES2/gl2chromium_autogen.h gpu/GLES2/gl2chromium_autogen.h index 404c05cee78b..d2ce3e8de6e9 100644 --- gpu/GLES2/gl2chromium_autogen.h +++ gpu/GLES2/gl2chromium_autogen.h @@ -416,6 +416,10 @@ GLES2_GET_FUN(CreateClientGpuFenceCHROMIUM) #define glWaitGpuFenceCHROMIUM GLES2_GET_FUN(WaitGpuFenceCHROMIUM) #define glDestroyGpuFenceCHROMIUM GLES2_GET_FUN(DestroyGpuFenceCHROMIUM) +#define glCreateSharedTexture GLES2_GET_FUN(CreateSharedTexture) +#define glLockSharedTexture GLES2_GET_FUN(LockSharedTexture) +#define glUnlockSharedTexture GLES2_GET_FUN(UnlockSharedTexture) +#define glDeleteSharedTexture GLES2_GET_FUN(DeleteSharedTexture) #define glInvalidateReadbackBufferShadowDataCHROMIUM \ GLES2_GET_FUN(InvalidateReadbackBufferShadowDataCHROMIUM) #define glFramebufferTextureMultiviewLayeredANGLE \ diff --git gpu/command_buffer/build_gles2_cmd_buffer.py gpu/command_buffer/build_gles2_cmd_buffer.py index 4032b2491109..02639f9b2080 100755 --- gpu/command_buffer/build_gles2_cmd_buffer.py +++ gpu/command_buffer/build_gles2_cmd_buffer.py @@ -4254,6 +4254,35 @@ _FUNCTION_INFO = { 'extension': 'CHROMIUM_gpu_fence', 'extension_flag': 'chromium_gpu_fence', }, + 'CreateSharedTexture': { + 'type': 'Custom', + 'data_transfer_methods': ['shm'], + 'cmd_args': 'GLint texture_id, GLint width, ' + 'GLint height, GLuint64* result', + 'result': ['GLuint64'], + 'unit_test': False, + 'impl_func': False, + 'client_test': False, + 'extension': True, + }, + 'LockSharedTexture': { + 'type': 'Custom', + 'unit_test': False, + 'client_test': False, + 'extension': True, + }, + 'UnlockSharedTexture': { + 'type': 'Custom', + 'unit_test': False, + 'client_test': False, + 'extension': True, + }, + 'DeleteSharedTexture': { + 'type': 'Custom', + 'unit_test': False, + 'client_test': False, + 'extension': True, + }, 'UnpremultiplyAndDitherCopyCHROMIUM': { 'decoder_func': 'DoUnpremultiplyAndDitherCopyCHROMIUM', 'cmd_args': 'GLuint source_id, GLuint dest_id, GLint x, GLint y, ' diff --git gpu/command_buffer/client/gles2_c_lib_autogen.h gpu/command_buffer/client/gles2_c_lib_autogen.h index b68942087179..2248762fcd77 100644 --- gpu/command_buffer/client/gles2_c_lib_autogen.h +++ gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -1909,6 +1909,20 @@ void GL_APIENTRY GLES2WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) { void GL_APIENTRY GLES2DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { gles2::GetGLContext()->DestroyGpuFenceCHROMIUM(gpu_fence_id); } +GLuint64 GL_APIENTRY GLES2CreateSharedTexture(GLuint texture_id, + GLsizei width, + GLsizei height) { + return gles2::GetGLContext()->CreateSharedTexture(texture_id, width, height); +} +void GL_APIENTRY GLES2LockSharedTexture(GLuint64 shared_handle) { + gles2::GetGLContext()->LockSharedTexture(shared_handle); +} +void GL_APIENTRY GLES2UnlockSharedTexture(GLuint64 shared_handle) { + gles2::GetGLContext()->UnlockSharedTexture(shared_handle); +} +void GL_APIENTRY GLES2DeleteSharedTexture(GLuint64 shared_handle) { + gles2::GetGLContext()->DeleteSharedTexture(shared_handle); +} void GL_APIENTRY GLES2InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) { gles2::GetGLContext()->InvalidateReadbackBufferShadowDataCHROMIUM(buffer_id); @@ -3434,6 +3448,22 @@ extern const NameToFunc g_gles2_function_table[] = { "glDestroyGpuFenceCHROMIUM", reinterpret_cast(glDestroyGpuFenceCHROMIUM), }, + { + "glCreateSharedTexture", + reinterpret_cast(glCreateSharedTexture), + }, + { + "glLockSharedTexture", + reinterpret_cast(glLockSharedTexture), + }, + { + "glUnlockSharedTexture", + reinterpret_cast(glUnlockSharedTexture), + }, + { + "glDeleteSharedTexture", + reinterpret_cast(glDeleteSharedTexture), + }, { "glInvalidateReadbackBufferShadowDataCHROMIUM", reinterpret_cast( diff --git gpu/command_buffer/client/gles2_cmd_helper_autogen.h gpu/command_buffer/client/gles2_cmd_helper_autogen.h index e2ac01959e22..83fb39054432 100644 --- gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -3521,6 +3521,42 @@ void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { } } +void CreateSharedTexture(GLint texture_id, + GLint width, + GLint height, + uint32_t result_shm_id, + uint32_t result_shm_offset) { + gles2::cmds::CreateSharedTexture* c = + GetCmdSpace(); + if (c) { + c->Init(texture_id, width, height, result_shm_id, result_shm_offset); + } +} + +void LockSharedTexture(GLuint64 shared_handle) { + gles2::cmds::LockSharedTexture* c = + GetCmdSpace(); + if (c) { + c->Init(shared_handle); + } +} + +void UnlockSharedTexture(GLuint64 shared_handle) { + gles2::cmds::UnlockSharedTexture* c = + GetCmdSpace(); + if (c) { + c->Init(shared_handle); + } +} + +void DeleteSharedTexture(GLuint64 shared_handle) { + gles2::cmds::DeleteSharedTexture* c = + GetCmdSpace(); + if (c) { + c->Init(shared_handle); + } +} + void SetReadbackBufferShadowAllocationINTERNAL(GLuint buffer_id, GLint shm_id, GLuint shm_offset, diff --git gpu/command_buffer/client/gles2_implementation.cc gpu/command_buffer/client/gles2_implementation.cc index e748a48a8e2a..a92b41df54d3 100644 --- gpu/command_buffer/client/gles2_implementation.cc +++ gpu/command_buffer/client/gles2_implementation.cc @@ -7687,6 +7687,22 @@ void GLES2Implementation::Viewport(GLint x, CheckGLError(); } +GLuint64 GLES2Implementation::CreateSharedTexture(GLuint texture_id, + GLsizei width, + GLsizei height) { + typedef cmds::CreateSharedTexture::Result Result; + auto result = GetResultAs(); + if (!result) { + return 0; + } + *result = 0; + helper_->CreateSharedTexture(texture_id, width, height, GetResultShmId(), + result.offset()); + + WaitForCmd(); + return *result; +} + void GLES2Implementation::IssueBeginQuery(GLenum target, GLuint id, uint32_t sync_data_shm_id, diff --git gpu/command_buffer/client/gles2_implementation_autogen.h gpu/command_buffer/client/gles2_implementation_autogen.h index 6882d12a79c4..b237ee953860 100644 --- gpu/command_buffer/client/gles2_implementation_autogen.h +++ gpu/command_buffer/client/gles2_implementation_autogen.h @@ -1345,6 +1345,16 @@ void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) override; void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) override; +GLuint64 CreateSharedTexture(GLuint texture_id, + GLsizei width, + GLsizei height) override; + +void LockSharedTexture(GLuint64 shared_handle) override; + +void UnlockSharedTexture(GLuint64 shared_handle) override; + +void DeleteSharedTexture(GLuint64 shared_handle) override; + void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) override; void FramebufferTextureMultiviewLayeredANGLE(GLenum target, diff --git gpu/command_buffer/client/gles2_implementation_impl_autogen.h gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 13b36769ae3d..d2351bb96021 100644 --- gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -3790,6 +3790,30 @@ void GLES2Implementation::DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { CheckGLError(); } +void GLES2Implementation::LockSharedTexture(GLuint64 shared_handle) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLockSharedTexture(" + << shared_handle << ")"); + helper_->LockSharedTexture(shared_handle); + CheckGLError(); +} + +void GLES2Implementation::UnlockSharedTexture(GLuint64 shared_handle) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnlockSharedTexture(" + << shared_handle << ")"); + helper_->UnlockSharedTexture(shared_handle); + CheckGLError(); +} + +void GLES2Implementation::DeleteSharedTexture(GLuint64 shared_handle) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSharedTexture(" + << shared_handle << ")"); + helper_->DeleteSharedTexture(shared_handle); + CheckGLError(); +} + void GLES2Implementation::FramebufferTextureMultiviewLayeredANGLE( GLenum target, GLenum attachment, diff --git gpu/command_buffer/client/gles2_interface_autogen.h gpu/command_buffer/client/gles2_interface_autogen.h index 2071473f0da8..77a29e65cafd 100644 --- gpu/command_buffer/client/gles2_interface_autogen.h +++ gpu/command_buffer/client/gles2_interface_autogen.h @@ -1010,6 +1010,12 @@ virtual GLuint CreateGpuFenceCHROMIUM() = 0; virtual GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) = 0; virtual void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) = 0; virtual void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) = 0; +virtual GLuint64 CreateSharedTexture(GLuint texture_id, + GLsizei width, + GLsizei height) = 0; +virtual void LockSharedTexture(GLuint64 shared_handle) = 0; +virtual void UnlockSharedTexture(GLuint64 shared_handle) = 0; +virtual void DeleteSharedTexture(GLuint64 shared_handle) = 0; virtual void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) = 0; virtual void FramebufferTextureMultiviewLayeredANGLE(GLenum target, GLenum attachment, diff --git gpu/command_buffer/client/gles2_interface_stub_autogen.h gpu/command_buffer/client/gles2_interface_stub_autogen.h index 158134cf608e..2990494dcc5e 100644 --- gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -980,6 +980,12 @@ GLuint CreateGpuFenceCHROMIUM() override; GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) override; void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) override; void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) override; +GLuint64 CreateSharedTexture(GLuint texture_id, + GLsizei width, + GLsizei height) override; +void LockSharedTexture(GLuint64 shared_handle) override; +void UnlockSharedTexture(GLuint64 shared_handle) override; +void DeleteSharedTexture(GLuint64 shared_handle) override; void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) override; void FramebufferTextureMultiviewLayeredANGLE(GLenum target, GLenum attachment, diff --git gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 29d079725c72..444c60df71a4 100644 --- gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -1303,6 +1303,14 @@ GLuint GLES2InterfaceStub::CreateClientGpuFenceCHROMIUM( } void GLES2InterfaceStub::WaitGpuFenceCHROMIUM(GLuint /* gpu_fence_id */) {} void GLES2InterfaceStub::DestroyGpuFenceCHROMIUM(GLuint /* gpu_fence_id */) {} +GLuint64 GLES2InterfaceStub::CreateSharedTexture(GLuint /* texture_id */, + GLsizei /* width */, + GLsizei /* height */) { + return 0; +} +void GLES2InterfaceStub::LockSharedTexture(GLuint64 /* shared_handle */) {} +void GLES2InterfaceStub::UnlockSharedTexture(GLuint64 /* shared_handle */) {} +void GLES2InterfaceStub::DeleteSharedTexture(GLuint64 /* shared_handle */) {} void GLES2InterfaceStub::InvalidateReadbackBufferShadowDataCHROMIUM( GLuint /* buffer_id */) {} void GLES2InterfaceStub::FramebufferTextureMultiviewLayeredANGLE( diff --git gpu/command_buffer/client/gles2_trace_implementation_autogen.h gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 7e94db26455d..d9de7879ea9a 100644 --- gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -980,6 +980,12 @@ GLuint CreateGpuFenceCHROMIUM() override; GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) override; void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) override; void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) override; +GLuint64 CreateSharedTexture(GLuint texture_id, + GLsizei width, + GLsizei height) override; +void LockSharedTexture(GLuint64 shared_handle) override; +void UnlockSharedTexture(GLuint64 shared_handle) override; +void DeleteSharedTexture(GLuint64 shared_handle) override; void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) override; void FramebufferTextureMultiviewLayeredANGLE(GLenum target, GLenum attachment, diff --git gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 4b7932e147b0..b0f5f2cafae3 100644 --- gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -2747,6 +2747,28 @@ void GLES2TraceImplementation::DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { gl_->DestroyGpuFenceCHROMIUM(gpu_fence_id); } +GLuint64 GLES2TraceImplementation::CreateSharedTexture(GLuint texture_id, + GLsizei width, + GLsizei height) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CreateSharedTexture"); + return gl_->CreateSharedTexture(texture_id, width, height); +} + +void GLES2TraceImplementation::LockSharedTexture(GLuint64 shared_handle) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::LockSharedTexture"); + gl_->LockSharedTexture(shared_handle); +} + +void GLES2TraceImplementation::UnlockSharedTexture(GLuint64 shared_handle) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UnlockSharedTexture"); + gl_->UnlockSharedTexture(shared_handle); +} + +void GLES2TraceImplementation::DeleteSharedTexture(GLuint64 shared_handle) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DeleteSharedTexture"); + gl_->DeleteSharedTexture(shared_handle); +} + void GLES2TraceImplementation::InvalidateReadbackBufferShadowDataCHROMIUM( GLuint buffer_id) { TRACE_EVENT_BINARY_EFFICIENT0( diff --git gpu/command_buffer/common/gles2_cmd_format_autogen.h gpu/command_buffer/common/gles2_cmd_format_autogen.h index 2a59e11c2d25..fbb6c4551d70 100644 --- gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -17336,6 +17336,193 @@ static_assert(offsetof(DestroyGpuFenceCHROMIUM, header) == 0, static_assert(offsetof(DestroyGpuFenceCHROMIUM, gpu_fence_id) == 4, "offset of DestroyGpuFenceCHROMIUM gpu_fence_id should be 4"); +struct CreateSharedTexture { + typedef CreateSharedTexture ValueType; + static const CommandId kCmdId = kCreateSharedTexture; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + typedef GLuint64 Result; + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLint _texture_id, + GLint _width, + GLint _height, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + SetHeader(); + texture_id = _texture_id; + width = _width; + height = _height; + result_shm_id = _result_shm_id; + result_shm_offset = _result_shm_offset; + } + + void* Set(void* cmd, + GLint _texture_id, + GLint _width, + GLint _height, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + static_cast(cmd)->Init(_texture_id, _width, _height, + _result_shm_id, _result_shm_offset); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + int32_t texture_id; + int32_t width; + int32_t height; + uint32_t result_shm_id; + uint32_t result_shm_offset; +}; + +static_assert(sizeof(CreateSharedTexture) == 24, + "size of CreateSharedTexture should be 24"); +static_assert(offsetof(CreateSharedTexture, header) == 0, + "offset of CreateSharedTexture header should be 0"); +static_assert(offsetof(CreateSharedTexture, texture_id) == 4, + "offset of CreateSharedTexture texture_id should be 4"); +static_assert(offsetof(CreateSharedTexture, width) == 8, + "offset of CreateSharedTexture width should be 8"); +static_assert(offsetof(CreateSharedTexture, height) == 12, + "offset of CreateSharedTexture height should be 12"); +static_assert(offsetof(CreateSharedTexture, result_shm_id) == 16, + "offset of CreateSharedTexture result_shm_id should be 16"); +static_assert(offsetof(CreateSharedTexture, result_shm_offset) == 20, + "offset of CreateSharedTexture result_shm_offset should be 20"); + +struct LockSharedTexture { + typedef LockSharedTexture ValueType; + static const CommandId kCmdId = kLockSharedTexture; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLuint64 _shared_handle) { + SetHeader(); + GLES2Util::MapUint64ToTwoUint32(static_cast(_shared_handle), + &shared_handle_0, &shared_handle_1); + } + + void* Set(void* cmd, GLuint64 _shared_handle) { + static_cast(cmd)->Init(_shared_handle); + return NextCmdAddress(cmd); + } + + GLuint64 shared_handle() const volatile { + return static_cast( + GLES2Util::MapTwoUint32ToUint64(shared_handle_0, shared_handle_1)); + } + + gpu::CommandHeader header; + uint32_t shared_handle_0; + uint32_t shared_handle_1; +}; + +static_assert(sizeof(LockSharedTexture) == 12, + "size of LockSharedTexture should be 12"); +static_assert(offsetof(LockSharedTexture, header) == 0, + "offset of LockSharedTexture header should be 0"); +static_assert(offsetof(LockSharedTexture, shared_handle_0) == 4, + "offset of LockSharedTexture shared_handle_0 should be 4"); +static_assert(offsetof(LockSharedTexture, shared_handle_1) == 8, + "offset of LockSharedTexture shared_handle_1 should be 8"); + +struct UnlockSharedTexture { + typedef UnlockSharedTexture ValueType; + static const CommandId kCmdId = kUnlockSharedTexture; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLuint64 _shared_handle) { + SetHeader(); + GLES2Util::MapUint64ToTwoUint32(static_cast(_shared_handle), + &shared_handle_0, &shared_handle_1); + } + + void* Set(void* cmd, GLuint64 _shared_handle) { + static_cast(cmd)->Init(_shared_handle); + return NextCmdAddress(cmd); + } + + GLuint64 shared_handle() const volatile { + return static_cast( + GLES2Util::MapTwoUint32ToUint64(shared_handle_0, shared_handle_1)); + } + + gpu::CommandHeader header; + uint32_t shared_handle_0; + uint32_t shared_handle_1; +}; + +static_assert(sizeof(UnlockSharedTexture) == 12, + "size of UnlockSharedTexture should be 12"); +static_assert(offsetof(UnlockSharedTexture, header) == 0, + "offset of UnlockSharedTexture header should be 0"); +static_assert(offsetof(UnlockSharedTexture, shared_handle_0) == 4, + "offset of UnlockSharedTexture shared_handle_0 should be 4"); +static_assert(offsetof(UnlockSharedTexture, shared_handle_1) == 8, + "offset of UnlockSharedTexture shared_handle_1 should be 8"); + +struct DeleteSharedTexture { + typedef DeleteSharedTexture ValueType; + static const CommandId kCmdId = kDeleteSharedTexture; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLuint64 _shared_handle) { + SetHeader(); + GLES2Util::MapUint64ToTwoUint32(static_cast(_shared_handle), + &shared_handle_0, &shared_handle_1); + } + + void* Set(void* cmd, GLuint64 _shared_handle) { + static_cast(cmd)->Init(_shared_handle); + return NextCmdAddress(cmd); + } + + GLuint64 shared_handle() const volatile { + return static_cast( + GLES2Util::MapTwoUint32ToUint64(shared_handle_0, shared_handle_1)); + } + + gpu::CommandHeader header; + uint32_t shared_handle_0; + uint32_t shared_handle_1; +}; + +static_assert(sizeof(DeleteSharedTexture) == 12, + "size of DeleteSharedTexture should be 12"); +static_assert(offsetof(DeleteSharedTexture, header) == 0, + "offset of DeleteSharedTexture header should be 0"); +static_assert(offsetof(DeleteSharedTexture, shared_handle_0) == 4, + "offset of DeleteSharedTexture shared_handle_0 should be 4"); +static_assert(offsetof(DeleteSharedTexture, shared_handle_1) == 8, + "offset of DeleteSharedTexture shared_handle_1 should be 8"); + struct SetReadbackBufferShadowAllocationINTERNAL { typedef SetReadbackBufferShadowAllocationINTERNAL ValueType; static const CommandId kCmdId = kSetReadbackBufferShadowAllocationINTERNAL; diff --git gpu/command_buffer/common/gles2_cmd_format_test_autogen.h gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 128473360af0..b4947682c816 100644 --- gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -5721,6 +5721,52 @@ TEST_F(GLES2FormatTest, DestroyGpuFenceCHROMIUM) { CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, CreateSharedTexture) { + cmds::CreateSharedTexture& cmd = *GetBufferAs(); + void* next_cmd = cmd.Set(&cmd, static_cast(11), static_cast(12), + static_cast(13), static_cast(14), + static_cast(15)); + EXPECT_EQ(static_cast(cmds::CreateSharedTexture::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.texture_id); + EXPECT_EQ(static_cast(12), cmd.width); + EXPECT_EQ(static_cast(13), cmd.height); + EXPECT_EQ(static_cast(14), cmd.result_shm_id); + EXPECT_EQ(static_cast(15), cmd.result_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, LockSharedTexture) { + cmds::LockSharedTexture& cmd = *GetBufferAs(); + void* next_cmd = cmd.Set(&cmd, static_cast(11)); + EXPECT_EQ(static_cast(cmds::LockSharedTexture::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.shared_handle()); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, UnlockSharedTexture) { + cmds::UnlockSharedTexture& cmd = *GetBufferAs(); + void* next_cmd = cmd.Set(&cmd, static_cast(11)); + EXPECT_EQ(static_cast(cmds::UnlockSharedTexture::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.shared_handle()); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, DeleteSharedTexture) { + cmds::DeleteSharedTexture& cmd = *GetBufferAs(); + void* next_cmd = cmd.Set(&cmd, static_cast(11)); + EXPECT_EQ(static_cast(cmds::DeleteSharedTexture::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.shared_handle()); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, SetReadbackBufferShadowAllocationINTERNAL) { cmds::SetReadbackBufferShadowAllocationINTERNAL& cmd = *GetBufferAs(); diff --git gpu/command_buffer/common/gles2_cmd_ids_autogen.h gpu/command_buffer/common/gles2_cmd_ids_autogen.h index b3dd9b38feba..bcb3656e4481 100644 --- gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -361,7 +361,11 @@ OP(MaxShaderCompilerThreadsKHR) /* 602 */ \ OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 603 */ \ OP(BeginSharedImageAccessDirectCHROMIUM) /* 604 */ \ - OP(EndSharedImageAccessDirectCHROMIUM) /* 605 */ + OP(EndSharedImageAccessDirectCHROMIUM) /* 605 */ \ + OP(CreateSharedTexture) /* 606 */ \ + OP(LockSharedTexture) /* 607 */ \ + OP(UnlockSharedTexture) /* 608 */ \ + OP(DeleteSharedTexture) /* 609 */ enum CommandId { kOneBeforeStartPoint = diff --git gpu/command_buffer/gles2_cmd_buffer_functions.txt gpu/command_buffer/gles2_cmd_buffer_functions.txt index 2f9b93fda757..9897a2790587 100644 --- gpu/command_buffer/gles2_cmd_buffer_functions.txt +++ gpu/command_buffer/gles2_cmd_buffer_functions.txt @@ -417,6 +417,12 @@ GL_APICALL GLuint GL_APIENTRY glCreateClientGpuFenceCHROMIUM (ClientGpuFen GL_APICALL void GL_APIENTRY glWaitGpuFenceCHROMIUM (GLuint gpu_fence_id); GL_APICALL void GL_APIENTRY glDestroyGpuFenceCHROMIUM (GLuint gpu_fence_id); +// shared handle extensions +GL_APICALL GLuint64 GL_APIENTRY glCreateSharedTexture (GLuint texture_id, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glLockSharedTexture (GLuint64 shared_handle); +GL_APICALL void GL_APIENTRY glUnlockSharedTexture (GLuint64 shared_handle); +GL_APICALL void GL_APIENTRY glDeleteSharedTexture (GLuint64 shared_handle); + // Extension CHROMIUM_nonblocking_readback GL_APICALL void GL_APIENTRY glInvalidateReadbackBufferShadowDataCHROMIUM (GLidBuffer buffer_id); // (used for CHROMIUM_nonblocking_readback implementation) diff --git gpu/command_buffer/service/BUILD.gn gpu/command_buffer/service/BUILD.gn index bbf81312c8d9..817a6b6fa421 100644 --- gpu/command_buffer/service/BUILD.gn +++ gpu/command_buffer/service/BUILD.gn @@ -107,6 +107,8 @@ target(link_target_type, "gles2_sources") { visibility = [ "//gpu/*" ] sources = [ + "//cef/libcef/browser/gpu/external_texture_manager.cc", + "//cef/libcef/browser/gpu/external_texture_manager.h", "abstract_texture.h", "abstract_texture_impl_shared_context_state.cc", "abstract_texture_impl_shared_context_state.h", diff --git gpu/command_buffer/service/gles2_cmd_decoder.cc gpu/command_buffer/service/gles2_cmd_decoder.cc index 5bb86a2a5d32..5439662701af 100644 --- gpu/command_buffer/service/gles2_cmd_decoder.cc +++ gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -38,6 +38,7 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "cef/libcef/browser/gpu/external_texture_manager.h" #include "gpu/command_buffer/common/debug_marker_manager.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -916,6 +917,13 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { return group_->mailbox_manager(); } + ExternalTextureManager* external_texture_manager() { + if (!external_texture_manager_.get()) { + external_texture_manager_.reset(new gles2::ExternalTextureManager()); + } + return external_texture_manager_.get(); + } + ImageManager* image_manager() { return group_->image_manager(); } VertexArrayManager* vertex_array_manager() { @@ -2644,6 +2652,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { std::unique_ptr vertex_array_manager_; + std::unique_ptr external_texture_manager_; + base::flat_set> writes_submitted_but_not_completed_; // The format of the back buffer_ @@ -5619,6 +5629,59 @@ error::Error GLES2DecoderImpl::HandleDestroyGpuFenceCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleCreateSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::CreateSharedTexture& c = + *static_cast(cmd_data); + GLuint texture_id = c.texture_id; + uint32_t width = c.width; + uint32_t height = c.height; + + typedef cmds::CreateSharedTexture::Result Result; + Result* result_dst = GetSharedMemoryAs( + c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); + if (!result_dst) { + return error::kOutOfBounds; + } + + void* shared_handle = external_texture_manager()->CreateTexture( + texture_id, width, height, texture_manager()); + + *result_dst = (GLuint64)(shared_handle); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleLockSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::LockSharedTexture& c = + *static_cast(cmd_data); + void* handle = (void*)(c.shared_handle()); + external_texture_manager()->LockTexture(handle); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleUnlockSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::UnlockSharedTexture& c = + *static_cast(cmd_data); + void* handle = (void*)(c.shared_handle()); + external_texture_manager()->UnlockTexture(handle); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleDeleteSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::DeleteSharedTexture& c = + *static_cast(cmd_data); + void* handle = (void*)(c.shared_handle()); + external_texture_manager()->DeleteTexture(handle, texture_manager()); + return error::kNoError; +} + void GLES2DecoderImpl::CreateBackTexture() { for (auto it = saved_back_textures_.begin(); it != saved_back_textures_.end(); ++it) { diff --git gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index 2766bcbc5418..417f26076423 100644 --- gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc @@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/stl_util.h" #include "base/strings/string_split.h" +#include "cef/libcef/browser/gpu/external_texture_manager.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/decoder_client.h" #include "gpu/command_buffer/service/feature_info.h" @@ -2512,6 +2513,67 @@ error::Error GLES2DecoderPassthroughImpl::CheckSwapBuffersResult( return error::kNoError; } +ExternalTextureManager* +GLES2DecoderPassthroughImpl::external_texture_manager() { + if (!external_texture_manager_.get()) { + external_texture_manager_.reset(new gles2::ExternalTextureManager()); + } + return external_texture_manager_.get(); +} + +error::Error GLES2DecoderPassthroughImpl::HandleCreateSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::CreateSharedTexture& c = + *static_cast(cmd_data); + GLuint texture_id = c.texture_id; + uint32_t width = c.width; + uint32_t height = c.height; + + typedef cmds::CreateSharedTexture::Result Result; + Result* result_dst = GetSharedMemoryAs( + c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); + if (!result_dst) { + return error::kOutOfBounds; + } + + void* shared_handle = external_texture_manager()->CreateTexture( + texture_id, width, height, nullptr); + + *result_dst = (GLuint64)(shared_handle); + return error::kNoError; +} + +error::Error GLES2DecoderPassthroughImpl::HandleLockSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::LockSharedTexture& c = + *static_cast(cmd_data); + void* handle = (void*)(c.shared_handle()); + external_texture_manager()->LockTexture(handle); + return error::kNoError; +} + +error::Error GLES2DecoderPassthroughImpl::HandleUnlockSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::UnlockSharedTexture& c = + *static_cast(cmd_data); + void* handle = (void*)(c.shared_handle()); + external_texture_manager()->UnlockTexture(handle); + return error::kNoError; +} + +error::Error GLES2DecoderPassthroughImpl::HandleDeleteSharedTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::DeleteSharedTexture& c = + *static_cast(cmd_data); + void* handle = (void*)(c.shared_handle()); + external_texture_manager()->DeleteTexture(handle, nullptr); + return error::kNoError; +} + // static GLES2DecoderPassthroughImpl::TextureTarget GLES2DecoderPassthroughImpl::GLenumToTextureTarget(GLenum target) { diff --git gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index ed682013976b..4bc28fe68a5d 100644 --- gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h @@ -45,6 +45,7 @@ class SharedImageRepresentationGLTexturePassthrough; namespace gles2 { class ContextGroup; +class ExternalTextureManager; class GPUTracer; class MultiDrawManager; class PassthroughAbstractTextureImpl; @@ -377,6 +378,8 @@ class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { void SetOptionalExtensionsRequestedForTesting(bool request_extensions); + ExternalTextureManager* external_texture_manager(); + void* GetScratchMemory(size_t size); template @@ -580,6 +583,8 @@ class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { std::unique_ptr multi_draw_manager_; + std::unique_ptr external_texture_manager_; + // State tracking of currently bound 2D textures (client IDs) size_t active_texture_unit_; diff --git ui/compositor/compositor.cc ui/compositor/compositor.cc index 311c26b6e0ea..8583fdfecc19 100644 --- ui/compositor/compositor.cc +++ ui/compositor/compositor.cc @@ -555,6 +555,16 @@ scoped_refptr Compositor::vsync_manager() const { return vsync_manager_; } +void* Compositor::GetSharedTexture() { + if (context_factory_private_) + return context_factory_private_->GetSharedTexture(this); + return nullptr; +} + +void Compositor::EnableSharedTexture(bool enable) { + shared_texture_enabled_ = enable; +} + void Compositor::AddObserver(CompositorObserver* observer) { observer_list_.AddObserver(observer); } diff --git ui/compositor/compositor.h ui/compositor/compositor.h index 4e28277f7750..cd283ca49bd7 100644 --- ui/compositor/compositor.h +++ ui/compositor/compositor.h @@ -25,6 +25,7 @@ #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/local_surface_id_allocation.h" #include "components/viz/host/host_frame_sink_client.h" +#include "components/viz/service/display/software_output_device.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkMatrix44.h" #include "ui/compositor/compositor_animation_observer.h" @@ -160,6 +161,8 @@ class COMPOSITOR_EXPORT ContextFactoryPrivate { const viz::BeginFrameArgs& args) = 0; virtual void SetOutputIsSecure(Compositor* compositor, bool secure) = 0; + + virtual void* GetSharedTexture(ui::Compositor* compositor) = 0; }; // This class abstracts the creation of the 3D context for the compositor. It is @@ -200,6 +203,17 @@ class COMPOSITOR_EXPORT ContextFactory { virtual bool SyncTokensRequiredForDisplayCompositor() = 0; }; +class COMPOSITOR_EXPORT CompositorDelegate { + public: + virtual std::unique_ptr CreateSoftwareOutputDevice( + ui::Compositor* compositor) { + return nullptr; + } + + protected: + virtual ~CompositorDelegate() {} +}; + // Compositor object to take care of GPU painting. // A Browser compositor object is responsible for generating the final // displayable form of pixels comprising a single widget's contents. It draws an @@ -242,6 +256,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, // Schedules a redraw of the layer tree associated with this compositor. void ScheduleDraw(); + CompositorDelegate* delegate() const { return delegate_; } + void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; } + // Sets the root of the layer tree drawn by this Compositor. The root layer // must have no parent. The compositor's root layer is reset if the root layer // is destroyed. NULL can be passed to reset the root layer, in which case the @@ -355,6 +372,10 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, return task_runner_; } + void* GetSharedTexture(); + void EnableSharedTexture(bool enable); + bool shared_texture_enabled() const { return shared_texture_enabled_; } + // Compositor does not own observers. It is the responsibility of the // observer to remove itself when it is done observing. void AddObserver(CompositorObserver* observer); @@ -465,6 +486,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, ui::ContextFactory* context_factory_; ui::ContextFactoryPrivate* context_factory_private_; + CompositorDelegate* delegate_ = nullptr; + // The root of the Layer tree drawn by this compositor. Layer* root_layer_ = nullptr; @@ -499,6 +522,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, ExternalBeginFrameClient* const external_begin_frame_client_; + bool shared_texture_enabled_ = false; + const bool force_software_compositor_; // The device scale factor of the monitor that this compositor is compositing diff --git ui/compositor/host/host_context_factory_private.cc ui/compositor/host/host_context_factory_private.cc index 2b23ed42a933..109841847888 100644 --- ui/compositor/host/host_context_factory_private.cc +++ ui/compositor/host/host_context_factory_private.cc @@ -254,6 +254,10 @@ void HostContextFactoryPrivate::SetOutputIsSecure(Compositor* compositor, iter->second.display_private->SetOutputIsSecure(secure); } +void* HostContextFactoryPrivate::GetSharedTexture(Compositor* /*compositor*/) { + return nullptr; +} + viz::FrameSinkManagerImpl* HostContextFactoryPrivate::GetFrameSinkManager() { // When running with viz there is no FrameSinkManagerImpl in the browser // process. FrameSinkManagerImpl runs in the GPU process instead. Anything in diff --git ui/compositor/host/host_context_factory_private.h ui/compositor/host/host_context_factory_private.h index 18cd096449d2..aa25ea058925 100644 --- ui/compositor/host/host_context_factory_private.h +++ ui/compositor/host/host_context_factory_private.h @@ -50,6 +50,8 @@ class HostContextFactoryPrivate : public ContextFactoryPrivate { void UnconfigureCompositor(Compositor* compositor); + void* GetSharedTexture(ui::Compositor* compositor) override; + void set_is_gpu_compositing_disabled(bool value) { is_gpu_compositing_disabled_ = value; }