Index: gpu/command_buffer/service/in_process_command_buffer.cc |
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc |
index 529ffc49b527ead87ae8106320ae8421d0b6c508..d43f84c0cbe58d729d72dea3a6603b7aba0498f3 100644 |
--- a/gpu/command_buffer/service/in_process_command_buffer.cc |
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc |
@@ -43,6 +43,11 @@ |
#include "ui/gl/android/surface_texture.h" |
#endif |
+#if defined(OS_WIN) |
+#include <windows.h> |
+#include "base/process/process_handle.h" |
+#endif |
+ |
namespace gpu { |
namespace { |
@@ -180,6 +185,53 @@ void SyncPointManager::WaitSyncPoint(uint32 sync_point) { |
base::LazyInstance<SyncPointManager> g_sync_point_manager = |
LAZY_INSTANCE_INITIALIZER; |
+base::SharedMemoryHandle ShareToGpuThread( |
+ base::SharedMemoryHandle source_handle) { |
+#if defined(OS_WIN) |
+ // Windows needs to explicitly duplicate the handle to current process. |
+ base::SharedMemoryHandle target_handle; |
+ if (!DuplicateHandle(GetCurrentProcess(), |
+ source_handle, |
+ GetCurrentProcess(), |
+ &target_handle, |
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE, |
+ FALSE, |
+ 0)) { |
+ return base::SharedMemory::NULLHandle(); |
+ } |
+ |
+ return target_handle; |
+#else |
+ int duped_handle = HANDLE_EINTR(dup(source_handle.fd)); |
+ if (duped_handle < 0) |
+ return base::SharedMemory::NULLHandle(); |
+ |
+ return base::FileDescriptor(duped_handle, true); |
+#endif |
+} |
+ |
+gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuThread( |
+ const gfx::GpuMemoryBufferHandle& source_handle, |
+ bool* requires_sync_point) { |
+ switch (source_handle.type) { |
+ case gfx::SHARED_MEMORY_BUFFER: { |
+ gfx::GpuMemoryBufferHandle handle; |
+ handle.type = gfx::SHARED_MEMORY_BUFFER; |
+ handle.handle = ShareToGpuThread(source_handle.handle); |
+ *requires_sync_point = false; |
+ return handle; |
+ } |
+ case gfx::IO_SURFACE_BUFFER: |
+ case gfx::SURFACE_TEXTURE_BUFFER: |
+ case gfx::OZONE_NATIVE_BUFFER: |
+ *requires_sync_point = true; |
+ return source_handle; |
+ default: |
+ NOTREACHED(); |
+ return gfx::GpuMemoryBufferHandle(); |
+ } |
+} |
+ |
} // anonyous namespace |
InProcessCommandBuffer::Service::Service() {} |
@@ -642,13 +694,28 @@ int32 InProcessCommandBuffer::CreateImage(ClientBuffer buffer, |
DCHECK(gpu::ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat( |
internalformat, gpu_memory_buffer->GetFormat())); |
+ |
+ // This handle is owned by the GPU thread and must be passed to it or it |
+ // will leak. In otherwords, do not early out on error between here and the |
+ // queuing of the CreateImage task below. |
+ bool requires_sync_point = false; |
+ gfx::GpuMemoryBufferHandle handle = |
+ ShareGpuMemoryBufferToGpuThread(gpu_memory_buffer->GetHandle(), |
+ &requires_sync_point); |
+ |
QueueTask(base::Bind(&InProcessCommandBuffer::CreateImageOnGpuThread, |
base::Unretained(this), |
new_id, |
- gpu_memory_buffer->GetHandle(), |
+ handle, |
gfx::Size(width, height), |
gpu_memory_buffer->GetFormat(), |
internalformat)); |
+ |
+ if (requires_sync_point) { |
+ gpu_memory_buffer_manager_->SetDestructionSyncPoint(gpu_memory_buffer, |
+ InsertSyncPoint()); |
+ } |
+ |
return new_id; |
} |