summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-18 05:15:50 +0000
committerreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-18 05:15:50 +0000
commitf4ba36512524dc3150261942ec9a89b4dfb7364a (patch)
treee9f7e293728188a158b4156a03eb713f5eeebada
parentfcb0f644c83064a695588aa74d755aff74a51286 (diff)
downloadchromium_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
-rw-r--r--content/browser/gpu/browser_gpu_channel_host_factory.cc66
-rw-r--r--content/browser/gpu/browser_gpu_channel_host_factory.h14
-rw-r--r--content/browser/gpu/gpu_process_host.cc43
-rw-r--r--content/browser/gpu/gpu_process_host.h19
-rw-r--r--content/common/gpu/client/gpu_channel_host.h7
-rw-r--r--content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc5
-rw-r--r--content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h3
-rw-r--r--content/common/gpu/gpu_channel.cc38
-rw-r--r--content/common/gpu/gpu_channel.h10
-rw-r--r--content/common/gpu/gpu_channel_manager.cc87
-rw-r--r--content/common/gpu/gpu_channel_manager.h20
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc2
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.h2
-rw-r--r--content/common/gpu/gpu_messages.h17
-rw-r--r--content/renderer/render_thread_impl.cc11
-rw-r--r--content/renderer/render_thread_impl.h5
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py12
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h6
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h16
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h12
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest_autogen.h22
-rw-r--r--gpu/command_buffer/cmd_buffer_functions.txt3
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h76
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h30
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h2
-rw-r--r--gpu/command_buffer/service/context_group.cc3
-rw-r--r--gpu/command_buffer/service/context_group.h7
-rw-r--r--gpu/command_buffer/service/context_group_unittest.cc2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc250
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h24
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc82
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc1
-rw-r--r--gpu/command_buffer/service/image_manager.cc35
-rw-r--r--gpu/command_buffer/service/image_manager.h43
-rw-r--r--gpu/command_buffer/service/texture_manager.cc61
-rw-r--r--gpu/command_buffer/service/texture_manager.h20
-rw-r--r--gpu/command_buffer/service/texture_manager_unittest.cc20
-rw-r--r--gpu/command_buffer/tests/gl_manager.cc1
-rw-r--r--gpu/command_buffer_service.gypi2
-rw-r--r--gpu/gles2_conform_support/egl/display.cc1
-rw-r--r--third_party/khronos/GLES2/gl2ext.h16
-rw-r--r--third_party/khronos/README.chromium1
-rw-r--r--ui/gl/gl.gyp16
-rw-r--r--ui/gl/gl_image.cc24
-rw-r--r--ui/gl/gl_image.h50
-rw-r--r--ui/gl/gl_image_android.cc24
-rw-r--r--ui/gl/gl_image_glx.cc175
-rw-r--r--ui/gl/gl_image_glx.h42
-rw-r--r--ui/gl/gl_image_linux.cc38
-rw-r--r--ui/gl/gl_image_mac.cc29
-rw-r--r--ui/gl/gl_image_stub.cc25
-rw-r--r--ui/gl/gl_image_stub.h27
-rw-r--r--ui/gl/gl_image_win.cc29
-rw-r--r--ui/gl/gl_surface_glx.cc8
-rw-r--r--ui/gl/gl_surface_glx.h1
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc8
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h3
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_impl.cc10
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_impl.h3
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();