#include "content/common/child_process_messages.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
+#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/common/cmd_buffer_common.h"
#include "gpu/command_buffer/common/command_buffer_shared.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
+#include "gpu/command_buffer/service/image_factory.h"
#include "ui/gfx/size.h"
+#include "ui/gl/gl_bindings.h"
namespace content {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CommandBufferProxyImpl, message)
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Destroyed, OnDestroyed);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_EchoAck, OnEchoAck);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ConsoleMsg, OnConsoleMessage);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetMemoryAllocation,
OnSetMemoryAllocation);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalSyncPointAck,
OnSignalSyncPointAck);
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SwapBuffersCompleted,
+ OnSwapBuffersCompleted);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
}
}
-void CommandBufferProxyImpl::OnEchoAck() {
- DCHECK(!echo_tasks_.empty());
- base::Closure callback = echo_tasks_.front();
- echo_tasks_.pop();
- callback.Run();
-}
-
void CommandBufferProxyImpl::OnConsoleMessage(
const GPUCommandBufferConsoleMessage& message) {
if (!console_message_callback_.is_null()) {
}
bool CommandBufferProxyImpl::Initialize() {
+ TRACE_EVENT0("gpu", "CommandBufferProxyImpl::Initialize");
shared_state_shm_.reset(channel_->factory()->AllocateSharedMemory(
sizeof(*shared_state())).release());
if (!shared_state_shm_)
if (!base::SharedMemory::IsHandleValid(handle))
return false;
- bool result;
+ bool result = false;
if (!Send(new GpuCommandBufferMsg_Initialize(
route_id_, handle, &result, &capabilities_))) {
LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize.";
return false;
}
- capabilities_.map_image = true;
+ capabilities_.image = true;
return true;
}
-gpu::CommandBuffer::State CommandBufferProxyImpl::GetState() {
- // Send will flag state with lost context if IPC fails.
- if (last_state_.error == gpu::error::kNoError) {
- gpu::CommandBuffer::State state;
- if (Send(new GpuCommandBufferMsg_GetState(route_id_, &state)))
- OnUpdateState(state);
- }
-
- TryUpdateState();
- return last_state_;
-}
-
gpu::CommandBuffer::State CommandBufferProxyImpl::GetLastState() {
return last_state_;
}
Send(new GpuCommandBufferMsg_AsyncFlush(route_id_,
put_offset,
- ++flush_count_));
+ ++flush_count_,
+ latency_info_));
+ latency_info_.clear();
}
void CommandBufferProxyImpl::SetLatencyInfo(
const std::vector<ui::LatencyInfo>& latency_info) {
- if (last_state_.error != gpu::error::kNoError)
- return;
- Send(new GpuCommandBufferMsg_SetLatencyInfo(route_id_, latency_info));
+ for (size_t i = 0; i < latency_info.size(); i++)
+ latency_info_.push_back(latency_info[i]);
+}
+
+void CommandBufferProxyImpl::SetSwapBuffersCompletionCallback(
+ const SwapBuffersCompletionCallback& callback) {
+ swap_buffers_completion_callback_ = callback;
}
void CommandBufferProxyImpl::WaitForTokenInRange(int32 start, int32 end) {
"end",
end);
TryUpdateState();
- while (!InRange(start, end, last_state_.token) &&
- last_state_.error == gpu::error::kNoError) {
+ if (!InRange(start, end, last_state_.token) &&
+ last_state_.error == gpu::error::kNoError) {
gpu::CommandBuffer::State state;
- if (Send(new GpuCommandBufferMsg_GetStateFast(route_id_, &state)))
+ if (Send(new GpuCommandBufferMsg_WaitForTokenInRange(
+ route_id_, start, end, &state)))
OnUpdateState(state);
- TryUpdateState();
}
+ DCHECK(InRange(start, end, last_state_.token) ||
+ last_state_.error != gpu::error::kNoError);
}
void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
"end",
end);
TryUpdateState();
- while (!InRange(start, end, last_state_.get_offset) &&
- last_state_.error == gpu::error::kNoError) {
+ if (!InRange(start, end, last_state_.get_offset) &&
+ last_state_.error == gpu::error::kNoError) {
gpu::CommandBuffer::State state;
- if (Send(new GpuCommandBufferMsg_GetStateFast(route_id_, &state)))
+ if (Send(new GpuCommandBufferMsg_WaitForGetOffsetInRange(
+ route_id_, start, end, &state)))
OnUpdateState(state);
- TryUpdateState();
}
+ DCHECK(InRange(start, end, last_state_.get_offset) ||
+ last_state_.error != gpu::error::kNoError);
}
void CommandBufferProxyImpl::SetGetBuffer(int32 shm_id) {
last_put_offset_ = -1;
}
-void CommandBufferProxyImpl::SetGetOffset(int32 get_offset) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer(
size_t size,
int32* id) {
return NULL;
int32 new_id = channel_->ReserveTransferBufferId();
- DCHECK(transfer_buffers_.find(new_id) == transfer_buffers_.end());
scoped_ptr<base::SharedMemory> shared_memory(
channel_->factory()->AllocateSharedMemory(size));
}
*id = new_id;
- scoped_refptr<gpu::Buffer> buffer =
- new gpu::Buffer(shared_memory.Pass(), size);
- transfer_buffers_[new_id] = buffer;
+ scoped_refptr<gpu::Buffer> buffer(
+ gpu::MakeBufferFromSharedMemory(shared_memory.Pass(), size));
return buffer;
}
if (last_state_.error != gpu::error::kNoError)
return;
- // Remove the transfer buffer from the client side cache.
- TransferBufferMap::iterator it = transfer_buffers_.find(id);
- if (it != transfer_buffers_.end())
- transfer_buffers_.erase(it);
-
Send(new GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id));
}
-scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::GetTransferBuffer(int32 id) {
- if (last_state_.error != gpu::error::kNoError)
- return NULL;
-
- // Check local cache to see if there is already a client side shared memory
- // object for this id.
- TransferBufferMap::iterator it = transfer_buffers_.find(id);
- if (it != transfer_buffers_.end()) {
- return it->second;
- }
-
- // Assuming we are in the renderer process, the service is responsible for
- // duplicating the handle. This might not be true for NaCl.
- base::SharedMemoryHandle handle = base::SharedMemoryHandle();
- uint32 size;
- if (!Send(new GpuCommandBufferMsg_GetTransferBuffer(route_id_,
- id,
- &handle,
- &size))) {
- return NULL;
- }
-
- // Cache the transfer buffer shared memory object client side.
- scoped_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(handle, false));
-
- // Map the shared memory on demand.
- if (!shared_memory->memory()) {
- if (!shared_memory->Map(size))
- return NULL;
- }
-
- scoped_refptr<gpu::Buffer> buffer =
- new gpu::Buffer(shared_memory.Pass(), size);
- transfer_buffers_[id] = buffer;
-
- return buffer;
-}
-
-void CommandBufferProxyImpl::SetToken(int32 token) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
-void CommandBufferProxyImpl::SetParseError(
- gpu::error::Error error) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
-void CommandBufferProxyImpl::SetContextLostReason(
- gpu::error::ContextLostReason reason) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
gpu::Capabilities CommandBufferProxyImpl::GetCapabilities() {
return capabilities_;
}
-gfx::GpuMemoryBuffer* CommandBufferProxyImpl::CreateGpuMemoryBuffer(
- size_t width,
- size_t height,
- unsigned internalformat,
- int32* id) {
- *id = -1;
-
+int32_t CommandBufferProxyImpl::CreateImage(ClientBuffer buffer,
+ size_t width,
+ size_t height,
+ unsigned internalformat) {
if (last_state_.error != gpu::error::kNoError)
- return NULL;
-
- int32 new_id = channel_->ReserveGpuMemoryBufferId();
- DCHECK(gpu_memory_buffers_.find(new_id) == gpu_memory_buffers_.end());
+ return -1;
- scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer(
- channel_->factory()->AllocateGpuMemoryBuffer(width,
- height,
- internalformat));
- if (!gpu_memory_buffer)
- return NULL;
+ int32 new_id = channel_->ReserveImageId();
- DCHECK(GpuChannelHost::IsValidGpuMemoryBuffer(
- gpu_memory_buffer->GetHandle()));
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager =
+ channel_->gpu_memory_buffer_manager();
+ gfx::GpuMemoryBuffer* gpu_memory_buffer =
+ gpu_memory_buffer_manager->GpuMemoryBufferFromClientBuffer(buffer);
+ DCHECK(gpu_memory_buffer);
// This handle is owned by the GPU process and must be passed to it or it
// will leak. In otherwords, do not early out on error between here and the
- // sending of the RegisterGpuMemoryBuffer IPC below.
+ // sending of the CreateImage IPC below.
+ bool requires_sync_point = false;
gfx::GpuMemoryBufferHandle handle =
- channel_->ShareGpuMemoryBufferToGpuProcess(
- gpu_memory_buffer->GetHandle());
-
- if (!Send(new GpuCommandBufferMsg_RegisterGpuMemoryBuffer(
- route_id_,
- new_id,
- handle,
- width,
- height,
- internalformat))) {
- return NULL;
+ channel_->ShareGpuMemoryBufferToGpuProcess(gpu_memory_buffer->GetHandle(),
+ &requires_sync_point);
+
+ DCHECK(gpu::ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat(
+ internalformat, gpu_memory_buffer->GetFormat()));
+ if (!Send(new GpuCommandBufferMsg_CreateImage(route_id_,
+ new_id,
+ handle,
+ gfx::Size(width, height),
+ gpu_memory_buffer->GetFormat(),
+ internalformat))) {
+ return -1;
}
- *id = new_id;
- gpu_memory_buffers_[new_id] = gpu_memory_buffer.release();
- return gpu_memory_buffers_[new_id];
+ if (requires_sync_point) {
+ gpu_memory_buffer_manager->SetDestructionSyncPoint(gpu_memory_buffer,
+ InsertSyncPoint());
+ }
+
+ return new_id;
}
-void CommandBufferProxyImpl::DestroyGpuMemoryBuffer(int32 id) {
+void CommandBufferProxyImpl::DestroyImage(int32 id) {
if (last_state_.error != gpu::error::kNoError)
return;
- // Remove the gpu memory buffer from the client side cache.
- GpuMemoryBufferMap::iterator it = gpu_memory_buffers_.find(id);
- if (it != gpu_memory_buffers_.end()) {
- delete it->second;
- gpu_memory_buffers_.erase(it);
- }
+ Send(new GpuCommandBufferMsg_DestroyImage(route_id_, id));
+}
- Send(new GpuCommandBufferMsg_DestroyGpuMemoryBuffer(route_id_, id));
+int32_t CommandBufferProxyImpl::CreateGpuMemoryBufferImage(
+ size_t width,
+ size_t height,
+ unsigned internalformat,
+ unsigned usage) {
+ scoped_ptr<gfx::GpuMemoryBuffer> buffer(
+ channel_->gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
+ gfx::Size(width, height),
+ gpu::ImageFactory::ImageFormatToGpuMemoryBufferFormat(internalformat),
+ gpu::ImageFactory::ImageUsageToGpuMemoryBufferUsage(usage)));
+ if (!buffer)
+ return -1;
+
+ return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
}
int CommandBufferProxyImpl::GetRouteID() const {
return route_id_;
}
-void CommandBufferProxyImpl::Echo(const base::Closure& callback) {
- if (last_state_.error != gpu::error::kNoError) {
- return;
- }
-
- if (!Send(new GpuCommandBufferMsg_Echo(
- route_id_, GpuCommandBufferMsg_EchoAck(route_id_)))) {
- return;
- }
-
- echo_tasks_.push(callback);
-}
-
uint32 CommandBufferProxyImpl::CreateStreamTexture(uint32 texture_id) {
if (last_state_.error != gpu::error::kNoError)
return 0;
- int32 stream_id = 0;
+ int32 stream_id = channel_->GenerateRouteID();
+ bool succeeded = false;
Send(new GpuCommandBufferMsg_CreateStreamTexture(
- route_id_, texture_id, &stream_id));
+ route_id_, texture_id, stream_id, &succeeded));
+ if (!succeeded) {
+ DLOG(ERROR) << "GpuCommandBufferMsg_CreateStreamTexture returned failure";
+ return 0;
+ }
return stream_id;
}
return 0;
uint32 sync_point = 0;
- Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, &sync_point));
+ Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, true, &sync_point));
+ return sync_point;
+}
+
+uint32_t CommandBufferProxyImpl::InsertFutureSyncPoint() {
+ if (last_state_.error != gpu::error::kNoError)
+ return 0;
+
+ uint32 sync_point = 0;
+ Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, false, &sync_point));
return sync_point;
}
+void CommandBufferProxyImpl::RetireSyncPoint(uint32_t sync_point) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ Send(new GpuCommandBufferMsg_RetireSyncPoint(route_id_, sync_point));
+}
+
void CommandBufferProxyImpl::SignalSyncPoint(uint32 sync_point,
const base::Closure& callback) {
if (last_state_.error != gpu::error::kNoError)
Send(new GpuCommandBufferMsg_SetSurfaceVisible(route_id_, visible));
}
-void CommandBufferProxyImpl::SendManagedMemoryStats(
- const gpu::ManagedMemoryStats& stats) {
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- Send(new GpuCommandBufferMsg_SendClientManagedMemoryStats(route_id_,
- stats));
-}
-
bool CommandBufferProxyImpl::ProduceFrontBuffer(const gpu::Mailbox& mailbox) {
if (last_state_.error != gpu::error::kNoError)
return false;
}
scoped_ptr<media::VideoDecodeAccelerator>
-CommandBufferProxyImpl::CreateVideoDecoder(media::VideoCodecProfile profile) {
- int decoder_route_id;
- scoped_ptr<media::VideoDecodeAccelerator> vda;
- if (!Send(new GpuCommandBufferMsg_CreateVideoDecoder(route_id_, profile,
- &decoder_route_id))) {
- LOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoDecoder) failed";
- return vda.Pass();
- }
-
- if (decoder_route_id < 0) {
- DLOG(ERROR) << "Failed to Initialize GPU decoder on profile: " << profile;
- return vda.Pass();
- }
+CommandBufferProxyImpl::CreateVideoDecoder() {
+ if (!channel_)
+ return scoped_ptr<media::VideoDecodeAccelerator>();
+ return scoped_ptr<media::VideoDecodeAccelerator>(
+ new GpuVideoDecodeAcceleratorHost(channel_, this));
+}
- GpuVideoDecodeAcceleratorHost* decoder_host =
- new GpuVideoDecodeAcceleratorHost(channel_, decoder_route_id, this);
- vda.reset(decoder_host);
- return vda.Pass();
+scoped_ptr<media::VideoEncodeAccelerator>
+CommandBufferProxyImpl::CreateVideoEncoder() {
+ if (!channel_)
+ return scoped_ptr<media::VideoEncodeAccelerator>();
+ return scoped_ptr<media::VideoEncodeAccelerator>(
+ new GpuVideoEncodeAcceleratorHost(channel_, this));
}
gpu::error::Error CommandBufferProxyImpl::GetLastError() {
shared_state()->Read(&last_state_);
}
+gpu::CommandBufferSharedState* CommandBufferProxyImpl::shared_state() const {
+ return reinterpret_cast<gpu::CommandBufferSharedState*>(
+ shared_state_shm_->memory());
+}
+
+void CommandBufferProxyImpl::OnSwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ if (!swap_buffers_completion_callback_.is_null()) {
+ if (!ui::LatencyInfo::Verify(
+ latency_info, "CommandBufferProxyImpl::OnSwapBuffersCompleted")) {
+ swap_buffers_completion_callback_.Run(std::vector<ui::LatencyInfo>());
+ return;
+ }
+ swap_buffers_completion_callback_.Run(latency_info);
+ }
+}
+
} // namespace content