diff options
author | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-18 05:15:50 +0000 |
---|---|---|
committer | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-18 05:15:50 +0000 |
commit | f4ba36512524dc3150261942ec9a89b4dfb7364a (patch) | |
tree | e9f7e293728188a158b4156a03eb713f5eeebada | |
parent | fcb0f644c83064a695588aa74d755aff74a51286 (diff) | |
download | chromium_src-f4ba36512524dc3150261942ec9a89b4dfb7364a.zip chromium_src-f4ba36512524dc3150261942ec9a89b4dfb7364a.tar.gz chromium_src-f4ba36512524dc3150261942ec9a89b4dfb7364a.tar.bz2 |
gpu: Add support for GLX_EXT_texture_from_pixmap extension.
Implement CHROMIUM_texture_from_image. This extension behaves just like
EXT_texture_from_pixmap but uses chromium specific image identifiers rather
than platform specific pixmap IDs.
Add IPC message for creating an image identifier using a
gfx::PluginWindowHandle. Each GPU channel maintains a different set of
images and deleting an image will cause the internal image representation
to be freed once it's no longer bound to a texture.
BUG=132342
TEST=gpu_unittests --gtest_filter=TextureInfoTest.GetLevelImage:GLES2DecoderTest.BindTexImage2DCHROMIUM:GLES2DecoderTest.ReleaseTexImage2DCHROMIUM and manual
Review URL: https://chromiumcodereview.appspot.com/10543125
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162654 0039d316-1c4b-4281-b951-d872f2087c98
60 files changed, 1532 insertions, 79 deletions
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index 11d7287..49717b4 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -134,6 +134,72 @@ int32 BrowserGpuChannelHostFactory::CreateViewCommandBuffer( return request.route_id; } +void BrowserGpuChannelHostFactory::CreateImageOnIO( + gfx::PluginWindowHandle window, + int32 image_id, + const CreateImageCallback& callback) { + GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); + if (!host) { + ImageCreatedOnIO(callback, gfx::Size()); + return; + } + + host->CreateImage( + window, + gpu_client_id_, + image_id, + base::Bind(&BrowserGpuChannelHostFactory::ImageCreatedOnIO, callback)); +} + +// static +void BrowserGpuChannelHostFactory::ImageCreatedOnIO( + const CreateImageCallback& callback, const gfx::Size size) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&BrowserGpuChannelHostFactory::OnImageCreated, + callback, size)); +} + +// static +void BrowserGpuChannelHostFactory::OnImageCreated( + const CreateImageCallback& callback, const gfx::Size size) { + callback.Run(size); +} + +void BrowserGpuChannelHostFactory::CreateImage( + gfx::PluginWindowHandle window, + int32 image_id, + const CreateImageCallback& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind( + &BrowserGpuChannelHostFactory::CreateImageOnIO, + base::Unretained(this), + window, + image_id, + callback)); +} + +void BrowserGpuChannelHostFactory::DeleteImageOnIO( + int32 image_id, int32 sync_point) { + GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); + if (!host) { + return; + } + + host->DeleteImage(gpu_client_id_, image_id, sync_point); +} + +void BrowserGpuChannelHostFactory::DeleteImage( + int32 image_id, int32 sync_point) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind( + &BrowserGpuChannelHostFactory::DeleteImageOnIO, + base::Unretained(this), + image_id, + sync_point)); +} + void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( EstablishRequest* request) { GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index 13058e5..83140b3 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h @@ -31,6 +31,11 @@ class BrowserGpuChannelHostFactory : public GpuChannelHostFactory { virtual int32 CreateViewCommandBuffer( int32 surface_id, const GPUCreateCommandBufferConfig& init_params) OVERRIDE; + virtual void CreateImage( + gfx::PluginWindowHandle window, + int32 image_id, + const CreateImageCallback& callback) OVERRIDE; + virtual void DeleteImage(int32 image_idu, int32 sync_point) OVERRIDE; virtual GpuChannelHost* EstablishGpuChannelSync( CauseForGpuLaunch cause_for_gpu_launch) OVERRIDE; @@ -62,6 +67,15 @@ class BrowserGpuChannelHostFactory : public GpuChannelHostFactory { int32 surface_id, const GPUCreateCommandBufferConfig& init_params); static void CommandBufferCreatedOnIO(CreateRequest* request, int32 route_id); + void CreateImageOnIO( + gfx::PluginWindowHandle window, + int32 image_id, + const CreateImageCallback& callback); + static void ImageCreatedOnIO( + const CreateImageCallback& callback, const gfx::Size size); + static void OnImageCreated( + const CreateImageCallback& callback, const gfx::Size size); + void DeleteImageOnIO(int32 image_id, int32 sync_point); void EstablishGpuChannelOnIO(EstablishRequest* request); void GpuChannelEstablishedOnIO( EstablishRequest* request, diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index b168118..618e014 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -478,6 +478,7 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished) IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated) IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer, OnDestroyCommandBuffer) + IPC_MESSAGE_HANDLER(GpuHostMsg_ImageCreated, OnImageCreated) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, OnAcceleratedSurfaceBuffersSwapped) @@ -566,6 +567,33 @@ void GpuProcessHost::CreateViewCommandBuffer( } } +void GpuProcessHost::CreateImage( + gfx::PluginWindowHandle window, + int client_id, + int image_id, + const CreateImageCallback& callback) { + TRACE_EVENT0("gpu", "GpuProcessHostUIShim::CreateImage"); + + DCHECK(CalledOnValidThread()); + + if (Send(new GpuMsg_CreateImage(window, client_id, image_id))) { + create_image_requests_.push(callback); + } else { + CreateImageError(callback, gfx::Size()); + } +} + +void GpuProcessHost::DeleteImage( + int client_id, + int image_id, + int sync_point) { + TRACE_EVENT0("gpu", "GpuProcessHostUIShim::DeleteImage"); + + DCHECK(CalledOnValidThread()); + + Send(new GpuMsg_DeleteImage(client_id, image_id, sync_point)); +} + void GpuProcessHost::OnInitialized(bool result) { UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", result); } @@ -621,6 +649,16 @@ void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) { #endif // defined(TOOLKIT_GTK) } +void GpuProcessHost::OnImageCreated(const gfx::Size size) { + TRACE_EVENT0("gpu", "GpuProcessHost::OnImageCreated"); + + if (!create_image_requests_.empty()) { + CreateImageCallback callback = create_image_requests_.front(); + create_image_requests_.pop(); + callback.Run(size); + } +} + #if defined(OS_MACOSX) void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) { @@ -914,3 +952,8 @@ void GpuProcessHost::CreateCommandBufferError( const CreateCommandBufferCallback& callback, int32 route_id) { callback.Run(route_id); } + +void GpuProcessHost::CreateImageError( + const CreateImageCallback& callback, const gfx::Size size) { + callback.Run(size); +} diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index f4b8341..1ecd7d3 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h @@ -20,6 +20,7 @@ #include "content/public/common/gpu_info.h" #include "ipc/ipc_sender.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" class GpuMainThread; struct GPUCreateCommandBufferConfig; @@ -49,6 +50,8 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, typedef base::Callback<void(int32)> CreateCommandBufferCallback; + typedef base::Callback<void(const gfx::Size)> CreateImageCallback; + static bool gpu_enabled() { return gpu_enabled_; } // Creates a new GpuProcessHost or gets an existing one, resulting in the @@ -90,6 +93,16 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, const GPUCreateCommandBufferConfig& init_params, const CreateCommandBufferCallback& callback); + // Tells the GPU process to create a new image using the given window. + void CreateImage( + gfx::PluginWindowHandle window, + int client_id, + int image_id, + const CreateImageCallback& callback); + + // Tells the GPU process to delete image. + void DeleteImage(int client_id, int image_id, int sync_point); + // Whether this GPU process is set up to use software rendering. bool software_rendering(); @@ -120,6 +133,7 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, void OnChannelEstablished(const IPC::ChannelHandle& channel_handle); void OnCommandBufferCreated(const int32 route_id); void OnDestroyCommandBuffer(int32 surface_id); + void OnImageCreated(const gfx::Size size); #if defined(OS_MACOSX) void OnAcceleratedSurfaceBuffersSwapped( @@ -146,6 +160,8 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, const content::GPUInfo& gpu_info); void CreateCommandBufferError(const CreateCommandBufferCallback& callback, int32 route_id); + void CreateImageError(const CreateImageCallback& callback, + const gfx::Size size); // The serial number of the GpuProcessHost / GpuProcessHostUIShim pair. int host_id_; @@ -157,6 +173,9 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, // The pending create command buffer requests we need to reply to. std::queue<CreateCommandBufferCallback> create_command_buffer_requests_; + // The pending create image requests we need to reply to. + std::queue<CreateImageCallback> create_image_requests_; + #if defined(TOOLKIT_GTK) // Encapsulates surfaces that we lock when creating view command buffers. // We release this lock once the command buffer (or associated GPU process) diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h index 2d10724..e2567c6 100644 --- a/content/common/gpu/client/gpu_channel_host.h +++ b/content/common/gpu/client/gpu_channel_host.h @@ -56,6 +56,8 @@ struct GpuListenerInfo { class CONTENT_EXPORT GpuChannelHostFactory { public: + typedef base::Callback<void(const gfx::Size)> CreateImageCallback; + virtual ~GpuChannelHostFactory() {} virtual bool IsMainThread() = 0; @@ -68,6 +70,11 @@ class CONTENT_EXPORT GpuChannelHostFactory { int32 surface_id, const GPUCreateCommandBufferConfig& init_params) = 0; virtual GpuChannelHost* EstablishGpuChannelSync( content::CauseForGpuLaunch) = 0; + virtual void CreateImage( + gfx::PluginWindowHandle window, + int32 image_id, + const CreateImageCallback& callback) = 0; + virtual void DeleteImage(int32 image_id, int32 sync_point) = 0; }; // Encapsulates an IPC channel between the client and one GPU process. diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc index 5abf63d..9a21f10 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc @@ -1557,6 +1557,11 @@ void WebGraphicsContext3DCommandBufferImpl::deleteVertexArrayOES( DELEGATE_TO_GL_1R(isVertexArrayOES, IsVertexArrayOES, WebGLId, WGC3Dboolean) DELEGATE_TO_GL_1(bindVertexArrayOES, BindVertexArrayOES, WebGLId) +DELEGATE_TO_GL_2(bindTexImage2DCHROMIUM, BindTexImage2DCHROMIUM, + WGC3Denum, WGC3Dint) +DELEGATE_TO_GL_2(releaseTexImage2DCHROMIUM, ReleaseTexImage2DCHROMIUM, + WGC3Denum, WGC3Dint) + GrGLInterface* WebGraphicsContext3DCommandBufferImpl::onCreateGrGLInterface() { return webkit_glue::CreateCommandBufferSkiaGLBinding(); } diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h index e2caa07..c8cde90 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h @@ -592,6 +592,9 @@ class WebGraphicsContext3DCommandBufferImpl virtual WGC3Dboolean isVertexArrayOES(WebGLId array); virtual void bindVertexArrayOES(WebGLId array); + virtual void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint image_id); + virtual void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint image_id); + protected: virtual GrGLInterface* onCreateGrGLInterface(); diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index 43335d56..106e922 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc @@ -19,11 +19,13 @@ #include "content/common/gpu/gpu_messages.h" #include "content/common/gpu/sync_point_manager.h" #include "content/public/common/content_switches.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/gpu_scheduler.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_channel_proxy.h" #include "ui/gl/gl_context.h" +#include "ui/gl/gl_image.h" #include "ui/gl/gl_surface.h" #if defined(OS_POSIX) @@ -153,6 +155,7 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, client_id_(client_id), share_group_(share_group ? share_group : new gfx::GLShareGroup), mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager), + image_manager_(new gpu::gles2::ImageManager), watchdog_(watchdog), software_(software), handle_messages_scheduled_(false), @@ -323,6 +326,7 @@ void GpuChannel::CreateViewCommandBuffer( share_group, window, mailbox_manager_, + image_manager_, gfx::Size(), disallowed_features_, init_params.allowed_extensions, @@ -344,6 +348,39 @@ GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) { return stubs_.Lookup(route_id); } +void GpuChannel::CreateImage( + gfx::PluginWindowHandle window, + int32 image_id, + gfx::Size* size) { + TRACE_EVENT1("gpu", + "GpuChannel::CreateImage", + "image_id", + image_id); + + *size = gfx::Size(); + + if (image_manager_->LookupImage(image_id)) { + LOG(ERROR) << "CreateImage failed, image_id already in use."; + return; + } + + scoped_refptr<gfx::GLImage> image = gfx::GLImage::CreateGLImage(window); + if (!image) + return; + + image_manager_->AddImage(image.get(), image_id); + *size = image->GetSize(); +} + +void GpuChannel::DeleteImage(int32 image_id) { + TRACE_EVENT1("gpu", + "GpuChannel::DeleteImage", + "image_id", + image_id); + + image_manager_->RemoveImage(image_id); +} + void GpuChannel::LoseAllContexts() { gpu_channel_manager_->LoseAllContexts(); } @@ -478,6 +515,7 @@ void GpuChannel::OnCreateOffscreenCommandBuffer( share_group, gfx::GLSurfaceHandle(), mailbox_manager_.get(), + image_manager_.get(), size, disallowed_features_, init_params.allowed_extensions, diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index 867c4ce..fc43820 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h @@ -39,6 +39,9 @@ class WaitableEvent; namespace gpu { struct RefCountedCounter; +namespace gles2 { +class ImageManager; +} } #if defined(OS_ANDROID) @@ -100,6 +103,12 @@ class GpuChannel : public IPC::Listener, const GPUCreateCommandBufferConfig& init_params, int32* route_id); + void CreateImage( + gfx::PluginWindowHandle window, + int32 image_id, + gfx::Size* size); + void DeleteImage(int32 image_id); + gfx::GLShareGroup* share_group() const { return share_group_.get(); } GpuCommandBufferStub* LookupCommandBuffer(int32 route_id); @@ -198,6 +207,7 @@ class GpuChannel : public IPC::Listener, scoped_refptr<gfx::GLShareGroup> share_group_; scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_; + scoped_refptr<gpu::gles2::ImageManager> image_manager_; #if defined(ENABLE_GPU) typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap; diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index 1da6aec..4b92daf 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc @@ -18,6 +18,15 @@ #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_share_group.h" +GpuChannelManager::ImageOperation::ImageOperation( + int32 sync_point, base::Closure callback) + : sync_point(sync_point), + callback(callback) { +} + +GpuChannelManager::ImageOperation::~ImageOperation() { +} + GpuChannelManager::GpuChannelManager(ChildThread* gpu_child_thread, GpuWatchdog* watchdog, base::MessageLoopProxy* io_message_loop, @@ -42,6 +51,7 @@ GpuChannelManager::~GpuChannelManager() { default_offscreen_surface_->Destroy(); default_offscreen_surface_ = NULL; } + DCHECK(image_operations_.empty()); } gpu::gles2::ProgramCache* GpuChannelManager::program_cache() { @@ -95,6 +105,8 @@ bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer, OnCreateViewCommandBuffer) + IPC_MESSAGE_HANDLER(GpuMsg_CreateImage, OnCreateImage) + IPC_MESSAGE_HANDLER(GpuMsg_DeleteImage, OnDeleteImage) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() return handled; @@ -169,6 +181,81 @@ void GpuChannelManager::OnCreateViewCommandBuffer( Send(new GpuHostMsg_CommandBufferCreated(route_id)); } +void GpuChannelManager::CreateImage( + gfx::PluginWindowHandle window, int32 client_id, int32 image_id) { + gfx::Size size; + + GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id); + if (iter != gpu_channels_.end()) { + iter->second->CreateImage(window, image_id, &size); + } + + Send(new GpuHostMsg_ImageCreated(size)); +} + +void GpuChannelManager::OnCreateImage( + gfx::PluginWindowHandle window, int32 client_id, int32 image_id) { + DCHECK(image_id); + + if (image_operations_.empty()) { + CreateImage(window, client_id, image_id); + } else { + image_operations_.push_back( + new ImageOperation(0, base::Bind(&GpuChannelManager::CreateImage, + base::Unretained(this), + window, + client_id, + image_id))); + } +} + +void GpuChannelManager::DeleteImage(int32 client_id, int32 image_id) { + GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id); + if (iter != gpu_channels_.end()) { + iter->second->DeleteImage(image_id); + } +} + +void GpuChannelManager::OnDeleteImage( + int32 client_id, int32 image_id, int32 sync_point) { + DCHECK(image_id); + + if (!sync_point && image_operations_.empty()) { + DeleteImage(client_id, image_id); + } else { + image_operations_.push_back( + new ImageOperation(sync_point, + base::Bind(&GpuChannelManager::DeleteImage, + base::Unretained(this), + client_id, + image_id))); + if (sync_point) { + sync_point_manager()->AddSyncPointCallback( + sync_point, + base::Bind(&GpuChannelManager::OnDeleteImageSyncPointRetired, + base::Unretained(this), + image_operations_.back())); + } + } +} + +void GpuChannelManager::OnDeleteImageSyncPointRetired( + ImageOperation* image_operation) { + // Mark operation as no longer having a pending sync point. + image_operation->sync_point = 0; + + // De-queue operations until we reach a pending sync point. + while (!image_operations_.empty()) { + // Check if operation has a pending sync point. + if (image_operations_.front()->sync_point) + return; + + image_operations_.front()->callback.Run(); + delete image_operations_.front(); + image_operations_.pop_front(); + } +} + void GpuChannelManager::LoseAllContexts() { MessageLoop::current()->PostTask( FROM_HERE, diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h index b256a56..78b5079 100644 --- a/content/common/gpu/gpu_channel_manager.h +++ b/content/common/gpu/gpu_channel_manager.h @@ -5,6 +5,7 @@ #ifndef CONTENT_COMMON_GPU_GPU_CHANNEL_MANAGER_H_ #define CONTENT_COMMON_GPU_GPU_CHANNEL_MANAGER_H_ +#include <deque> #include <vector> #include "base/hash_tables.h" @@ -96,6 +97,16 @@ class GpuChannelManager : public IPC::Listener, gfx::GLSurface* GetDefaultOffscreenSurface(); private: + struct ImageOperation { + ImageOperation(int32 sync_point, base::Closure callback); + ~ImageOperation(); + + int32 sync_point; + base::Closure callback; + }; + typedef base::hash_map<int, scoped_refptr<GpuChannel> > GpuChannelMap; + typedef std::deque<ImageOperation*> ImageOperationQueue; + // Message handlers. void OnEstablishChannel(int client_id, bool share_context); void OnCloseChannel(const IPC::ChannelHandle& channel_handle); @@ -106,6 +117,13 @@ class GpuChannelManager : public IPC::Listener, int32 render_view_id, int32 client_id, const GPUCreateCommandBufferConfig& init_params); + void CreateImage( + gfx::PluginWindowHandle window, int32 client_id, int32 image_id); + void OnCreateImage( + gfx::PluginWindowHandle window, int32 client_id, int32 image_id); + void DeleteImage(int32 client_id, int32 image_id); + void OnDeleteImage(int32 client_id, int32 image_id, int32 sync_point); + void OnDeleteImageSyncPointRetired(ImageOperation*); void OnLoseAllContexts(); @@ -118,7 +136,6 @@ class GpuChannelManager : public IPC::Listener, // These objects manage channels to individual renderer processes there is // one channel for each renderer process that has connected to this GPU // process. - typedef base::hash_map<int, scoped_refptr<GpuChannel> > GpuChannelMap; GpuChannelMap gpu_channels_; scoped_refptr<gfx::GLShareGroup> share_group_; scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_; @@ -127,6 +144,7 @@ class GpuChannelManager : public IPC::Listener, scoped_refptr<SyncPointManager> sync_point_manager_; scoped_ptr<gpu::gles2::ProgramCache> program_cache_; scoped_refptr<gfx::GLSurface> default_offscreen_surface_; + ImageOperationQueue image_operations_; DISALLOW_COPY_AND_ASSIGN(GpuChannelManager); }; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 15418bd..32aa0dc 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -102,6 +102,7 @@ GpuCommandBufferStub::GpuCommandBufferStub( GpuCommandBufferStub* share_group, const gfx::GLSurfaceHandle& handle, gpu::gles2::MailboxManager* mailbox_manager, + gpu::gles2::ImageManager* image_manager, const gfx::Size& size, const gpu::gles2::DisallowedFeatures& disallowed_features, const std::string& allowed_extensions, @@ -136,6 +137,7 @@ GpuCommandBufferStub::GpuCommandBufferStub( } else { context_group_ = new gpu::gles2::ContextGroup( mailbox_manager, + image_manager, new GpuCommandBufferMemoryTracker(channel), true); } diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h index 98703d1..2bb79b6c 100644 --- a/content/common/gpu/gpu_command_buffer_stub.h +++ b/content/common/gpu/gpu_command_buffer_stub.h @@ -40,6 +40,7 @@ class GpuWatchdog; namespace gpu { namespace gles2 { +class ImageManager; class MailboxManager; } } @@ -99,6 +100,7 @@ class GpuCommandBufferStub GpuCommandBufferStub* share_group, const gfx::GLSurfaceHandle& handle, gpu::gles2::MailboxManager* mailbox_manager, + gpu::gles2::ImageManager* image_manager, const gfx::Size& size, const gpu::gles2::DisallowedFeatures& disallowed_features, const std::string& allowed_extensions, diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 82af22c..e731d98 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -238,6 +238,19 @@ IPC_MESSAGE_CONTROL4(GpuMsg_CreateViewCommandBuffer, int32, /* client_id */ GPUCreateCommandBufferConfig /* init_params */) +// Tells the GPU process to create a new image from a window. Images +// can be bound to textures using CHROMIUM_texture_from_image. +IPC_MESSAGE_CONTROL3(GpuMsg_CreateImage, + gfx::PluginWindowHandle, /* window */ + int32, /* client_id */ + int32 /* image_id */) + +// Tells the GPU process to delete image. +IPC_MESSAGE_CONTROL3(GpuMsg_DeleteImage, + int32, /* client_id */ + int32, /* image_id */ + int32 /* sync_point */) + // Tells the GPU process to create a context for collecting graphics card // information. IPC_MESSAGE_CONTROL0(GpuMsg_CollectGraphicsInfo) @@ -311,6 +324,10 @@ IPC_MESSAGE_CONTROL1(GpuHostMsg_CommandBufferCreated, IPC_MESSAGE_CONTROL1(GpuHostMsg_DestroyCommandBuffer, int32 /* surface_id */) +// Response from GPU to a GpuMsg_CreateImage message. +IPC_MESSAGE_CONTROL1(GpuHostMsg_ImageCreated, + gfx::Size /* size */) + // Response from GPU to a GpuMsg_CollectGraphicsInfo. IPC_MESSAGE_CONTROL1(GpuHostMsg_GraphicsInfoCollected, content::GPUInfo /* GPU logging stats */) diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 81da444..57af88c 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -963,6 +963,17 @@ int32 RenderThreadImpl::CreateViewCommandBuffer( return route_id; } +void RenderThreadImpl::CreateImage( + gfx::PluginWindowHandle window, + int32 image_id, + const CreateImageCallback& callback) { + NOTREACHED(); +} + +void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) { + NOTREACHED(); +} + void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { suspend_webkit_shared_timer_ = false; } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 1e3d984..4c08164 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -153,6 +153,11 @@ class CONTENT_EXPORT RenderThreadImpl : public content::RenderThread, virtual int32 CreateViewCommandBuffer( int32 surface_id, const GPUCreateCommandBufferConfig& init_params) OVERRIDE; + virtual void CreateImage( + gfx::PluginWindowHandle window, + int32 image_id, + const CreateImageCallback& callback) OVERRIDE; + virtual void DeleteImage(int32 image_id, int32 sync_point) OVERRIDE; // Synchronously establish a channel to the GPU plugin if not previously // established or if it has been lost (for example if the GPU plugin crashed). diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 1b9db9f..21b8e69 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1759,6 +1759,18 @@ _FUNCTION_INFO = { 'expectation': False, 'unit_test': False, }, + 'BindTexImage2DCHROMIUM': { + 'decoder_func': 'DoBindTexImage2DCHROMIUM', + 'unit_test': False, + 'extension': True, + 'chromium': True, + }, + 'ReleaseTexImage2DCHROMIUM': { + 'decoder_func': 'DoReleaseTexImage2DCHROMIUM', + 'unit_test': False, + 'extension': True, + 'chromium': True, + }, } diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 8e5b255..a0d3fa6 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -679,6 +679,12 @@ void GLES2BindUniformLocationCHROMIUM( GLuint program, GLint location, const char* name) { gles2::GetGLContext()->BindUniformLocationCHROMIUM(program, location, name); } +void GLES2BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::GetGLContext()->BindTexImage2DCHROMIUM(target, imageId); +} +void GLES2ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::GetGLContext()->ReleaseTexImage2DCHROMIUM(target, imageId); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_C_LIB_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index c311d6c..080cc8a 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1902,5 +1902,21 @@ } } + void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::BindTexImage2DCHROMIUM* c = + GetCmdSpace<gles2::BindTexImage2DCHROMIUM>(); + if (c) { + c->Init(target, imageId); + } + } + + void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::ReleaseTexImage2DCHROMIUM* c = + GetCmdSpace<gles2::ReleaseTexImage2DCHROMIUM>(); + if (c) { + c->Init(target, imageId); + } + } + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 7ecd17d..57835fb 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -498,5 +498,17 @@ virtual void ConsumeTextureCHROMIUM( virtual void BindUniformLocationCHROMIUM( GLuint program, GLint location, const char* name) OVERRIDE; +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindTexImage2DCHROMIUM(" << GLES2Util::GetStringTextureBindTarget(target) << ", " << imageId << ")"); // NOLINT + helper_->BindTexImage2DCHROMIUM(target, imageId); +} + +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReleaseTexImage2DCHROMIUM(" << GLES2Util::GetStringTextureBindTarget(target) << ", " << imageId << ")"); // NOLINT + helper_->ReleaseTexImage2DCHROMIUM(target, imageId); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index a70a73e..0692887 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -1771,5 +1771,27 @@ TEST_F(GLES2ImplementationTest, ConsumeTextureCHROMIUM) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } // TODO: Implement unit test for BindUniformLocationCHROMIUM + +TEST_F(GLES2ImplementationTest, BindTexImage2DCHROMIUM) { + struct Cmds { + BindTexImage2DCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, 2); + + gl_->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, ReleaseTexImage2DCHROMIUM) { + struct Cmds { + ReleaseTexImage2DCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, 2); + + gl_->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_UNITTEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 0ad28c8..f9914a9 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt @@ -196,4 +196,5 @@ GL_APICALL void GL_APIENTRY glGenMailboxCHROMIUM (GLbyte* mailbox); GL_APICALL void GL_APIENTRY glProduceTextureCHROMIUM (GLenumTextureTarget target, const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glConsumeTextureCHROMIUM (GLenumTextureTarget target, const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glBindUniformLocationCHROMIUM (GLidProgram program, GLint location, const char* name); - +GL_APICALL void GL_APIENTRY glBindTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); +GL_APICALL void GL_APIENTRY glReleaseTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 04fd1b2..4a0e20e 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -10432,6 +10432,82 @@ COMPILE_ASSERT( offsetof(BindUniformLocationCHROMIUMBucket, name_bucket_id) == 12, OffsetOf_BindUniformLocationCHROMIUMBucket_name_bucket_id_not_12); // NOLINT +struct BindTexImage2DCHROMIUM { + typedef BindTexImage2DCHROMIUM ValueType; + static const CommandId kCmdId = kBindTexImage2DCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init(GLenum _target, GLint _imageId) { + SetHeader(); + target = _target; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLint _imageId) { + static_cast<ValueType*>(cmd)->Init(_target, _imageId); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 target; + int32 imageId; +}; + +COMPILE_ASSERT(sizeof(BindTexImage2DCHROMIUM) == 12, + Sizeof_BindTexImage2DCHROMIUM_is_not_12); +COMPILE_ASSERT(offsetof(BindTexImage2DCHROMIUM, header) == 0, + OffsetOf_BindTexImage2DCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(BindTexImage2DCHROMIUM, target) == 4, + OffsetOf_BindTexImage2DCHROMIUM_target_not_4); +COMPILE_ASSERT(offsetof(BindTexImage2DCHROMIUM, imageId) == 8, + OffsetOf_BindTexImage2DCHROMIUM_imageId_not_8); + +struct ReleaseTexImage2DCHROMIUM { + typedef ReleaseTexImage2DCHROMIUM ValueType; + static const CommandId kCmdId = kReleaseTexImage2DCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init(GLenum _target, GLint _imageId) { + SetHeader(); + target = _target; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLint _imageId) { + static_cast<ValueType*>(cmd)->Init(_target, _imageId); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 target; + int32 imageId; +}; + +COMPILE_ASSERT(sizeof(ReleaseTexImage2DCHROMIUM) == 12, + Sizeof_ReleaseTexImage2DCHROMIUM_is_not_12); +COMPILE_ASSERT(offsetof(ReleaseTexImage2DCHROMIUM, header) == 0, + OffsetOf_ReleaseTexImage2DCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(ReleaseTexImage2DCHROMIUM, target) == 4, + OffsetOf_ReleaseTexImage2DCHROMIUM_target_not_4); +COMPILE_ASSERT(offsetof(ReleaseTexImage2DCHROMIUM, imageId) == 8, + OffsetOf_ReleaseTexImage2DCHROMIUM_imageId_not_8); + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index cee8095..a7b1e85 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -4202,5 +4202,35 @@ TEST_F(GLES2FormatTest, BindUniformLocationCHROMIUMBucket) { next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, BindTexImage2DCHROMIUM) { + BindTexImage2DCHROMIUM& cmd = *GetBufferAs<BindTexImage2DCHROMIUM>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<GLint>(12)); + EXPECT_EQ(static_cast<uint32>(BindTexImage2DCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLint>(12), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, ReleaseTexImage2DCHROMIUM) { + ReleaseTexImage2DCHROMIUM& cmd = *GetBufferAs<ReleaseTexImage2DCHROMIUM>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<GLint>(12)); + EXPECT_EQ(static_cast<uint32>(ReleaseTexImage2DCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLint>(12), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index bed63e2..6543de3 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -239,6 +239,8 @@ OP(BindUniformLocationCHROMIUM) /* 482 */ \ OP(BindUniformLocationCHROMIUMImmediate) /* 483 */ \ OP(BindUniformLocationCHROMIUMBucket) /* 484 */ \ + OP(BindTexImage2DCHROMIUM) /* 485 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 486 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index ecaf700..3fe50ad 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -14,6 +14,7 @@ #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/program_manager.h" @@ -28,9 +29,11 @@ namespace gles2 { ContextGroup::ContextGroup( MailboxManager* mailbox_manager, + ImageManager* image_manager, MemoryTracker* memory_tracker, bool bind_generates_resource) : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager), + image_manager_(image_manager ? image_manager : new ImageManager), memory_tracker_(memory_tracker), num_contexts_(0), enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch( diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 671d0ff..c459c56 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -27,6 +27,7 @@ class ProgramCache; class BufferManager; class GLES2Decoder; class FramebufferManager; +class ImageManager; class MailboxManager; class RenderbufferManager; class ProgramManager; @@ -43,6 +44,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { ContextGroup( MailboxManager* mailbox_manager, + ImageManager* image_manager, MemoryTracker* memory_tracker, bool bind_generates_resource); @@ -59,6 +61,10 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { return mailbox_manager_.get(); } + ImageManager* image_manager() const { + return image_manager_.get(); + } + MemoryTracker* memory_tracker() const { return memory_tracker_.get(); } @@ -149,6 +155,7 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { bool QueryGLFeatureU(GLenum pname, GLint min_required, uint32* v); scoped_refptr<MailboxManager> mailbox_manager_; + scoped_refptr<ImageManager> image_manager_; scoped_refptr<MemoryTracker> memory_tracker_; scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc index 6f6c919..5a15abf 100644 --- a/gpu/command_buffer/service/context_group_unittest.cc +++ b/gpu/command_buffer/service/context_group_unittest.cc @@ -36,7 +36,7 @@ class ContextGroupTest : public testing::Test { virtual void SetUp() { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); - group_ = ContextGroup::Ref(new ContextGroup(NULL, NULL, true)); + group_ = ContextGroup::Ref(new ContextGroup(NULL, NULL, NULL, true)); } virtual void TearDown() { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 748eb21..f7e3ebc 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -39,6 +39,7 @@ #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/program_manager.h" @@ -54,6 +55,7 @@ #include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" #include "ui/gl/gl_context.h" +#include "ui/gl/gl_image.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" #if defined(OS_MACOSX) @@ -616,6 +618,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, return group_->mailbox_manager(); } + ImageManager* image_manager() { + return group_->image_manager(); + } + VertexArrayManager* vertex_array_manager() { return vertex_array_manager_.get(); } @@ -653,100 +659,107 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Wrapper for CompressedTexImage2D commands. error::Error DoCompressedTexImage2D( - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLint border, - GLsizei image_size, - const void* data); + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLint border, + GLsizei image_size, + const void* data); // Wrapper for CompressedTexSubImage2D. void DoCompressedTexSubImage2D( - GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLsizei imageSize, - const void * data); + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLsizei imageSize, + const void * data); // Wrapper for CopyTexImage2D. void DoCopyTexImage2D( - GLenum target, - GLint level, - GLenum internal_format, - GLint x, - GLint y, - GLsizei width, - GLsizei height, - GLint border); + GLenum target, + GLint level, + GLenum internal_format, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border); // Wrapper for CopyTexSubImage2D. void DoCopyTexSubImage2D( - GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint x, - GLint y, - GLsizei width, - GLsizei height); + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); // Wrapper for TexImage2D commands. error::Error DoTexImage2D( - GLenum target, - GLint level, - GLenum internal_format, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels, - uint32 pixels_size); + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const void* pixels, + uint32 pixels_size); // Wrapper for TexSubImage2D. void DoTexSubImage2D( - GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void * data); + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const void * data); // Wrapper for TexImageIOSurface2DCHROMIUM. void DoTexImageIOSurface2DCHROMIUM( - GLenum target, - GLsizei width, - GLsizei height, - GLuint io_surface_id, - GLuint plane); + GLenum target, + GLsizei width, + GLsizei height, + GLuint io_surface_id, + GLuint plane); void DoCopyTextureCHROMIUM( - GLenum target, - GLuint source_id, - GLuint target_id, - GLint level, - GLenum internal_format); + GLenum target, + GLuint source_id, + GLuint target_id, + GLint level, + GLenum internal_format); // Wrapper for TexStorage2DEXT. void DoTexStorage2DEXT( - GLenum target, - GLint levels, - GLenum internal_format, - GLsizei width, - GLsizei height); + GLenum target, + GLint levels, + GLenum internal_format, + GLsizei width, + GLsizei height); void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key); void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key); + void DoBindTexImage2DCHROMIUM( + GLenum target, + GLint image_id); + void DoReleaseTexImage2DCHROMIUM( + GLenum target, + GLint image_id); + // Creates a ProgramInfo for the given program. ProgramManager::ProgramInfo* CreateProgramInfo( GLuint client_id, GLuint service_id) { @@ -1268,6 +1281,16 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, return info; } + TextureManager::TextureInfo* GetTextureInfoForTargetUnlessDefault( + GLenum target) { + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) + return NULL; + if (info == texture_manager()->GetDefaultTextureInfo(target)) + return NULL; + return info; + } + GLenum GetBindTargetForSamplerType(GLenum type) { DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB); @@ -8922,18 +8945,15 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( return; } - TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + // Default target might be conceptually valid, but disallow it to avoid + // accidents. + TextureManager::TextureInfo* info = GetTextureInfoForTargetUnlessDefault( + target); if (!info) { SetGLError(GL_INVALID_OPERATION, "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound"); return; } - if (info == texture_manager()->GetDefaultTextureInfo(target)) { - // Maybe this is conceptually valid, but disallow it to avoid accidents. - SetGLError(GL_INVALID_OPERATION, - "glTexImageIOSurface2DCHROMIUM", "can't bind default texture"); - return; - } // Look up the new IOSurface. Note that because of asynchrony // between processes this might fail; during live resizing the @@ -9333,6 +9353,88 @@ void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) { debug_marker_manager_.PopGroup(); } +void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM( + GLenum target, GLint image_id) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM"); + if (target != GL_TEXTURE_2D) { + // This might be supported in the future. + SetGLError( + GL_INVALID_OPERATION, + "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target"); + return; + } + + // Default target might be conceptually valid, but disallow it to avoid + // accidents. + TextureManager::TextureInfo* info = GetTextureInfoForTargetUnlessDefault( + target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glBindTexImage2DCHROMIUM", "no texture bound"); + return; + } + + gfx::GLImage* gl_image = image_manager()->LookupImage(image_id); + if (!gl_image) { + SetGLError(GL_INVALID_OPERATION, + "glBindTexImage2DCHROMIUM", + "no image found with the given ID"); + return; + } + + if (!gl_image->BindTexImage()) { + SetGLError(GL_INVALID_OPERATION, + "glBindTexImage2DCHROMIUM", + "fail to bind image with the given ID"); + return; + } + + gfx::Size size = gl_image->GetSize(); + texture_manager()->SetLevelInfo( + info, target, 0, GL_RGBA, size.width(), size.height(), 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, true); + texture_manager()->SetLevelImage(info, target, 0, gl_image); +} + +void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM( + GLenum target, GLint image_id) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM"); + if (target != GL_TEXTURE_2D) { + // This might be supported in the future. + SetGLError( + GL_INVALID_OPERATION, + "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target"); + return; + } + + // Default target might be conceptually valid, but disallow it to avoid + // accidents. + TextureManager::TextureInfo* info = GetTextureInfoForTargetUnlessDefault( + target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glReleaseTexImage2DCHROMIUM", "no texture bound"); + return; + } + + gfx::GLImage* gl_image = image_manager()->LookupImage(image_id); + if (!gl_image) { + SetGLError(GL_INVALID_OPERATION, + "glReleaseTexImage2DCHROMIUM", + "no image found with the given ID"); + return; + } + + // Do nothing when image is not currently bound. + if (info->GetLevelImage(target, 0) != gl_image) + return; + + gl_image->ReleaseTexImage(); + + texture_manager()->SetLevelInfo( + info, target, 0, GL_RGBA, 0, 0, 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, false); +} // Include the auto-generated part of this file. We split this because it means // we can easily edit the non-auto generated parts right here in this file diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index e347ba8..fe5806f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2887,5 +2887,29 @@ error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUMImmediate( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBindTexImage2DCHROMIUM( + uint32 immediate_data_size, const gles2::BindTexImage2DCHROMIUM& c) { + GLenum target = static_cast<GLenum>(c.target); + GLint imageId = static_cast<GLint>(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + SetGLErrorInvalidEnum("glBindTexImage2DCHROMIUM", target, "target"); + return error::kNoError; + } + DoBindTexImage2DCHROMIUM(target, imageId); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleReleaseTexImage2DCHROMIUM( + uint32 immediate_data_size, const gles2::ReleaseTexImage2DCHROMIUM& c) { + GLenum target = static_cast<GLenum>(c.target); + GLint imageId = static_cast<GLint>(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + SetGLErrorInvalidEnum("glReleaseTexImage2DCHROMIUM", target, "target"); + return error::kNoError; + } + DoReleaseTexImage2DCHROMIUM(target, imageId); + return error::kNoError; +} + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 59e82c9..b698bf9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -13,6 +13,7 @@ #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gl_surface_mock.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/stream_texture_manager_mock.h" @@ -7807,6 +7808,87 @@ TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, BindVertexArrayOESValidArgsNewId(); } +TEST_F(GLES2DecoderTest, BindTexImage2DCHROMIUM) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + TextureManager::TextureInfo* info = + group().texture_manager()->GetTextureInfo(client_texture_id_); + EXPECT_EQ(kServiceTextureId, info->service_id()); + + group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0), 1); + EXPECT_FALSE(group().image_manager()->LookupImage(1) == NULL); + + GLsizei width; + GLsizei height; + GLenum type; + GLenum internal_format; + + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(info->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + EXPECT_TRUE(info->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Bind image to texture. + BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; + bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should now be set. + EXPECT_FALSE(info->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Define new texture image. + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should no longer be set. + EXPECT_TRUE(info->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); +} + +TEST_F(GLES2DecoderTest, ReleaseTexImage2DCHROMIUM) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + TextureManager::TextureInfo* info = + group().texture_manager()->GetTextureInfo(client_texture_id_); + EXPECT_EQ(kServiceTextureId, info->service_id()); + + group().image_manager()->AddImage(gfx::GLImage::CreateGLImage(0), 1); + EXPECT_FALSE(group().image_manager()->LookupImage(1) == NULL); + + GLsizei width; + GLsizei height; + GLenum type; + GLenum internal_format; + + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(info->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + EXPECT_TRUE(info->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Bind image to texture. + BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; + bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should now be set. + EXPECT_FALSE(info->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Release image from texture. + ReleaseTexImage2DCHROMIUM release_tex_image_2d_cmd; + release_tex_image_2d_cmd.Init(GL_TEXTURE_2D, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(release_tex_image_2d_cmd)); + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + // Image should no longer be set. + EXPECT_TRUE(info->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); +} + // TODO(gman): Complete this test. // TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) { // } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index ff37553..79ec1c2 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -55,5 +55,7 @@ // TODO(gman): BindUniformLocationCHROMIUMImmediate // TODO(gman): BindUniformLocationCHROMIUMBucket +// TODO(gman): BindTexImage2DCHROMIUM +// TODO(gman): ReleaseTexImage2DCHROMIUM #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index b51aa55..f8a77d1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -88,6 +88,7 @@ void GLES2DecoderTestBase::InitDecoder( ::gfx::GLInterface::SetGLInterface(gl_.get()); group_ = ContextGroup::Ref(new ContextGroup(NULL, NULL, + NULL, bind_generates_resource)); InSequence sequence; diff --git a/gpu/command_buffer/service/image_manager.cc b/gpu/command_buffer/service/image_manager.cc new file mode 100644 index 0000000..b424770 --- /dev/null +++ b/gpu/command_buffer/service/image_manager.cc @@ -0,0 +1,35 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/image_manager.h" + +#include "ui/gl/gl_image.h" + +namespace gpu { +namespace gles2 { + +ImageManager::ImageManager() { +} + +ImageManager::~ImageManager() { +} + +void ImageManager::AddImage(gfx::GLImage* image, int32 service_id) { + gl_images_[service_id] = image; +} + +void ImageManager::RemoveImage(int32 service_id) { + gl_images_.erase(service_id); +} + +gfx::GLImage* ImageManager::LookupImage(int32 service_id) { + GLImageMap::const_iterator iter = gl_images_.find(service_id); + if (iter != gl_images_.end()) + return iter->second; + + return NULL; +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/service/image_manager.h b/gpu/command_buffer/service/image_manager.h new file mode 100644 index 0000000..06a02bc --- /dev/null +++ b/gpu/command_buffer/service/image_manager.h @@ -0,0 +1,43 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/memory/ref_counted.h" +#include "gpu/gpu_export.h" + +namespace gfx { +class GLImage; +} + +namespace gpu { +namespace gles2 { + +// Interface used by the cmd decoder to lookup images. +class GPU_EXPORT ImageManager : public base::RefCounted<ImageManager> { + public: + ImageManager(); + + void AddImage(gfx::GLImage* gl_image, int32 service_id); + void RemoveImage(int32 service_id); + gfx::GLImage* LookupImage(int32 service_id); + + private: + friend class base::RefCounted<ImageManager>; + + ~ImageManager(); + + typedef base::hash_map<uint32, scoped_refptr<gfx::GLImage> > GLImageMap; + GLImageMap gl_images_; + + DISALLOW_COPY_AND_ASSIGN(ImageManager); +}; + +} // namespage gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 7c378d4..3206281 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -150,9 +150,13 @@ TextureManager::TextureInfo::LevelInfo::LevelInfo(const LevelInfo& rhs) border(rhs.border), format(rhs.format), type(rhs.type), + image(rhs.image), estimated_size(rhs.estimated_size) { } +TextureManager::TextureInfo::LevelInfo::~LevelInfo() { +} + bool TextureManager::TextureInfo::CanRender( const FeatureInfo* feature_info) const { if (target_ == 0) { @@ -252,7 +256,8 @@ bool TextureManager::TextureInfo::CanGenerateMipmaps( (info.internal_format != first.internal_format) || (info.type != first.type) || feature_info->validators()->compressed_texture_format.IsValid( - info.internal_format)) { + info.internal_format) || + info.image) { return false; } } @@ -327,6 +332,7 @@ void TextureManager::TextureInfo::SetLevelInfo( info.border = border; info.format = format; info.type = type; + info.image = 0; estimated_size_ -= info.estimated_size; GLES2Util::ComputeImageDataSizes( @@ -616,6 +622,36 @@ bool TextureManager::TextureInfo::ClearLevel( return info.cleared; } +void TextureManager::TextureInfo::SetLevelImage( + const FeatureInfo* feature_info, + GLenum target, + GLint level, + gfx::GLImage* image) { + DCHECK_GE(level, 0); + DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), + level_infos_.size()); + DCHECK_LT(static_cast<size_t>(level), + level_infos_[GLTargetToFaceIndex(target)].size()); + TextureInfo::LevelInfo& info = + level_infos_[GLTargetToFaceIndex(target)][level]; + DCHECK_EQ(info.target, target); + DCHECK_EQ(info.level, level); + info.image = image; +} + +gfx::GLImage* TextureManager::TextureInfo::GetLevelImage( + GLint face, GLint level) const { + size_t face_index = GLTargetToFaceIndex(face); + if (level >= 0 && face_index < level_infos_.size() && + static_cast<size_t>(level) < level_infos_[face_index].size()) { + const LevelInfo& info = level_infos_[GLTargetToFaceIndex(face)][level]; + if (info.target != 0) { + return info.image; + } + } + return 0; +} + TextureManager::TextureManager( MemoryTracker* memory_tracker, FeatureInfo* feature_info, @@ -1070,5 +1106,28 @@ GLsizei TextureManager::ComputeMipMapCount( return 1 + base::bits::Log2Floor(std::max(std::max(width, height), depth)); } +void TextureManager::SetLevelImage( + TextureManager::TextureInfo* info, + GLenum target, + GLint level, + gfx::GLImage* image) { + DCHECK(info); + if (!info->CanRender(feature_info_)) { + DCHECK_NE(0, num_unrenderable_textures_); + --num_unrenderable_textures_; + } + if (!info->SafeToRenderFrom()) { + DCHECK_NE(0, num_unsafe_textures_); + --num_unsafe_textures_; + } + info->SetLevelImage(feature_info_, target, level, image); + if (!info->CanRender(feature_info_)) { + ++num_unrenderable_textures_; + } + if (!info->SafeToRenderFrom()) { + ++num_unsafe_textures_; + } +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 26c0c0c..ef9e020 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -13,6 +13,7 @@ #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" +#include "ui/gl/gl_image.h" namespace gpu { namespace gles2 { @@ -124,6 +125,10 @@ class GPU_EXPORT TextureManager { bool GetLevelType( GLint face, GLint level, GLenum* type, GLenum* internal_format) const; + // Get the image bound to a particular level. Returns NULL if level + // does not exist. + gfx::GLImage* GetLevelImage(GLint face, GLint level) const; + bool IsDeleted() const { return deleted_; } @@ -189,6 +194,7 @@ class GPU_EXPORT TextureManager { struct LevelInfo { LevelInfo(); LevelInfo(const LevelInfo& rhs); + ~LevelInfo(); bool cleared; GLenum target; @@ -200,6 +206,7 @@ class GPU_EXPORT TextureManager { GLint border; GLenum format; GLenum type; + scoped_refptr<gfx::GLImage> image; uint32 estimated_size; }; @@ -265,6 +272,13 @@ class GPU_EXPORT TextureManager { // 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); + // Info about each face and level of texture. std::vector<std::vector<LevelInfo> > level_infos_; @@ -490,6 +504,12 @@ class GPU_EXPORT TextureManager { return mem_represented_; } + void SetLevelImage( + TextureInfo* info, + GLenum target, + GLint level, + gfx::GLImage* image); + private: // Helper for Initialize(). TextureInfo::Ref CreateDefaultAndBlackTextures( diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index dad2cf1..487bde7 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -999,6 +999,26 @@ TEST_F(TextureInfoTest, UseDeletedTexture) { info = NULL; } +TEST_F(TextureInfoTest, GetLevelImage) { + manager_.SetInfoTarget(info_, GL_TEXTURE_2D); + manager_.SetLevelInfo(info_, + GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); + EXPECT_TRUE(info_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); + // Set image. + manager_.SetLevelImage(info_, + GL_TEXTURE_2D, 1, gfx::GLImage::CreateGLImage(0)); + EXPECT_FALSE(info_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); + // Remove it. + manager_.SetLevelImage(info_, GL_TEXTURE_2D, 1, NULL); + EXPECT_TRUE(info_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); + manager_.SetLevelImage(info_, + GL_TEXTURE_2D, 1, gfx::GLImage::CreateGLImage(0)); + // Image should be reset when SetLevelInfo is called. + manager_.SetLevelInfo(info_, + GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); + EXPECT_TRUE(info_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 45589b6..fc2ab61 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -99,6 +99,7 @@ void GLManager::Setup( if (!context_group) { context_group = new gles2::ContextGroup(mailbox_manager_.get(), NULL, + NULL, kBindGeneratesResource); } diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi index 06fda1b..78f4078 100644 --- a/gpu/command_buffer_service.gypi +++ b/gpu/command_buffer_service.gypi @@ -57,6 +57,8 @@ 'command_buffer/service/gpu_switches.cc', 'command_buffer/service/id_manager.h', 'command_buffer/service/id_manager.cc', + 'command_buffer/service/image_manager.cc', + 'command_buffer/service/image_manager.h', 'command_buffer/service/mailbox_manager.cc', 'command_buffer/service/mailbox_manager.h', 'command_buffer/service/memory_program_cache.h', diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index 34e48639..ed72c01 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -113,6 +113,7 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup(NULL, NULL, + NULL, true)); decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); diff --git a/third_party/khronos/GLES2/gl2ext.h b/third_party/khronos/GLES2/gl2ext.h index fee1192..a452f3f 100644 --- a/third_party/khronos/GLES2/gl2ext.h +++ b/third_party/khronos/GLES2/gl2ext.h @@ -2037,6 +2037,22 @@ typedef void (GL_APIENTRYP PFNGLBINDUNIFORMLOCATIONCHROMIUM) (GLuint program, GL #endif #endif +/* GL_CHROMIUM_texture_from_image */ +#ifndef GL_CHROMIUM_texture_from_image +#define GL_CHROMIUM_texture_from_image 1 +#ifdef GL_GLEXT_PROTOTYPES +#define glBindTexImage2DCHROMIUM GLES2_GET_FUN(BindTexImage2DCHROMIUM) +#define glReleaseTexImage2DCHROMIUM GLES2_GET_FUN(ReleaseTexImage2DCHROMIUM) +#if !defined(GLES2_USE_CPP_BINDINGS) +GL_APICALL void GL_APIENTRY glBindTexImage2DCHROMIUM (GLenum target, GLint imageId); +GL_APICALL void GL_APIENTRY glReleaseTexImage2DCHROMIUM (GLenum target, GLint imageId); +#endif +#else +typedef void (GL_APIENTRYP PFNGLBINDTEXIMAGE2DCHROMIUM) (GLenum target, GLint imageId); +typedef void (GL_APIENTRYP PFNGLRELEASETEXIMAGE2DCHROMIUM) (GLenum target, GLint imageId); +#endif +#endif + #ifdef __cplusplus } #endif diff --git a/third_party/khronos/README.chromium b/third_party/khronos/README.chromium index f49e752..4128e35 100644 --- a/third_party/khronos/README.chromium +++ b/third_party/khronos/README.chromium @@ -27,6 +27,7 @@ GLES2/gl2ext.h - Added GL_CHROMIUM_copy_texture - Added GL_CHROMIUM_bind_uniform_location - Added GL_CHROMIUM_get_error_query + - Added GL_CHROMIUM_texture_from_image - Added GL_NVX_gpu_memory_info EGL/eglplatform.h - Added EGLNative*Type for Mac. diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp index 85e4303..32d5e69 100644 --- a/ui/gl/gl.gyp +++ b/ui/gl/gl.gyp @@ -53,6 +53,14 @@ 'gl_export.h', 'gl_fence.cc', 'gl_fence.h', + 'gl_image.cc', + 'gl_image.h', + 'gl_image_android.cc', + 'gl_image_linux.cc', + 'gl_image_mac.cc', + 'gl_image_stub.cc', + 'gl_image_stub.h', + 'gl_image_win.cc', 'gl_implementation.cc', 'gl_implementation.h', 'gl_implementation_android.cc', @@ -143,6 +151,8 @@ 'sources': [ 'gl_context_glx.cc', 'gl_context_glx.h', + 'gl_image_glx.cc', + 'gl_image_glx.h', 'gl_surface_glx.cc', 'gl_surface_glx.h', '<(gl_binding_output_dir)/gl_bindings_autogen_glx.cc', @@ -153,6 +163,12 @@ 'GL_GLEXT_PROTOTYPES', ], }, + 'link_settings': { + 'libraries': [ + '-lX11', + '-lXcomposite', + ], + }, }], ['OS=="win"', { 'sources': [ diff --git a/ui/gl/gl_image.cc b/ui/gl/gl_image.cc new file mode 100644 index 0000000..aaefb94 --- /dev/null +++ b/ui/gl/gl_image.cc @@ -0,0 +1,24 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_image.h" + +#include "base/logging.h" + +namespace gfx { + +GLImage::GLImage() {} + +bool GLImage::BindTexImage() { + NOTIMPLEMENTED(); + return false; +} + +void GLImage::ReleaseTexImage() { + NOTIMPLEMENTED(); +} + +GLImage::~GLImage() {} + +} // namespace gfx diff --git a/ui/gl/gl_image.h b/ui/gl/gl_image.h new file mode 100644 index 0000000..8df7c71 --- /dev/null +++ b/ui/gl/gl_image.h @@ -0,0 +1,50 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_GL_IMAGE_H_ +#define UI_GL_GL_IMAGE_H_ + +#include "base/memory/ref_counted.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_export.h" + +namespace gfx { + +class GLSurface; + +// Encapsulates an image that can be bound to a texture, hiding platform +// specific management. +class GL_EXPORT GLImage : public base::RefCounted<GLImage> { + public: + GLImage(); + + // Destroys the image. + virtual void Destroy() = 0; + + // Get the size of the image. + virtual gfx::Size GetSize() = 0; + + // Bind image to texture currently bound to GL_TEXTURE_2D target. + virtual bool BindTexImage(); + + // Release image from texture currently bound to GL_TEXTURE_2D target. + virtual void ReleaseTexImage(); + + // Create a GL image for a window. + static scoped_refptr<GLImage> CreateGLImage(gfx::PluginWindowHandle window); + + protected: + virtual ~GLImage(); + + private: + friend class base::RefCounted<GLImage>; + + DISALLOW_COPY_AND_ASSIGN(GLImage); +}; + +} // namespace gfx + +#endif // UI_GL_GL_IMAGE_H_ diff --git a/ui/gl/gl_image_android.cc b/ui/gl/gl_image_android.cc new file mode 100644 index 0000000..78d8663 --- /dev/null +++ b/ui/gl/gl_image_android.cc @@ -0,0 +1,24 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_image.h" + +#include "base/debug/trace_event.h" +#include "ui/gl/gl_implementation.h" + +namespace gfx { + +scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { + TRACE_EVENT0("gpu", "GLImage::CreateGLImage"); + switch (GetGLImplementation()) { + case kGLImplementationEGLGLES2: { + return NULL; + } + default: + NOTREACHED(); + return NULL; + } +} + +} // namespace gfx diff --git a/ui/gl/gl_image_glx.cc b/ui/gl/gl_image_glx.cc new file mode 100644 index 0000000..5bb4077 --- /dev/null +++ b/ui/gl/gl_image_glx.cc @@ -0,0 +1,175 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern "C" { +#include <X11/extensions/Xcomposite.h> +} + +#include "ui/gl/gl_image_glx.h" + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "ui/gl/gl_surface_glx.h" + +namespace gfx { + +namespace { + +// scoped_ptr functor for XFree(). Use as follows: +// scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...); +// where "XVisualInfo" is any X type that is freed with XFree. +class ScopedPtrXFree { + public: + void operator()(void* x) const { + ::XFree(x); + } +}; + +int BindToTextureFormat(int depth) { + if (depth == 32) + return GLX_BIND_TO_TEXTURE_RGBA_EXT; + + return GLX_BIND_TO_TEXTURE_RGB_EXT; +} + +int TextureFormat(int depth) { + if (depth == 32) + return GLX_TEXTURE_FORMAT_RGBA_EXT; + + return GLX_TEXTURE_FORMAT_RGB_EXT; +} + +} // namespace anonymous + +GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window) + : display_(base::MessagePumpForUI::GetDefaultXDisplay()), + window_(window), + pixmap_(0), + glx_pixmap_(0) { +} + +bool GLImageGLX::Initialize() { + if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) { + LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported."; + return false; + } + + XWindowAttributes attributes; + if (!XGetWindowAttributes(display_, window_, &attributes)) { + LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; + return false; + } + + XVisualInfo templ; + templ.visualid = XVisualIDFromVisual(attributes.visual); + int num_visinfo = 0; + scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visinfo( + XGetVisualInfo(display_, + VisualIDMask, + &templ, + &num_visinfo)); + if (!visinfo.get()) { + LOG(ERROR) << "XGetVisualInfo failed for visual id " << + templ.visualid << "."; + return false; + } + if (!num_visinfo) { + LOG(ERROR) << "XGetVisualInfo returned 0 elements."; + return false; + } + + int config_attribs[] = { + GLX_VISUAL_ID, visinfo->visualid, + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_EXT, + BindToTextureFormat(visinfo->depth), GL_TRUE, + 0 + }; + int num_elements = 0; + scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config( + glXChooseFBConfig(display_, + DefaultScreen(display_), + config_attribs, + &num_elements)); + if (!config.get()) { + LOG(ERROR) << "glXChooseFBConfig failed."; + return false; + } + if (!num_elements) { + LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; + return false; + } + + // Create backing pixmap reference. + pixmap_ = XCompositeNameWindowPixmap(display_, window_); + + XID root = 0; + int x = 0; + int y = 0; + unsigned int width = 0; + unsigned int height = 0; + unsigned int bw = 0; + unsigned int depth = 0; + if (!XGetGeometry( + display_, pixmap_, &root, &x, &y, &width, &height, &bw, &depth)) { + LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap_ << "."; + return false; + } + + int pixmap_attribs[] = { + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, + GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth), + 0 + }; + glx_pixmap_ = glXCreatePixmap( + display_, + *config.get(), + pixmap_, + pixmap_attribs); + if (!glx_pixmap_) { + LOG(ERROR) << "glXCreatePixmap failed."; + return false; + } + + size_ = gfx::Size(width, height); + return true; +} + +void GLImageGLX::Destroy() { + if (glx_pixmap_) { + glXDestroyGLXPixmap(display_, glx_pixmap_); + glx_pixmap_ = 0; + } + if (pixmap_) { + XFreePixmap(display_, pixmap_); + pixmap_ = 0; + } +} + +gfx::Size GLImageGLX::GetSize() { + return size_; +} + +bool GLImageGLX::BindTexImage() { + if (!glx_pixmap_) + return false; + + glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0); + return true; +} + +void GLImageGLX::ReleaseTexImage() { + if (!glx_pixmap_) + return; + + glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT); +} + +GLImageGLX::~GLImageGLX() { + Destroy(); +} + +} // namespace gfx diff --git a/ui/gl/gl_image_glx.h b/ui/gl/gl_image_glx.h new file mode 100644 index 0000000..a3cec2d --- /dev/null +++ b/ui/gl/gl_image_glx.h @@ -0,0 +1,42 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_GL_IMAGE_GLX_H_ +#define UI_GL_GL_IMAGE_GLX_H_ + +#include "ui/base/x/x11_util.h" +#include "ui/gfx/size.h" +#include "ui/gl/gl_export.h" +#include "ui/gl/gl_image.h" + +namespace gfx { + +class GL_EXPORT GLImageGLX : public GLImage { + public: + explicit GLImageGLX(gfx::PluginWindowHandle window); + + virtual bool Initialize(); + + // Implement GLImage. + virtual void Destroy() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual bool BindTexImage() OVERRIDE; + virtual void ReleaseTexImage() OVERRIDE; + + protected: + virtual ~GLImageGLX(); + + private: + Display* display_; + gfx::PluginWindowHandle window_; + XID pixmap_; + XID glx_pixmap_; + gfx::Size size_; + + DISALLOW_COPY_AND_ASSIGN(GLImageGLX); +}; + +} // namespace gfx + +#endif // UI_GL_GL_IMAGE_GLX_H_ diff --git a/ui/gl/gl_image_linux.cc b/ui/gl/gl_image_linux.cc new file mode 100644 index 0000000..75efd2a --- /dev/null +++ b/ui/gl/gl_image_linux.cc @@ -0,0 +1,38 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_image.h" + +#include "base/debug/trace_event.h" +#include "ui/gl/gl_image_glx.h" +#include "ui/gl/gl_image_stub.h" +#include "ui/gl/gl_implementation.h" + +namespace gfx { + +scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { + TRACE_EVENT0("gpu", "GLImage::CreateGLImage"); + switch (GetGLImplementation()) { + case kGLImplementationOSMesaGL: { + return NULL; + } + case kGLImplementationDesktopGL: { + scoped_refptr<GLImageGLX> image(new GLImageGLX(window)); + if (!image->Initialize()) + return NULL; + + return image; + } + case kGLImplementationEGLGLES2: { + return NULL; + } + case kGLImplementationMockGL: + return new GLImageStub; + default: + NOTREACHED(); + return NULL; + } +} + +} // namespace gfx diff --git a/ui/gl/gl_image_mac.cc b/ui/gl/gl_image_mac.cc new file mode 100644 index 0000000..a4b522a --- /dev/null +++ b/ui/gl/gl_image_mac.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_image.h" + +#include "base/debug/trace_event.h" +#include "ui/gl/gl_image_stub.h" +#include "ui/gl/gl_implementation.h" + +namespace gfx { + +scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { + TRACE_EVENT0("gpu", "GLImage::CreateGLImage"); + switch (GetGLImplementation()) { + case kGLImplementationOSMesaGL: + case kGLImplementationDesktopGL: + case kGLImplementationAppleGL: { + return NULL; + } + case kGLImplementationMockGL: + return new GLImageStub; + default: + NOTREACHED(); + return NULL; + } +} + +} // namespace gfx diff --git a/ui/gl/gl_image_stub.cc b/ui/gl/gl_image_stub.cc new file mode 100644 index 0000000..86efe6e --- /dev/null +++ b/ui/gl/gl_image_stub.cc @@ -0,0 +1,25 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_image_stub.h" + +namespace gfx { + +void GLImageStub::Destroy() { +} + +gfx::Size GLImageStub::GetSize() { + return gfx::Size(1, 1); +} + +bool GLImageStub::BindTexImage() { + return true; +} + +void GLImageStub::ReleaseTexImage() { +} + +GLImageStub::~GLImageStub() {} + +} // namespace gfx diff --git a/ui/gl/gl_image_stub.h b/ui/gl/gl_image_stub.h new file mode 100644 index 0000000..8b47358 --- /dev/null +++ b/ui/gl/gl_image_stub.h @@ -0,0 +1,27 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_GL_IMAGE_STUB_H_ +#define UI_GL_GL_IMAGE_STUB_H_ + +#include "ui/gl/gl_image.h" + +namespace gfx { + +// A GLImage that does nothing for unit tests. +class GL_EXPORT GLImageStub : public GLImage { + public: + // Implement GLImage. + virtual void Destroy() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual bool BindTexImage() OVERRIDE; + virtual void ReleaseTexImage() OVERRIDE; + + protected: + virtual ~GLImageStub(); +}; + +} // namespace gfx + +#endif // UI_GL_GL_IMAGE_STUB_H_ diff --git a/ui/gl/gl_image_win.cc b/ui/gl/gl_image_win.cc new file mode 100644 index 0000000..8c54bf4 --- /dev/null +++ b/ui/gl/gl_image_win.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_image.h" + +#include "base/debug/trace_event.h" +#include "ui/gl/gl_image_stub.h" +#include "ui/gl/gl_implementation.h" + +namespace gfx { + +scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { + TRACE_EVENT0("gpu", "GLImage::CreateGLImage"); + switch (GetGLImplementation()) { + case kGLImplementationOSMesaGL: + case kGLImplementationDesktopGL: + case kGLImplementationEGLGLES2: { + return NULL; + } + case kGLImplementationMockGL: + return new GLImageStub; + default: + NOTREACHED(); + return NULL; + } +} + +} // namespace gfx diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc index 8428cfc..6e16754 100644 --- a/ui/gl/gl_surface_glx.cc +++ b/ui/gl/gl_surface_glx.cc @@ -36,6 +36,7 @@ class ScopedPtrXFree { Display* g_display; const char* g_glx_extensions = NULL; bool g_glx_create_context_robustness_supported = false; +bool g_glx_texture_from_pixmap_supported = false; } // namespace @@ -66,6 +67,8 @@ bool GLSurfaceGLX::InitializeOneOff() { g_glx_extensions = glXQueryExtensionsString(g_display, 0); g_glx_create_context_robustness_supported = HasGLXExtension("GLX_ARB_create_context_robustness"); + g_glx_texture_from_pixmap_supported = + HasGLXExtension("GLX_EXT_texture_from_pixmap"); initialized = true; return true; @@ -86,6 +89,11 @@ bool GLSurfaceGLX::IsCreateContextRobustnessSupported() { return g_glx_create_context_robustness_supported; } +// static +bool GLSurfaceGLX::IsTextureFromPixmapSupported() { + return g_glx_texture_from_pixmap_supported; +} + void* GLSurfaceGLX::GetDisplay() { return g_display; } diff --git a/ui/gl/gl_surface_glx.h b/ui/gl/gl_surface_glx.h index 644b51b..0dc235c 100644 --- a/ui/gl/gl_surface_glx.h +++ b/ui/gl/gl_surface_glx.h @@ -27,6 +27,7 @@ class GL_EXPORT GLSurfaceGLX : public GLSurface { static const char* GetGLXExtensions(); static bool HasGLXExtension(const char* name); static bool IsCreateContextRobustnessSupported(); + static bool IsTextureFromPixmapSupported(); virtual void* GetDisplay() OVERRIDE; diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc index e766332..46403d7 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc @@ -414,7 +414,8 @@ bool GLInProcessContext::Initialize(const gfx::Size& size, bool bind_generates_resource = false; decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group ? context_group->decoder_->GetContextGroup() : - new ::gpu::gles2::ContextGroup(NULL, NULL, bind_generates_resource))); + new ::gpu::gles2::ContextGroup( + NULL, NULL, NULL, bind_generates_resource))); gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), decoder_.get(), @@ -1637,6 +1638,11 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::pushGroupMarkerEXT( DELEGATE_TO_GL(popGroupMarkerEXT, PopGroupMarkerEXT); +DELEGATE_TO_GL_2(bindTexImage2DCHROMIUM, BindTexImage2DCHROMIUM, + WGC3Denum, WGC3Dint) +DELEGATE_TO_GL_2(releaseTexImage2DCHROMIUM, ReleaseTexImage2DCHROMIUM, + WGC3Denum, WGC3Dint) + GrGLInterface* WebGraphicsContext3DInProcessCommandBufferImpl:: onCreateGrGLInterface() { return webkit_glue::CreateCommandBufferSkiaGLBinding(); diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h index 6dd92aa..d4b0b3a 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h +++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h @@ -461,6 +461,9 @@ class WebGraphicsContext3DInProcessCommandBufferImpl WGC3Denum target, WGC3Dint width, WGC3Dint height, WGC3Duint ioSurfaceId, WGC3Duint plane); + virtual void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId); + virtual void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId); + virtual void texStorage2DEXT( WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat, WGC3Dint width, WGC3Dint height); diff --git a/webkit/gpu/webgraphicscontext3d_in_process_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc index 6decabf..ff11852 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_impl.cc +++ b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc @@ -1698,6 +1698,16 @@ void WebGraphicsContext3DInProcessImpl::copyTextureCHROMIUM( NOTIMPLEMENTED(); } +void WebGraphicsContext3DInProcessImpl::bindTexImage2DCHROMIUM( + WGC3Denum target, WGC3Dint imageId) { + NOTIMPLEMENTED(); +} + +void WebGraphicsContext3DInProcessImpl::releaseTexImage2DCHROMIUM( + WGC3Denum target, WGC3Dint imageId) { + NOTIMPLEMENTED(); +} + GrGLInterface* WebGraphicsContext3DInProcessImpl::onCreateGrGLInterface() { return gfx::CreateInProcessSkiaGLBinding(); } diff --git a/webkit/gpu/webgraphicscontext3d_in_process_impl.h b/webkit/gpu/webgraphicscontext3d_in_process_impl.h index 0b248ce..eb0ed57 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_impl.h +++ b/webkit/gpu/webgraphicscontext3d_in_process_impl.h @@ -489,6 +489,9 @@ class WebGraphicsContext3DInProcessImpl : public WebGraphicsContext3D { virtual void consumeTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailbox); + virtual void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId); + virtual void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId); + protected: virtual GrGLInterface* onCreateGrGLInterface(); |