Home | History | Annotate | Download | only in dri
      1 // Copyright 2013 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/gfx/ozone/dri/dri_surface.h"
      6 
      7 #include <errno.h>
      8 #include <sys/mman.h>
      9 #include <sys/types.h>
     10 #include <xf86drm.h>
     11 
     12 #include "base/logging.h"
     13 #include "third_party/skia/include/core/SkBitmap.h"
     14 #include "third_party/skia/include/core/SkBitmapDevice.h"
     15 #include "third_party/skia/include/core/SkCanvas.h"
     16 #include "ui/gfx/ozone/dri/dri_skbitmap.h"
     17 #include "ui/gfx/ozone/dri/hardware_display_controller.h"
     18 #include "ui/gfx/skia_util.h"
     19 
     20 namespace gfx {
     21 
     22 namespace {
     23 
     24 // Extends the SkBitmapDevice to allow setting the SkPixelRef. We use the setter
     25 // to change the SkPixelRef such that the device always points to the
     26 // backbuffer.
     27 class CustomSkBitmapDevice : public SkBitmapDevice {
     28  public:
     29   CustomSkBitmapDevice(const SkBitmap& bitmap) : SkBitmapDevice(bitmap) {}
     30   virtual ~CustomSkBitmapDevice() {}
     31 
     32   void SetPixelRef(SkPixelRef* pixel_ref) { setPixelRef(pixel_ref, 0); }
     33 
     34  private:
     35   DISALLOW_COPY_AND_ASSIGN(CustomSkBitmapDevice);
     36 };
     37 
     38 }  // namespace
     39 
     40 ////////////////////////////////////////////////////////////////////////////////
     41 // DriSurface implementation
     42 
     43 DriSurface::DriSurface(
     44     HardwareDisplayController* controller)
     45     : controller_(controller),
     46       bitmaps_(),
     47       front_buffer_(0) {
     48 }
     49 
     50 DriSurface::~DriSurface() {
     51 }
     52 
     53 bool DriSurface::Initialize() {
     54   for (int i = 0; i < 2; ++i) {
     55     bitmaps_[i].reset(CreateBuffer());
     56     // TODO(dnicoara) Should select the configuration based on what the
     57     // underlying system supports.
     58     bitmaps_[i]->setConfig(SkBitmap::kARGB_8888_Config,
     59                            controller_->get_mode().hdisplay,
     60                            controller_->get_mode().vdisplay);
     61 
     62     if (!bitmaps_[i]->Initialize()) {
     63       return false;
     64     }
     65   }
     66 
     67   skia_device_ = skia::AdoptRef(
     68       new CustomSkBitmapDevice(*bitmaps_[front_buffer_ ^ 1].get()));
     69   skia_canvas_ = skia::AdoptRef(new SkCanvas(skia_device_.get()));
     70 
     71   return true;
     72 }
     73 
     74 uint32_t DriSurface::GetFramebufferId() const {
     75   CHECK(bitmaps_[0].get() && bitmaps_[1].get());
     76   return bitmaps_[front_buffer_ ^ 1]->get_framebuffer();
     77 }
     78 
     79 // This call is made after the hardware just started displaying our back buffer.
     80 // We need to update our pointer reference and synchronize the two buffers.
     81 void DriSurface::SwapBuffers() {
     82   CHECK(bitmaps_[0].get() && bitmaps_[1].get());
     83 
     84   // Update our front buffer pointer.
     85   front_buffer_ ^= 1;
     86 
     87   // Unlocking will unset the pixel pointer, so it won't be pointing to the old
     88   // PixelRef.
     89   skia_device_->accessBitmap(false).unlockPixels();
     90   // Update the backing pixels for the bitmap device.
     91   static_cast<CustomSkBitmapDevice*>(skia_device_.get())->SetPixelRef(
     92       bitmaps_[front_buffer_ ^ 1]->pixelRef());
     93   // Locking the pixels will set the pixel pointer based on the PixelRef value.
     94   skia_device_->accessBitmap(false).lockPixels();
     95 
     96   SkIRect device_damage;
     97   skia_canvas_->getClipDeviceBounds(&device_damage);
     98   SkRect damage = SkRect::Make(device_damage);
     99 
    100   skia_canvas_->drawBitmapRectToRect(*bitmaps_[front_buffer_].get(),
    101                                      &damage,
    102                                      damage);
    103 }
    104 
    105 SkCanvas* DriSurface::GetDrawableForWidget() {
    106   return skia_canvas_.get();
    107 }
    108 
    109 DriSkBitmap* DriSurface::CreateBuffer() {
    110   return new DriSkBitmap(controller_->get_fd());
    111 }
    112 
    113 }  // namespace gfx
    114