Index: content/browser/gpu/browser_gpu_channel_host_factory.cc |
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc |
index 075c8f993f5da2332a185895ee210b8e68d8155c..7d62ac074be7ddfca2ba322c4000f41433c8118f 100644 |
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc |
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc |
@@ -11,12 +11,154 @@ |
#include "content/browser/gpu/gpu_process_host.h" |
#include "content/browser/gpu/gpu_surface_tracker.h" |
#include "content/common/child_process_host_impl.h" |
+#include "content/common/gpu/client/gpu_memory_buffer_impl_foobar.h" |
#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" |
#include "content/common/gpu/gpu_messages.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/gpu_data_manager.h" |
#include "content/public/common/content_client.h" |
#include "ipc/ipc_forwarding_message_filter.h" |
+#include "ui/gfx/x/x11_types.h" |
+ |
+extern char GetZCopy(); |
+ |
+namespace foobar { |
+ |
+extern "C" { |
+#include <fcntl.h> |
+#include <libdrm/i915_drm.h> |
+#include <libdrm/intel_bufmgr.h> |
+#include <xf86drm.h> |
+#include <X11/Xlib.h> |
+#include <X11/Xlibint.h> |
+#include <X11/extensions/Xext.h> |
+#include <X11/extensions/extutil.h> |
+#include <X11/extensions/dri2proto.h> |
+} |
+ |
+static char dri2ExtensionName[] = DRI2_NAME; |
+static XExtensionInfo *dri2Info; |
+ |
+static /* const */ XExtensionHooks dri2ExtensionHooks = { |
+ NULL, /* create_gc */ |
+ NULL, /* copy_gc */ |
+ NULL, /* flush_gc */ |
+ NULL, /* free_gc */ |
+ NULL, /* create_font */ |
+ NULL, /* free_font */ |
+ NULL, /* close_display */ |
+ NULL, /* wire_to_event */ |
+ NULL, /* event_to_wire */ |
+ NULL, /* error */ |
+ NULL, /* error_string */ |
+}; |
+ |
+static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, |
+ dri2Info, |
+ dri2ExtensionName, |
+ &dri2ExtensionHooks, |
+ 0, NULL) |
+ |
+static int dri_fd = -1; |
+static drm_intel_bufmgr *bufmgr = NULL; |
+ |
+static Bool OpenDri() { |
+ if (bufmgr) return True; |
+ |
+ dri_fd = open("/dev/dri/card0", O_RDWR); |
+ if (dri_fd < 0) { |
+ TRACE_EVENT_INSTANT0("zcopy", "open dri device failed", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ return False; |
+ } |
+ |
+ drm_magic_t magic; |
+ if (drmGetMagic(dri_fd, &magic)) { |
+ close(dri_fd); |
+ TRACE_EVENT_INSTANT0("zcopy", "drmGetMagic failed", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ return False; |
+ } |
+ |
+ Display *dpy = (Display *) gfx::GetXDisplay(); |
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy); |
+ xDRI2AuthenticateReq *req; |
+ xDRI2AuthenticateReply rep; |
+ |
+ XextCheckExtension(dpy, info, dri2ExtensionName, False); |
+ |
+ LockDisplay(dpy); |
+ GetReq(DRI2Authenticate, req); |
+ req->reqType = info->codes->major_opcode; |
+ req->dri2ReqType = X_DRI2Authenticate; |
+ req->window = DefaultRootWindow(dpy); |
+ req->magic = magic; |
+ |
+ if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { |
+ dri_fd = -1; |
+ } |
+ UnlockDisplay(dpy); |
+ SyncHandle(); |
+ |
+ if (dri_fd < 0 || !rep.authenticated) { |
+ close(dri_fd); |
+ TRACE_EVENT_INSTANT0("zcopy", "authentication failed", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ } else { |
+ bufmgr = drm_intel_bufmgr_gem_init(dri_fd, 2048); //XXX what is this number? |
+ if (!bufmgr) { |
+ TRACE_EVENT_INSTANT0("zcopy", "gem_init failed", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ } |
+ } |
+ |
+ return bufmgr != NULL; |
+} |
+ |
+static void *AllocTexture(unsigned width, unsigned height, unsigned bpp) { |
+ // Figuring out how much memory to allocate for a texture is pretty |
+ // complicated due to padding and alignment concerns, and mipmaps, to |
+ // name a few reasons. |
+ // There's a lot of logic in the mesa i965 driver to handle it, which |
+ // is one of the drawbacks to allocating the texture memory here. |
+ // The checks here will catch some problems, but maybe not all. |
+ uint32_t tiling, want; |
+ unsigned long pitch; |
+ |
+ if ((width % 4) || (height % 2)) { |
+ TRACE_EVENT_INSTANT2("zcopy", "can't handle texure size", |
+ TRACE_EVENT_SCOPE_THREAD, |
+ "width", width, |
+ "height", height); |
+ return NULL; |
+ } |
+ |
+ tiling = want = GetZCopy() == 'u' ? I915_TILING_NONE : I915_TILING_Y; |
+ drm_intel_bo *bo = drm_intel_bo_alloc_tiled(bufmgr, "region", width, height, |
+ bpp, &tiling, &pitch, 0); |
+ |
+ if (tiling != want) { |
+ TRACE_EVENT_INSTANT2("zcopy", "did not get requested tiling", |
+ TRACE_EVENT_SCOPE_THREAD, |
+ "width", width, |
+ "height", height); |
+ drm_intel_bo_unreference(bo); |
+ return NULL; |
+ } |
+ |
+ if (pitch != width * 4) { |
+ TRACE_EVENT_INSTANT2("zcopy", "did not get expected pitch", |
+ TRACE_EVENT_SCOPE_THREAD, |
+ "width", width, |
+ "height", height); |
+ drm_intel_bo_unreference(bo); |
+ return NULL; |
+ } |
+ |
+ return bo; |
+} |
+ |
+} // namespace foobar |
namespace content { |
@@ -379,6 +521,27 @@ scoped_ptr<gfx::GpuMemoryBuffer> |
if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) |
return scoped_ptr<gfx::GpuMemoryBuffer>(); |
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) |
+ if (GetZCopy()) { |
+ if (!GpuMemoryBufferImplFoobar::IsFormatSupported(internalformat)) { |
+ TRACE_EVENT_INSTANT0("zcopy", "can't handle texure format", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ } else if (foobar::OpenDri()) { |
+ // This object needs to be created somehow. Can be something |
+ // platform/driver specific. |
+ void *foobar_object = foobar::AllocTexture(width, height, |
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat)); |
+ if (foobar_object) { |
+ scoped_ptr<GpuMemoryBufferImplFoobar> foobar_buffer( |
+ new GpuMemoryBufferImplFoobar(gfx::Size(width, height), |
+ internalformat)); |
+ if (foobar_buffer->InitializeFromFoobarObject(foobar_object)) |
+ return foobar_buffer.PassAs<gfx::GpuMemoryBuffer>(); |
+ } |
+ } |
+ } |
+#endif |
+ |
size_t size = width * height * |
GpuMemoryBufferImpl::BytesPerPixel(internalformat); |
scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); |