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