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 namespace content {
     23 
     24 ImageTransportSurface::ImageTransportSurface() {}
     25 
     26 ImageTransportSurface::~ImageTransportSurface() {}
     27 
     28 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
     29     GpuChannelManager* manager,
     30     GpuCommandBufferStub* stub,
     31     const gfx::GLSurfaceHandle& handle) {
     32   scoped_refptr<gfx::GLSurface> surface;
     33   if (handle.transport_type == gfx::TEXTURE_TRANSPORT)
     34     surface = new TextureImageTransportSurface(manager, stub, handle);
     35   else
     36     surface = CreateNativeSurface(manager, stub, handle);
     37 
     38   if (!surface.get() || !surface->Initialize())
     39     return NULL;
     40   return surface;
     41 }
     42 
     43 ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
     44                                            GpuChannelManager* manager,
     45                                            GpuCommandBufferStub* stub,
     46                                            gfx::PluginWindowHandle handle)
     47     : surface_(surface),
     48       manager_(manager),
     49       stub_(stub->AsWeakPtr()),
     50       handle_(handle) {
     51   route_id_ = manager_->GenerateRouteID();
     52   manager_->AddRoute(route_id_, this);
     53 }
     54 
     55 ImageTransportHelper::~ImageTransportHelper() {
     56   if (stub_.get()) {
     57     stub_->SetLatencyInfoCallback(
     58         base::Callback<void(const ui::LatencyInfo&)>());
     59   }
     60   manager_->RemoveRoute(route_id_);
     61 }
     62 
     63 bool ImageTransportHelper::Initialize() {
     64   gpu::gles2::GLES2Decoder* decoder = Decoder();
     65 
     66   if (!decoder)
     67     return false;
     68 
     69   decoder->SetResizeCallback(
     70        base::Bind(&ImageTransportHelper::Resize, base::Unretained(this)));
     71 
     72   stub_->SetLatencyInfoCallback(
     73       base::Bind(&ImageTransportHelper::SetLatencyInfo,
     74                  base::Unretained(this)));
     75 
     76   manager_->Send(new GpuHostMsg_AcceleratedSurfaceInitialized(
     77       stub_->surface_id(), route_id_));
     78 
     79   return true;
     80 }
     81 
     82 void ImageTransportHelper::Destroy() {}
     83 
     84 bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
     85   bool handled = true;
     86   IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
     87     IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
     88                         OnBufferPresented)
     89     IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_ResizeViewACK, OnResizeViewACK);
     90     IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu);
     91     IPC_MESSAGE_UNHANDLED(handled = false)
     92   IPC_END_MESSAGE_MAP()
     93   return handled;
     94 }
     95 
     96 void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
     97     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) {
     98   // TRACE_EVENT for gpu tests:
     99   TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
    100                        TRACE_EVENT_SCOPE_THREAD,
    101                        "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
    102                        "width", params.size.width());
    103   params.surface_id = stub_->surface_id();
    104   params.route_id = route_id_;
    105   manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
    106 }
    107 
    108 void ImageTransportHelper::SendAcceleratedSurfacePostSubBuffer(
    109     GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params) {
    110   params.surface_id = stub_->surface_id();
    111   params.route_id = route_id_;
    112   manager_->Send(new GpuHostMsg_AcceleratedSurfacePostSubBuffer(params));
    113 }
    114 
    115 void ImageTransportHelper::SendAcceleratedSurfaceRelease() {
    116   GpuHostMsg_AcceleratedSurfaceRelease_Params params;
    117   params.surface_id = stub_->surface_id();
    118   manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
    119 }
    120 
    121 void ImageTransportHelper::SendResizeView(const gfx::Size& size) {
    122   manager_->Send(new GpuHostMsg_ResizeView(stub_->surface_id(),
    123                                            route_id_,
    124                                            size));
    125 }
    126 
    127 void ImageTransportHelper::SendUpdateVSyncParameters(
    128       base::TimeTicks timebase, base::TimeDelta interval) {
    129   manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(),
    130                                                       timebase,
    131                                                       interval));
    132 }
    133 
    134 void ImageTransportHelper::SendLatencyInfo(
    135     const ui::LatencyInfo& latency_info) {
    136   manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
    137 }
    138 
    139 void ImageTransportHelper::SetScheduled(bool is_scheduled) {
    140   gpu::GpuScheduler* scheduler = Scheduler();
    141   if (!scheduler)
    142     return;
    143 
    144   scheduler->SetScheduled(is_scheduled);
    145 }
    146 
    147 void ImageTransportHelper::DeferToFence(base::Closure task) {
    148   gpu::GpuScheduler* scheduler = Scheduler();
    149   DCHECK(scheduler);
    150 
    151   scheduler->DeferToFence(task);
    152 }
    153 
    154 void ImageTransportHelper::SetPreemptByFlag(
    155     scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
    156   stub_->channel()->SetPreemptByFlag(preemption_flag);
    157 }
    158 
    159 bool ImageTransportHelper::MakeCurrent() {
    160   gpu::gles2::GLES2Decoder* decoder = Decoder();
    161   if (!decoder)
    162     return false;
    163   return decoder->MakeCurrent();
    164 }
    165 
    166 void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
    167   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
    168     context->SetSwapInterval(0);
    169   else
    170     context->SetSwapInterval(1);
    171 }
    172 
    173 void ImageTransportHelper::Suspend() {
    174   manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id()));
    175 }
    176 
    177 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
    178   if (!stub_.get())
    179     return NULL;
    180   return stub_->scheduler();
    181 }
    182 
    183 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
    184   if (!stub_.get())
    185     return NULL;
    186   return stub_->decoder();
    187 }
    188 
    189 void ImageTransportHelper::OnBufferPresented(
    190     const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
    191   surface_->OnBufferPresented(params);
    192 }
    193 
    194 void ImageTransportHelper::OnResizeViewACK() {
    195   surface_->OnResizeViewACK();
    196 }
    197 
    198 void ImageTransportHelper::OnWakeUpGpu() {
    199   surface_->WakeUpGpu();
    200 }
    201 
    202 void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) {
    203   surface_->OnResize(size, scale_factor);
    204 
    205 #if defined(OS_ANDROID)
    206   manager_->gpu_memory_manager()->ScheduleManage(
    207       GpuMemoryManager::kScheduleManageNow);
    208 #endif
    209 }
    210 
    211 void ImageTransportHelper::SetLatencyInfo(
    212     const ui::LatencyInfo& latency_info) {
    213   surface_->SetLatencyInfo(latency_info);
    214 }
    215 
    216 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
    217     GpuChannelManager* manager,
    218     GpuCommandBufferStub* stub,
    219     gfx::GLSurface* surface,
    220     bool transport)
    221     : GLSurfaceAdapter(surface),
    222       transport_(transport),
    223       did_set_swap_interval_(false),
    224       did_unschedule_(false),
    225       is_swap_buffers_pending_(false) {
    226   helper_.reset(new ImageTransportHelper(this,
    227                                          manager,
    228                                          stub,
    229                                          gfx::kNullPluginWindow));
    230 }
    231 
    232 bool PassThroughImageTransportSurface::Initialize() {
    233   // The surface is assumed to have already been initialized.
    234   return helper_->Initialize();
    235 }
    236 
    237 void PassThroughImageTransportSurface::Destroy() {
    238   helper_->Destroy();
    239   GLSurfaceAdapter::Destroy();
    240 }
    241 
    242 bool PassThroughImageTransportSurface::DeferDraws() {
    243   if (is_swap_buffers_pending_) {
    244     DCHECK(!did_unschedule_);
    245     did_unschedule_ = true;
    246     helper_->SetScheduled(false);
    247     return true;
    248   }
    249   return false;
    250 }
    251 
    252 void PassThroughImageTransportSurface::SetLatencyInfo(
    253     const ui::LatencyInfo& latency_info) {
    254   latency_info_ = latency_info;
    255 }
    256 
    257 bool PassThroughImageTransportSurface::SwapBuffers() {
    258   // GetVsyncValues before SwapBuffers to work around Mali driver bug:
    259   // crbug.com/223558.
    260   SendVSyncUpdateIfAvailable();
    261   bool result = gfx::GLSurfaceAdapter::SwapBuffers();
    262   latency_info_.AddLatencyNumber(
    263       ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
    264 
    265   if (transport_) {
    266     DCHECK(!is_swap_buffers_pending_);
    267     is_swap_buffers_pending_ = true;
    268 
    269     // Round trip to the browser UI thread, for throttling, by sending a dummy
    270     // SwapBuffers message.
    271     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
    272     params.surface_handle = 0;
    273     params.latency_info = latency_info_;
    274     params.size = surface()->GetSize();
    275     helper_->SendAcceleratedSurfaceBuffersSwapped(params);
    276   } else {
    277     helper_->SendLatencyInfo(latency_info_);
    278   }
    279   return result;
    280 }
    281 
    282 bool PassThroughImageTransportSurface::PostSubBuffer(
    283     int x, int y, int width, int height) {
    284   SendVSyncUpdateIfAvailable();
    285   bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
    286   latency_info_.AddLatencyNumber(
    287       ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
    288 
    289   if (transport_) {
    290     DCHECK(!is_swap_buffers_pending_);
    291     is_swap_buffers_pending_ = true;
    292 
    293     // Round trip to the browser UI thread, for throttling, by sending a dummy
    294     // PostSubBuffer message.
    295     GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
    296     params.surface_handle = 0;
    297     params.latency_info = latency_info_;
    298     params.surface_size = surface()->GetSize();
    299     params.x = x;
    300     params.y = y;
    301     params.width = width;
    302     params.height = height;
    303     helper_->SendAcceleratedSurfacePostSubBuffer(params);
    304 
    305     helper_->SetScheduled(false);
    306   } else {
    307     helper_->SendLatencyInfo(latency_info_);
    308   }
    309   return result;
    310 }
    311 
    312 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
    313   if (!did_set_swap_interval_) {
    314     ImageTransportHelper::SetSwapInterval(context);
    315     did_set_swap_interval_ = true;
    316   }
    317   return true;
    318 }
    319 
    320 void PassThroughImageTransportSurface::OnBufferPresented(
    321     const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
    322   DCHECK(transport_);
    323   DCHECK(is_swap_buffers_pending_);
    324   is_swap_buffers_pending_ = false;
    325   if (did_unschedule_) {
    326     did_unschedule_ = false;
    327     helper_->SetScheduled(true);
    328   }
    329 }
    330 
    331 void PassThroughImageTransportSurface::OnResizeViewACK() {
    332   DCHECK(transport_);
    333   Resize(new_size_);
    334 
    335   TRACE_EVENT_ASYNC_END0("gpu", "OnResize", this);
    336   helper_->SetScheduled(true);
    337 }
    338 
    339 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
    340                                                 float scale_factor) {
    341   new_size_ = size;
    342 
    343   if (transport_) {
    344     helper_->SendResizeView(size);
    345     helper_->SetScheduled(false);
    346     TRACE_EVENT_ASYNC_BEGIN2("gpu", "OnResize", this,
    347                              "width", size.width(), "height", size.height());
    348   } else {
    349     Resize(new_size_);
    350   }
    351 }
    352 
    353 gfx::Size PassThroughImageTransportSurface::GetSize() {
    354   return GLSurfaceAdapter::GetSize();
    355 }
    356 
    357 void PassThroughImageTransportSurface::WakeUpGpu() {
    358   NOTIMPLEMENTED();
    359 }
    360 
    361 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
    362 
    363 void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
    364   gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
    365   if (vsync_provider) {
    366     vsync_provider->GetVSyncParameters(
    367       base::Bind(&ImageTransportHelper::SendUpdateVSyncParameters,
    368                  helper_->AsWeakPtr()));
    369   }
    370 }
    371 
    372 }  // namespace content
    373