Home | History | Annotate | Download | only in surface
      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 "ui/surface/transport_dib.h"
      6 
      7 #include <windows.h>
      8 
      9 #include <limits>
     10 
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/sys_info.h"
     14 #include "skia/ext/platform_canvas.h"
     15 
     16 TransportDIB::TransportDIB()
     17     : size_(0) {
     18 }
     19 
     20 TransportDIB::~TransportDIB() {
     21 }
     22 
     23 TransportDIB::TransportDIB(HANDLE handle)
     24     : shared_memory_(handle, false /* read write */),
     25       size_(0) {
     26 }
     27 
     28 // static
     29 TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) {
     30   TransportDIB* dib = new TransportDIB;
     31 
     32   if (!dib->shared_memory_.CreateAnonymous(size)) {
     33     delete dib;
     34     return NULL;
     35   }
     36 
     37   dib->size_ = size;
     38   dib->sequence_num_ = sequence_num;
     39 
     40   return dib;
     41 }
     42 
     43 // static
     44 TransportDIB* TransportDIB::Map(Handle handle) {
     45   scoped_ptr<TransportDIB> dib(CreateWithHandle(handle));
     46   if (!dib->Map())
     47     return NULL;
     48   return dib.release();
     49 }
     50 
     51 // static
     52 TransportDIB* TransportDIB::CreateWithHandle(Handle handle) {
     53   return new TransportDIB(handle);
     54 }
     55 
     56 // static
     57 bool TransportDIB::is_valid_handle(Handle dib) {
     58   return dib != NULL;
     59 }
     60 
     61 // static
     62 bool TransportDIB::is_valid_id(TransportDIB::Id id) {
     63   return is_valid_handle(id.handle);
     64 }
     65 
     66 skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) {
     67   // This DIB already mapped the file into this process, but PlatformCanvas
     68   // will map it again.
     69   DCHECK(!memory()) << "Mapped file twice in the same process.";
     70 
     71   // We can't check the canvas size before mapping, but it's safe because
     72   // Windows will fail to map the section if the dimensions of the canvas
     73   // are too large.
     74   skia::PlatformCanvas* canvas =
     75       skia::CreatePlatformCanvas(w, h, true, handle(),
     76                                  skia::RETURN_NULL_ON_FAILURE);
     77 
     78   // Calculate the size for the memory region backing the canvas.
     79   if (canvas)
     80     size_ = skia::PlatformCanvasStrideForWidth(w) * h;
     81 
     82   return canvas;
     83 }
     84 
     85 bool TransportDIB::Map() {
     86   if (!is_valid_handle(handle()))
     87     return false;
     88   if (memory())
     89     return true;
     90 
     91   if (!shared_memory_.Map(0 /* map whole shared memory segment */)) {
     92     LOG(ERROR) << "Failed to map transport DIB"
     93                << " handle:" << shared_memory_.handle()
     94                << " error:" << ::GetLastError();
     95     return false;
     96   }
     97 
     98   size_ = shared_memory_.mapped_size();
     99   return true;
    100 }
    101 
    102 void* TransportDIB::memory() const {
    103   return shared_memory_.memory();
    104 }
    105 
    106 TransportDIB::Handle TransportDIB::handle() const {
    107   return shared_memory_.handle();
    108 }
    109 
    110 TransportDIB::Id TransportDIB::id() const {
    111   return Id(handle(), sequence_num_);
    112 }
    113