Home | History | Annotate | Download | only in gpu
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/common/gpu/image_transport_surface.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/command_line.h"
     10 #include "base/debug/trace_event.h"
     11 #include "content/common/gpu/gpu_channel.h"
     12 #include "content/common/gpu/gpu_channel_manager.h"
     13 #include "content/common/gpu/gpu_command_buffer_stub.h"
     14 #include "content/common/gpu/gpu_messages.h"
     15 #include "content/common/gpu/sync_point_manager.h"
     16 #include "content/common/gpu/texture_image_transport_surface.h"
     17 #include "gpu/command_buffer/service/gpu_scheduler.h"
     18 #include "ui/gfx/vsync_provider.h"
     19 #include "ui/gl/gl_implementation.h"
     20 #include "ui/gl/gl_switches.h"
     21 
     22 #if defined(OS_WIN)
     23 #include "ui/base/win/shell.h"
     24 #endif
     25 
     26 namespace content {
     27 
     28 ImageTransportSurface::ImageTransportSurface() {}
     29 
     30 ImageTransportSurface::~ImageTransportSurface() {}
     31 
     32 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
     33     GpuChannelManager* manager,
     34     GpuCommandBufferStub* stub,
     35     const gfx::GLSurfaceHandle& handle) {
     36   scoped_refptr<gfx::GLSurface> surface;
     37   if (handle.transport_type == gfx::TEXTURE_TRANSPORT)
     38     surface = new TextureImageTransportSurface(manager, stub, handle);
     39   else
     40     surface = CreateNativeSurface(manager, stub, handle);
     41 
     42   if (!surface.get() || !surface->Initialize())
     43     return NULL;
     44   return surface;
     45 }
     46 
     47 ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
     48                                            GpuChannelManager* manager,
     49                                            GpuCommandBufferStub* stub,
     50                                            gfx::PluginWindowHandle handle)
     51     : surface_(surface),
     52       manager_(manager),
     53       stub_(stub->AsWeakPtr()),
     54       handle_(handle) {
     55   route_id_ = manager_->GenerateRouteID();
     56   manager_->AddRoute(route_id_, this);
     57 }
     58 
     59 ImageTransportHelper::~ImageTransportHelper() {
     60   if (stub_.get()) {
     61     stub_->SetLatencyInfoCallback(
     62         base::Callback<void(const std::vector<ui::LatencyInfo>&)>());
     63   }
     64   manager_->RemoveRoute(route_id_);
     65 }
     66 
     67 bool ImageTransportHelper::Initialize() {
     68   gpu::gles2::GLES2Decoder* decoder = Decoder();
     69 
     70   if (!decoder)
     71     return false;
     72 
     73   decoder->SetResizeCallback(
     74        base::Bind(&ImageTransportHelper::Resize, base::Unretained(this)));
     75 
     76   stub_->SetLatencyInfoCallback(
     77       base::Bind(&ImageTransportHelper::SetLatencyInfo,
     78                  base::Unretained(this)));
     79 
     80   manager_->Send(new GpuHostMsg_AcceleratedSurfaceInitialized(
     81       stub_->surface_id(), route_id_));
     82 
     83   return true;
     84 }
     85 
     86 void ImageTransportHelper::Destroy() {}
     87 
     88 bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
     89   bool handled = true;
     90   IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
     91     IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
     92                         OnBufferPresented)
     93     IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu);
     94     IPC_MESSAGE_UNHANDLED(handled = false)
     95   IPC_END_MESSAGE_MAP()
     96   return handled;
     97 }
     98 
     99 void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
    100     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) {
    101   // TRACE_EVENT for gpu tests:
    102   TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
    103                        TRACE_EVENT_SCOPE_THREAD,
    104                        "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
    105                        "width", params.size.width());
    106   params.surface_id = stub_->surface_id();
    107   params.route_id = route_id_;
    108   manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
    109 }
    110 
    111 void ImageTransportHelper::SendAcceleratedSurfacePostSubBuffer(
    112     GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params) {
    113   params.surface_id = stub_->surface_id();
    114   params.route_id = route_id_;
    115   manager_->Send(new GpuHostMsg_AcceleratedSurfacePostSubBuffer(params));
    116 }
    117 
    118 void ImageTransportHelper::SendAcceleratedSurfaceRelease() {
    119   GpuHostMsg_AcceleratedSurfaceRelease_Params params;
    120   params.surface_id = stub_->surface_id();
    121   manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
    122 }
    123 
    124 void ImageTransportHelper::SendUpdateVSyncParameters(
    125       base::TimeTicks timebase, base::TimeDelta interval) {
    126   manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(),
    127                                                       timebase,
    128                                                       interval));
    129 }
    130 
    131 void ImageTransportHelper::SendLatencyInfo(
    132     const std::vector<ui::LatencyInfo>& latency_info) {
    133   manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
    134 }
    135 
    136 void ImageTransportHelper::SetScheduled(bool is_scheduled) {
    137   gpu::GpuScheduler* scheduler = Scheduler();
    138   if (!scheduler)
    139     return;
    140 
    141   scheduler->SetScheduled(is_scheduled);
    142 }
    143 
    144 void ImageTransportHelper::DeferToFence(base::Closure task) {
    145   gpu::GpuScheduler* scheduler = Scheduler();
    146   DCHECK(scheduler);
    147 
    148   scheduler->DeferToFence(task);
    149 }
    150 
    151 void ImageTransportHelper::SetPreemptByFlag(
    152     scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
    153   stub_->channel()->SetPreemptByFlag(preemption_flag);
    154 }
    155 
    156 bool ImageTransportHelper::MakeCurrent() {
    157   gpu::gles2::GLES2Decoder* decoder = Decoder();
    158   if (!decoder)
    159     return false;
    160   return decoder->MakeCurrent();
    161 }
    162 
    163 void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
    164 #if defined(OS_WIN)
    165   // If Aero Glass is enabled, then the renderer will handle ratelimiting and
    166   // there's no tearing, so waiting for vsync is unnecessary.
    167   if (ui::win::IsAeroGlassEnabled()) {
    168     context->SetSwapInterval(0);
    169     return;
    170   }
    171 #endif
    172   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
    173     context->SetSwapInterval(0);
    174   else
    175     context->SetSwapInterval(1);
    176 }
    177 
    178 void ImageTransportHelper::Suspend() {
    179   manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id()));
    180 }
    181 
    182 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
    183   if (!stub_.get())
    184     return NULL;
    185   return stub_->scheduler();
    186 }
    187 
    188 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
    189   if (!stub_.get())
    190     return NULL;
    191   return stub_->decoder();
    192 }
    193 
    194 void ImageTransportHelper::OnBufferPresented(
    195     const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
    196   surface_->OnBufferPresented(params);
    197 }
    198 
    199 void ImageTransportHelper::OnWakeUpGpu() {
    200   surface_->WakeUpGpu();
    201 }
    202 
    203 void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) {
    204   surface_->OnResize(size, scale_factor);
    205 
    206 #if defined(OS_ANDROID)
    207   manager_->gpu_memory_manager()->ScheduleManage(
    208       GpuMemoryManager::kScheduleManageNow);
    209 #endif
    210 }
    211 
    212 void ImageTransportHelper::SetLatencyInfo(
    213     const std::vector<ui::LatencyInfo>& latency_info) {
    214   surface_->SetLatencyInfo(latency_info);
    215 }
    216 
    217 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
    218     GpuChannelManager* manager,
    219     GpuCommandBufferStub* stub,
    220     gfx::GLSurface* surface)
    221     : GLSurfaceAdapter(surface),
    222       did_set_swap_interval_(false) {
    223   helper_.reset(new ImageTransportHelper(this,
    224                                          manager,
    225                                          stub,
    226                                          gfx::kNullPluginWindow));
    227 }
    228 
    229 bool PassThroughImageTransportSurface::Initialize() {
    230   // The surface is assumed to have already been initialized.
    231   return helper_->Initialize();
    232 }
    233 
    234 void PassThroughImageTransportSurface::Destroy() {
    235   helper_->Destroy();
    236   GLSurfaceAdapter::Destroy();
    237 }
    238 
    239 void PassThroughImageTransportSurface::SetLatencyInfo(
    240     const std::vector<ui::LatencyInfo>& latency_info) {
    241   for (size_t i = 0; i < latency_info.size(); i++)
    242     latency_info_.push_back(latency_info[i]);
    243 }
    244 
    245 bool PassThroughImageTransportSurface::SwapBuffers() {
    246   // GetVsyncValues before SwapBuffers to work around Mali driver bug:
    247   // crbug.com/223558.
    248   SendVSyncUpdateIfAvailable();
    249   bool result = gfx::GLSurfaceAdapter::SwapBuffers();
    250   for (size_t i = 0; i < latency_info_.size(); i++) {
    251     latency_info_[i].AddLatencyNumber(
    252         ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
    253   }
    254 
    255   helper_->SendLatencyInfo(latency_info_);
    256   latency_info_.clear();
    257   return result;
    258 }
    259 
    260 bool PassThroughImageTransportSurface::PostSubBuffer(
    261     int x, int y, int width, int height) {
    262   SendVSyncUpdateIfAvailable();
    263   bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
    264   for (size_t i = 0; i < latency_info_.size(); i++) {
    265     latency_info_[i].AddLatencyNumber(
    266         ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
    267   }
    268 
    269   helper_->SendLatencyInfo(latency_info_);
    270   latency_info_.clear();
    271   return result;
    272 }
    273 
    274 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
    275   if (!did_set_swap_interval_) {
    276     ImageTransportHelper::SetSwapInterval(context);
    277     did_set_swap_interval_ = true;
    278   }
    279   return true;
    280 }
    281 
    282 void PassThroughImageTransportSurface::OnBufferPresented(
    283     const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
    284   NOTREACHED();
    285 }
    286 
    287 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
    288                                                 float scale_factor) {
    289   Resize(size);
    290 }
    291 
    292 gfx::Size PassThroughImageTransportSurface::GetSize() {
    293   return GLSurfaceAdapter::GetSize();
    294 }
    295 
    296 void PassThroughImageTransportSurface::WakeUpGpu() {
    297   NOTIMPLEMENTED();
    298 }
    299 
    300 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
    301 
    302 void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
    303   gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
    304   if (vsync_provider) {
    305     vsync_provider->GetVSyncParameters(
    306       base::Bind(&ImageTransportHelper::SendUpdateVSyncParameters,
    307                  helper_->AsWeakPtr()));
    308   }
    309 }
    310 
    311 }  // namespace content
    312