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